14bff34e3Sthurlow /* 24bff34e3Sthurlow * CDDL HEADER START 34bff34e3Sthurlow * 44bff34e3Sthurlow * The contents of this file are subject to the terms of the 54bff34e3Sthurlow * Common Development and Distribution License (the "License"). 64bff34e3Sthurlow * You may not use this file except in compliance with the License. 74bff34e3Sthurlow * 84bff34e3Sthurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94bff34e3Sthurlow * or http://www.opensolaris.org/os/licensing. 104bff34e3Sthurlow * See the License for the specific language governing permissions 114bff34e3Sthurlow * and limitations under the License. 124bff34e3Sthurlow * 134bff34e3Sthurlow * When distributing Covered Code, include this CDDL HEADER in each 144bff34e3Sthurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154bff34e3Sthurlow * If applicable, add the following below this CDDL HEADER, with the 164bff34e3Sthurlow * fields enclosed by brackets "[]" replaced with your own identifying 174bff34e3Sthurlow * information: Portions Copyright [yyyy] [name of copyright owner] 184bff34e3Sthurlow * 194bff34e3Sthurlow * CDDL HEADER END 204bff34e3Sthurlow */ 21613a2f6bSGordon Ross 224bff34e3Sthurlow /* 23a19609f8Sjv227347 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 244bff34e3Sthurlow * 254bff34e3Sthurlow * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. 264bff34e3Sthurlow * All rights reserved. 274bff34e3Sthurlow */ 284bff34e3Sthurlow 294bff34e3Sthurlow #include <sys/param.h> 304bff34e3Sthurlow #include <sys/systm.h> 314bff34e3Sthurlow #include <sys/thread.h> 324bff34e3Sthurlow #include <sys/t_lock.h> 334bff34e3Sthurlow #include <sys/time.h> 344bff34e3Sthurlow #include <sys/vnode.h> 354bff34e3Sthurlow #include <sys/vfs.h> 364bff34e3Sthurlow #include <sys/errno.h> 374bff34e3Sthurlow #include <sys/buf.h> 384bff34e3Sthurlow #include <sys/stat.h> 394bff34e3Sthurlow #include <sys/cred.h> 404bff34e3Sthurlow #include <sys/kmem.h> 414bff34e3Sthurlow #include <sys/debug.h> 424bff34e3Sthurlow #include <sys/vmsystm.h> 434bff34e3Sthurlow #include <sys/flock.h> 444bff34e3Sthurlow #include <sys/share.h> 454bff34e3Sthurlow #include <sys/cmn_err.h> 464bff34e3Sthurlow #include <sys/tiuser.h> 474bff34e3Sthurlow #include <sys/sysmacros.h> 484bff34e3Sthurlow #include <sys/callb.h> 494bff34e3Sthurlow #include <sys/acl.h> 504bff34e3Sthurlow #include <sys/kstat.h> 514bff34e3Sthurlow #include <sys/signal.h> 524bff34e3Sthurlow #include <sys/list.h> 534bff34e3Sthurlow #include <sys/zone.h> 544bff34e3Sthurlow 5502d09e03SGordon Ross #include <netsmb/smb.h> 564bff34e3Sthurlow #include <netsmb/smb_conn.h> 5702d09e03SGordon Ross #include <netsmb/smb_subr.h> 584bff34e3Sthurlow 594bff34e3Sthurlow #include <smbfs/smbfs.h> 604bff34e3Sthurlow #include <smbfs/smbfs_node.h> 614bff34e3Sthurlow #include <smbfs/smbfs_subr.h> 624bff34e3Sthurlow 634bff34e3Sthurlow #include <vm/hat.h> 644bff34e3Sthurlow #include <vm/as.h> 654bff34e3Sthurlow #include <vm/page.h> 664bff34e3Sthurlow #include <vm/pvn.h> 674bff34e3Sthurlow #include <vm/seg.h> 684bff34e3Sthurlow #include <vm/seg_map.h> 694bff34e3Sthurlow #include <vm/seg_vn.h> 704bff34e3Sthurlow 71*5f4fc069Sjilinxpd #define ATTRCACHE_VALID(vp) (gethrtime() < VTOSMB(vp)->r_attrtime) 72*5f4fc069Sjilinxpd 7328162916SGordon Ross static int smbfs_getattr_cache(vnode_t *, smbfattr_t *); 7428162916SGordon Ross static void smbfattr_to_vattr(vnode_t *, smbfattr_t *, vattr_t *); 7528162916SGordon Ross static void smbfattr_to_xvattr(smbfattr_t *, vattr_t *); 76*5f4fc069Sjilinxpd static int smbfs_getattr_otw(vnode_t *, struct smbfattr *, cred_t *); 77*5f4fc069Sjilinxpd 7802d09e03SGordon Ross 794bff34e3Sthurlow /* 804bff34e3Sthurlow * The following code provide zone support in order to perform an action 814bff34e3Sthurlow * for each smbfs mount in a zone. This is also where we would add 824bff34e3Sthurlow * per-zone globals and kernel threads for the smbfs module (since 834bff34e3Sthurlow * they must be terminated by the shutdown callback). 844bff34e3Sthurlow */ 854bff34e3Sthurlow 864bff34e3Sthurlow struct smi_globals { 874bff34e3Sthurlow kmutex_t smg_lock; /* lock protecting smg_list */ 884bff34e3Sthurlow list_t smg_list; /* list of SMBFS mounts in zone */ 894bff34e3Sthurlow boolean_t smg_destructor_called; 904bff34e3Sthurlow }; 914bff34e3Sthurlow typedef struct smi_globals smi_globals_t; 924bff34e3Sthurlow 934bff34e3Sthurlow static zone_key_t smi_list_key; 944bff34e3Sthurlow 9502d09e03SGordon Ross /* 9602d09e03SGordon Ross * Attributes caching: 9702d09e03SGordon Ross * 9802d09e03SGordon Ross * Attributes are cached in the smbnode in struct vattr form. 9902d09e03SGordon Ross * There is a time associated with the cached attributes (r_attrtime) 10002d09e03SGordon Ross * which tells whether the attributes are valid. The time is initialized 10102d09e03SGordon Ross * to the difference between current time and the modify time of the vnode 10202d09e03SGordon Ross * when new attributes are cached. This allows the attributes for 10302d09e03SGordon Ross * files that have changed recently to be timed out sooner than for files 10402d09e03SGordon Ross * that have not changed for a long time. There are minimum and maximum 10502d09e03SGordon Ross * timeout values that can be set per mount point. 10602d09e03SGordon Ross */ 10702d09e03SGordon Ross 10802d09e03SGordon Ross /* 109*5f4fc069Sjilinxpd * Helper for _validate_caches 110*5f4fc069Sjilinxpd */ 111*5f4fc069Sjilinxpd int 112*5f4fc069Sjilinxpd smbfs_waitfor_purge_complete(vnode_t *vp) 113*5f4fc069Sjilinxpd { 114*5f4fc069Sjilinxpd smbnode_t *np; 115*5f4fc069Sjilinxpd k_sigset_t smask; 116*5f4fc069Sjilinxpd 117*5f4fc069Sjilinxpd np = VTOSMB(vp); 118*5f4fc069Sjilinxpd if (np->r_serial != NULL && np->r_serial != curthread) { 119*5f4fc069Sjilinxpd mutex_enter(&np->r_statelock); 120*5f4fc069Sjilinxpd sigintr(&smask, VTOSMI(vp)->smi_flags & SMI_INT); 121*5f4fc069Sjilinxpd while (np->r_serial != NULL) { 122*5f4fc069Sjilinxpd if (!cv_wait_sig(&np->r_cv, &np->r_statelock)) { 123*5f4fc069Sjilinxpd sigunintr(&smask); 124*5f4fc069Sjilinxpd mutex_exit(&np->r_statelock); 125*5f4fc069Sjilinxpd return (EINTR); 126*5f4fc069Sjilinxpd } 127*5f4fc069Sjilinxpd } 128*5f4fc069Sjilinxpd sigunintr(&smask); 129*5f4fc069Sjilinxpd mutex_exit(&np->r_statelock); 130*5f4fc069Sjilinxpd } 131*5f4fc069Sjilinxpd return (0); 132*5f4fc069Sjilinxpd } 133*5f4fc069Sjilinxpd 134*5f4fc069Sjilinxpd /* 135*5f4fc069Sjilinxpd * Validate caches by checking cached attributes. If the cached 136*5f4fc069Sjilinxpd * attributes have timed out, then get new attributes from the server. 137*5f4fc069Sjilinxpd * As a side affect, this will do cache invalidation if the attributes 138*5f4fc069Sjilinxpd * have changed. 139*5f4fc069Sjilinxpd * 140*5f4fc069Sjilinxpd * If the attributes have not timed out and if there is a cache 141*5f4fc069Sjilinxpd * invalidation being done by some other thread, then wait until that 142*5f4fc069Sjilinxpd * thread has completed the cache invalidation. 14302d09e03SGordon Ross */ 14402d09e03SGordon Ross int 14502d09e03SGordon Ross smbfs_validate_caches( 14602d09e03SGordon Ross struct vnode *vp, 14702d09e03SGordon Ross cred_t *cr) 14802d09e03SGordon Ross { 149*5f4fc069Sjilinxpd struct smbfattr fa; 150*5f4fc069Sjilinxpd int error; 15102d09e03SGordon Ross 152*5f4fc069Sjilinxpd if (ATTRCACHE_VALID(vp)) { 153*5f4fc069Sjilinxpd error = smbfs_waitfor_purge_complete(vp); 154*5f4fc069Sjilinxpd if (error) 155*5f4fc069Sjilinxpd return (error); 156*5f4fc069Sjilinxpd return (0); 157*5f4fc069Sjilinxpd } 158*5f4fc069Sjilinxpd 159*5f4fc069Sjilinxpd return (smbfs_getattr_otw(vp, &fa, cr)); 16002d09e03SGordon Ross } 16102d09e03SGordon Ross 16202d09e03SGordon Ross /* 16302d09e03SGordon Ross * Purge all of the various data caches. 164*5f4fc069Sjilinxpd * 165*5f4fc069Sjilinxpd * Here NFS also had a flags arg to control what gets flushed. 166*5f4fc069Sjilinxpd * We only have the page cache, so no flags arg. 16702d09e03SGordon Ross */ 16802d09e03SGordon Ross /* ARGSUSED */ 16902d09e03SGordon Ross void 170*5f4fc069Sjilinxpd smbfs_purge_caches(struct vnode *vp, cred_t *cr) 17102d09e03SGordon Ross { 172*5f4fc069Sjilinxpd 17302d09e03SGordon Ross /* 174*5f4fc069Sjilinxpd * Here NFS has: Purge the DNLC for this vp, 17502d09e03SGordon Ross * Clear any readdir state bits, 17602d09e03SGordon Ross * the readlink response cache, ... 17702d09e03SGordon Ross */ 17802d09e03SGordon Ross 17902d09e03SGordon Ross /* 18002d09e03SGordon Ross * Flush the page cache. 18102d09e03SGordon Ross */ 18202d09e03SGordon Ross if (vn_has_cached_data(vp)) { 18302d09e03SGordon Ross (void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_INVAL, cr, NULL); 18402d09e03SGordon Ross } 185*5f4fc069Sjilinxpd 186*5f4fc069Sjilinxpd /* 187*5f4fc069Sjilinxpd * Here NFS has: Flush the readdir response cache. 188*5f4fc069Sjilinxpd * No readdir cache in smbfs. 189*5f4fc069Sjilinxpd */ 19002d09e03SGordon Ross } 19102d09e03SGordon Ross 19202d09e03SGordon Ross /* 193*5f4fc069Sjilinxpd * Here NFS has: 194*5f4fc069Sjilinxpd * nfs_purge_rddir_cache() 195*5f4fc069Sjilinxpd * nfs3_cache_post_op_attr() 196*5f4fc069Sjilinxpd * nfs3_cache_post_op_vattr() 197*5f4fc069Sjilinxpd * nfs3_cache_wcc_data() 198*5f4fc069Sjilinxpd */ 199*5f4fc069Sjilinxpd 200*5f4fc069Sjilinxpd /* 20102d09e03SGordon Ross * Check the attribute cache to see if the new attributes match 20202d09e03SGordon Ross * those cached. If they do, the various `data' caches are 20302d09e03SGordon Ross * considered to be good. Otherwise, purge the cached data. 20402d09e03SGordon Ross */ 205*5f4fc069Sjilinxpd static void 20602d09e03SGordon Ross smbfs_cache_check( 20702d09e03SGordon Ross struct vnode *vp, 208*5f4fc069Sjilinxpd struct smbfattr *fap, 209*5f4fc069Sjilinxpd cred_t *cr) 21002d09e03SGordon Ross { 21102d09e03SGordon Ross smbnode_t *np; 21202d09e03SGordon Ross int purge_data = 0; 21302d09e03SGordon Ross int purge_acl = 0; 21402d09e03SGordon Ross 21502d09e03SGordon Ross np = VTOSMB(vp); 21602d09e03SGordon Ross mutex_enter(&np->r_statelock); 21702d09e03SGordon Ross 21802d09e03SGordon Ross /* 21902d09e03SGordon Ross * Compare with NFS macro: CACHE_VALID 22002d09e03SGordon Ross * If the mtime or size has changed, 22102d09e03SGordon Ross * purge cached data. 22202d09e03SGordon Ross */ 22302d09e03SGordon Ross if (np->r_attr.fa_mtime.tv_sec != fap->fa_mtime.tv_sec || 22402d09e03SGordon Ross np->r_attr.fa_mtime.tv_nsec != fap->fa_mtime.tv_nsec) 22502d09e03SGordon Ross purge_data = 1; 22602d09e03SGordon Ross if (np->r_attr.fa_size != fap->fa_size) 22702d09e03SGordon Ross purge_data = 1; 22802d09e03SGordon Ross 22902d09e03SGordon Ross if (np->r_attr.fa_ctime.tv_sec != fap->fa_ctime.tv_sec || 23002d09e03SGordon Ross np->r_attr.fa_ctime.tv_nsec != fap->fa_ctime.tv_nsec) 23102d09e03SGordon Ross purge_acl = 1; 232bd7c6f51SGordon Ross 233bd7c6f51SGordon Ross if (purge_acl) { 234bd7c6f51SGordon Ross np->r_sectime = gethrtime(); 235bd7c6f51SGordon Ross } 23602d09e03SGordon Ross 23702d09e03SGordon Ross mutex_exit(&np->r_statelock); 23802d09e03SGordon Ross 23902d09e03SGordon Ross if (purge_data) 240*5f4fc069Sjilinxpd smbfs_purge_caches(vp, cr); 24102d09e03SGordon Ross } 24202d09e03SGordon Ross 24302d09e03SGordon Ross /* 24402d09e03SGordon Ross * Set attributes cache for given vnode using SMB fattr 24502d09e03SGordon Ross * and update the attribute cache timeout. 24602d09e03SGordon Ross * 247*5f4fc069Sjilinxpd * Based on NFS: nfs_attrcache, nfs_attrcache_va 24802d09e03SGordon Ross */ 24902d09e03SGordon Ross void 25002d09e03SGordon Ross smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap) 25102d09e03SGordon Ross { 25202d09e03SGordon Ross smbnode_t *np; 25302d09e03SGordon Ross smbmntinfo_t *smi; 25402d09e03SGordon Ross hrtime_t delta, now; 25502d09e03SGordon Ross u_offset_t newsize; 25602d09e03SGordon Ross vtype_t vtype, oldvt; 25702d09e03SGordon Ross mode_t mode; 25802d09e03SGordon Ross 25902d09e03SGordon Ross np = VTOSMB(vp); 26002d09e03SGordon Ross smi = VTOSMI(vp); 26102d09e03SGordon Ross 26202d09e03SGordon Ross /* 26302d09e03SGordon Ross * We allow v_type to change, so set that here 26442d15982SGordon Ross * (and the mode, which depends on the type). 26502d09e03SGordon Ross */ 26602d09e03SGordon Ross if (fap->fa_attr & SMB_FA_DIR) { 26702d09e03SGordon Ross vtype = VDIR; 26842d15982SGordon Ross mode = smi->smi_dmode; 26902d09e03SGordon Ross } else { 27002d09e03SGordon Ross vtype = VREG; 27142d15982SGordon Ross mode = smi->smi_fmode; 27202d09e03SGordon Ross } 27302d09e03SGordon Ross 27402d09e03SGordon Ross mutex_enter(&np->r_statelock); 27502d09e03SGordon Ross now = gethrtime(); 27602d09e03SGordon Ross 27702d09e03SGordon Ross /* 27802d09e03SGordon Ross * Delta is the number of nanoseconds that we will 27902d09e03SGordon Ross * cache the attributes of the file. It is based on 28002d09e03SGordon Ross * the number of nanoseconds since the last time that 28102d09e03SGordon Ross * we detected a change. The assumption is that files 28202d09e03SGordon Ross * that changed recently are likely to change again. 28302d09e03SGordon Ross * There is a minimum and a maximum for regular files 28402d09e03SGordon Ross * and for directories which is enforced though. 28502d09e03SGordon Ross * 28602d09e03SGordon Ross * Using the time since last change was detected 28702d09e03SGordon Ross * eliminates direct comparison or calculation 28802d09e03SGordon Ross * using mixed client and server times. SMBFS 28902d09e03SGordon Ross * does not make any assumptions regarding the 29002d09e03SGordon Ross * client and server clocks being synchronized. 29102d09e03SGordon Ross */ 29202d09e03SGordon Ross if (fap->fa_mtime.tv_sec != np->r_attr.fa_mtime.tv_sec || 29302d09e03SGordon Ross fap->fa_mtime.tv_nsec != np->r_attr.fa_mtime.tv_nsec || 29402d09e03SGordon Ross fap->fa_size != np->r_attr.fa_size) 29502d09e03SGordon Ross np->r_mtime = now; 29602d09e03SGordon Ross 29702d09e03SGordon Ross if ((smi->smi_flags & SMI_NOAC) || (vp->v_flag & VNOCACHE)) 29802d09e03SGordon Ross delta = 0; 29902d09e03SGordon Ross else { 30002d09e03SGordon Ross delta = now - np->r_mtime; 30102d09e03SGordon Ross if (vtype == VDIR) { 30202d09e03SGordon Ross if (delta < smi->smi_acdirmin) 30302d09e03SGordon Ross delta = smi->smi_acdirmin; 30402d09e03SGordon Ross else if (delta > smi->smi_acdirmax) 30502d09e03SGordon Ross delta = smi->smi_acdirmax; 30602d09e03SGordon Ross } else { 30702d09e03SGordon Ross if (delta < smi->smi_acregmin) 30802d09e03SGordon Ross delta = smi->smi_acregmin; 30902d09e03SGordon Ross else if (delta > smi->smi_acregmax) 31002d09e03SGordon Ross delta = smi->smi_acregmax; 31102d09e03SGordon Ross } 31202d09e03SGordon Ross } 31302d09e03SGordon Ross 31402d09e03SGordon Ross np->r_attrtime = now + delta; 31502d09e03SGordon Ross np->r_attr = *fap; 31602d09e03SGordon Ross np->n_mode = mode; 31702d09e03SGordon Ross oldvt = vp->v_type; 31802d09e03SGordon Ross vp->v_type = vtype; 31902d09e03SGordon Ross 32002d09e03SGordon Ross /* 32102d09e03SGordon Ross * Shall we update r_size? (local notion of size) 32202d09e03SGordon Ross * 32302d09e03SGordon Ross * The real criteria for updating r_size should be: 32402d09e03SGordon Ross * if the file has grown on the server, or if 32502d09e03SGordon Ross * the client has not modified the file. 32602d09e03SGordon Ross * 32702d09e03SGordon Ross * Also deal with the fact that SMB presents 32802d09e03SGordon Ross * directories as having size=0. Doing that 32902d09e03SGordon Ross * here and leaving fa_size as returned OtW 33002d09e03SGordon Ross * avoids fixing the size lots of places. 33102d09e03SGordon Ross */ 33202d09e03SGordon Ross newsize = fap->fa_size; 33302d09e03SGordon Ross if (vtype == VDIR && newsize < DEV_BSIZE) 33402d09e03SGordon Ross newsize = DEV_BSIZE; 33502d09e03SGordon Ross 336*5f4fc069Sjilinxpd if (np->r_size != newsize && 337*5f4fc069Sjilinxpd (!vn_has_cached_data(vp) || 338*5f4fc069Sjilinxpd (!(np->r_flags & RDIRTY) && np->r_count == 0))) { 33902d09e03SGordon Ross /* OK to set the size. */ 34002d09e03SGordon Ross np->r_size = newsize; 34102d09e03SGordon Ross } 34202d09e03SGordon Ross 343*5f4fc069Sjilinxpd /* 344*5f4fc069Sjilinxpd * Here NFS has: 345*5f4fc069Sjilinxpd * nfs_setswaplike(vp, va); 346*5f4fc069Sjilinxpd * np->r_flags &= ~RWRITEATTR; 347*5f4fc069Sjilinxpd * (not needed here) 348*5f4fc069Sjilinxpd */ 34902d09e03SGordon Ross 350*5f4fc069Sjilinxpd np->n_flag &= ~NATTRCHANGED; 35102d09e03SGordon Ross mutex_exit(&np->r_statelock); 35202d09e03SGordon Ross 35302d09e03SGordon Ross if (oldvt != vtype) { 35402d09e03SGordon Ross SMBVDEBUG("vtype change %d to %d\n", oldvt, vtype); 35502d09e03SGordon Ross } 35602d09e03SGordon Ross } 35702d09e03SGordon Ross 35802d09e03SGordon Ross /* 35902d09e03SGordon Ross * Fill in attribute from the cache. 36002d09e03SGordon Ross * 36102d09e03SGordon Ross * If valid, copy to *fap and return zero, 36202d09e03SGordon Ross * otherwise return an error. 36302d09e03SGordon Ross * 36402d09e03SGordon Ross * From NFS: nfs_getattr_cache() 36502d09e03SGordon Ross */ 36602d09e03SGordon Ross int 36702d09e03SGordon Ross smbfs_getattr_cache(vnode_t *vp, struct smbfattr *fap) 36802d09e03SGordon Ross { 36902d09e03SGordon Ross smbnode_t *np; 37002d09e03SGordon Ross int error; 37102d09e03SGordon Ross 37202d09e03SGordon Ross np = VTOSMB(vp); 37302d09e03SGordon Ross 37402d09e03SGordon Ross mutex_enter(&np->r_statelock); 37502d09e03SGordon Ross if (gethrtime() >= np->r_attrtime) { 37602d09e03SGordon Ross /* cache expired */ 37702d09e03SGordon Ross error = ENOENT; 37802d09e03SGordon Ross } else { 37902d09e03SGordon Ross /* cache is valid */ 38002d09e03SGordon Ross *fap = np->r_attr; 38102d09e03SGordon Ross error = 0; 38202d09e03SGordon Ross } 38302d09e03SGordon Ross mutex_exit(&np->r_statelock); 38402d09e03SGordon Ross 38502d09e03SGordon Ross return (error); 38602d09e03SGordon Ross } 38702d09e03SGordon Ross 38802d09e03SGordon Ross /* 38902d09e03SGordon Ross * Get attributes over-the-wire and update attributes cache 39002d09e03SGordon Ross * if no error occurred in the over-the-wire operation. 39102d09e03SGordon Ross * Return 0 if successful, otherwise error. 39202d09e03SGordon Ross * From NFS: nfs_getattr_otw 39302d09e03SGordon Ross */ 394*5f4fc069Sjilinxpd static int 39502d09e03SGordon Ross smbfs_getattr_otw(vnode_t *vp, struct smbfattr *fap, cred_t *cr) 39602d09e03SGordon Ross { 39702d09e03SGordon Ross struct smbnode *np; 39802d09e03SGordon Ross struct smb_cred scred; 39902d09e03SGordon Ross int error; 40002d09e03SGordon Ross 40102d09e03SGordon Ross np = VTOSMB(vp); 40202d09e03SGordon Ross 40302d09e03SGordon Ross /* 404*5f4fc069Sjilinxpd * Here NFS uses the ACL RPC (if smi_flags & SMI_ACL) 405bd7c6f51SGordon Ross * With SMB, getting the ACL is a significantly more 406bd7c6f51SGordon Ross * expensive operation, so we do that only when asked 407bd7c6f51SGordon Ross * for the uid/gid. See smbfsgetattr(). 40802d09e03SGordon Ross */ 40902d09e03SGordon Ross 41002d09e03SGordon Ross /* Shared lock for (possible) n_fid use. */ 41102d09e03SGordon Ross if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 41202d09e03SGordon Ross return (EINTR); 41302d09e03SGordon Ross smb_credinit(&scred, cr); 41402d09e03SGordon Ross 41502d09e03SGordon Ross bzero(fap, sizeof (*fap)); 41602d09e03SGordon Ross error = smbfs_smb_getfattr(np, fap, &scred); 41702d09e03SGordon Ross 41802d09e03SGordon Ross smb_credrele(&scred); 41902d09e03SGordon Ross smbfs_rw_exit(&np->r_lkserlock); 42002d09e03SGordon Ross 42102d09e03SGordon Ross if (error) { 422*5f4fc069Sjilinxpd /* Here NFS has: PURGE_STALE_FH(error, vp, cr) */ 42302d09e03SGordon Ross smbfs_attrcache_remove(np); 42402d09e03SGordon Ross if (error == ENOENT || error == ENOTDIR) { 42502d09e03SGordon Ross /* 42602d09e03SGordon Ross * Getattr failed because the object was 42702d09e03SGordon Ross * removed or renamed by another client. 42802d09e03SGordon Ross * Remove any cached attributes under it. 42902d09e03SGordon Ross */ 43002d09e03SGordon Ross smbfs_attrcache_prune(np); 43102d09e03SGordon Ross } 43202d09e03SGordon Ross return (error); 43302d09e03SGordon Ross } 43402d09e03SGordon Ross 43502d09e03SGordon Ross /* 436*5f4fc069Sjilinxpd * Here NFS has: nfs_cache_fattr(vap, fa, vap, t, cr); 43702d09e03SGordon Ross * which did: fattr_to_vattr, nfs_attr_cache. 43802d09e03SGordon Ross * We cache the fattr form, so just do the 43902d09e03SGordon Ross * cache check and store the attributes. 44002d09e03SGordon Ross */ 441*5f4fc069Sjilinxpd smbfs_cache_check(vp, fap, cr); 44202d09e03SGordon Ross smbfs_attrcache_fa(vp, fap); 44302d09e03SGordon Ross 44402d09e03SGordon Ross return (0); 44502d09e03SGordon Ross } 44602d09e03SGordon Ross 44702d09e03SGordon Ross /* 448*5f4fc069Sjilinxpd * Return either cached or remote attributes. If we get remote attrs, 44902d09e03SGordon Ross * use them to check and invalidate caches, then cache the new attributes. 45002d09e03SGordon Ross * 45102d09e03SGordon Ross * From NFS: nfsgetattr() 45202d09e03SGordon Ross */ 45302d09e03SGordon Ross int 45402d09e03SGordon Ross smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr) 45502d09e03SGordon Ross { 45602d09e03SGordon Ross struct smbfattr fa; 457bd7c6f51SGordon Ross smbmntinfo_t *smi; 458bd7c6f51SGordon Ross uint_t mask; 45902d09e03SGordon Ross int error; 46002d09e03SGordon Ross 461bd7c6f51SGordon Ross smi = VTOSMI(vp); 462bd7c6f51SGordon Ross 463a19609f8Sjv227347 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone); 464bd7c6f51SGordon Ross 465bd7c6f51SGordon Ross /* 466bd7c6f51SGordon Ross * If asked for UID or GID, update n_uid, n_gid. 467bd7c6f51SGordon Ross */ 468bd7c6f51SGordon Ross mask = AT_ALL; 469bd7c6f51SGordon Ross if (vap->va_mask & (AT_UID | AT_GID)) { 470bd7c6f51SGordon Ross if (smi->smi_flags & SMI_ACL) 471bd7c6f51SGordon Ross (void) smbfs_acl_getids(vp, cr); 472bd7c6f51SGordon Ross /* else leave as set in make_smbnode */ 473bd7c6f51SGordon Ross } else { 474bd7c6f51SGordon Ross mask &= ~(AT_UID | AT_GID); 475bd7c6f51SGordon Ross } 47602d09e03SGordon Ross 47702d09e03SGordon Ross /* 47802d09e03SGordon Ross * If we've got cached attributes, just use them; 47902d09e03SGordon Ross * otherwise go to the server to get attributes, 48002d09e03SGordon Ross * which will update the cache in the process. 48102d09e03SGordon Ross */ 48202d09e03SGordon Ross error = smbfs_getattr_cache(vp, &fa); 48302d09e03SGordon Ross if (error) 48402d09e03SGordon Ross error = smbfs_getattr_otw(vp, &fa, cr); 48502d09e03SGordon Ross if (error) 48602d09e03SGordon Ross return (error); 48728162916SGordon Ross vap->va_mask |= mask; 48802d09e03SGordon Ross 48902d09e03SGordon Ross /* 49002d09e03SGordon Ross * Re. client's view of the file size, see: 49102d09e03SGordon Ross * smbfs_attrcache_fa, smbfs_getattr_otw 49202d09e03SGordon Ross */ 49328162916SGordon Ross smbfattr_to_vattr(vp, &fa, vap); 49428162916SGordon Ross if (vap->va_mask & AT_XVATTR) 49528162916SGordon Ross smbfattr_to_xvattr(&fa, vap); 49602d09e03SGordon Ross 49728162916SGordon Ross return (0); 49802d09e03SGordon Ross } 49902d09e03SGordon Ross 50002d09e03SGordon Ross 50102d09e03SGordon Ross /* 50202d09e03SGordon Ross * Convert SMB over the wire attributes to vnode form. 50302d09e03SGordon Ross * Returns 0 for success, error if failed (overflow, etc). 50402d09e03SGordon Ross * From NFS: nattr_to_vattr() 50502d09e03SGordon Ross */ 50628162916SGordon Ross void 50702d09e03SGordon Ross smbfattr_to_vattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap) 50802d09e03SGordon Ross { 50902d09e03SGordon Ross struct smbnode *np = VTOSMB(vp); 51002d09e03SGordon Ross 51102d09e03SGordon Ross /* 51202d09e03SGordon Ross * Take type, mode, uid, gid from the smbfs node, 51302d09e03SGordon Ross * which has have been updated by _getattr_otw. 51402d09e03SGordon Ross */ 51502d09e03SGordon Ross vap->va_type = vp->v_type; 51602d09e03SGordon Ross vap->va_mode = np->n_mode; 51702d09e03SGordon Ross 51802d09e03SGordon Ross vap->va_uid = np->n_uid; 51902d09e03SGordon Ross vap->va_gid = np->n_gid; 52002d09e03SGordon Ross 52102d09e03SGordon Ross vap->va_fsid = vp->v_vfsp->vfs_dev; 52202d09e03SGordon Ross vap->va_nodeid = np->n_ino; 52302d09e03SGordon Ross vap->va_nlink = 1; 52402d09e03SGordon Ross 52502d09e03SGordon Ross /* 52602d09e03SGordon Ross * Difference from NFS here: We cache attributes as 52702d09e03SGordon Ross * reported by the server, so r_attr.fa_size is the 52802d09e03SGordon Ross * server's idea of the file size. This is called 52902d09e03SGordon Ross * for getattr, so we want to return the client's 53002d09e03SGordon Ross * idea of the file size. NFS deals with that in 53102d09e03SGordon Ross * nfsgetattr(), the equivalent of our caller. 53202d09e03SGordon Ross */ 53302d09e03SGordon Ross vap->va_size = np->r_size; 53402d09e03SGordon Ross 53502d09e03SGordon Ross /* 53602d09e03SGordon Ross * Times. Note, already converted from NT to 53702d09e03SGordon Ross * Unix form (in the unmarshalling code). 53802d09e03SGordon Ross */ 53902d09e03SGordon Ross vap->va_atime = fa->fa_atime; 54002d09e03SGordon Ross vap->va_mtime = fa->fa_mtime; 54102d09e03SGordon Ross vap->va_ctime = fa->fa_ctime; 54202d09e03SGordon Ross 54302d09e03SGordon Ross /* 54402d09e03SGordon Ross * rdev, blksize, seq are made up. 54502d09e03SGordon Ross * va_nblocks is 512 byte blocks. 54602d09e03SGordon Ross */ 54702d09e03SGordon Ross vap->va_rdev = vp->v_rdev; 54802d09e03SGordon Ross vap->va_blksize = MAXBSIZE; 54902d09e03SGordon Ross vap->va_nblocks = (fsblkcnt64_t)btod(np->r_attr.fa_allocsz); 55002d09e03SGordon Ross vap->va_seq = 0; 55102d09e03SGordon Ross } 55202d09e03SGordon Ross 55328162916SGordon Ross /* 55428162916SGordon Ross * smbfattr_to_xvattr: like smbfattr_to_vattr but for 55528162916SGordon Ross * Extensible system attributes (PSARC 2007/315) 55628162916SGordon Ross */ 55728162916SGordon Ross static void 55828162916SGordon Ross smbfattr_to_xvattr(struct smbfattr *fa, struct vattr *vap) 55928162916SGordon Ross { 56028162916SGordon Ross xvattr_t *xvap = (xvattr_t *)vap; /* *vap may be xvattr_t */ 56128162916SGordon Ross xoptattr_t *xoap = NULL; 56228162916SGordon Ross 56328162916SGordon Ross if ((xoap = xva_getxoptattr(xvap)) == NULL) 56428162916SGordon Ross return; 56528162916SGordon Ross 56628162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { 56728162916SGordon Ross xoap->xoa_createtime = fa->fa_createtime; 56828162916SGordon Ross XVA_SET_RTN(xvap, XAT_CREATETIME); 56928162916SGordon Ross } 57028162916SGordon Ross 57128162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { 57228162916SGordon Ross xoap->xoa_archive = 57328162916SGordon Ross ((fa->fa_attr & SMB_FA_ARCHIVE) != 0); 57428162916SGordon Ross XVA_SET_RTN(xvap, XAT_ARCHIVE); 57528162916SGordon Ross } 57628162916SGordon Ross 57728162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { 57828162916SGordon Ross xoap->xoa_system = 57928162916SGordon Ross ((fa->fa_attr & SMB_FA_SYSTEM) != 0); 58028162916SGordon Ross XVA_SET_RTN(xvap, XAT_SYSTEM); 58128162916SGordon Ross } 58228162916SGordon Ross 58328162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { 58428162916SGordon Ross xoap->xoa_readonly = 58528162916SGordon Ross ((fa->fa_attr & SMB_FA_RDONLY) != 0); 58628162916SGordon Ross XVA_SET_RTN(xvap, XAT_READONLY); 58728162916SGordon Ross } 58828162916SGordon Ross 58928162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { 59028162916SGordon Ross xoap->xoa_hidden = 59128162916SGordon Ross ((fa->fa_attr & SMB_FA_HIDDEN) != 0); 59228162916SGordon Ross XVA_SET_RTN(xvap, XAT_HIDDEN); 59328162916SGordon Ross } 59428162916SGordon Ross } 59502d09e03SGordon Ross 59602d09e03SGordon Ross /* 597*5f4fc069Sjilinxpd * Here NFS has: 598*5f4fc069Sjilinxpd * nfs_async_... stuff 599*5f4fc069Sjilinxpd * which we're not using (no async I/O), and: 600*5f4fc069Sjilinxpd * writerp(), 601*5f4fc069Sjilinxpd * nfs_putpages() 602*5f4fc069Sjilinxpd * nfs_invalidate_pages() 603*5f4fc069Sjilinxpd * which we have in smbfs_vnops.c, and 604*5f4fc069Sjilinxpd * nfs_printfhandle() 605*5f4fc069Sjilinxpd * nfs_write_error() 606*5f4fc069Sjilinxpd * not needed here. 607*5f4fc069Sjilinxpd */ 608*5f4fc069Sjilinxpd 609*5f4fc069Sjilinxpd /* 610*5f4fc069Sjilinxpd * Helper function for smbfs_sync 611*5f4fc069Sjilinxpd * 612*5f4fc069Sjilinxpd * Walk the per-zone list of smbfs mounts, calling smbfs_rflush 613*5f4fc069Sjilinxpd * on each one. This is a little tricky because we need to exit 614*5f4fc069Sjilinxpd * the list mutex before each _rflush call and then try to resume 615*5f4fc069Sjilinxpd * where we were in the list after re-entering the mutex. 616*5f4fc069Sjilinxpd */ 617*5f4fc069Sjilinxpd void 618*5f4fc069Sjilinxpd smbfs_flushall(cred_t *cr) 619*5f4fc069Sjilinxpd { 620*5f4fc069Sjilinxpd smi_globals_t *smg; 621*5f4fc069Sjilinxpd smbmntinfo_t *tmp_smi, *cur_smi, *next_smi; 622*5f4fc069Sjilinxpd 623*5f4fc069Sjilinxpd smg = zone_getspecific(smi_list_key, crgetzone(cr)); 624*5f4fc069Sjilinxpd ASSERT(smg != NULL); 625*5f4fc069Sjilinxpd 626*5f4fc069Sjilinxpd mutex_enter(&smg->smg_lock); 627*5f4fc069Sjilinxpd cur_smi = list_head(&smg->smg_list); 628*5f4fc069Sjilinxpd if (cur_smi == NULL) { 629*5f4fc069Sjilinxpd mutex_exit(&smg->smg_lock); 630*5f4fc069Sjilinxpd return; 631*5f4fc069Sjilinxpd } 632*5f4fc069Sjilinxpd VFS_HOLD(cur_smi->smi_vfsp); 633*5f4fc069Sjilinxpd mutex_exit(&smg->smg_lock); 634*5f4fc069Sjilinxpd 635*5f4fc069Sjilinxpd flush: 636*5f4fc069Sjilinxpd smbfs_rflush(cur_smi->smi_vfsp, cr); 637*5f4fc069Sjilinxpd 638*5f4fc069Sjilinxpd mutex_enter(&smg->smg_lock); 639*5f4fc069Sjilinxpd /* 640*5f4fc069Sjilinxpd * Resume after cur_smi if that's still on the list, 641*5f4fc069Sjilinxpd * otherwise restart at the head. 642*5f4fc069Sjilinxpd */ 643*5f4fc069Sjilinxpd for (tmp_smi = list_head(&smg->smg_list); 644*5f4fc069Sjilinxpd tmp_smi != NULL; 645*5f4fc069Sjilinxpd tmp_smi = list_next(&smg->smg_list, tmp_smi)) 646*5f4fc069Sjilinxpd if (tmp_smi == cur_smi) 647*5f4fc069Sjilinxpd break; 648*5f4fc069Sjilinxpd if (tmp_smi != NULL) 649*5f4fc069Sjilinxpd next_smi = list_next(&smg->smg_list, tmp_smi); 650*5f4fc069Sjilinxpd else 651*5f4fc069Sjilinxpd next_smi = list_head(&smg->smg_list); 652*5f4fc069Sjilinxpd 653*5f4fc069Sjilinxpd if (next_smi != NULL) 654*5f4fc069Sjilinxpd VFS_HOLD(next_smi->smi_vfsp); 655*5f4fc069Sjilinxpd VFS_RELE(cur_smi->smi_vfsp); 656*5f4fc069Sjilinxpd 657*5f4fc069Sjilinxpd mutex_exit(&smg->smg_lock); 658*5f4fc069Sjilinxpd 659*5f4fc069Sjilinxpd if (next_smi != NULL) { 660*5f4fc069Sjilinxpd cur_smi = next_smi; 661*5f4fc069Sjilinxpd goto flush; 662*5f4fc069Sjilinxpd } 663*5f4fc069Sjilinxpd } 664*5f4fc069Sjilinxpd 665*5f4fc069Sjilinxpd /* 66602d09e03SGordon Ross * SMB Client initialization and cleanup. 66702d09e03SGordon Ross * Much of it is per-zone now. 66802d09e03SGordon Ross */ 66902d09e03SGordon Ross 67002d09e03SGordon Ross 6714bff34e3Sthurlow /* ARGSUSED */ 6724bff34e3Sthurlow static void * 6734bff34e3Sthurlow smbfs_zone_init(zoneid_t zoneid) 6744bff34e3Sthurlow { 6754bff34e3Sthurlow smi_globals_t *smg; 6764bff34e3Sthurlow 6774bff34e3Sthurlow smg = kmem_alloc(sizeof (*smg), KM_SLEEP); 6784bff34e3Sthurlow mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL); 6794bff34e3Sthurlow list_create(&smg->smg_list, sizeof (smbmntinfo_t), 6804bff34e3Sthurlow offsetof(smbmntinfo_t, smi_zone_node)); 6814bff34e3Sthurlow smg->smg_destructor_called = B_FALSE; 6824bff34e3Sthurlow return (smg); 6834bff34e3Sthurlow } 6844bff34e3Sthurlow 6854bff34e3Sthurlow /* 6864bff34e3Sthurlow * Callback routine to tell all SMBFS mounts in the zone to stop creating new 6874bff34e3Sthurlow * threads. Existing threads should exit. 6884bff34e3Sthurlow */ 6894bff34e3Sthurlow /* ARGSUSED */ 6904bff34e3Sthurlow static void 6914bff34e3Sthurlow smbfs_zone_shutdown(zoneid_t zoneid, void *data) 6924bff34e3Sthurlow { 6934bff34e3Sthurlow smi_globals_t *smg = data; 6944bff34e3Sthurlow smbmntinfo_t *smi; 6954bff34e3Sthurlow 6964bff34e3Sthurlow ASSERT(smg != NULL); 6974bff34e3Sthurlow again: 6984bff34e3Sthurlow mutex_enter(&smg->smg_lock); 6994bff34e3Sthurlow for (smi = list_head(&smg->smg_list); smi != NULL; 7004bff34e3Sthurlow smi = list_next(&smg->smg_list, smi)) { 7014bff34e3Sthurlow 7024bff34e3Sthurlow /* 7034bff34e3Sthurlow * If we've done the shutdown work for this FS, skip. 7044bff34e3Sthurlow * Once we go off the end of the list, we're done. 7054bff34e3Sthurlow */ 7064bff34e3Sthurlow if (smi->smi_flags & SMI_DEAD) 7074bff34e3Sthurlow continue; 7084bff34e3Sthurlow 7094bff34e3Sthurlow /* 7104bff34e3Sthurlow * We will do work, so not done. Get a hold on the FS. 7114bff34e3Sthurlow */ 7124bff34e3Sthurlow VFS_HOLD(smi->smi_vfsp); 7134bff34e3Sthurlow 7144bff34e3Sthurlow mutex_enter(&smi->smi_lock); 7154bff34e3Sthurlow smi->smi_flags |= SMI_DEAD; 7164bff34e3Sthurlow mutex_exit(&smi->smi_lock); 7174bff34e3Sthurlow 7184bff34e3Sthurlow /* 7194bff34e3Sthurlow * Drop lock and release FS, which may change list, then repeat. 7204bff34e3Sthurlow * We're done when every mi has been done or the list is empty. 7214bff34e3Sthurlow */ 7224bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7234bff34e3Sthurlow VFS_RELE(smi->smi_vfsp); 7244bff34e3Sthurlow goto again; 7254bff34e3Sthurlow } 7264bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7274bff34e3Sthurlow } 7284bff34e3Sthurlow 7294bff34e3Sthurlow static void 7304bff34e3Sthurlow smbfs_zone_free_globals(smi_globals_t *smg) 7314bff34e3Sthurlow { 7324bff34e3Sthurlow list_destroy(&smg->smg_list); /* makes sure the list is empty */ 7334bff34e3Sthurlow mutex_destroy(&smg->smg_lock); 7344bff34e3Sthurlow kmem_free(smg, sizeof (*smg)); 7354bff34e3Sthurlow 7364bff34e3Sthurlow } 7374bff34e3Sthurlow 7384bff34e3Sthurlow /* ARGSUSED */ 7394bff34e3Sthurlow static void 7404bff34e3Sthurlow smbfs_zone_destroy(zoneid_t zoneid, void *data) 7414bff34e3Sthurlow { 7424bff34e3Sthurlow smi_globals_t *smg = data; 7434bff34e3Sthurlow 7444bff34e3Sthurlow ASSERT(smg != NULL); 7454bff34e3Sthurlow mutex_enter(&smg->smg_lock); 7464bff34e3Sthurlow if (list_head(&smg->smg_list) != NULL) { 7474bff34e3Sthurlow /* Still waiting for VFS_FREEVFS() */ 7484bff34e3Sthurlow smg->smg_destructor_called = B_TRUE; 7494bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7504bff34e3Sthurlow return; 7514bff34e3Sthurlow } 7524bff34e3Sthurlow smbfs_zone_free_globals(smg); 7534bff34e3Sthurlow } 7544bff34e3Sthurlow 7554bff34e3Sthurlow /* 7564bff34e3Sthurlow * Add an SMBFS mount to the per-zone list of SMBFS mounts. 7574bff34e3Sthurlow */ 7584bff34e3Sthurlow void 7594bff34e3Sthurlow smbfs_zonelist_add(smbmntinfo_t *smi) 7604bff34e3Sthurlow { 7614bff34e3Sthurlow smi_globals_t *smg; 7624bff34e3Sthurlow 763a19609f8Sjv227347 smg = zone_getspecific(smi_list_key, smi->smi_zone_ref.zref_zone); 7644bff34e3Sthurlow mutex_enter(&smg->smg_lock); 7654bff34e3Sthurlow list_insert_head(&smg->smg_list, smi); 7664bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7674bff34e3Sthurlow } 7684bff34e3Sthurlow 7694bff34e3Sthurlow /* 7704bff34e3Sthurlow * Remove an SMBFS mount from the per-zone list of SMBFS mounts. 7714bff34e3Sthurlow */ 7724bff34e3Sthurlow void 7734bff34e3Sthurlow smbfs_zonelist_remove(smbmntinfo_t *smi) 7744bff34e3Sthurlow { 7754bff34e3Sthurlow smi_globals_t *smg; 7764bff34e3Sthurlow 777a19609f8Sjv227347 smg = zone_getspecific(smi_list_key, smi->smi_zone_ref.zref_zone); 7784bff34e3Sthurlow mutex_enter(&smg->smg_lock); 7794bff34e3Sthurlow list_remove(&smg->smg_list, smi); 7804bff34e3Sthurlow /* 7814bff34e3Sthurlow * We can be called asynchronously by VFS_FREEVFS() after the zone 7824bff34e3Sthurlow * shutdown/destroy callbacks have executed; if so, clean up the zone's 7834bff34e3Sthurlow * smi_globals. 7844bff34e3Sthurlow */ 7854bff34e3Sthurlow if (list_head(&smg->smg_list) == NULL && 7864bff34e3Sthurlow smg->smg_destructor_called == B_TRUE) { 7874bff34e3Sthurlow smbfs_zone_free_globals(smg); 7884bff34e3Sthurlow return; 7894bff34e3Sthurlow } 7904bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7914bff34e3Sthurlow } 7924bff34e3Sthurlow 793613a2f6bSGordon Ross #ifdef lint 794613a2f6bSGordon Ross #define NEED_SMBFS_CALLBACKS 1 795613a2f6bSGordon Ross #endif 7964bff34e3Sthurlow 7974bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 7984bff34e3Sthurlow /* 7994bff34e3Sthurlow * Call-back hooks for netsmb, in case we want them. 8004bff34e3Sthurlow * Apple's VFS wants them. We may not need them. 8014bff34e3Sthurlow */ 802613a2f6bSGordon Ross /*ARGSUSED*/ 8034bff34e3Sthurlow static void smbfs_dead(smb_share_t *ssp) 8044bff34e3Sthurlow { 805613a2f6bSGordon Ross /* 806613a2f6bSGordon Ross * Walk the mount list, finding all mounts 807613a2f6bSGordon Ross * using this share... 808613a2f6bSGordon Ross */ 8094bff34e3Sthurlow } 8104bff34e3Sthurlow 811613a2f6bSGordon Ross /*ARGSUSED*/ 812613a2f6bSGordon Ross static void smbfs_cb_nop(smb_share_t *ss) 8134bff34e3Sthurlow { 8144bff34e3Sthurlow /* no-op */ 8154bff34e3Sthurlow } 8164bff34e3Sthurlow 8174bff34e3Sthurlow smb_fscb_t smbfs_cb = { 818613a2f6bSGordon Ross .fscb_disconn = smbfs_dead, 819613a2f6bSGordon Ross .fscb_connect = smbfs_cb_nop, 820613a2f6bSGordon Ross .fscb_down = smbfs_cb_nop, 821613a2f6bSGordon Ross .fscb_up = smbfs_cb_nop }; 8224bff34e3Sthurlow 8234bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 8244bff34e3Sthurlow 8254bff34e3Sthurlow /* 8264bff34e3Sthurlow * SMBFS Client initialization routine. This routine should only be called 8274bff34e3Sthurlow * once. It performs the following tasks: 8284bff34e3Sthurlow * - Initalize all global locks 8294bff34e3Sthurlow * - Call sub-initialization routines (localize access to variables) 8304bff34e3Sthurlow */ 8314bff34e3Sthurlow int 8324bff34e3Sthurlow smbfs_clntinit(void) 8334bff34e3Sthurlow { 8344bff34e3Sthurlow 8354bff34e3Sthurlow zone_key_create(&smi_list_key, smbfs_zone_init, smbfs_zone_shutdown, 8364bff34e3Sthurlow smbfs_zone_destroy); 8374bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 838c1374a13SSurya Prakki (void) smb_fscb_set(&smbfs_cb); 8394bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 8404bff34e3Sthurlow return (0); 8414bff34e3Sthurlow } 8424bff34e3Sthurlow 8434bff34e3Sthurlow /* 8444bff34e3Sthurlow * This routine is called when the modunload is called. This will cleanup 8454bff34e3Sthurlow * the previously allocated/initialized nodes. 8464bff34e3Sthurlow */ 8474bff34e3Sthurlow void 8484bff34e3Sthurlow smbfs_clntfini(void) 8494bff34e3Sthurlow { 8504bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 851c1374a13SSurya Prakki (void) smb_fscb_set(NULL); 8524bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 8534bff34e3Sthurlow (void) zone_key_delete(smi_list_key); 8544bff34e3Sthurlow } 855