xref: /titanic_51/usr/src/uts/common/fs/smbsrv/smb_thread.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
1*b819cea2SGordon Ross /*
2*b819cea2SGordon Ross  * CDDL HEADER START
3*b819cea2SGordon Ross  *
4*b819cea2SGordon Ross  * The contents of this file are subject to the terms of the
5*b819cea2SGordon Ross  * Common Development and Distribution License (the "License").
6*b819cea2SGordon Ross  * You may not use this file except in compliance with the License.
7*b819cea2SGordon Ross  *
8*b819cea2SGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*b819cea2SGordon Ross  * or http://www.opensolaris.org/os/licensing.
10*b819cea2SGordon Ross  * See the License for the specific language governing permissions
11*b819cea2SGordon Ross  * and limitations under the License.
12*b819cea2SGordon Ross  *
13*b819cea2SGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
14*b819cea2SGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*b819cea2SGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
16*b819cea2SGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
17*b819cea2SGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
18*b819cea2SGordon Ross  *
19*b819cea2SGordon Ross  * CDDL HEADER END
20*b819cea2SGordon Ross  */
21*b819cea2SGordon Ross 
22*b819cea2SGordon Ross /*
23*b819cea2SGordon Ross  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24*b819cea2SGordon Ross  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25*b819cea2SGordon Ross  */
26*b819cea2SGordon Ross 
27*b819cea2SGordon Ross #include <sys/param.h>
28*b819cea2SGordon Ross #include <sys/types.h>
29*b819cea2SGordon Ross #include <sys/tzfile.h>
30*b819cea2SGordon Ross #include <sys/atomic.h>
31*b819cea2SGordon Ross #include <sys/kidmap.h>
32*b819cea2SGordon Ross #include <sys/time.h>
33*b819cea2SGordon Ross #include <sys/spl.h>
34*b819cea2SGordon Ross #include <sys/random.h>
35*b819cea2SGordon Ross #include <smbsrv/smb_kproto.h>
36*b819cea2SGordon Ross #include <smbsrv/smb_fsops.h>
37*b819cea2SGordon Ross #include <smbsrv/smbinfo.h>
38*b819cea2SGordon Ross #include <smbsrv/smb_xdr.h>
39*b819cea2SGordon Ross #include <smbsrv/smb_vops.h>
40*b819cea2SGordon Ross #include <smbsrv/smb_idmap.h>
41*b819cea2SGordon Ross 
42*b819cea2SGordon Ross #include <sys/sid.h>
43*b819cea2SGordon Ross #include <sys/priv_names.h>
44*b819cea2SGordon Ross 
45*b819cea2SGordon Ross #ifdef	_FAKE_KERNEL
46*b819cea2SGordon Ross #define	THR_TO_DID(t)	((kt_did_t)(uintptr_t)t)
47*b819cea2SGordon Ross #else
48*b819cea2SGordon Ross #define	THR_TO_DID(t)	(t->t_did)
49*b819cea2SGordon Ross #endif
50*b819cea2SGordon Ross 
51*b819cea2SGordon Ross static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int);
52*b819cea2SGordon Ross 
53*b819cea2SGordon Ross /*
54*b819cea2SGordon Ross  * smb_thread_entry_point
55*b819cea2SGordon Ross  *
56*b819cea2SGordon Ross  * Common entry point for all the threads created through smb_thread_start.
57*b819cea2SGordon Ross  * The state of the thread is set to "running" at the beginning and moved to
58*b819cea2SGordon Ross  * "exiting" just before calling thread_exit(). The condition variable is
59*b819cea2SGordon Ross  *  also signaled.
60*b819cea2SGordon Ross  */
61*b819cea2SGordon Ross static void
62*b819cea2SGordon Ross smb_thread_entry_point(
63*b819cea2SGordon Ross     smb_thread_t	*thread)
64*b819cea2SGordon Ross {
65*b819cea2SGordon Ross 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
66*b819cea2SGordon Ross 	mutex_enter(&thread->sth_mtx);
67*b819cea2SGordon Ross 	ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING);
68*b819cea2SGordon Ross 
69*b819cea2SGordon Ross 	if (!thread->sth_kill) {
70*b819cea2SGordon Ross 		thread->sth_state = SMB_THREAD_STATE_RUNNING;
71*b819cea2SGordon Ross 		cv_signal(&thread->sth_cv);
72*b819cea2SGordon Ross 		mutex_exit(&thread->sth_mtx);
73*b819cea2SGordon Ross 
74*b819cea2SGordon Ross 		/* Run the real thread entry point. */
75*b819cea2SGordon Ross 		thread->sth_ep(thread, thread->sth_ep_arg);
76*b819cea2SGordon Ross 
77*b819cea2SGordon Ross 		mutex_enter(&thread->sth_mtx);
78*b819cea2SGordon Ross 	}
79*b819cea2SGordon Ross 	/*
80*b819cea2SGordon Ross 	 * It's tempting to clear sth_did here too, but don't.
81*b819cea2SGordon Ross 	 * That's needed in thread_join().
82*b819cea2SGordon Ross 	 */
83*b819cea2SGordon Ross 	thread->sth_th = NULL;
84*b819cea2SGordon Ross 	thread->sth_state = SMB_THREAD_STATE_EXITING;
85*b819cea2SGordon Ross 	cv_broadcast(&thread->sth_cv);
86*b819cea2SGordon Ross 	mutex_exit(&thread->sth_mtx);
87*b819cea2SGordon Ross 	zthread_exit();
88*b819cea2SGordon Ross }
89*b819cea2SGordon Ross 
90*b819cea2SGordon Ross /*
91*b819cea2SGordon Ross  * smb_thread_init
92*b819cea2SGordon Ross  */
93*b819cea2SGordon Ross void
94*b819cea2SGordon Ross smb_thread_init(
95*b819cea2SGordon Ross     smb_thread_t	*thread,
96*b819cea2SGordon Ross     char		*name,
97*b819cea2SGordon Ross     smb_thread_ep_t	ep,
98*b819cea2SGordon Ross     void		*ep_arg,
99*b819cea2SGordon Ross     pri_t		pri)
100*b819cea2SGordon Ross {
101*b819cea2SGordon Ross 	ASSERT(thread->sth_magic != SMB_THREAD_MAGIC);
102*b819cea2SGordon Ross 
103*b819cea2SGordon Ross 	bzero(thread, sizeof (*thread));
104*b819cea2SGordon Ross 
105*b819cea2SGordon Ross 	(void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name));
106*b819cea2SGordon Ross 	thread->sth_ep = ep;
107*b819cea2SGordon Ross 	thread->sth_ep_arg = ep_arg;
108*b819cea2SGordon Ross 	thread->sth_state = SMB_THREAD_STATE_EXITED;
109*b819cea2SGordon Ross 	thread->sth_pri = pri;
110*b819cea2SGordon Ross 	mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL);
111*b819cea2SGordon Ross 	cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL);
112*b819cea2SGordon Ross 	thread->sth_magic = SMB_THREAD_MAGIC;
113*b819cea2SGordon Ross }
114*b819cea2SGordon Ross 
115*b819cea2SGordon Ross /*
116*b819cea2SGordon Ross  * smb_thread_destroy
117*b819cea2SGordon Ross  */
118*b819cea2SGordon Ross void
119*b819cea2SGordon Ross smb_thread_destroy(
120*b819cea2SGordon Ross     smb_thread_t	*thread)
121*b819cea2SGordon Ross {
122*b819cea2SGordon Ross 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
123*b819cea2SGordon Ross 	ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED);
124*b819cea2SGordon Ross 	thread->sth_magic = 0;
125*b819cea2SGordon Ross 	mutex_destroy(&thread->sth_mtx);
126*b819cea2SGordon Ross 	cv_destroy(&thread->sth_cv);
127*b819cea2SGordon Ross }
128*b819cea2SGordon Ross 
129*b819cea2SGordon Ross /*
130*b819cea2SGordon Ross  * smb_thread_start
131*b819cea2SGordon Ross  *
132*b819cea2SGordon Ross  * This function starts a thread with the parameters provided. It waits until
133*b819cea2SGordon Ross  * the state of the thread has been moved to running.
134*b819cea2SGordon Ross  */
135*b819cea2SGordon Ross /*ARGSUSED*/
136*b819cea2SGordon Ross int
137*b819cea2SGordon Ross smb_thread_start(
138*b819cea2SGordon Ross     smb_thread_t	*thread)
139*b819cea2SGordon Ross {
140*b819cea2SGordon Ross 	int		rc = 0;
141*b819cea2SGordon Ross 	kthread_t	*tmpthread;
142*b819cea2SGordon Ross 
143*b819cea2SGordon Ross 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
144*b819cea2SGordon Ross 
145*b819cea2SGordon Ross 	mutex_enter(&thread->sth_mtx);
146*b819cea2SGordon Ross 	switch (thread->sth_state) {
147*b819cea2SGordon Ross 	case SMB_THREAD_STATE_EXITED:
148*b819cea2SGordon Ross 		thread->sth_state = SMB_THREAD_STATE_STARTING;
149*b819cea2SGordon Ross 		mutex_exit(&thread->sth_mtx);
150*b819cea2SGordon Ross 		tmpthread = zthread_create(NULL, 0, smb_thread_entry_point,
151*b819cea2SGordon Ross 		    thread, 0, thread->sth_pri);
152*b819cea2SGordon Ross 		ASSERT(tmpthread != NULL);
153*b819cea2SGordon Ross 		mutex_enter(&thread->sth_mtx);
154*b819cea2SGordon Ross 		thread->sth_th = tmpthread;
155*b819cea2SGordon Ross 		thread->sth_did = THR_TO_DID(tmpthread);
156*b819cea2SGordon Ross 		while (thread->sth_state == SMB_THREAD_STATE_STARTING)
157*b819cea2SGordon Ross 			cv_wait(&thread->sth_cv, &thread->sth_mtx);
158*b819cea2SGordon Ross 		if (thread->sth_state != SMB_THREAD_STATE_RUNNING)
159*b819cea2SGordon Ross 			rc = -1;
160*b819cea2SGordon Ross 		break;
161*b819cea2SGordon Ross 	default:
162*b819cea2SGordon Ross 		ASSERT(0);
163*b819cea2SGordon Ross 		rc = -1;
164*b819cea2SGordon Ross 		break;
165*b819cea2SGordon Ross 	}
166*b819cea2SGordon Ross 	mutex_exit(&thread->sth_mtx);
167*b819cea2SGordon Ross 	return (rc);
168*b819cea2SGordon Ross }
169*b819cea2SGordon Ross 
170*b819cea2SGordon Ross /*
171*b819cea2SGordon Ross  * smb_thread_stop
172*b819cea2SGordon Ross  *
173*b819cea2SGordon Ross  * This function signals a thread to kill itself and waits until the "exiting"
174*b819cea2SGordon Ross  * state has been reached.
175*b819cea2SGordon Ross  */
176*b819cea2SGordon Ross void
177*b819cea2SGordon Ross smb_thread_stop(smb_thread_t *thread)
178*b819cea2SGordon Ross {
179*b819cea2SGordon Ross 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
180*b819cea2SGordon Ross 
181*b819cea2SGordon Ross 	mutex_enter(&thread->sth_mtx);
182*b819cea2SGordon Ross 	switch (thread->sth_state) {
183*b819cea2SGordon Ross 	case SMB_THREAD_STATE_RUNNING:
184*b819cea2SGordon Ross 	case SMB_THREAD_STATE_STARTING:
185*b819cea2SGordon Ross 		if (!thread->sth_kill) {
186*b819cea2SGordon Ross 			thread->sth_kill = B_TRUE;
187*b819cea2SGordon Ross 			cv_broadcast(&thread->sth_cv);
188*b819cea2SGordon Ross 			while (thread->sth_state != SMB_THREAD_STATE_EXITING)
189*b819cea2SGordon Ross 				cv_wait(&thread->sth_cv, &thread->sth_mtx);
190*b819cea2SGordon Ross 			mutex_exit(&thread->sth_mtx);
191*b819cea2SGordon Ross 			thread_join(thread->sth_did);
192*b819cea2SGordon Ross 			mutex_enter(&thread->sth_mtx);
193*b819cea2SGordon Ross 			thread->sth_state = SMB_THREAD_STATE_EXITED;
194*b819cea2SGordon Ross 			thread->sth_did = 0;
195*b819cea2SGordon Ross 			thread->sth_kill = B_FALSE;
196*b819cea2SGordon Ross 			cv_broadcast(&thread->sth_cv);
197*b819cea2SGordon Ross 			break;
198*b819cea2SGordon Ross 		}
199*b819cea2SGordon Ross 		/* FALLTHROUGH */
200*b819cea2SGordon Ross 
201*b819cea2SGordon Ross 	case SMB_THREAD_STATE_EXITING:
202*b819cea2SGordon Ross 		if (thread->sth_kill) {
203*b819cea2SGordon Ross 			while (thread->sth_state != SMB_THREAD_STATE_EXITED)
204*b819cea2SGordon Ross 				cv_wait(&thread->sth_cv, &thread->sth_mtx);
205*b819cea2SGordon Ross 		} else {
206*b819cea2SGordon Ross 			thread->sth_state = SMB_THREAD_STATE_EXITED;
207*b819cea2SGordon Ross 			thread->sth_did = 0;
208*b819cea2SGordon Ross 		}
209*b819cea2SGordon Ross 		break;
210*b819cea2SGordon Ross 
211*b819cea2SGordon Ross 	case SMB_THREAD_STATE_EXITED:
212*b819cea2SGordon Ross 		break;
213*b819cea2SGordon Ross 
214*b819cea2SGordon Ross 	default:
215*b819cea2SGordon Ross 		ASSERT(0);
216*b819cea2SGordon Ross 		break;
217*b819cea2SGordon Ross 	}
218*b819cea2SGordon Ross 	mutex_exit(&thread->sth_mtx);
219*b819cea2SGordon Ross }
220*b819cea2SGordon Ross 
221*b819cea2SGordon Ross /*
222*b819cea2SGordon Ross  * smb_thread_signal
223*b819cea2SGordon Ross  *
224*b819cea2SGordon Ross  * This function signals a thread.
225*b819cea2SGordon Ross  */
226*b819cea2SGordon Ross void
227*b819cea2SGordon Ross smb_thread_signal(smb_thread_t *thread)
228*b819cea2SGordon Ross {
229*b819cea2SGordon Ross 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
230*b819cea2SGordon Ross 
231*b819cea2SGordon Ross 	mutex_enter(&thread->sth_mtx);
232*b819cea2SGordon Ross 	switch (thread->sth_state) {
233*b819cea2SGordon Ross 	case SMB_THREAD_STATE_RUNNING:
234*b819cea2SGordon Ross 		cv_signal(&thread->sth_cv);
235*b819cea2SGordon Ross 		break;
236*b819cea2SGordon Ross 
237*b819cea2SGordon Ross 	default:
238*b819cea2SGordon Ross 		break;
239*b819cea2SGordon Ross 	}
240*b819cea2SGordon Ross 	mutex_exit(&thread->sth_mtx);
241*b819cea2SGordon Ross }
242*b819cea2SGordon Ross 
243*b819cea2SGordon Ross boolean_t
244*b819cea2SGordon Ross smb_thread_continue(smb_thread_t *thread)
245*b819cea2SGordon Ross {
246*b819cea2SGordon Ross 	boolean_t result;
247*b819cea2SGordon Ross 
248*b819cea2SGordon Ross 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
249*b819cea2SGordon Ross 
250*b819cea2SGordon Ross 	mutex_enter(&thread->sth_mtx);
251*b819cea2SGordon Ross 	result = smb_thread_continue_timedwait_locked(thread, 0);
252*b819cea2SGordon Ross 	mutex_exit(&thread->sth_mtx);
253*b819cea2SGordon Ross 
254*b819cea2SGordon Ross 	return (result);
255*b819cea2SGordon Ross }
256*b819cea2SGordon Ross 
257*b819cea2SGordon Ross boolean_t
258*b819cea2SGordon Ross smb_thread_continue_nowait(smb_thread_t *thread)
259*b819cea2SGordon Ross {
260*b819cea2SGordon Ross 	boolean_t result;
261*b819cea2SGordon Ross 
262*b819cea2SGordon Ross 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
263*b819cea2SGordon Ross 
264*b819cea2SGordon Ross 	mutex_enter(&thread->sth_mtx);
265*b819cea2SGordon Ross 	/*
266*b819cea2SGordon Ross 	 * Setting ticks=-1 requests a non-blocking check.  We will
267*b819cea2SGordon Ross 	 * still block if the thread is in "suspend" state.
268*b819cea2SGordon Ross 	 */
269*b819cea2SGordon Ross 	result = smb_thread_continue_timedwait_locked(thread, -1);
270*b819cea2SGordon Ross 	mutex_exit(&thread->sth_mtx);
271*b819cea2SGordon Ross 
272*b819cea2SGordon Ross 	return (result);
273*b819cea2SGordon Ross }
274*b819cea2SGordon Ross 
275*b819cea2SGordon Ross boolean_t
276*b819cea2SGordon Ross smb_thread_continue_timedwait(smb_thread_t *thread, int seconds)
277*b819cea2SGordon Ross {
278*b819cea2SGordon Ross 	boolean_t result;
279*b819cea2SGordon Ross 
280*b819cea2SGordon Ross 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
281*b819cea2SGordon Ross 
282*b819cea2SGordon Ross 	mutex_enter(&thread->sth_mtx);
283*b819cea2SGordon Ross 	result = smb_thread_continue_timedwait_locked(thread,
284*b819cea2SGordon Ross 	    SEC_TO_TICK(seconds));
285*b819cea2SGordon Ross 	mutex_exit(&thread->sth_mtx);
286*b819cea2SGordon Ross 
287*b819cea2SGordon Ross 	return (result);
288*b819cea2SGordon Ross }
289*b819cea2SGordon Ross 
290*b819cea2SGordon Ross /*
291*b819cea2SGordon Ross  * smb_thread_continue_timedwait_locked
292*b819cea2SGordon Ross  *
293*b819cea2SGordon Ross  * Internal only.  Ticks==-1 means don't block, Ticks == 0 means wait
294*b819cea2SGordon Ross  * indefinitely
295*b819cea2SGordon Ross  */
296*b819cea2SGordon Ross static boolean_t
297*b819cea2SGordon Ross smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks)
298*b819cea2SGordon Ross {
299*b819cea2SGordon Ross 	boolean_t	result;
300*b819cea2SGordon Ross 
301*b819cea2SGordon Ross 	/* -1 means don't block */
302*b819cea2SGordon Ross 	if (ticks != -1 && !thread->sth_kill) {
303*b819cea2SGordon Ross 		if (ticks == 0) {
304*b819cea2SGordon Ross 			cv_wait(&thread->sth_cv, &thread->sth_mtx);
305*b819cea2SGordon Ross 		} else {
306*b819cea2SGordon Ross 			(void) cv_reltimedwait(&thread->sth_cv,
307*b819cea2SGordon Ross 			    &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK);
308*b819cea2SGordon Ross 		}
309*b819cea2SGordon Ross 	}
310*b819cea2SGordon Ross 	result = (thread->sth_kill == 0);
311*b819cea2SGordon Ross 
312*b819cea2SGordon Ross 	return (result);
313*b819cea2SGordon Ross }
314