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