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. 27*8329232eSGordon Ross * 28*8329232eSGordon Ross * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 294bff34e3Sthurlow */ 304bff34e3Sthurlow 314bff34e3Sthurlow #include <sys/param.h> 324bff34e3Sthurlow #include <sys/systm.h> 334bff34e3Sthurlow #include <sys/thread.h> 344bff34e3Sthurlow #include <sys/t_lock.h> 354bff34e3Sthurlow #include <sys/time.h> 364bff34e3Sthurlow #include <sys/vnode.h> 374bff34e3Sthurlow #include <sys/vfs.h> 384bff34e3Sthurlow #include <sys/errno.h> 394bff34e3Sthurlow #include <sys/buf.h> 404bff34e3Sthurlow #include <sys/stat.h> 414bff34e3Sthurlow #include <sys/cred.h> 424bff34e3Sthurlow #include <sys/kmem.h> 434bff34e3Sthurlow #include <sys/debug.h> 444bff34e3Sthurlow #include <sys/vmsystm.h> 454bff34e3Sthurlow #include <sys/flock.h> 464bff34e3Sthurlow #include <sys/share.h> 474bff34e3Sthurlow #include <sys/cmn_err.h> 484bff34e3Sthurlow #include <sys/tiuser.h> 494bff34e3Sthurlow #include <sys/sysmacros.h> 504bff34e3Sthurlow #include <sys/callb.h> 514bff34e3Sthurlow #include <sys/acl.h> 524bff34e3Sthurlow #include <sys/kstat.h> 534bff34e3Sthurlow #include <sys/signal.h> 544bff34e3Sthurlow #include <sys/list.h> 554bff34e3Sthurlow #include <sys/zone.h> 564bff34e3Sthurlow 5702d09e03SGordon Ross #include <netsmb/smb.h> 584bff34e3Sthurlow #include <netsmb/smb_conn.h> 5902d09e03SGordon Ross #include <netsmb/smb_subr.h> 604bff34e3Sthurlow 614bff34e3Sthurlow #include <smbfs/smbfs.h> 624bff34e3Sthurlow #include <smbfs/smbfs_node.h> 634bff34e3Sthurlow #include <smbfs/smbfs_subr.h> 644bff34e3Sthurlow 65*8329232eSGordon Ross #ifdef _KERNEL 664bff34e3Sthurlow #include <vm/hat.h> 674bff34e3Sthurlow #include <vm/as.h> 684bff34e3Sthurlow #include <vm/page.h> 694bff34e3Sthurlow #include <vm/pvn.h> 704bff34e3Sthurlow #include <vm/seg.h> 714bff34e3Sthurlow #include <vm/seg_map.h> 724bff34e3Sthurlow #include <vm/seg_vn.h> 73*8329232eSGordon Ross #endif // _KERNEL 744bff34e3Sthurlow 755f4fc069Sjilinxpd #define ATTRCACHE_VALID(vp) (gethrtime() < VTOSMB(vp)->r_attrtime) 765f4fc069Sjilinxpd 7728162916SGordon Ross static int smbfs_getattr_cache(vnode_t *, smbfattr_t *); 7828162916SGordon Ross static void smbfattr_to_vattr(vnode_t *, smbfattr_t *, vattr_t *); 7928162916SGordon Ross static void smbfattr_to_xvattr(smbfattr_t *, vattr_t *); 805f4fc069Sjilinxpd static int smbfs_getattr_otw(vnode_t *, struct smbfattr *, cred_t *); 815f4fc069Sjilinxpd 8202d09e03SGordon Ross 834bff34e3Sthurlow /* 844bff34e3Sthurlow * The following code provide zone support in order to perform an action 854bff34e3Sthurlow * for each smbfs mount in a zone. This is also where we would add 864bff34e3Sthurlow * per-zone globals and kernel threads for the smbfs module (since 874bff34e3Sthurlow * they must be terminated by the shutdown callback). 884bff34e3Sthurlow */ 894bff34e3Sthurlow 904bff34e3Sthurlow struct smi_globals { 914bff34e3Sthurlow kmutex_t smg_lock; /* lock protecting smg_list */ 924bff34e3Sthurlow list_t smg_list; /* list of SMBFS mounts in zone */ 934bff34e3Sthurlow boolean_t smg_destructor_called; 944bff34e3Sthurlow }; 954bff34e3Sthurlow typedef struct smi_globals smi_globals_t; 964bff34e3Sthurlow 974bff34e3Sthurlow static zone_key_t smi_list_key; 984bff34e3Sthurlow 9902d09e03SGordon Ross /* 10002d09e03SGordon Ross * Attributes caching: 10102d09e03SGordon Ross * 10202d09e03SGordon Ross * Attributes are cached in the smbnode in struct vattr form. 10302d09e03SGordon Ross * There is a time associated with the cached attributes (r_attrtime) 10402d09e03SGordon Ross * which tells whether the attributes are valid. The time is initialized 10502d09e03SGordon Ross * to the difference between current time and the modify time of the vnode 10602d09e03SGordon Ross * when new attributes are cached. This allows the attributes for 10702d09e03SGordon Ross * files that have changed recently to be timed out sooner than for files 10802d09e03SGordon Ross * that have not changed for a long time. There are minimum and maximum 10902d09e03SGordon Ross * timeout values that can be set per mount point. 11002d09e03SGordon Ross */ 11102d09e03SGordon Ross 11202d09e03SGordon Ross /* 1135f4fc069Sjilinxpd * Helper for _validate_caches 1145f4fc069Sjilinxpd */ 1155f4fc069Sjilinxpd int 1165f4fc069Sjilinxpd smbfs_waitfor_purge_complete(vnode_t *vp) 1175f4fc069Sjilinxpd { 1185f4fc069Sjilinxpd smbnode_t *np; 1195f4fc069Sjilinxpd k_sigset_t smask; 1205f4fc069Sjilinxpd 1215f4fc069Sjilinxpd np = VTOSMB(vp); 1225f4fc069Sjilinxpd if (np->r_serial != NULL && np->r_serial != curthread) { 1235f4fc069Sjilinxpd mutex_enter(&np->r_statelock); 1245f4fc069Sjilinxpd sigintr(&smask, VTOSMI(vp)->smi_flags & SMI_INT); 1255f4fc069Sjilinxpd while (np->r_serial != NULL) { 1265f4fc069Sjilinxpd if (!cv_wait_sig(&np->r_cv, &np->r_statelock)) { 1275f4fc069Sjilinxpd sigunintr(&smask); 1285f4fc069Sjilinxpd mutex_exit(&np->r_statelock); 1295f4fc069Sjilinxpd return (EINTR); 1305f4fc069Sjilinxpd } 1315f4fc069Sjilinxpd } 1325f4fc069Sjilinxpd sigunintr(&smask); 1335f4fc069Sjilinxpd mutex_exit(&np->r_statelock); 1345f4fc069Sjilinxpd } 1355f4fc069Sjilinxpd return (0); 1365f4fc069Sjilinxpd } 1375f4fc069Sjilinxpd 1385f4fc069Sjilinxpd /* 1395f4fc069Sjilinxpd * Validate caches by checking cached attributes. If the cached 1405f4fc069Sjilinxpd * attributes have timed out, then get new attributes from the server. 1415f4fc069Sjilinxpd * As a side affect, this will do cache invalidation if the attributes 1425f4fc069Sjilinxpd * have changed. 1435f4fc069Sjilinxpd * 1445f4fc069Sjilinxpd * If the attributes have not timed out and if there is a cache 1455f4fc069Sjilinxpd * invalidation being done by some other thread, then wait until that 1465f4fc069Sjilinxpd * thread has completed the cache invalidation. 14702d09e03SGordon Ross */ 14802d09e03SGordon Ross int 14902d09e03SGordon Ross smbfs_validate_caches( 15002d09e03SGordon Ross struct vnode *vp, 15102d09e03SGordon Ross cred_t *cr) 15202d09e03SGordon Ross { 1535f4fc069Sjilinxpd struct smbfattr fa; 1545f4fc069Sjilinxpd int error; 15502d09e03SGordon Ross 1565f4fc069Sjilinxpd if (ATTRCACHE_VALID(vp)) { 1575f4fc069Sjilinxpd error = smbfs_waitfor_purge_complete(vp); 1585f4fc069Sjilinxpd if (error) 1595f4fc069Sjilinxpd return (error); 1605f4fc069Sjilinxpd return (0); 1615f4fc069Sjilinxpd } 1625f4fc069Sjilinxpd 1635f4fc069Sjilinxpd return (smbfs_getattr_otw(vp, &fa, cr)); 16402d09e03SGordon Ross } 16502d09e03SGordon Ross 16602d09e03SGordon Ross /* 16702d09e03SGordon Ross * Purge all of the various data caches. 1685f4fc069Sjilinxpd * 1695f4fc069Sjilinxpd * Here NFS also had a flags arg to control what gets flushed. 1705f4fc069Sjilinxpd * We only have the page cache, so no flags arg. 17102d09e03SGordon Ross */ 17202d09e03SGordon Ross /* ARGSUSED */ 17302d09e03SGordon Ross void 1745f4fc069Sjilinxpd smbfs_purge_caches(struct vnode *vp, cred_t *cr) 17502d09e03SGordon Ross { 1765f4fc069Sjilinxpd 17702d09e03SGordon Ross /* 1785f4fc069Sjilinxpd * Here NFS has: Purge the DNLC for this vp, 17902d09e03SGordon Ross * Clear any readdir state bits, 18002d09e03SGordon Ross * the readlink response cache, ... 18102d09e03SGordon Ross */ 18202d09e03SGordon Ross 18302d09e03SGordon Ross /* 18402d09e03SGordon Ross * Flush the page cache. 18502d09e03SGordon Ross */ 18602d09e03SGordon Ross if (vn_has_cached_data(vp)) { 18702d09e03SGordon Ross (void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_INVAL, cr, NULL); 18802d09e03SGordon Ross } 1895f4fc069Sjilinxpd 1905f4fc069Sjilinxpd /* 1915f4fc069Sjilinxpd * Here NFS has: Flush the readdir response cache. 1925f4fc069Sjilinxpd * No readdir cache in smbfs. 1935f4fc069Sjilinxpd */ 19402d09e03SGordon Ross } 19502d09e03SGordon Ross 19602d09e03SGordon Ross /* 1975f4fc069Sjilinxpd * Here NFS has: 1985f4fc069Sjilinxpd * nfs_purge_rddir_cache() 1995f4fc069Sjilinxpd * nfs3_cache_post_op_attr() 2005f4fc069Sjilinxpd * nfs3_cache_post_op_vattr() 2015f4fc069Sjilinxpd * nfs3_cache_wcc_data() 2025f4fc069Sjilinxpd */ 2035f4fc069Sjilinxpd 2045f4fc069Sjilinxpd /* 20502d09e03SGordon Ross * Check the attribute cache to see if the new attributes match 20602d09e03SGordon Ross * those cached. If they do, the various `data' caches are 20702d09e03SGordon Ross * considered to be good. Otherwise, purge the cached data. 20802d09e03SGordon Ross */ 2095f4fc069Sjilinxpd static void 21002d09e03SGordon Ross smbfs_cache_check( 21102d09e03SGordon Ross struct vnode *vp, 2125f4fc069Sjilinxpd struct smbfattr *fap, 2135f4fc069Sjilinxpd cred_t *cr) 21402d09e03SGordon Ross { 21502d09e03SGordon Ross smbnode_t *np; 21602d09e03SGordon Ross int purge_data = 0; 21702d09e03SGordon Ross int purge_acl = 0; 21802d09e03SGordon Ross 21902d09e03SGordon Ross np = VTOSMB(vp); 22002d09e03SGordon Ross mutex_enter(&np->r_statelock); 22102d09e03SGordon Ross 22202d09e03SGordon Ross /* 22302d09e03SGordon Ross * Compare with NFS macro: CACHE_VALID 22402d09e03SGordon Ross * If the mtime or size has changed, 22502d09e03SGordon Ross * purge cached data. 22602d09e03SGordon Ross */ 22702d09e03SGordon Ross if (np->r_attr.fa_mtime.tv_sec != fap->fa_mtime.tv_sec || 22802d09e03SGordon Ross np->r_attr.fa_mtime.tv_nsec != fap->fa_mtime.tv_nsec) 22902d09e03SGordon Ross purge_data = 1; 23002d09e03SGordon Ross if (np->r_attr.fa_size != fap->fa_size) 23102d09e03SGordon Ross purge_data = 1; 23202d09e03SGordon Ross 23302d09e03SGordon Ross if (np->r_attr.fa_ctime.tv_sec != fap->fa_ctime.tv_sec || 23402d09e03SGordon Ross np->r_attr.fa_ctime.tv_nsec != fap->fa_ctime.tv_nsec) 23502d09e03SGordon Ross purge_acl = 1; 236bd7c6f51SGordon Ross 237bd7c6f51SGordon Ross if (purge_acl) { 238bd7c6f51SGordon Ross np->r_sectime = gethrtime(); 239bd7c6f51SGordon Ross } 24002d09e03SGordon Ross 24102d09e03SGordon Ross mutex_exit(&np->r_statelock); 24202d09e03SGordon Ross 24302d09e03SGordon Ross if (purge_data) 2445f4fc069Sjilinxpd smbfs_purge_caches(vp, cr); 24502d09e03SGordon Ross } 24602d09e03SGordon Ross 24702d09e03SGordon Ross /* 24802d09e03SGordon Ross * Set attributes cache for given vnode using SMB fattr 24902d09e03SGordon Ross * and update the attribute cache timeout. 25002d09e03SGordon Ross * 2515f4fc069Sjilinxpd * Based on NFS: nfs_attrcache, nfs_attrcache_va 25202d09e03SGordon Ross */ 25302d09e03SGordon Ross void 25402d09e03SGordon Ross smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap) 25502d09e03SGordon Ross { 25602d09e03SGordon Ross smbnode_t *np; 25702d09e03SGordon Ross smbmntinfo_t *smi; 25802d09e03SGordon Ross hrtime_t delta, now; 25902d09e03SGordon Ross u_offset_t newsize; 26002d09e03SGordon Ross vtype_t vtype, oldvt; 26102d09e03SGordon Ross mode_t mode; 26202d09e03SGordon Ross 26302d09e03SGordon Ross np = VTOSMB(vp); 26402d09e03SGordon Ross smi = VTOSMI(vp); 26502d09e03SGordon Ross 26602d09e03SGordon Ross /* 26702d09e03SGordon Ross * We allow v_type to change, so set that here 26842d15982SGordon Ross * (and the mode, which depends on the type). 26902d09e03SGordon Ross */ 27002d09e03SGordon Ross if (fap->fa_attr & SMB_FA_DIR) { 27102d09e03SGordon Ross vtype = VDIR; 27242d15982SGordon Ross mode = smi->smi_dmode; 27302d09e03SGordon Ross } else { 27402d09e03SGordon Ross vtype = VREG; 27542d15982SGordon Ross mode = smi->smi_fmode; 27602d09e03SGordon Ross } 27702d09e03SGordon Ross 27802d09e03SGordon Ross mutex_enter(&np->r_statelock); 27902d09e03SGordon Ross now = gethrtime(); 28002d09e03SGordon Ross 28102d09e03SGordon Ross /* 28202d09e03SGordon Ross * Delta is the number of nanoseconds that we will 28302d09e03SGordon Ross * cache the attributes of the file. It is based on 28402d09e03SGordon Ross * the number of nanoseconds since the last time that 28502d09e03SGordon Ross * we detected a change. The assumption is that files 28602d09e03SGordon Ross * that changed recently are likely to change again. 28702d09e03SGordon Ross * There is a minimum and a maximum for regular files 28802d09e03SGordon Ross * and for directories which is enforced though. 28902d09e03SGordon Ross * 29002d09e03SGordon Ross * Using the time since last change was detected 29102d09e03SGordon Ross * eliminates direct comparison or calculation 29202d09e03SGordon Ross * using mixed client and server times. SMBFS 29302d09e03SGordon Ross * does not make any assumptions regarding the 29402d09e03SGordon Ross * client and server clocks being synchronized. 29502d09e03SGordon Ross */ 29602d09e03SGordon Ross if (fap->fa_mtime.tv_sec != np->r_attr.fa_mtime.tv_sec || 29702d09e03SGordon Ross fap->fa_mtime.tv_nsec != np->r_attr.fa_mtime.tv_nsec || 29802d09e03SGordon Ross fap->fa_size != np->r_attr.fa_size) 29902d09e03SGordon Ross np->r_mtime = now; 30002d09e03SGordon Ross 30102d09e03SGordon Ross if ((smi->smi_flags & SMI_NOAC) || (vp->v_flag & VNOCACHE)) 30202d09e03SGordon Ross delta = 0; 30302d09e03SGordon Ross else { 30402d09e03SGordon Ross delta = now - np->r_mtime; 30502d09e03SGordon Ross if (vtype == VDIR) { 30602d09e03SGordon Ross if (delta < smi->smi_acdirmin) 30702d09e03SGordon Ross delta = smi->smi_acdirmin; 30802d09e03SGordon Ross else if (delta > smi->smi_acdirmax) 30902d09e03SGordon Ross delta = smi->smi_acdirmax; 31002d09e03SGordon Ross } else { 31102d09e03SGordon Ross if (delta < smi->smi_acregmin) 31202d09e03SGordon Ross delta = smi->smi_acregmin; 31302d09e03SGordon Ross else if (delta > smi->smi_acregmax) 31402d09e03SGordon Ross delta = smi->smi_acregmax; 31502d09e03SGordon Ross } 31602d09e03SGordon Ross } 31702d09e03SGordon Ross 31802d09e03SGordon Ross np->r_attrtime = now + delta; 31902d09e03SGordon Ross np->r_attr = *fap; 32002d09e03SGordon Ross np->n_mode = mode; 32102d09e03SGordon Ross oldvt = vp->v_type; 32202d09e03SGordon Ross vp->v_type = vtype; 32302d09e03SGordon Ross 32402d09e03SGordon Ross /* 32502d09e03SGordon Ross * Shall we update r_size? (local notion of size) 32602d09e03SGordon Ross * 32702d09e03SGordon Ross * The real criteria for updating r_size should be: 32802d09e03SGordon Ross * if the file has grown on the server, or if 32902d09e03SGordon Ross * the client has not modified the file. 33002d09e03SGordon Ross * 33102d09e03SGordon Ross * Also deal with the fact that SMB presents 33202d09e03SGordon Ross * directories as having size=0. Doing that 33302d09e03SGordon Ross * here and leaving fa_size as returned OtW 33402d09e03SGordon Ross * avoids fixing the size lots of places. 33502d09e03SGordon Ross */ 33602d09e03SGordon Ross newsize = fap->fa_size; 33702d09e03SGordon Ross if (vtype == VDIR && newsize < DEV_BSIZE) 33802d09e03SGordon Ross newsize = DEV_BSIZE; 33902d09e03SGordon Ross 3405f4fc069Sjilinxpd if (np->r_size != newsize && 3415f4fc069Sjilinxpd (!vn_has_cached_data(vp) || 3425f4fc069Sjilinxpd (!(np->r_flags & RDIRTY) && np->r_count == 0))) { 34302d09e03SGordon Ross /* OK to set the size. */ 34402d09e03SGordon Ross np->r_size = newsize; 34502d09e03SGordon Ross } 34602d09e03SGordon Ross 3475f4fc069Sjilinxpd /* 3485f4fc069Sjilinxpd * Here NFS has: 3495f4fc069Sjilinxpd * nfs_setswaplike(vp, va); 3505f4fc069Sjilinxpd * np->r_flags &= ~RWRITEATTR; 3515f4fc069Sjilinxpd * (not needed here) 3525f4fc069Sjilinxpd */ 35302d09e03SGordon Ross 3545f4fc069Sjilinxpd np->n_flag &= ~NATTRCHANGED; 35502d09e03SGordon Ross mutex_exit(&np->r_statelock); 35602d09e03SGordon Ross 35702d09e03SGordon Ross if (oldvt != vtype) { 35802d09e03SGordon Ross SMBVDEBUG("vtype change %d to %d\n", oldvt, vtype); 35902d09e03SGordon Ross } 36002d09e03SGordon Ross } 36102d09e03SGordon Ross 36202d09e03SGordon Ross /* 36302d09e03SGordon Ross * Fill in attribute from the cache. 36402d09e03SGordon Ross * 36502d09e03SGordon Ross * If valid, copy to *fap and return zero, 36602d09e03SGordon Ross * otherwise return an error. 36702d09e03SGordon Ross * 36802d09e03SGordon Ross * From NFS: nfs_getattr_cache() 36902d09e03SGordon Ross */ 37002d09e03SGordon Ross int 37102d09e03SGordon Ross smbfs_getattr_cache(vnode_t *vp, struct smbfattr *fap) 37202d09e03SGordon Ross { 37302d09e03SGordon Ross smbnode_t *np; 37402d09e03SGordon Ross int error; 37502d09e03SGordon Ross 37602d09e03SGordon Ross np = VTOSMB(vp); 37702d09e03SGordon Ross 37802d09e03SGordon Ross mutex_enter(&np->r_statelock); 37902d09e03SGordon Ross if (gethrtime() >= np->r_attrtime) { 38002d09e03SGordon Ross /* cache expired */ 38102d09e03SGordon Ross error = ENOENT; 38202d09e03SGordon Ross } else { 38302d09e03SGordon Ross /* cache is valid */ 38402d09e03SGordon Ross *fap = np->r_attr; 38502d09e03SGordon Ross error = 0; 38602d09e03SGordon Ross } 38702d09e03SGordon Ross mutex_exit(&np->r_statelock); 38802d09e03SGordon Ross 38902d09e03SGordon Ross return (error); 39002d09e03SGordon Ross } 39102d09e03SGordon Ross 39202d09e03SGordon Ross /* 39302d09e03SGordon Ross * Get attributes over-the-wire and update attributes cache 39402d09e03SGordon Ross * if no error occurred in the over-the-wire operation. 39502d09e03SGordon Ross * Return 0 if successful, otherwise error. 39602d09e03SGordon Ross * From NFS: nfs_getattr_otw 39702d09e03SGordon Ross */ 3985f4fc069Sjilinxpd static int 39902d09e03SGordon Ross smbfs_getattr_otw(vnode_t *vp, struct smbfattr *fap, cred_t *cr) 40002d09e03SGordon Ross { 40102d09e03SGordon Ross struct smbnode *np; 40202d09e03SGordon Ross struct smb_cred scred; 40302d09e03SGordon Ross int error; 40402d09e03SGordon Ross 40502d09e03SGordon Ross np = VTOSMB(vp); 40602d09e03SGordon Ross 40702d09e03SGordon Ross /* 4085f4fc069Sjilinxpd * Here NFS uses the ACL RPC (if smi_flags & SMI_ACL) 409bd7c6f51SGordon Ross * With SMB, getting the ACL is a significantly more 410bd7c6f51SGordon Ross * expensive operation, so we do that only when asked 411bd7c6f51SGordon Ross * for the uid/gid. See smbfsgetattr(). 41202d09e03SGordon Ross */ 41302d09e03SGordon Ross 41402d09e03SGordon Ross /* Shared lock for (possible) n_fid use. */ 41502d09e03SGordon Ross if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 41602d09e03SGordon Ross return (EINTR); 41702d09e03SGordon Ross smb_credinit(&scred, cr); 41802d09e03SGordon Ross 41902d09e03SGordon Ross bzero(fap, sizeof (*fap)); 42002d09e03SGordon Ross error = smbfs_smb_getfattr(np, fap, &scred); 42102d09e03SGordon Ross 42202d09e03SGordon Ross smb_credrele(&scred); 42302d09e03SGordon Ross smbfs_rw_exit(&np->r_lkserlock); 42402d09e03SGordon Ross 42502d09e03SGordon Ross if (error) { 4265f4fc069Sjilinxpd /* Here NFS has: PURGE_STALE_FH(error, vp, cr) */ 42702d09e03SGordon Ross smbfs_attrcache_remove(np); 42802d09e03SGordon Ross if (error == ENOENT || error == ENOTDIR) { 42902d09e03SGordon Ross /* 43002d09e03SGordon Ross * Getattr failed because the object was 43102d09e03SGordon Ross * removed or renamed by another client. 43202d09e03SGordon Ross * Remove any cached attributes under it. 43302d09e03SGordon Ross */ 43402d09e03SGordon Ross smbfs_attrcache_prune(np); 43502d09e03SGordon Ross } 43602d09e03SGordon Ross return (error); 43702d09e03SGordon Ross } 43802d09e03SGordon Ross 43902d09e03SGordon Ross /* 4405f4fc069Sjilinxpd * Here NFS has: nfs_cache_fattr(vap, fa, vap, t, cr); 44102d09e03SGordon Ross * which did: fattr_to_vattr, nfs_attr_cache. 44202d09e03SGordon Ross * We cache the fattr form, so just do the 44302d09e03SGordon Ross * cache check and store the attributes. 44402d09e03SGordon Ross */ 4455f4fc069Sjilinxpd smbfs_cache_check(vp, fap, cr); 44602d09e03SGordon Ross smbfs_attrcache_fa(vp, fap); 44702d09e03SGordon Ross 44802d09e03SGordon Ross return (0); 44902d09e03SGordon Ross } 45002d09e03SGordon Ross 45102d09e03SGordon Ross /* 4525f4fc069Sjilinxpd * Return either cached or remote attributes. If we get remote attrs, 45302d09e03SGordon Ross * use them to check and invalidate caches, then cache the new attributes. 45402d09e03SGordon Ross * 45502d09e03SGordon Ross * From NFS: nfsgetattr() 45602d09e03SGordon Ross */ 45702d09e03SGordon Ross int 45802d09e03SGordon Ross smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr) 45902d09e03SGordon Ross { 46002d09e03SGordon Ross struct smbfattr fa; 461bd7c6f51SGordon Ross smbmntinfo_t *smi; 462bd7c6f51SGordon Ross uint_t mask; 46302d09e03SGordon Ross int error; 46402d09e03SGordon Ross 465bd7c6f51SGordon Ross smi = VTOSMI(vp); 466bd7c6f51SGordon Ross 467a19609f8Sjv227347 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone); 468bd7c6f51SGordon Ross 469bd7c6f51SGordon Ross /* 470bd7c6f51SGordon Ross * If asked for UID or GID, update n_uid, n_gid. 471bd7c6f51SGordon Ross */ 472bd7c6f51SGordon Ross mask = AT_ALL; 473bd7c6f51SGordon Ross if (vap->va_mask & (AT_UID | AT_GID)) { 474bd7c6f51SGordon Ross if (smi->smi_flags & SMI_ACL) 475bd7c6f51SGordon Ross (void) smbfs_acl_getids(vp, cr); 476bd7c6f51SGordon Ross /* else leave as set in make_smbnode */ 477bd7c6f51SGordon Ross } else { 478bd7c6f51SGordon Ross mask &= ~(AT_UID | AT_GID); 479bd7c6f51SGordon Ross } 48002d09e03SGordon Ross 48102d09e03SGordon Ross /* 48202d09e03SGordon Ross * If we've got cached attributes, just use them; 48302d09e03SGordon Ross * otherwise go to the server to get attributes, 48402d09e03SGordon Ross * which will update the cache in the process. 48502d09e03SGordon Ross */ 48602d09e03SGordon Ross error = smbfs_getattr_cache(vp, &fa); 48702d09e03SGordon Ross if (error) 48802d09e03SGordon Ross error = smbfs_getattr_otw(vp, &fa, cr); 48902d09e03SGordon Ross if (error) 49002d09e03SGordon Ross return (error); 49128162916SGordon Ross vap->va_mask |= mask; 49202d09e03SGordon Ross 49302d09e03SGordon Ross /* 49402d09e03SGordon Ross * Re. client's view of the file size, see: 49502d09e03SGordon Ross * smbfs_attrcache_fa, smbfs_getattr_otw 49602d09e03SGordon Ross */ 49728162916SGordon Ross smbfattr_to_vattr(vp, &fa, vap); 49828162916SGordon Ross if (vap->va_mask & AT_XVATTR) 49928162916SGordon Ross smbfattr_to_xvattr(&fa, vap); 50002d09e03SGordon Ross 50128162916SGordon Ross return (0); 50202d09e03SGordon Ross } 50302d09e03SGordon Ross 50402d09e03SGordon Ross 50502d09e03SGordon Ross /* 50602d09e03SGordon Ross * Convert SMB over the wire attributes to vnode form. 50702d09e03SGordon Ross * Returns 0 for success, error if failed (overflow, etc). 50802d09e03SGordon Ross * From NFS: nattr_to_vattr() 50902d09e03SGordon Ross */ 51028162916SGordon Ross void 51102d09e03SGordon Ross smbfattr_to_vattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap) 51202d09e03SGordon Ross { 51302d09e03SGordon Ross struct smbnode *np = VTOSMB(vp); 51402d09e03SGordon Ross 51502d09e03SGordon Ross /* 51602d09e03SGordon Ross * Take type, mode, uid, gid from the smbfs node, 51702d09e03SGordon Ross * which has have been updated by _getattr_otw. 51802d09e03SGordon Ross */ 51902d09e03SGordon Ross vap->va_type = vp->v_type; 52002d09e03SGordon Ross vap->va_mode = np->n_mode; 52102d09e03SGordon Ross 52202d09e03SGordon Ross vap->va_uid = np->n_uid; 52302d09e03SGordon Ross vap->va_gid = np->n_gid; 52402d09e03SGordon Ross 52502d09e03SGordon Ross vap->va_fsid = vp->v_vfsp->vfs_dev; 52602d09e03SGordon Ross vap->va_nodeid = np->n_ino; 52702d09e03SGordon Ross vap->va_nlink = 1; 52802d09e03SGordon Ross 52902d09e03SGordon Ross /* 53002d09e03SGordon Ross * Difference from NFS here: We cache attributes as 53102d09e03SGordon Ross * reported by the server, so r_attr.fa_size is the 53202d09e03SGordon Ross * server's idea of the file size. This is called 53302d09e03SGordon Ross * for getattr, so we want to return the client's 53402d09e03SGordon Ross * idea of the file size. NFS deals with that in 53502d09e03SGordon Ross * nfsgetattr(), the equivalent of our caller. 53602d09e03SGordon Ross */ 53702d09e03SGordon Ross vap->va_size = np->r_size; 53802d09e03SGordon Ross 53902d09e03SGordon Ross /* 54002d09e03SGordon Ross * Times. Note, already converted from NT to 54102d09e03SGordon Ross * Unix form (in the unmarshalling code). 54202d09e03SGordon Ross */ 54302d09e03SGordon Ross vap->va_atime = fa->fa_atime; 54402d09e03SGordon Ross vap->va_mtime = fa->fa_mtime; 54502d09e03SGordon Ross vap->va_ctime = fa->fa_ctime; 54602d09e03SGordon Ross 54702d09e03SGordon Ross /* 54802d09e03SGordon Ross * rdev, blksize, seq are made up. 54902d09e03SGordon Ross * va_nblocks is 512 byte blocks. 55002d09e03SGordon Ross */ 55102d09e03SGordon Ross vap->va_rdev = vp->v_rdev; 55202d09e03SGordon Ross vap->va_blksize = MAXBSIZE; 55302d09e03SGordon Ross vap->va_nblocks = (fsblkcnt64_t)btod(np->r_attr.fa_allocsz); 55402d09e03SGordon Ross vap->va_seq = 0; 55502d09e03SGordon Ross } 55602d09e03SGordon Ross 55728162916SGordon Ross /* 55828162916SGordon Ross * smbfattr_to_xvattr: like smbfattr_to_vattr but for 55928162916SGordon Ross * Extensible system attributes (PSARC 2007/315) 56028162916SGordon Ross */ 56128162916SGordon Ross static void 56228162916SGordon Ross smbfattr_to_xvattr(struct smbfattr *fa, struct vattr *vap) 56328162916SGordon Ross { 56428162916SGordon Ross xvattr_t *xvap = (xvattr_t *)vap; /* *vap may be xvattr_t */ 56528162916SGordon Ross xoptattr_t *xoap = NULL; 56628162916SGordon Ross 56728162916SGordon Ross if ((xoap = xva_getxoptattr(xvap)) == NULL) 56828162916SGordon Ross return; 56928162916SGordon Ross 57028162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { 57128162916SGordon Ross xoap->xoa_createtime = fa->fa_createtime; 57228162916SGordon Ross XVA_SET_RTN(xvap, XAT_CREATETIME); 57328162916SGordon Ross } 57428162916SGordon Ross 57528162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { 57628162916SGordon Ross xoap->xoa_archive = 57728162916SGordon Ross ((fa->fa_attr & SMB_FA_ARCHIVE) != 0); 57828162916SGordon Ross XVA_SET_RTN(xvap, XAT_ARCHIVE); 57928162916SGordon Ross } 58028162916SGordon Ross 58128162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { 58228162916SGordon Ross xoap->xoa_system = 58328162916SGordon Ross ((fa->fa_attr & SMB_FA_SYSTEM) != 0); 58428162916SGordon Ross XVA_SET_RTN(xvap, XAT_SYSTEM); 58528162916SGordon Ross } 58628162916SGordon Ross 58728162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { 58828162916SGordon Ross xoap->xoa_readonly = 58928162916SGordon Ross ((fa->fa_attr & SMB_FA_RDONLY) != 0); 59028162916SGordon Ross XVA_SET_RTN(xvap, XAT_READONLY); 59128162916SGordon Ross } 59228162916SGordon Ross 59328162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { 59428162916SGordon Ross xoap->xoa_hidden = 59528162916SGordon Ross ((fa->fa_attr & SMB_FA_HIDDEN) != 0); 59628162916SGordon Ross XVA_SET_RTN(xvap, XAT_HIDDEN); 59728162916SGordon Ross } 59828162916SGordon Ross } 59902d09e03SGordon Ross 60002d09e03SGordon Ross /* 6015f4fc069Sjilinxpd * Here NFS has: 6025f4fc069Sjilinxpd * nfs_async_... stuff 6035f4fc069Sjilinxpd * which we're not using (no async I/O), and: 6045f4fc069Sjilinxpd * writerp(), 6055f4fc069Sjilinxpd * nfs_putpages() 6065f4fc069Sjilinxpd * nfs_invalidate_pages() 6075f4fc069Sjilinxpd * which we have in smbfs_vnops.c, and 6085f4fc069Sjilinxpd * nfs_printfhandle() 6095f4fc069Sjilinxpd * nfs_write_error() 6105f4fc069Sjilinxpd * not needed here. 6115f4fc069Sjilinxpd */ 6125f4fc069Sjilinxpd 6135f4fc069Sjilinxpd /* 6145f4fc069Sjilinxpd * Helper function for smbfs_sync 6155f4fc069Sjilinxpd * 6165f4fc069Sjilinxpd * Walk the per-zone list of smbfs mounts, calling smbfs_rflush 6175f4fc069Sjilinxpd * on each one. This is a little tricky because we need to exit 6185f4fc069Sjilinxpd * the list mutex before each _rflush call and then try to resume 6195f4fc069Sjilinxpd * where we were in the list after re-entering the mutex. 6205f4fc069Sjilinxpd */ 6215f4fc069Sjilinxpd void 6225f4fc069Sjilinxpd smbfs_flushall(cred_t *cr) 6235f4fc069Sjilinxpd { 6245f4fc069Sjilinxpd smi_globals_t *smg; 6255f4fc069Sjilinxpd smbmntinfo_t *tmp_smi, *cur_smi, *next_smi; 6265f4fc069Sjilinxpd 6275f4fc069Sjilinxpd smg = zone_getspecific(smi_list_key, crgetzone(cr)); 6285f4fc069Sjilinxpd ASSERT(smg != NULL); 6295f4fc069Sjilinxpd 6305f4fc069Sjilinxpd mutex_enter(&smg->smg_lock); 6315f4fc069Sjilinxpd cur_smi = list_head(&smg->smg_list); 6325f4fc069Sjilinxpd if (cur_smi == NULL) { 6335f4fc069Sjilinxpd mutex_exit(&smg->smg_lock); 6345f4fc069Sjilinxpd return; 6355f4fc069Sjilinxpd } 6365f4fc069Sjilinxpd VFS_HOLD(cur_smi->smi_vfsp); 6375f4fc069Sjilinxpd mutex_exit(&smg->smg_lock); 6385f4fc069Sjilinxpd 6395f4fc069Sjilinxpd flush: 6405f4fc069Sjilinxpd smbfs_rflush(cur_smi->smi_vfsp, cr); 6415f4fc069Sjilinxpd 6425f4fc069Sjilinxpd mutex_enter(&smg->smg_lock); 6435f4fc069Sjilinxpd /* 6445f4fc069Sjilinxpd * Resume after cur_smi if that's still on the list, 6455f4fc069Sjilinxpd * otherwise restart at the head. 6465f4fc069Sjilinxpd */ 6475f4fc069Sjilinxpd for (tmp_smi = list_head(&smg->smg_list); 6485f4fc069Sjilinxpd tmp_smi != NULL; 6495f4fc069Sjilinxpd tmp_smi = list_next(&smg->smg_list, tmp_smi)) 6505f4fc069Sjilinxpd if (tmp_smi == cur_smi) 6515f4fc069Sjilinxpd break; 6525f4fc069Sjilinxpd if (tmp_smi != NULL) 6535f4fc069Sjilinxpd next_smi = list_next(&smg->smg_list, tmp_smi); 6545f4fc069Sjilinxpd else 6555f4fc069Sjilinxpd next_smi = list_head(&smg->smg_list); 6565f4fc069Sjilinxpd 6575f4fc069Sjilinxpd if (next_smi != NULL) 6585f4fc069Sjilinxpd VFS_HOLD(next_smi->smi_vfsp); 6595f4fc069Sjilinxpd VFS_RELE(cur_smi->smi_vfsp); 6605f4fc069Sjilinxpd 6615f4fc069Sjilinxpd mutex_exit(&smg->smg_lock); 6625f4fc069Sjilinxpd 6635f4fc069Sjilinxpd if (next_smi != NULL) { 6645f4fc069Sjilinxpd cur_smi = next_smi; 6655f4fc069Sjilinxpd goto flush; 6665f4fc069Sjilinxpd } 6675f4fc069Sjilinxpd } 6685f4fc069Sjilinxpd 6695f4fc069Sjilinxpd /* 67002d09e03SGordon Ross * SMB Client initialization and cleanup. 67102d09e03SGordon Ross * Much of it is per-zone now. 67202d09e03SGordon Ross */ 67302d09e03SGordon Ross 67402d09e03SGordon Ross 6754bff34e3Sthurlow /* ARGSUSED */ 6764bff34e3Sthurlow static void * 6774bff34e3Sthurlow smbfs_zone_init(zoneid_t zoneid) 6784bff34e3Sthurlow { 6794bff34e3Sthurlow smi_globals_t *smg; 6804bff34e3Sthurlow 6814bff34e3Sthurlow smg = kmem_alloc(sizeof (*smg), KM_SLEEP); 6824bff34e3Sthurlow mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL); 6834bff34e3Sthurlow list_create(&smg->smg_list, sizeof (smbmntinfo_t), 6844bff34e3Sthurlow offsetof(smbmntinfo_t, smi_zone_node)); 6854bff34e3Sthurlow smg->smg_destructor_called = B_FALSE; 6864bff34e3Sthurlow return (smg); 6874bff34e3Sthurlow } 6884bff34e3Sthurlow 6894bff34e3Sthurlow /* 6904bff34e3Sthurlow * Callback routine to tell all SMBFS mounts in the zone to stop creating new 6914bff34e3Sthurlow * threads. Existing threads should exit. 6924bff34e3Sthurlow */ 6934bff34e3Sthurlow /* ARGSUSED */ 6944bff34e3Sthurlow static void 6954bff34e3Sthurlow smbfs_zone_shutdown(zoneid_t zoneid, void *data) 6964bff34e3Sthurlow { 6974bff34e3Sthurlow smi_globals_t *smg = data; 6984bff34e3Sthurlow smbmntinfo_t *smi; 6994bff34e3Sthurlow 7004bff34e3Sthurlow ASSERT(smg != NULL); 7014bff34e3Sthurlow again: 7024bff34e3Sthurlow mutex_enter(&smg->smg_lock); 7034bff34e3Sthurlow for (smi = list_head(&smg->smg_list); smi != NULL; 7044bff34e3Sthurlow smi = list_next(&smg->smg_list, smi)) { 7054bff34e3Sthurlow 7064bff34e3Sthurlow /* 7074bff34e3Sthurlow * If we've done the shutdown work for this FS, skip. 7084bff34e3Sthurlow * Once we go off the end of the list, we're done. 7094bff34e3Sthurlow */ 7104bff34e3Sthurlow if (smi->smi_flags & SMI_DEAD) 7114bff34e3Sthurlow continue; 7124bff34e3Sthurlow 7134bff34e3Sthurlow /* 7144bff34e3Sthurlow * We will do work, so not done. Get a hold on the FS. 7154bff34e3Sthurlow */ 7164bff34e3Sthurlow VFS_HOLD(smi->smi_vfsp); 7174bff34e3Sthurlow 7184bff34e3Sthurlow mutex_enter(&smi->smi_lock); 7194bff34e3Sthurlow smi->smi_flags |= SMI_DEAD; 7204bff34e3Sthurlow mutex_exit(&smi->smi_lock); 7214bff34e3Sthurlow 7224bff34e3Sthurlow /* 7234bff34e3Sthurlow * Drop lock and release FS, which may change list, then repeat. 7244bff34e3Sthurlow * We're done when every mi has been done or the list is empty. 7254bff34e3Sthurlow */ 7264bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7274bff34e3Sthurlow VFS_RELE(smi->smi_vfsp); 7284bff34e3Sthurlow goto again; 7294bff34e3Sthurlow } 7304bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7314bff34e3Sthurlow } 7324bff34e3Sthurlow 7334bff34e3Sthurlow static void 7344bff34e3Sthurlow smbfs_zone_free_globals(smi_globals_t *smg) 7354bff34e3Sthurlow { 7364bff34e3Sthurlow list_destroy(&smg->smg_list); /* makes sure the list is empty */ 7374bff34e3Sthurlow mutex_destroy(&smg->smg_lock); 7384bff34e3Sthurlow kmem_free(smg, sizeof (*smg)); 7394bff34e3Sthurlow 7404bff34e3Sthurlow } 7414bff34e3Sthurlow 7424bff34e3Sthurlow /* ARGSUSED */ 7434bff34e3Sthurlow static void 7444bff34e3Sthurlow smbfs_zone_destroy(zoneid_t zoneid, void *data) 7454bff34e3Sthurlow { 7464bff34e3Sthurlow smi_globals_t *smg = data; 7474bff34e3Sthurlow 7484bff34e3Sthurlow ASSERT(smg != NULL); 7494bff34e3Sthurlow mutex_enter(&smg->smg_lock); 7504bff34e3Sthurlow if (list_head(&smg->smg_list) != NULL) { 7514bff34e3Sthurlow /* Still waiting for VFS_FREEVFS() */ 7524bff34e3Sthurlow smg->smg_destructor_called = B_TRUE; 7534bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7544bff34e3Sthurlow return; 7554bff34e3Sthurlow } 7564bff34e3Sthurlow smbfs_zone_free_globals(smg); 7574bff34e3Sthurlow } 7584bff34e3Sthurlow 7594bff34e3Sthurlow /* 7604bff34e3Sthurlow * Add an SMBFS mount to the per-zone list of SMBFS mounts. 7614bff34e3Sthurlow */ 7624bff34e3Sthurlow void 7634bff34e3Sthurlow smbfs_zonelist_add(smbmntinfo_t *smi) 7644bff34e3Sthurlow { 7654bff34e3Sthurlow smi_globals_t *smg; 7664bff34e3Sthurlow 767a19609f8Sjv227347 smg = zone_getspecific(smi_list_key, smi->smi_zone_ref.zref_zone); 7684bff34e3Sthurlow mutex_enter(&smg->smg_lock); 7694bff34e3Sthurlow list_insert_head(&smg->smg_list, smi); 7704bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7714bff34e3Sthurlow } 7724bff34e3Sthurlow 7734bff34e3Sthurlow /* 7744bff34e3Sthurlow * Remove an SMBFS mount from the per-zone list of SMBFS mounts. 7754bff34e3Sthurlow */ 7764bff34e3Sthurlow void 7774bff34e3Sthurlow smbfs_zonelist_remove(smbmntinfo_t *smi) 7784bff34e3Sthurlow { 7794bff34e3Sthurlow smi_globals_t *smg; 7804bff34e3Sthurlow 781a19609f8Sjv227347 smg = zone_getspecific(smi_list_key, smi->smi_zone_ref.zref_zone); 7824bff34e3Sthurlow mutex_enter(&smg->smg_lock); 7834bff34e3Sthurlow list_remove(&smg->smg_list, smi); 7844bff34e3Sthurlow /* 7854bff34e3Sthurlow * We can be called asynchronously by VFS_FREEVFS() after the zone 7864bff34e3Sthurlow * shutdown/destroy callbacks have executed; if so, clean up the zone's 7874bff34e3Sthurlow * smi_globals. 7884bff34e3Sthurlow */ 7894bff34e3Sthurlow if (list_head(&smg->smg_list) == NULL && 7904bff34e3Sthurlow smg->smg_destructor_called == B_TRUE) { 7914bff34e3Sthurlow smbfs_zone_free_globals(smg); 7924bff34e3Sthurlow return; 7934bff34e3Sthurlow } 7944bff34e3Sthurlow mutex_exit(&smg->smg_lock); 7954bff34e3Sthurlow } 7964bff34e3Sthurlow 797613a2f6bSGordon Ross #ifdef lint 798613a2f6bSGordon Ross #define NEED_SMBFS_CALLBACKS 1 799613a2f6bSGordon Ross #endif 8004bff34e3Sthurlow 8014bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 8024bff34e3Sthurlow /* 8034bff34e3Sthurlow * Call-back hooks for netsmb, in case we want them. 8044bff34e3Sthurlow * Apple's VFS wants them. We may not need them. 8054bff34e3Sthurlow */ 806613a2f6bSGordon Ross /*ARGSUSED*/ 8074bff34e3Sthurlow static void smbfs_dead(smb_share_t *ssp) 8084bff34e3Sthurlow { 809613a2f6bSGordon Ross /* 810613a2f6bSGordon Ross * Walk the mount list, finding all mounts 811613a2f6bSGordon Ross * using this share... 812613a2f6bSGordon Ross */ 8134bff34e3Sthurlow } 8144bff34e3Sthurlow 815613a2f6bSGordon Ross /*ARGSUSED*/ 816613a2f6bSGordon Ross static void smbfs_cb_nop(smb_share_t *ss) 8174bff34e3Sthurlow { 8184bff34e3Sthurlow /* no-op */ 8194bff34e3Sthurlow } 8204bff34e3Sthurlow 8214bff34e3Sthurlow smb_fscb_t smbfs_cb = { 822613a2f6bSGordon Ross .fscb_disconn = smbfs_dead, 823613a2f6bSGordon Ross .fscb_connect = smbfs_cb_nop, 824613a2f6bSGordon Ross .fscb_down = smbfs_cb_nop, 825613a2f6bSGordon Ross .fscb_up = smbfs_cb_nop }; 8264bff34e3Sthurlow 8274bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 8284bff34e3Sthurlow 8294bff34e3Sthurlow /* 8304bff34e3Sthurlow * SMBFS Client initialization routine. This routine should only be called 8314bff34e3Sthurlow * once. It performs the following tasks: 8324bff34e3Sthurlow * - Initalize all global locks 8334bff34e3Sthurlow * - Call sub-initialization routines (localize access to variables) 8344bff34e3Sthurlow */ 8354bff34e3Sthurlow int 8364bff34e3Sthurlow smbfs_clntinit(void) 8374bff34e3Sthurlow { 8384bff34e3Sthurlow 8394bff34e3Sthurlow zone_key_create(&smi_list_key, smbfs_zone_init, smbfs_zone_shutdown, 8404bff34e3Sthurlow smbfs_zone_destroy); 8414bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 842c1374a13SSurya Prakki (void) smb_fscb_set(&smbfs_cb); 8434bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 8444bff34e3Sthurlow return (0); 8454bff34e3Sthurlow } 8464bff34e3Sthurlow 8474bff34e3Sthurlow /* 8484bff34e3Sthurlow * This routine is called when the modunload is called. This will cleanup 8494bff34e3Sthurlow * the previously allocated/initialized nodes. 8504bff34e3Sthurlow */ 8514bff34e3Sthurlow void 8524bff34e3Sthurlow smbfs_clntfini(void) 8534bff34e3Sthurlow { 8544bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 855c1374a13SSurya Prakki (void) smb_fscb_set(NULL); 8564bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 8574bff34e3Sthurlow (void) zone_key_delete(smi_list_key); 8584bff34e3Sthurlow } 859