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