1*4bff34e3Sthurlow /*
2*4bff34e3Sthurlow  * CDDL HEADER START
3*4bff34e3Sthurlow  *
4*4bff34e3Sthurlow  * The contents of this file are subject to the terms of the
5*4bff34e3Sthurlow  * Common Development and Distribution License (the "License").
6*4bff34e3Sthurlow  * You may not use this file except in compliance with the License.
7*4bff34e3Sthurlow  *
8*4bff34e3Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4bff34e3Sthurlow  * or http://www.opensolaris.org/os/licensing.
10*4bff34e3Sthurlow  * See the License for the specific language governing permissions
11*4bff34e3Sthurlow  * and limitations under the License.
12*4bff34e3Sthurlow  *
13*4bff34e3Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
14*4bff34e3Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4bff34e3Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
16*4bff34e3Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
17*4bff34e3Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4bff34e3Sthurlow  *
19*4bff34e3Sthurlow  * CDDL HEADER END
20*4bff34e3Sthurlow  */
21*4bff34e3Sthurlow /*
22*4bff34e3Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*4bff34e3Sthurlow  * Use is subject to license terms.
24*4bff34e3Sthurlow  *
25*4bff34e3Sthurlow  *  	Copyright (c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
26*4bff34e3Sthurlow  *	All rights reserved.
27*4bff34e3Sthurlow  */
28*4bff34e3Sthurlow 
29*4bff34e3Sthurlow #pragma ident	"%Z%%M%	%I%	%E% SMI"
30*4bff34e3Sthurlow 
31*4bff34e3Sthurlow #include <sys/param.h>
32*4bff34e3Sthurlow #include <sys/systm.h>
33*4bff34e3Sthurlow #include <sys/thread.h>
34*4bff34e3Sthurlow #include <sys/t_lock.h>
35*4bff34e3Sthurlow #include <sys/time.h>
36*4bff34e3Sthurlow #include <sys/vnode.h>
37*4bff34e3Sthurlow #include <sys/vfs.h>
38*4bff34e3Sthurlow #include <sys/errno.h>
39*4bff34e3Sthurlow #include <sys/buf.h>
40*4bff34e3Sthurlow #include <sys/stat.h>
41*4bff34e3Sthurlow #include <sys/cred.h>
42*4bff34e3Sthurlow #include <sys/kmem.h>
43*4bff34e3Sthurlow #include <sys/debug.h>
44*4bff34e3Sthurlow #include <sys/dnlc.h>
45*4bff34e3Sthurlow #include <sys/vmsystm.h>
46*4bff34e3Sthurlow #include <sys/flock.h>
47*4bff34e3Sthurlow #include <sys/share.h>
48*4bff34e3Sthurlow #include <sys/cmn_err.h>
49*4bff34e3Sthurlow #include <sys/tiuser.h>
50*4bff34e3Sthurlow #include <sys/sysmacros.h>
51*4bff34e3Sthurlow #include <sys/callb.h>
52*4bff34e3Sthurlow #include <sys/acl.h>
53*4bff34e3Sthurlow #include <sys/kstat.h>
54*4bff34e3Sthurlow #include <sys/signal.h>
55*4bff34e3Sthurlow #include <sys/list.h>
56*4bff34e3Sthurlow #include <sys/zone.h>
57*4bff34e3Sthurlow 
58*4bff34e3Sthurlow #include <netsmb/smb_conn.h>
59*4bff34e3Sthurlow 
60*4bff34e3Sthurlow #include <smbfs/smbfs.h>
61*4bff34e3Sthurlow #include <smbfs/smbfs_node.h>
62*4bff34e3Sthurlow #include <smbfs/smbfs_subr.h>
63*4bff34e3Sthurlow 
64*4bff34e3Sthurlow #include <vm/hat.h>
65*4bff34e3Sthurlow #include <vm/as.h>
66*4bff34e3Sthurlow #include <vm/page.h>
67*4bff34e3Sthurlow #include <vm/pvn.h>
68*4bff34e3Sthurlow #include <vm/seg.h>
69*4bff34e3Sthurlow #include <vm/seg_map.h>
70*4bff34e3Sthurlow #include <vm/seg_vn.h>
71*4bff34e3Sthurlow 
72*4bff34e3Sthurlow /*
73*4bff34e3Sthurlow  * The following code provide zone support in order to perform an action
74*4bff34e3Sthurlow  * for each smbfs mount in a zone.  This is also where we would add
75*4bff34e3Sthurlow  * per-zone globals and kernel threads for the smbfs module (since
76*4bff34e3Sthurlow  * they must be terminated by the shutdown callback).
77*4bff34e3Sthurlow  */
78*4bff34e3Sthurlow 
79*4bff34e3Sthurlow struct smi_globals {
80*4bff34e3Sthurlow 	kmutex_t	smg_lock;  /* lock protecting smg_list */
81*4bff34e3Sthurlow 	list_t		smg_list;  /* list of SMBFS mounts in zone */
82*4bff34e3Sthurlow 	boolean_t	smg_destructor_called;
83*4bff34e3Sthurlow };
84*4bff34e3Sthurlow typedef struct smi_globals smi_globals_t;
85*4bff34e3Sthurlow 
86*4bff34e3Sthurlow static zone_key_t smi_list_key;
87*4bff34e3Sthurlow 
88*4bff34e3Sthurlow /* ARGSUSED */
89*4bff34e3Sthurlow static void *
90*4bff34e3Sthurlow smbfs_zone_init(zoneid_t zoneid)
91*4bff34e3Sthurlow {
92*4bff34e3Sthurlow 	smi_globals_t *smg;
93*4bff34e3Sthurlow 
94*4bff34e3Sthurlow 	smg = kmem_alloc(sizeof (*smg), KM_SLEEP);
95*4bff34e3Sthurlow 	mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL);
96*4bff34e3Sthurlow 	list_create(&smg->smg_list, sizeof (smbmntinfo_t),
97*4bff34e3Sthurlow 	    offsetof(smbmntinfo_t, smi_zone_node));
98*4bff34e3Sthurlow 	smg->smg_destructor_called = B_FALSE;
99*4bff34e3Sthurlow 	return (smg);
100*4bff34e3Sthurlow }
101*4bff34e3Sthurlow 
102*4bff34e3Sthurlow /*
103*4bff34e3Sthurlow  * Callback routine to tell all SMBFS mounts in the zone to stop creating new
104*4bff34e3Sthurlow  * threads.  Existing threads should exit.
105*4bff34e3Sthurlow  */
106*4bff34e3Sthurlow /* ARGSUSED */
107*4bff34e3Sthurlow static void
108*4bff34e3Sthurlow smbfs_zone_shutdown(zoneid_t zoneid, void *data)
109*4bff34e3Sthurlow {
110*4bff34e3Sthurlow 	smi_globals_t *smg = data;
111*4bff34e3Sthurlow 	smbmntinfo_t *smi;
112*4bff34e3Sthurlow 
113*4bff34e3Sthurlow 	ASSERT(smg != NULL);
114*4bff34e3Sthurlow again:
115*4bff34e3Sthurlow 	mutex_enter(&smg->smg_lock);
116*4bff34e3Sthurlow 	for (smi = list_head(&smg->smg_list); smi != NULL;
117*4bff34e3Sthurlow 	    smi = list_next(&smg->smg_list, smi)) {
118*4bff34e3Sthurlow 
119*4bff34e3Sthurlow 		/*
120*4bff34e3Sthurlow 		 * If we've done the shutdown work for this FS, skip.
121*4bff34e3Sthurlow 		 * Once we go off the end of the list, we're done.
122*4bff34e3Sthurlow 		 */
123*4bff34e3Sthurlow 		if (smi->smi_flags & SMI_DEAD)
124*4bff34e3Sthurlow 			continue;
125*4bff34e3Sthurlow 
126*4bff34e3Sthurlow 		/*
127*4bff34e3Sthurlow 		 * We will do work, so not done.  Get a hold on the FS.
128*4bff34e3Sthurlow 		 */
129*4bff34e3Sthurlow 		VFS_HOLD(smi->smi_vfsp);
130*4bff34e3Sthurlow 
131*4bff34e3Sthurlow 		/*
132*4bff34e3Sthurlow 		 * purge the DNLC for this filesystem
133*4bff34e3Sthurlow 		 */
134*4bff34e3Sthurlow 		(void) dnlc_purge_vfsp(smi->smi_vfsp, 0);
135*4bff34e3Sthurlow 
136*4bff34e3Sthurlow 		mutex_enter(&smi->smi_lock);
137*4bff34e3Sthurlow 		smi->smi_flags |= SMI_DEAD;
138*4bff34e3Sthurlow 		mutex_exit(&smi->smi_lock);
139*4bff34e3Sthurlow 
140*4bff34e3Sthurlow 		/*
141*4bff34e3Sthurlow 		 * Drop lock and release FS, which may change list, then repeat.
142*4bff34e3Sthurlow 		 * We're done when every mi has been done or the list is empty.
143*4bff34e3Sthurlow 		 */
144*4bff34e3Sthurlow 		mutex_exit(&smg->smg_lock);
145*4bff34e3Sthurlow 		VFS_RELE(smi->smi_vfsp);
146*4bff34e3Sthurlow 		goto again;
147*4bff34e3Sthurlow 	}
148*4bff34e3Sthurlow 	mutex_exit(&smg->smg_lock);
149*4bff34e3Sthurlow }
150*4bff34e3Sthurlow 
151*4bff34e3Sthurlow static void
152*4bff34e3Sthurlow smbfs_zone_free_globals(smi_globals_t *smg)
153*4bff34e3Sthurlow {
154*4bff34e3Sthurlow 	list_destroy(&smg->smg_list);	/* makes sure the list is empty */
155*4bff34e3Sthurlow 	mutex_destroy(&smg->smg_lock);
156*4bff34e3Sthurlow 	kmem_free(smg, sizeof (*smg));
157*4bff34e3Sthurlow 
158*4bff34e3Sthurlow }
159*4bff34e3Sthurlow 
160*4bff34e3Sthurlow /* ARGSUSED */
161*4bff34e3Sthurlow static void
162*4bff34e3Sthurlow smbfs_zone_destroy(zoneid_t zoneid, void *data)
163*4bff34e3Sthurlow {
164*4bff34e3Sthurlow 	smi_globals_t *smg = data;
165*4bff34e3Sthurlow 
166*4bff34e3Sthurlow 	ASSERT(smg != NULL);
167*4bff34e3Sthurlow 	mutex_enter(&smg->smg_lock);
168*4bff34e3Sthurlow 	if (list_head(&smg->smg_list) != NULL) {
169*4bff34e3Sthurlow 		/* Still waiting for VFS_FREEVFS() */
170*4bff34e3Sthurlow 		smg->smg_destructor_called = B_TRUE;
171*4bff34e3Sthurlow 		mutex_exit(&smg->smg_lock);
172*4bff34e3Sthurlow 		return;
173*4bff34e3Sthurlow 	}
174*4bff34e3Sthurlow 	smbfs_zone_free_globals(smg);
175*4bff34e3Sthurlow }
176*4bff34e3Sthurlow 
177*4bff34e3Sthurlow /*
178*4bff34e3Sthurlow  * Add an SMBFS mount to the per-zone list of SMBFS mounts.
179*4bff34e3Sthurlow  */
180*4bff34e3Sthurlow void
181*4bff34e3Sthurlow smbfs_zonelist_add(smbmntinfo_t *smi)
182*4bff34e3Sthurlow {
183*4bff34e3Sthurlow 	smi_globals_t *smg;
184*4bff34e3Sthurlow 
185*4bff34e3Sthurlow 	smg = zone_getspecific(smi_list_key, smi->smi_zone);
186*4bff34e3Sthurlow 	mutex_enter(&smg->smg_lock);
187*4bff34e3Sthurlow 	list_insert_head(&smg->smg_list, smi);
188*4bff34e3Sthurlow 	mutex_exit(&smg->smg_lock);
189*4bff34e3Sthurlow }
190*4bff34e3Sthurlow 
191*4bff34e3Sthurlow /*
192*4bff34e3Sthurlow  * Remove an SMBFS mount from the per-zone list of SMBFS mounts.
193*4bff34e3Sthurlow  */
194*4bff34e3Sthurlow void
195*4bff34e3Sthurlow smbfs_zonelist_remove(smbmntinfo_t *smi)
196*4bff34e3Sthurlow {
197*4bff34e3Sthurlow 	smi_globals_t *smg;
198*4bff34e3Sthurlow 
199*4bff34e3Sthurlow 	smg = zone_getspecific(smi_list_key, smi->smi_zone);
200*4bff34e3Sthurlow 	mutex_enter(&smg->smg_lock);
201*4bff34e3Sthurlow 	list_remove(&smg->smg_list, smi);
202*4bff34e3Sthurlow 	/*
203*4bff34e3Sthurlow 	 * We can be called asynchronously by VFS_FREEVFS() after the zone
204*4bff34e3Sthurlow 	 * shutdown/destroy callbacks have executed; if so, clean up the zone's
205*4bff34e3Sthurlow 	 * smi_globals.
206*4bff34e3Sthurlow 	 */
207*4bff34e3Sthurlow 	if (list_head(&smg->smg_list) == NULL &&
208*4bff34e3Sthurlow 	    smg->smg_destructor_called == B_TRUE) {
209*4bff34e3Sthurlow 		smbfs_zone_free_globals(smg);
210*4bff34e3Sthurlow 		return;
211*4bff34e3Sthurlow 	}
212*4bff34e3Sthurlow 	mutex_exit(&smg->smg_lock);
213*4bff34e3Sthurlow }
214*4bff34e3Sthurlow 
215*4bff34e3Sthurlow 
216*4bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS
217*4bff34e3Sthurlow /*
218*4bff34e3Sthurlow  * Call-back hooks for netsmb, in case we want them.
219*4bff34e3Sthurlow  * Apple's VFS wants them.  We may not need them.
220*4bff34e3Sthurlow  *
221*4bff34e3Sthurlow  * I thought I could use the "dead" callback from netsmb
222*4bff34e3Sthurlow  * to set the SMI_DEAD flag, but that looks like it will
223*4bff34e3Sthurlow  * interfere with the zone shutdown mechanisms.
224*4bff34e3Sthurlow  */
225*4bff34e3Sthurlow static void smbfs_dead(smb_share_t *ssp)
226*4bff34e3Sthurlow {
227*4bff34e3Sthurlow #if 0 /* see above */
228*4bff34e3Sthurlow 	smbmntinfo_t *smi = ssp->ss_mount;
229*4bff34e3Sthurlow 	if (smi) {
230*4bff34e3Sthurlow 		mutex_enter(&smi->smi_lock);
231*4bff34e3Sthurlow 		smi->smi_flags |= SMI_DEAD;
232*4bff34e3Sthurlow 		mutex_exit(&smi->smi_lock);
233*4bff34e3Sthurlow 	}
234*4bff34e3Sthurlow #endif
235*4bff34e3Sthurlow }
236*4bff34e3Sthurlow 
237*4bff34e3Sthurlow static void smbfs_down(smb_share_t *ss)
238*4bff34e3Sthurlow {
239*4bff34e3Sthurlow 	/* no-op */
240*4bff34e3Sthurlow }
241*4bff34e3Sthurlow 
242*4bff34e3Sthurlow static void smbfs_up(smb_share_t *ss)
243*4bff34e3Sthurlow {
244*4bff34e3Sthurlow 	/* no-op */
245*4bff34e3Sthurlow }
246*4bff34e3Sthurlow 
247*4bff34e3Sthurlow smb_fscb_t smbfs_cb = {
248*4bff34e3Sthurlow 	.fscb_dead = smbfs_dead,
249*4bff34e3Sthurlow 	.fscb_down = smbfs_down,
250*4bff34e3Sthurlow 	.fscb_up   = smbfs_up };
251*4bff34e3Sthurlow 
252*4bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */
253*4bff34e3Sthurlow 
254*4bff34e3Sthurlow /*
255*4bff34e3Sthurlow  * SMBFS Client initialization routine.  This routine should only be called
256*4bff34e3Sthurlow  * once.  It performs the following tasks:
257*4bff34e3Sthurlow  *      - Initalize all global locks
258*4bff34e3Sthurlow  *      - Call sub-initialization routines (localize access to variables)
259*4bff34e3Sthurlow  */
260*4bff34e3Sthurlow int
261*4bff34e3Sthurlow smbfs_clntinit(void)
262*4bff34e3Sthurlow {
263*4bff34e3Sthurlow 	int error;
264*4bff34e3Sthurlow 
265*4bff34e3Sthurlow 	error = smbfs_subrinit();
266*4bff34e3Sthurlow 	if (error)
267*4bff34e3Sthurlow 		return (error);
268*4bff34e3Sthurlow 	zone_key_create(&smi_list_key, smbfs_zone_init, smbfs_zone_shutdown,
269*4bff34e3Sthurlow 	    smbfs_zone_destroy);
270*4bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS
271*4bff34e3Sthurlow 	smb_fscb_set(&smbfs_cb);
272*4bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */
273*4bff34e3Sthurlow 	return (0);
274*4bff34e3Sthurlow }
275*4bff34e3Sthurlow 
276*4bff34e3Sthurlow /*
277*4bff34e3Sthurlow  * This routine is called when the modunload is called. This will cleanup
278*4bff34e3Sthurlow  * the previously allocated/initialized nodes.
279*4bff34e3Sthurlow  */
280*4bff34e3Sthurlow void
281*4bff34e3Sthurlow smbfs_clntfini(void)
282*4bff34e3Sthurlow {
283*4bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS
284*4bff34e3Sthurlow 	smb_fscb_set(NULL);
285*4bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */
286*4bff34e3Sthurlow 	(void) zone_key_delete(smi_list_key);
287*4bff34e3Sthurlow 	smbfs_subrfini();
288*4bff34e3Sthurlow }
289