1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte /* 22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*fcf3ce44SJohn Forte * Use is subject to license terms. 24*fcf3ce44SJohn Forte */ 25*fcf3ce44SJohn Forte 26*fcf3ce44SJohn Forte #include <sys/types.h> 27*fcf3ce44SJohn Forte #include <sys/ksynch.h> 28*fcf3ce44SJohn Forte #include <sys/errno.h> 29*fcf3ce44SJohn Forte #include <sys/ddi.h> 30*fcf3ce44SJohn Forte #include <sys/sunddi.h> 31*fcf3ce44SJohn Forte 32*fcf3ce44SJohn Forte #include "../nsctl.h" 33*fcf3ce44SJohn Forte #include "../nsctl/nsc_ioctl.h" 34*fcf3ce44SJohn Forte #include "nskernd.h" 35*fcf3ce44SJohn Forte 36*fcf3ce44SJohn Forte void *proc_nskernd; 37*fcf3ce44SJohn Forte int nskernd_iscluster; 38*fcf3ce44SJohn Forte 39*fcf3ce44SJohn Forte static kmutex_t nskernd_lock; 40*fcf3ce44SJohn Forte 41*fcf3ce44SJohn Forte static kcondvar_t nskernd_ask_cv; 42*fcf3ce44SJohn Forte static kcondvar_t nskernd_k_cv; 43*fcf3ce44SJohn Forte static kcondvar_t nskernd_u_cv; 44*fcf3ce44SJohn Forte 45*fcf3ce44SJohn Forte static volatile int nskernd_k_wait; 46*fcf3ce44SJohn Forte static volatile int nskernd_u_wait; 47*fcf3ce44SJohn Forte 48*fcf3ce44SJohn Forte static int nskernd_norun; 49*fcf3ce44SJohn Forte 50*fcf3ce44SJohn Forte static volatile int nskernd_ask; 51*fcf3ce44SJohn Forte static struct nskernd nskernd_kdata; 52*fcf3ce44SJohn Forte 53*fcf3ce44SJohn Forte void 54*fcf3ce44SJohn Forte nskernd_init(void) 55*fcf3ce44SJohn Forte { 56*fcf3ce44SJohn Forte mutex_init(&nskernd_lock, NULL, MUTEX_DRIVER, NULL); 57*fcf3ce44SJohn Forte cv_init(&nskernd_ask_cv, NULL, CV_DRIVER, NULL); 58*fcf3ce44SJohn Forte cv_init(&nskernd_k_cv, NULL, CV_DRIVER, NULL); 59*fcf3ce44SJohn Forte cv_init(&nskernd_u_cv, NULL, CV_DRIVER, NULL); 60*fcf3ce44SJohn Forte 61*fcf3ce44SJohn Forte nskernd_norun = 0; 62*fcf3ce44SJohn Forte } 63*fcf3ce44SJohn Forte 64*fcf3ce44SJohn Forte 65*fcf3ce44SJohn Forte void 66*fcf3ce44SJohn Forte nskernd_deinit(void) 67*fcf3ce44SJohn Forte { 68*fcf3ce44SJohn Forte mutex_destroy(&nskernd_lock); 69*fcf3ce44SJohn Forte cv_destroy(&nskernd_ask_cv); 70*fcf3ce44SJohn Forte cv_destroy(&nskernd_k_cv); 71*fcf3ce44SJohn Forte cv_destroy(&nskernd_u_cv); 72*fcf3ce44SJohn Forte } 73*fcf3ce44SJohn Forte 74*fcf3ce44SJohn Forte 75*fcf3ce44SJohn Forte static int 76*fcf3ce44SJohn Forte nskernd_start(const int iscluster) 77*fcf3ce44SJohn Forte { 78*fcf3ce44SJohn Forte int rc = 0; 79*fcf3ce44SJohn Forte 80*fcf3ce44SJohn Forte mutex_enter(&nskernd_lock); 81*fcf3ce44SJohn Forte 82*fcf3ce44SJohn Forte if (proc_nskernd != NULL) { 83*fcf3ce44SJohn Forte rc = 1; 84*fcf3ce44SJohn Forte } else if (nskernd_norun != 0) { 85*fcf3ce44SJohn Forte rc = 2; 86*fcf3ce44SJohn Forte } else { 87*fcf3ce44SJohn Forte (void) drv_getparm(UPROCP, (void *)&proc_nskernd); 88*fcf3ce44SJohn Forte nskernd_iscluster = iscluster; 89*fcf3ce44SJohn Forte } 90*fcf3ce44SJohn Forte 91*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 92*fcf3ce44SJohn Forte 93*fcf3ce44SJohn Forte return (rc); 94*fcf3ce44SJohn Forte } 95*fcf3ce44SJohn Forte 96*fcf3ce44SJohn Forte 97*fcf3ce44SJohn Forte /* 98*fcf3ce44SJohn Forte * must be called with nskernd_lock held. 99*fcf3ce44SJohn Forte */ 100*fcf3ce44SJohn Forte void 101*fcf3ce44SJohn Forte nskernd_cleanup(void) 102*fcf3ce44SJohn Forte { 103*fcf3ce44SJohn Forte proc_nskernd = NULL; 104*fcf3ce44SJohn Forte cv_broadcast(&nskernd_ask_cv); 105*fcf3ce44SJohn Forte cv_broadcast(&nskernd_k_cv); 106*fcf3ce44SJohn Forte } 107*fcf3ce44SJohn Forte 108*fcf3ce44SJohn Forte 109*fcf3ce44SJohn Forte void 110*fcf3ce44SJohn Forte nskernd_stop(void) 111*fcf3ce44SJohn Forte { 112*fcf3ce44SJohn Forte mutex_enter(&nskernd_lock); 113*fcf3ce44SJohn Forte 114*fcf3ce44SJohn Forte if (proc_nskernd == NULL) { 115*fcf3ce44SJohn Forte nskernd_norun = 1; 116*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 117*fcf3ce44SJohn Forte return; 118*fcf3ce44SJohn Forte } 119*fcf3ce44SJohn Forte 120*fcf3ce44SJohn Forte while (nskernd_u_wait == 0) { 121*fcf3ce44SJohn Forte nskernd_k_wait++; 122*fcf3ce44SJohn Forte cv_wait(&nskernd_k_cv, &nskernd_lock); 123*fcf3ce44SJohn Forte nskernd_k_wait--; 124*fcf3ce44SJohn Forte 125*fcf3ce44SJohn Forte if (proc_nskernd == NULL) { 126*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 127*fcf3ce44SJohn Forte return; 128*fcf3ce44SJohn Forte } 129*fcf3ce44SJohn Forte } 130*fcf3ce44SJohn Forte 131*fcf3ce44SJohn Forte nskernd_kdata.command = NSKERND_STOP; 132*fcf3ce44SJohn Forte nskernd_kdata.data1 = (uint64_t)1; /* kernel has done cleanup */ 133*fcf3ce44SJohn Forte 134*fcf3ce44SJohn Forte nskernd_cleanup(); 135*fcf3ce44SJohn Forte 136*fcf3ce44SJohn Forte cv_signal(&nskernd_u_cv); 137*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 138*fcf3ce44SJohn Forte } 139*fcf3ce44SJohn Forte 140*fcf3ce44SJohn Forte 141*fcf3ce44SJohn Forte int 142*fcf3ce44SJohn Forte nskernd_get(struct nskernd *nskp) 143*fcf3ce44SJohn Forte { 144*fcf3ce44SJohn Forte mutex_enter(&nskernd_lock); 145*fcf3ce44SJohn Forte 146*fcf3ce44SJohn Forte if (proc_nskernd == NULL) { 147*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 148*fcf3ce44SJohn Forte return (ENXIO); 149*fcf3ce44SJohn Forte } 150*fcf3ce44SJohn Forte 151*fcf3ce44SJohn Forte while (nskernd_u_wait == 0 || nskernd_ask) { 152*fcf3ce44SJohn Forte nskernd_k_wait++; 153*fcf3ce44SJohn Forte cv_wait(&nskernd_k_cv, &nskernd_lock); 154*fcf3ce44SJohn Forte nskernd_k_wait--; 155*fcf3ce44SJohn Forte 156*fcf3ce44SJohn Forte if (proc_nskernd == NULL) { 157*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 158*fcf3ce44SJohn Forte return (ENXIO); 159*fcf3ce44SJohn Forte } 160*fcf3ce44SJohn Forte } 161*fcf3ce44SJohn Forte 162*fcf3ce44SJohn Forte bcopy(nskp, &nskernd_kdata, sizeof (*nskp)); 163*fcf3ce44SJohn Forte nskernd_ask++; 164*fcf3ce44SJohn Forte 165*fcf3ce44SJohn Forte cv_signal(&nskernd_u_cv); 166*fcf3ce44SJohn Forte 167*fcf3ce44SJohn Forte cv_wait(&nskernd_ask_cv, &nskernd_lock); 168*fcf3ce44SJohn Forte 169*fcf3ce44SJohn Forte if (proc_nskernd == NULL) { 170*fcf3ce44SJohn Forte nskernd_ask--; 171*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 172*fcf3ce44SJohn Forte return (ENXIO); 173*fcf3ce44SJohn Forte } 174*fcf3ce44SJohn Forte 175*fcf3ce44SJohn Forte bcopy(&nskernd_kdata, nskp, sizeof (*nskp)); 176*fcf3ce44SJohn Forte nskernd_ask--; 177*fcf3ce44SJohn Forte 178*fcf3ce44SJohn Forte if (nskernd_k_wait > 0) 179*fcf3ce44SJohn Forte cv_signal(&nskernd_k_cv); 180*fcf3ce44SJohn Forte 181*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 182*fcf3ce44SJohn Forte return (0); 183*fcf3ce44SJohn Forte } 184*fcf3ce44SJohn Forte 185*fcf3ce44SJohn Forte 186*fcf3ce44SJohn Forte int 187*fcf3ce44SJohn Forte nskernd_command(intptr_t arg, int mode, int *rvalp) 188*fcf3ce44SJohn Forte { 189*fcf3ce44SJohn Forte struct nskernd *udata = NULL; 190*fcf3ce44SJohn Forte uint64_t arg1, arg2; 191*fcf3ce44SJohn Forte int rc; 192*fcf3ce44SJohn Forte 193*fcf3ce44SJohn Forte *rvalp = 0; 194*fcf3ce44SJohn Forte rc = 0; 195*fcf3ce44SJohn Forte 196*fcf3ce44SJohn Forte udata = kmem_alloc(sizeof (*udata), KM_SLEEP); 197*fcf3ce44SJohn Forte if (ddi_copyin((void *)arg, udata, sizeof (*udata), mode) < 0) { 198*fcf3ce44SJohn Forte kmem_free(udata, sizeof (*udata)); 199*fcf3ce44SJohn Forte return (EFAULT); 200*fcf3ce44SJohn Forte } 201*fcf3ce44SJohn Forte 202*fcf3ce44SJohn Forte switch (udata->command) { 203*fcf3ce44SJohn Forte case NSKERND_START: /* User program start */ 204*fcf3ce44SJohn Forte *rvalp = nskernd_start(udata->data1); 205*fcf3ce44SJohn Forte break; 206*fcf3ce44SJohn Forte 207*fcf3ce44SJohn Forte case NSKERND_STOP: /* User program requesting stop */ 208*fcf3ce44SJohn Forte mutex_enter(&nskernd_lock); 209*fcf3ce44SJohn Forte nskernd_cleanup(); 210*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 211*fcf3ce44SJohn Forte break; 212*fcf3ce44SJohn Forte 213*fcf3ce44SJohn Forte case NSKERND_WAIT: 214*fcf3ce44SJohn Forte mutex_enter(&nskernd_lock); 215*fcf3ce44SJohn Forte 216*fcf3ce44SJohn Forte bcopy(udata, &nskernd_kdata, sizeof (*udata)); 217*fcf3ce44SJohn Forte 218*fcf3ce44SJohn Forte if (nskernd_ask > 0) 219*fcf3ce44SJohn Forte cv_signal(&nskernd_ask_cv); 220*fcf3ce44SJohn Forte 221*fcf3ce44SJohn Forte nskernd_u_wait++; 222*fcf3ce44SJohn Forte 223*fcf3ce44SJohn Forte if (cv_wait_sig(&nskernd_u_cv, &nskernd_lock) != 0) { 224*fcf3ce44SJohn Forte /* 225*fcf3ce44SJohn Forte * woken by cv_signal() or cv_broadcast() 226*fcf3ce44SJohn Forte */ 227*fcf3ce44SJohn Forte bcopy(&nskernd_kdata, udata, sizeof (*udata)); 228*fcf3ce44SJohn Forte } else { 229*fcf3ce44SJohn Forte /* 230*fcf3ce44SJohn Forte * signal - the user process has blocked all 231*fcf3ce44SJohn Forte * signals except for SIGTERM and the 232*fcf3ce44SJohn Forte * uncatchables, so the process is about to die 233*fcf3ce44SJohn Forte * and we need to clean up. 234*fcf3ce44SJohn Forte */ 235*fcf3ce44SJohn Forte udata->command = NSKERND_STOP; 236*fcf3ce44SJohn Forte udata->data1 = (uint64_t)1; /* cleanup done */ 237*fcf3ce44SJohn Forte 238*fcf3ce44SJohn Forte nskernd_cleanup(); 239*fcf3ce44SJohn Forte } 240*fcf3ce44SJohn Forte 241*fcf3ce44SJohn Forte nskernd_u_wait--; 242*fcf3ce44SJohn Forte 243*fcf3ce44SJohn Forte mutex_exit(&nskernd_lock); 244*fcf3ce44SJohn Forte 245*fcf3ce44SJohn Forte if (ddi_copyout(udata, (void *)arg, 246*fcf3ce44SJohn Forte sizeof (*udata), mode) < 0) { 247*fcf3ce44SJohn Forte rc = EFAULT; 248*fcf3ce44SJohn Forte break; 249*fcf3ce44SJohn Forte } 250*fcf3ce44SJohn Forte 251*fcf3ce44SJohn Forte break; 252*fcf3ce44SJohn Forte 253*fcf3ce44SJohn Forte case NSKERND_NEWLWP: 254*fcf3ce44SJohn Forte /* save kmem by freeing the udata structure */ 255*fcf3ce44SJohn Forte arg1 = udata->data1; 256*fcf3ce44SJohn Forte kmem_free(udata, sizeof (*udata)); 257*fcf3ce44SJohn Forte udata = NULL; 258*fcf3ce44SJohn Forte nsc_runlwp(arg1); 259*fcf3ce44SJohn Forte break; 260*fcf3ce44SJohn Forte 261*fcf3ce44SJohn Forte case NSKERND_LOCK: 262*fcf3ce44SJohn Forte /* save kmem by freeing the udata structure */ 263*fcf3ce44SJohn Forte arg1 = udata->data1; 264*fcf3ce44SJohn Forte arg2 = udata->data2; 265*fcf3ce44SJohn Forte kmem_free(udata, sizeof (*udata)); 266*fcf3ce44SJohn Forte udata = NULL; 267*fcf3ce44SJohn Forte nsc_lockchild(arg1, arg2); 268*fcf3ce44SJohn Forte break; 269*fcf3ce44SJohn Forte 270*fcf3ce44SJohn Forte default: 271*fcf3ce44SJohn Forte cmn_err(CE_WARN, "nskernd: unknown command %d", udata->command); 272*fcf3ce44SJohn Forte rc = EINVAL; 273*fcf3ce44SJohn Forte break; 274*fcf3ce44SJohn Forte } 275*fcf3ce44SJohn Forte 276*fcf3ce44SJohn Forte if (udata != NULL) { 277*fcf3ce44SJohn Forte kmem_free(udata, sizeof (*udata)); 278*fcf3ce44SJohn Forte udata = NULL; 279*fcf3ce44SJohn Forte } 280*fcf3ce44SJohn Forte 281*fcf3ce44SJohn Forte return (rc); 282*fcf3ce44SJohn Forte } 283*fcf3ce44SJohn Forte 284*fcf3ce44SJohn Forte /* 285*fcf3ce44SJohn Forte * This function is included for SV ioctl processing only. 286*fcf3ce44SJohn Forte */ 287*fcf3ce44SJohn Forte 288*fcf3ce44SJohn Forte int 289*fcf3ce44SJohn Forte nskernd_isdaemon(void) 290*fcf3ce44SJohn Forte { 291*fcf3ce44SJohn Forte void *this_proc; 292*fcf3ce44SJohn Forte 293*fcf3ce44SJohn Forte if (proc_nskernd == NULL) 294*fcf3ce44SJohn Forte return (0); 295*fcf3ce44SJohn Forte if (drv_getparm(UPROCP, (void *)&this_proc) != 0) 296*fcf3ce44SJohn Forte return (0); 297*fcf3ce44SJohn Forte return (proc_nskernd == this_proc); 298*fcf3ce44SJohn Forte } 299