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
smb_thread_entry_point(smb_thread_t * thread)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
smb_thread_init(smb_thread_t * thread,char * name,smb_thread_ep_t ep,void * ep_arg,pri_t pri)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
smb_thread_destroy(smb_thread_t * thread)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
smb_thread_start(smb_thread_t * thread)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
smb_thread_stop(smb_thread_t * thread)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
smb_thread_signal(smb_thread_t * thread)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
smb_thread_continue(smb_thread_t * thread)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
smb_thread_continue_nowait(smb_thread_t * thread)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
smb_thread_continue_timedwait(smb_thread_t * thread,int seconds)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
smb_thread_continue_timedwait_locked(smb_thread_t * thread,int ticks)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