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 /*
23a19609f8Sjv * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
244bff34e3Sthurlow *
255f4fc069Sjilinxpd * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
264bff34e3Sthurlow * All rights reserved.
278329232eSGordon Ross *
28*adee6784SGordon Ross * Copyright 2018 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
658329232eSGordon 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>
738329232eSGordon 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
smbfs_waitfor_purge_complete(vnode_t * vp)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
smbfs_validate_caches(struct vnode * vp,cred_t * cr)14902d09e03SGordon Ross smbfs_validate_caches(
15002d09e03SGordon Ross struct vnode *vp,
15102d09e03SGordon Ross cred_t *cr)
15202d09e03SGordon Ross {
1535f4fc069Sjilinxpd struct smbfattr fa;
1545f4fc069Sjilinxpd int error;
1555f4fc069Sjilinxpd
1565f4fc069Sjilinxpd if (ATTRCACHE_VALID(vp)) {
1575f4fc069Sjilinxpd error = smbfs_waitfor_purge_complete(vp);
1585f4fc069Sjilinxpd if (error)
1595f4fc069Sjilinxpd return (error);
1605f4fc069Sjilinxpd return (0);
1615f4fc069Sjilinxpd }
16202d09e03SGordon Ross
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 */
1725f4fc069Sjilinxpd /* ARGSUSED */
17302d09e03SGordon Ross void
smbfs_purge_caches(struct vnode * vp,cred_t * cr)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
1965f4fc069Sjilinxpd /*
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
20402d09e03SGordon Ross /*
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
smbfs_cache_check(struct vnode * vp,struct smbfattr * fap,cred_t * cr)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
smbfs_attrcache_fa(vnode_t * vp,struct smbfattr * fap)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
smbfs_getattr_cache(vnode_t * vp,struct smbfattr * fap)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
smbfs_getattr_otw(vnode_t * vp,struct smbfattr * fap,cred_t * cr)39902d09e03SGordon Ross smbfs_getattr_otw(vnode_t *vp, struct smbfattr *fap, cred_t *cr)
40002d09e03SGordon Ross {
40102d09e03SGordon Ross struct smb_cred scred;
402*adee6784SGordon Ross smbnode_t *np = VTOSMB(vp);
403*adee6784SGordon Ross smb_share_t *ssp = np->n_mount->smi_share;
404*adee6784SGordon Ross smb_fh_t *fhp = NULL;
40502d09e03SGordon Ross int error;
40602d09e03SGordon Ross
407*adee6784SGordon Ross bzero(fap, sizeof (*fap));
408*adee6784SGordon Ross
409*adee6784SGordon Ross /*
410*adee6784SGordon Ross * Special case the XATTR directory here (all fake).
411*adee6784SGordon Ross * OK to leave a,c,m times zero (expected).
412*adee6784SGordon Ross */
413*adee6784SGordon Ross if (vp->v_flag & V_XATTRDIR) {
414*adee6784SGordon Ross fap->fa_attr = SMB_FA_DIR;
415*adee6784SGordon Ross fap->fa_size = DEV_BSIZE;
416*adee6784SGordon Ross return (0);
417*adee6784SGordon Ross }
41802d09e03SGordon Ross
41902d09e03SGordon Ross /*
4205f4fc069Sjilinxpd * Here NFS uses the ACL RPC (if smi_flags & SMI_ACL)
421bd7c6f51SGordon Ross * With SMB, getting the ACL is a significantly more
422bd7c6f51SGordon Ross * expensive operation, so we do that only when asked
423bd7c6f51SGordon Ross * for the uid/gid. See smbfsgetattr().
42402d09e03SGordon Ross */
42502d09e03SGordon Ross
42602d09e03SGordon Ross /* Shared lock for (possible) n_fid use. */
42702d09e03SGordon Ross if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
42802d09e03SGordon Ross return (EINTR);
42902d09e03SGordon Ross smb_credinit(&scred, cr);
43002d09e03SGordon Ross
431*adee6784SGordon Ross // Does the attr. open code path work for streams?
432*adee6784SGordon Ross // Trying that, and if it doesn't work enable this.
433*adee6784SGordon Ross #if 0 // XXX
434*adee6784SGordon Ross /*
435*adee6784SGordon Ross * Extended attribute files
436*adee6784SGordon Ross */
437*adee6784SGordon Ross if (np->n_flag & N_XATTR) {
438*adee6784SGordon Ross error = smbfs_xa_getfattr(np, fap, scrp);
439*adee6784SGordon Ross goto out;
440*adee6784SGordon Ross }
441*adee6784SGordon Ross #endif // XXX
442*adee6784SGordon Ross
443*adee6784SGordon Ross if (np->n_fidrefs > 0 &&
444*adee6784SGordon Ross (fhp = np->n_fid) != NULL &&
445*adee6784SGordon Ross (fhp->fh_vcgenid == ssp->ss_vcgenid)) {
446*adee6784SGordon Ross /* Use the FID we have. */
447*adee6784SGordon Ross error = smbfs_smb_getfattr(np, fhp, fap, &scred);
448*adee6784SGordon Ross
449*adee6784SGordon Ross } else {
450*adee6784SGordon Ross /* This will do an attr open */
451*adee6784SGordon Ross error = smbfs_smb_getpattr(np, fap, &scred);
452*adee6784SGordon Ross }
45302d09e03SGordon Ross
45402d09e03SGordon Ross smb_credrele(&scred);
45502d09e03SGordon Ross smbfs_rw_exit(&np->r_lkserlock);
45602d09e03SGordon Ross
45702d09e03SGordon Ross if (error) {
4585f4fc069Sjilinxpd /* Here NFS has: PURGE_STALE_FH(error, vp, cr) */
45902d09e03SGordon Ross smbfs_attrcache_remove(np);
46002d09e03SGordon Ross if (error == ENOENT || error == ENOTDIR) {
46102d09e03SGordon Ross /*
46202d09e03SGordon Ross * Getattr failed because the object was
46302d09e03SGordon Ross * removed or renamed by another client.
46402d09e03SGordon Ross * Remove any cached attributes under it.
46502d09e03SGordon Ross */
46602d09e03SGordon Ross smbfs_attrcache_prune(np);
46702d09e03SGordon Ross }
46802d09e03SGordon Ross return (error);
46902d09e03SGordon Ross }
47002d09e03SGordon Ross
47102d09e03SGordon Ross /*
4725f4fc069Sjilinxpd * Here NFS has: nfs_cache_fattr(vap, fa, vap, t, cr);
47302d09e03SGordon Ross * which did: fattr_to_vattr, nfs_attr_cache.
47402d09e03SGordon Ross * We cache the fattr form, so just do the
47502d09e03SGordon Ross * cache check and store the attributes.
47602d09e03SGordon Ross */
4775f4fc069Sjilinxpd smbfs_cache_check(vp, fap, cr);
47802d09e03SGordon Ross smbfs_attrcache_fa(vp, fap);
47902d09e03SGordon Ross
48002d09e03SGordon Ross return (0);
48102d09e03SGordon Ross }
48202d09e03SGordon Ross
48302d09e03SGordon Ross /*
4845f4fc069Sjilinxpd * Return either cached or remote attributes. If we get remote attrs,
48502d09e03SGordon Ross * use them to check and invalidate caches, then cache the new attributes.
48602d09e03SGordon Ross *
48702d09e03SGordon Ross * From NFS: nfsgetattr()
48802d09e03SGordon Ross */
48902d09e03SGordon Ross int
smbfsgetattr(vnode_t * vp,struct vattr * vap,cred_t * cr)49002d09e03SGordon Ross smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr)
49102d09e03SGordon Ross {
49202d09e03SGordon Ross struct smbfattr fa;
493bd7c6f51SGordon Ross smbmntinfo_t *smi;
494bd7c6f51SGordon Ross uint_t mask;
49502d09e03SGordon Ross int error;
49602d09e03SGordon Ross
497bd7c6f51SGordon Ross smi = VTOSMI(vp);
498bd7c6f51SGordon Ross
499a19609f8Sjv ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
500bd7c6f51SGordon Ross
501bd7c6f51SGordon Ross /*
502bd7c6f51SGordon Ross * If asked for UID or GID, update n_uid, n_gid.
503bd7c6f51SGordon Ross */
504bd7c6f51SGordon Ross mask = AT_ALL;
505bd7c6f51SGordon Ross if (vap->va_mask & (AT_UID | AT_GID)) {
506bd7c6f51SGordon Ross if (smi->smi_flags & SMI_ACL)
507bd7c6f51SGordon Ross (void) smbfs_acl_getids(vp, cr);
508bd7c6f51SGordon Ross /* else leave as set in make_smbnode */
509bd7c6f51SGordon Ross } else {
510bd7c6f51SGordon Ross mask &= ~(AT_UID | AT_GID);
511bd7c6f51SGordon Ross }
51202d09e03SGordon Ross
51302d09e03SGordon Ross /*
51402d09e03SGordon Ross * If we've got cached attributes, just use them;
51502d09e03SGordon Ross * otherwise go to the server to get attributes,
51602d09e03SGordon Ross * which will update the cache in the process.
51702d09e03SGordon Ross */
51802d09e03SGordon Ross error = smbfs_getattr_cache(vp, &fa);
51902d09e03SGordon Ross if (error)
52002d09e03SGordon Ross error = smbfs_getattr_otw(vp, &fa, cr);
52102d09e03SGordon Ross if (error)
52202d09e03SGordon Ross return (error);
52328162916SGordon Ross vap->va_mask |= mask;
52402d09e03SGordon Ross
52502d09e03SGordon Ross /*
52602d09e03SGordon Ross * Re. client's view of the file size, see:
52702d09e03SGordon Ross * smbfs_attrcache_fa, smbfs_getattr_otw
52802d09e03SGordon Ross */
52928162916SGordon Ross smbfattr_to_vattr(vp, &fa, vap);
53028162916SGordon Ross if (vap->va_mask & AT_XVATTR)
53128162916SGordon Ross smbfattr_to_xvattr(&fa, vap);
53202d09e03SGordon Ross
53328162916SGordon Ross return (0);
53402d09e03SGordon Ross }
53502d09e03SGordon Ross
53602d09e03SGordon Ross
53702d09e03SGordon Ross /*
53802d09e03SGordon Ross * Convert SMB over the wire attributes to vnode form.
53902d09e03SGordon Ross * Returns 0 for success, error if failed (overflow, etc).
54002d09e03SGordon Ross * From NFS: nattr_to_vattr()
54102d09e03SGordon Ross */
54228162916SGordon Ross void
smbfattr_to_vattr(vnode_t * vp,struct smbfattr * fa,struct vattr * vap)54302d09e03SGordon Ross smbfattr_to_vattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap)
54402d09e03SGordon Ross {
54502d09e03SGordon Ross struct smbnode *np = VTOSMB(vp);
54602d09e03SGordon Ross
54702d09e03SGordon Ross /*
54802d09e03SGordon Ross * Take type, mode, uid, gid from the smbfs node,
54902d09e03SGordon Ross * which has have been updated by _getattr_otw.
55002d09e03SGordon Ross */
55102d09e03SGordon Ross vap->va_type = vp->v_type;
55202d09e03SGordon Ross vap->va_mode = np->n_mode;
55302d09e03SGordon Ross
55402d09e03SGordon Ross vap->va_uid = np->n_uid;
55502d09e03SGordon Ross vap->va_gid = np->n_gid;
55602d09e03SGordon Ross
55702d09e03SGordon Ross vap->va_fsid = vp->v_vfsp->vfs_dev;
55802d09e03SGordon Ross vap->va_nodeid = np->n_ino;
55902d09e03SGordon Ross vap->va_nlink = 1;
56002d09e03SGordon Ross
56102d09e03SGordon Ross /*
56202d09e03SGordon Ross * Difference from NFS here: We cache attributes as
56302d09e03SGordon Ross * reported by the server, so r_attr.fa_size is the
56402d09e03SGordon Ross * server's idea of the file size. This is called
56502d09e03SGordon Ross * for getattr, so we want to return the client's
56602d09e03SGordon Ross * idea of the file size. NFS deals with that in
56702d09e03SGordon Ross * nfsgetattr(), the equivalent of our caller.
56802d09e03SGordon Ross */
56902d09e03SGordon Ross vap->va_size = np->r_size;
57002d09e03SGordon Ross
57102d09e03SGordon Ross /*
57202d09e03SGordon Ross * Times. Note, already converted from NT to
57302d09e03SGordon Ross * Unix form (in the unmarshalling code).
57402d09e03SGordon Ross */
57502d09e03SGordon Ross vap->va_atime = fa->fa_atime;
57602d09e03SGordon Ross vap->va_mtime = fa->fa_mtime;
57702d09e03SGordon Ross vap->va_ctime = fa->fa_ctime;
57802d09e03SGordon Ross
57902d09e03SGordon Ross /*
58002d09e03SGordon Ross * rdev, blksize, seq are made up.
58102d09e03SGordon Ross * va_nblocks is 512 byte blocks.
58202d09e03SGordon Ross */
58302d09e03SGordon Ross vap->va_rdev = vp->v_rdev;
58402d09e03SGordon Ross vap->va_blksize = MAXBSIZE;
58502d09e03SGordon Ross vap->va_nblocks = (fsblkcnt64_t)btod(np->r_attr.fa_allocsz);
58602d09e03SGordon Ross vap->va_seq = 0;
58702d09e03SGordon Ross }
58802d09e03SGordon Ross
58928162916SGordon Ross /*
59028162916SGordon Ross * smbfattr_to_xvattr: like smbfattr_to_vattr but for
59128162916SGordon Ross * Extensible system attributes (PSARC 2007/315)
59228162916SGordon Ross */
59328162916SGordon Ross static void
smbfattr_to_xvattr(struct smbfattr * fa,struct vattr * vap)59428162916SGordon Ross smbfattr_to_xvattr(struct smbfattr *fa, struct vattr *vap)
59528162916SGordon Ross {
59628162916SGordon Ross xvattr_t *xvap = (xvattr_t *)vap; /* *vap may be xvattr_t */
59728162916SGordon Ross xoptattr_t *xoap = NULL;
59828162916SGordon Ross
59928162916SGordon Ross if ((xoap = xva_getxoptattr(xvap)) == NULL)
60028162916SGordon Ross return;
60128162916SGordon Ross
60228162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
60328162916SGordon Ross xoap->xoa_createtime = fa->fa_createtime;
60428162916SGordon Ross XVA_SET_RTN(xvap, XAT_CREATETIME);
60528162916SGordon Ross }
60628162916SGordon Ross
60728162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
60828162916SGordon Ross xoap->xoa_archive =
60928162916SGordon Ross ((fa->fa_attr & SMB_FA_ARCHIVE) != 0);
61028162916SGordon Ross XVA_SET_RTN(xvap, XAT_ARCHIVE);
61128162916SGordon Ross }
61228162916SGordon Ross
61328162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
61428162916SGordon Ross xoap->xoa_system =
61528162916SGordon Ross ((fa->fa_attr & SMB_FA_SYSTEM) != 0);
61628162916SGordon Ross XVA_SET_RTN(xvap, XAT_SYSTEM);
61728162916SGordon Ross }
61828162916SGordon Ross
61928162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
62028162916SGordon Ross xoap->xoa_readonly =
62128162916SGordon Ross ((fa->fa_attr & SMB_FA_RDONLY) != 0);
62228162916SGordon Ross XVA_SET_RTN(xvap, XAT_READONLY);
62328162916SGordon Ross }
62428162916SGordon Ross
62528162916SGordon Ross if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
62628162916SGordon Ross xoap->xoa_hidden =
62728162916SGordon Ross ((fa->fa_attr & SMB_FA_HIDDEN) != 0);
62828162916SGordon Ross XVA_SET_RTN(xvap, XAT_HIDDEN);
62928162916SGordon Ross }
63028162916SGordon Ross }
63102d09e03SGordon Ross
6325f4fc069Sjilinxpd /*
6335f4fc069Sjilinxpd * Here NFS has:
6345f4fc069Sjilinxpd * nfs_async_... stuff
6355f4fc069Sjilinxpd * which we're not using (no async I/O), and:
6365f4fc069Sjilinxpd * writerp(),
6375f4fc069Sjilinxpd * nfs_putpages()
6385f4fc069Sjilinxpd * nfs_invalidate_pages()
6395f4fc069Sjilinxpd * which we have in smbfs_vnops.c, and
6405f4fc069Sjilinxpd * nfs_printfhandle()
6415f4fc069Sjilinxpd * nfs_write_error()
6425f4fc069Sjilinxpd * not needed here.
6435f4fc069Sjilinxpd */
6445f4fc069Sjilinxpd
6455f4fc069Sjilinxpd /*
6465f4fc069Sjilinxpd * Helper function for smbfs_sync
6475f4fc069Sjilinxpd *
6485f4fc069Sjilinxpd * Walk the per-zone list of smbfs mounts, calling smbfs_rflush
6495f4fc069Sjilinxpd * on each one. This is a little tricky because we need to exit
6505f4fc069Sjilinxpd * the list mutex before each _rflush call and then try to resume
6515f4fc069Sjilinxpd * where we were in the list after re-entering the mutex.
6525f4fc069Sjilinxpd */
6535f4fc069Sjilinxpd void
smbfs_flushall(cred_t * cr)6545f4fc069Sjilinxpd smbfs_flushall(cred_t *cr)
6555f4fc069Sjilinxpd {
6565f4fc069Sjilinxpd smi_globals_t *smg;
6575f4fc069Sjilinxpd smbmntinfo_t *tmp_smi, *cur_smi, *next_smi;
6585f4fc069Sjilinxpd
6595f4fc069Sjilinxpd smg = zone_getspecific(smi_list_key, crgetzone(cr));
6605f4fc069Sjilinxpd ASSERT(smg != NULL);
6615f4fc069Sjilinxpd
6625f4fc069Sjilinxpd mutex_enter(&smg->smg_lock);
6635f4fc069Sjilinxpd cur_smi = list_head(&smg->smg_list);
6645f4fc069Sjilinxpd if (cur_smi == NULL) {
6655f4fc069Sjilinxpd mutex_exit(&smg->smg_lock);
6665f4fc069Sjilinxpd return;
6675f4fc069Sjilinxpd }
6685f4fc069Sjilinxpd VFS_HOLD(cur_smi->smi_vfsp);
6695f4fc069Sjilinxpd mutex_exit(&smg->smg_lock);
6705f4fc069Sjilinxpd
6715f4fc069Sjilinxpd flush:
6725f4fc069Sjilinxpd smbfs_rflush(cur_smi->smi_vfsp, cr);
6735f4fc069Sjilinxpd
6745f4fc069Sjilinxpd mutex_enter(&smg->smg_lock);
6755f4fc069Sjilinxpd /*
6765f4fc069Sjilinxpd * Resume after cur_smi if that's still on the list,
6775f4fc069Sjilinxpd * otherwise restart at the head.
6785f4fc069Sjilinxpd */
6795f4fc069Sjilinxpd for (tmp_smi = list_head(&smg->smg_list);
6805f4fc069Sjilinxpd tmp_smi != NULL;
6815f4fc069Sjilinxpd tmp_smi = list_next(&smg->smg_list, tmp_smi))
6825f4fc069Sjilinxpd if (tmp_smi == cur_smi)
6835f4fc069Sjilinxpd break;
6845f4fc069Sjilinxpd if (tmp_smi != NULL)
6855f4fc069Sjilinxpd next_smi = list_next(&smg->smg_list, tmp_smi);
6865f4fc069Sjilinxpd else
6875f4fc069Sjilinxpd next_smi = list_head(&smg->smg_list);
6885f4fc069Sjilinxpd
6895f4fc069Sjilinxpd if (next_smi != NULL)
6905f4fc069Sjilinxpd VFS_HOLD(next_smi->smi_vfsp);
6915f4fc069Sjilinxpd VFS_RELE(cur_smi->smi_vfsp);
6925f4fc069Sjilinxpd
6935f4fc069Sjilinxpd mutex_exit(&smg->smg_lock);
6945f4fc069Sjilinxpd
6955f4fc069Sjilinxpd if (next_smi != NULL) {
6965f4fc069Sjilinxpd cur_smi = next_smi;
6975f4fc069Sjilinxpd goto flush;
6985f4fc069Sjilinxpd }
6995f4fc069Sjilinxpd }
7005f4fc069Sjilinxpd
70102d09e03SGordon Ross /*
70202d09e03SGordon Ross * SMB Client initialization and cleanup.
70302d09e03SGordon Ross * Much of it is per-zone now.
70402d09e03SGordon Ross */
70502d09e03SGordon Ross
70602d09e03SGordon Ross
7074bff34e3Sthurlow /* ARGSUSED */
7084bff34e3Sthurlow static void *
smbfs_zone_init(zoneid_t zoneid)7094bff34e3Sthurlow smbfs_zone_init(zoneid_t zoneid)
7104bff34e3Sthurlow {
7114bff34e3Sthurlow smi_globals_t *smg;
7124bff34e3Sthurlow
7134bff34e3Sthurlow smg = kmem_alloc(sizeof (*smg), KM_SLEEP);
7144bff34e3Sthurlow mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL);
7154bff34e3Sthurlow list_create(&smg->smg_list, sizeof (smbmntinfo_t),
7164bff34e3Sthurlow offsetof(smbmntinfo_t, smi_zone_node));
7174bff34e3Sthurlow smg->smg_destructor_called = B_FALSE;
7184bff34e3Sthurlow return (smg);
7194bff34e3Sthurlow }
7204bff34e3Sthurlow
7214bff34e3Sthurlow /*
7224bff34e3Sthurlow * Callback routine to tell all SMBFS mounts in the zone to stop creating new
7234bff34e3Sthurlow * threads. Existing threads should exit.
7244bff34e3Sthurlow */
7254bff34e3Sthurlow /* ARGSUSED */
7264bff34e3Sthurlow static void
smbfs_zone_shutdown(zoneid_t zoneid,void * data)7274bff34e3Sthurlow smbfs_zone_shutdown(zoneid_t zoneid, void *data)
7284bff34e3Sthurlow {
7294bff34e3Sthurlow smi_globals_t *smg = data;
7304bff34e3Sthurlow smbmntinfo_t *smi;
7314bff34e3Sthurlow
7324bff34e3Sthurlow ASSERT(smg != NULL);
7334bff34e3Sthurlow again:
7344bff34e3Sthurlow mutex_enter(&smg->smg_lock);
7354bff34e3Sthurlow for (smi = list_head(&smg->smg_list); smi != NULL;
7364bff34e3Sthurlow smi = list_next(&smg->smg_list, smi)) {
7374bff34e3Sthurlow
7384bff34e3Sthurlow /*
7394bff34e3Sthurlow * If we've done the shutdown work for this FS, skip.
7404bff34e3Sthurlow * Once we go off the end of the list, we're done.
7414bff34e3Sthurlow */
7424bff34e3Sthurlow if (smi->smi_flags & SMI_DEAD)
7434bff34e3Sthurlow continue;
7444bff34e3Sthurlow
7454bff34e3Sthurlow /*
7464bff34e3Sthurlow * We will do work, so not done. Get a hold on the FS.
7474bff34e3Sthurlow */
7484bff34e3Sthurlow VFS_HOLD(smi->smi_vfsp);
7494bff34e3Sthurlow
7504bff34e3Sthurlow mutex_enter(&smi->smi_lock);
7514bff34e3Sthurlow smi->smi_flags |= SMI_DEAD;
7524bff34e3Sthurlow mutex_exit(&smi->smi_lock);
7534bff34e3Sthurlow
7544bff34e3Sthurlow /*
7554bff34e3Sthurlow * Drop lock and release FS, which may change list, then repeat.
7564bff34e3Sthurlow * We're done when every mi has been done or the list is empty.
7574bff34e3Sthurlow */
7584bff34e3Sthurlow mutex_exit(&smg->smg_lock);
7594bff34e3Sthurlow VFS_RELE(smi->smi_vfsp);
7604bff34e3Sthurlow goto again;
7614bff34e3Sthurlow }
7624bff34e3Sthurlow mutex_exit(&smg->smg_lock);
7634bff34e3Sthurlow }
7644bff34e3Sthurlow
7654bff34e3Sthurlow static void
smbfs_zone_free_globals(smi_globals_t * smg)7664bff34e3Sthurlow smbfs_zone_free_globals(smi_globals_t *smg)
7674bff34e3Sthurlow {
7684bff34e3Sthurlow list_destroy(&smg->smg_list); /* makes sure the list is empty */
7694bff34e3Sthurlow mutex_destroy(&smg->smg_lock);
7704bff34e3Sthurlow kmem_free(smg, sizeof (*smg));
7714bff34e3Sthurlow
7724bff34e3Sthurlow }
7734bff34e3Sthurlow
7744bff34e3Sthurlow /* ARGSUSED */
7754bff34e3Sthurlow static void
smbfs_zone_destroy(zoneid_t zoneid,void * data)7764bff34e3Sthurlow smbfs_zone_destroy(zoneid_t zoneid, void *data)
7774bff34e3Sthurlow {
7784bff34e3Sthurlow smi_globals_t *smg = data;
7794bff34e3Sthurlow
7804bff34e3Sthurlow ASSERT(smg != NULL);
7814bff34e3Sthurlow mutex_enter(&smg->smg_lock);
7824bff34e3Sthurlow if (list_head(&smg->smg_list) != NULL) {
7834bff34e3Sthurlow /* Still waiting for VFS_FREEVFS() */
7844bff34e3Sthurlow smg->smg_destructor_called = B_TRUE;
7854bff34e3Sthurlow mutex_exit(&smg->smg_lock);
7864bff34e3Sthurlow return;
7874bff34e3Sthurlow }
7884bff34e3Sthurlow smbfs_zone_free_globals(smg);
7894bff34e3Sthurlow }
7904bff34e3Sthurlow
7914bff34e3Sthurlow /*
7924bff34e3Sthurlow * Add an SMBFS mount to the per-zone list of SMBFS mounts.
7934bff34e3Sthurlow */
7944bff34e3Sthurlow void
smbfs_zonelist_add(smbmntinfo_t * smi)7954bff34e3Sthurlow smbfs_zonelist_add(smbmntinfo_t *smi)
7964bff34e3Sthurlow {
7974bff34e3Sthurlow smi_globals_t *smg;
7984bff34e3Sthurlow
799a19609f8Sjv smg = zone_getspecific(smi_list_key, smi->smi_zone_ref.zref_zone);
8004bff34e3Sthurlow mutex_enter(&smg->smg_lock);
8014bff34e3Sthurlow list_insert_head(&smg->smg_list, smi);
8024bff34e3Sthurlow mutex_exit(&smg->smg_lock);
8034bff34e3Sthurlow }
8044bff34e3Sthurlow
8054bff34e3Sthurlow /*
8064bff34e3Sthurlow * Remove an SMBFS mount from the per-zone list of SMBFS mounts.
8074bff34e3Sthurlow */
8084bff34e3Sthurlow void
smbfs_zonelist_remove(smbmntinfo_t * smi)8094bff34e3Sthurlow smbfs_zonelist_remove(smbmntinfo_t *smi)
8104bff34e3Sthurlow {
8114bff34e3Sthurlow smi_globals_t *smg;
8124bff34e3Sthurlow
813a19609f8Sjv smg = zone_getspecific(smi_list_key, smi->smi_zone_ref.zref_zone);
8144bff34e3Sthurlow mutex_enter(&smg->smg_lock);
8154bff34e3Sthurlow list_remove(&smg->smg_list, smi);
8164bff34e3Sthurlow /*
8174bff34e3Sthurlow * We can be called asynchronously by VFS_FREEVFS() after the zone
8184bff34e3Sthurlow * shutdown/destroy callbacks have executed; if so, clean up the zone's
8194bff34e3Sthurlow * smi_globals.
8204bff34e3Sthurlow */
8214bff34e3Sthurlow if (list_head(&smg->smg_list) == NULL &&
8224bff34e3Sthurlow smg->smg_destructor_called == B_TRUE) {
8234bff34e3Sthurlow smbfs_zone_free_globals(smg);
8244bff34e3Sthurlow return;
8254bff34e3Sthurlow }
8264bff34e3Sthurlow mutex_exit(&smg->smg_lock);
8274bff34e3Sthurlow }
8284bff34e3Sthurlow
829613a2f6bSGordon Ross #ifdef lint
830613a2f6bSGordon Ross #define NEED_SMBFS_CALLBACKS 1
831613a2f6bSGordon Ross #endif
8324bff34e3Sthurlow
8334bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS
8344bff34e3Sthurlow /*
8354bff34e3Sthurlow * Call-back hooks for netsmb, in case we want them.
8364bff34e3Sthurlow * Apple's VFS wants them. We may not need them.
8374bff34e3Sthurlow */
838613a2f6bSGordon Ross /*ARGSUSED*/
smbfs_dead(smb_share_t * ssp)8394bff34e3Sthurlow static void smbfs_dead(smb_share_t *ssp)
8404bff34e3Sthurlow {
841613a2f6bSGordon Ross /*
842613a2f6bSGordon Ross * Walk the mount list, finding all mounts
843613a2f6bSGordon Ross * using this share...
844613a2f6bSGordon Ross */
8454bff34e3Sthurlow }
8464bff34e3Sthurlow
847613a2f6bSGordon Ross /*ARGSUSED*/
smbfs_cb_nop(smb_share_t * ss)848613a2f6bSGordon Ross static void smbfs_cb_nop(smb_share_t *ss)
8494bff34e3Sthurlow {
8504bff34e3Sthurlow /* no-op */
8514bff34e3Sthurlow }
8524bff34e3Sthurlow
8534bff34e3Sthurlow smb_fscb_t smbfs_cb = {
854613a2f6bSGordon Ross .fscb_disconn = smbfs_dead,
855*adee6784SGordon Ross .fscb_connect = smbfs_cb_nop
856*adee6784SGordon Ross };
8574bff34e3Sthurlow
8584bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */
8594bff34e3Sthurlow
8604bff34e3Sthurlow /*
8614bff34e3Sthurlow * SMBFS Client initialization routine. This routine should only be called
8624bff34e3Sthurlow * once. It performs the following tasks:
8634bff34e3Sthurlow * - Initalize all global locks
8644bff34e3Sthurlow * - Call sub-initialization routines (localize access to variables)
8654bff34e3Sthurlow */
8664bff34e3Sthurlow int
smbfs_clntinit(void)8674bff34e3Sthurlow smbfs_clntinit(void)
8684bff34e3Sthurlow {
8694bff34e3Sthurlow
8704bff34e3Sthurlow zone_key_create(&smi_list_key, smbfs_zone_init, smbfs_zone_shutdown,
8714bff34e3Sthurlow smbfs_zone_destroy);
8724bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS
873c1374a13SSurya Prakki (void) smb_fscb_set(&smbfs_cb);
8744bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */
8754bff34e3Sthurlow return (0);
8764bff34e3Sthurlow }
8774bff34e3Sthurlow
8784bff34e3Sthurlow /*
8794bff34e3Sthurlow * This routine is called when the modunload is called. This will cleanup
8804bff34e3Sthurlow * the previously allocated/initialized nodes.
8814bff34e3Sthurlow */
8824bff34e3Sthurlow void
smbfs_clntfini(void)8834bff34e3Sthurlow smbfs_clntfini(void)
8844bff34e3Sthurlow {
8854bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS
886c1374a13SSurya Prakki (void) smb_fscb_set(NULL);
8874bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */
8884bff34e3Sthurlow (void) zone_key_delete(smi_list_key);
8894bff34e3Sthurlow }
890