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