1*1ae08745Sheppo /* 2*1ae08745Sheppo * CDDL HEADER START 3*1ae08745Sheppo * 4*1ae08745Sheppo * The contents of this file are subject to the terms of the 5*1ae08745Sheppo * Common Development and Distribution License (the "License"). 6*1ae08745Sheppo * You may not use this file except in compliance with the License. 7*1ae08745Sheppo * 8*1ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 10*1ae08745Sheppo * See the License for the specific language governing permissions 11*1ae08745Sheppo * and limitations under the License. 12*1ae08745Sheppo * 13*1ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 14*1ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 16*1ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 17*1ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 18*1ae08745Sheppo * 19*1ae08745Sheppo * CDDL HEADER END 20*1ae08745Sheppo */ 21*1ae08745Sheppo /* 22*1ae08745Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*1ae08745Sheppo * Use is subject to license terms. 24*1ae08745Sheppo */ 25*1ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 26*1ae08745Sheppo 27*1ae08745Sheppo /* 28*1ae08745Sheppo * Configuration and setup interface to vcc driver. 29*1ae08745Sheppo * At intialization time, vntsd opens vcc ctrl port and read initial 30*1ae08745Sheppo * configuratioa. It manages console groups, creates the listen thread, 31*1ae08745Sheppo * dynamically adds and removes virtual console within a group. 32*1ae08745Sheppo */ 33*1ae08745Sheppo 34*1ae08745Sheppo 35*1ae08745Sheppo #include <syslog.h> 36*1ae08745Sheppo #include <stdio.h> 37*1ae08745Sheppo #include <sys/types.h> 38*1ae08745Sheppo #include <sys/ipc.h> 39*1ae08745Sheppo #include <stdlib.h> 40*1ae08745Sheppo #include <string.h> 41*1ae08745Sheppo #include <unistd.h> 42*1ae08745Sheppo #include <sys/socket.h> 43*1ae08745Sheppo #include <sys/ipc.h> 44*1ae08745Sheppo #include <sys/shm.h> 45*1ae08745Sheppo #include <sys/sem.h> 46*1ae08745Sheppo #include <wait.h> 47*1ae08745Sheppo #include <time.h> 48*1ae08745Sheppo #include <synch.h> 49*1ae08745Sheppo #include <netinet/in.h> 50*1ae08745Sheppo #include <thread.h> 51*1ae08745Sheppo #include <signal.h> 52*1ae08745Sheppo #include "vntsd.h" 53*1ae08745Sheppo 54*1ae08745Sheppo /* signal all clients that console has been deleted */ 55*1ae08745Sheppo boolean_t 56*1ae08745Sheppo vntsd_notify_client_cons_del(vntsd_client_t *clientp) 57*1ae08745Sheppo { 58*1ae08745Sheppo (void) mutex_lock(&clientp->lock); 59*1ae08745Sheppo clientp->status |= VNTSD_CLIENT_CONS_DELETED; 60*1ae08745Sheppo (void) thr_kill(clientp->cons_tid, SIGUSR1); 61*1ae08745Sheppo (void) mutex_unlock(&clientp->lock); 62*1ae08745Sheppo return (B_FALSE); 63*1ae08745Sheppo } 64*1ae08745Sheppo 65*1ae08745Sheppo /* free console structure */ 66*1ae08745Sheppo static void 67*1ae08745Sheppo free_cons(vntsd_cons_t *consp) 68*1ae08745Sheppo { 69*1ae08745Sheppo assert(consp); 70*1ae08745Sheppo (void) mutex_destroy(&consp->lock); 71*1ae08745Sheppo (void) cond_destroy(&consp->cvp); 72*1ae08745Sheppo free(consp); 73*1ae08745Sheppo } 74*1ae08745Sheppo 75*1ae08745Sheppo /* 76*1ae08745Sheppo * all clients connected to a console must disconnect before 77*1ae08745Sheppo * removing a console. 78*1ae08745Sheppo */ 79*1ae08745Sheppo static void 80*1ae08745Sheppo cleanup_cons(vntsd_cons_t *consp) 81*1ae08745Sheppo { 82*1ae08745Sheppo vntsd_group_t *groupp; 83*1ae08745Sheppo timestruc_t to; 84*1ae08745Sheppo 85*1ae08745Sheppo assert(consp); 86*1ae08745Sheppo D1(stderr, "t@%d vntsd_disconn_clients@%d\n", thr_self(), 87*1ae08745Sheppo consp->cons_no); 88*1ae08745Sheppo 89*1ae08745Sheppo groupp = consp->group; 90*1ae08745Sheppo assert(groupp); 91*1ae08745Sheppo 92*1ae08745Sheppo 93*1ae08745Sheppo (void) mutex_lock(&consp->lock); 94*1ae08745Sheppo 95*1ae08745Sheppo /* wait for all clients disconnect from the console */ 96*1ae08745Sheppo while (consp->clientpq != NULL) { 97*1ae08745Sheppo consp->status |= VNTSD_CONS_SIG_WAIT; 98*1ae08745Sheppo 99*1ae08745Sheppo /* signal client to disconnect the console */ 100*1ae08745Sheppo (void) vntsd_que_walk(consp->clientpq, 101*1ae08745Sheppo (el_func_t)vntsd_notify_client_cons_del); 102*1ae08745Sheppo 103*1ae08745Sheppo (void) thr_kill(consp->wr_tid, SIGUSR1); 104*1ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 105*1ae08745Sheppo to.tv_nsec = 0; 106*1ae08745Sheppo 107*1ae08745Sheppo /* wait for clients to disconnect */ 108*1ae08745Sheppo (void) cond_reltimedwait(&consp->cvp, &consp->lock, &to); 109*1ae08745Sheppo } 110*1ae08745Sheppo 111*1ae08745Sheppo (void) mutex_unlock(&consp->lock); 112*1ae08745Sheppo 113*1ae08745Sheppo free_cons(consp); 114*1ae08745Sheppo } 115*1ae08745Sheppo 116*1ae08745Sheppo /* search for a group whose console is being deleted */ 117*1ae08745Sheppo static boolean_t 118*1ae08745Sheppo find_clean_cons_group(vntsd_group_t *groupp) 119*1ae08745Sheppo { 120*1ae08745Sheppo if (groupp->status & VNTSD_GROUP_CLEAN_CONS) { 121*1ae08745Sheppo return (B_TRUE); 122*1ae08745Sheppo } else { 123*1ae08745Sheppo return (B_FALSE); 124*1ae08745Sheppo } 125*1ae08745Sheppo } 126*1ae08745Sheppo 127*1ae08745Sheppo /* search for a console that is being deleted */ 128*1ae08745Sheppo static boolean_t 129*1ae08745Sheppo find_clean_cons(vntsd_cons_t *consp) 130*1ae08745Sheppo { 131*1ae08745Sheppo if (consp->status & VNTSD_CONS_DELETED) { 132*1ae08745Sheppo return (B_TRUE); 133*1ae08745Sheppo } else { 134*1ae08745Sheppo return (B_FALSE); 135*1ae08745Sheppo } 136*1ae08745Sheppo } 137*1ae08745Sheppo 138*1ae08745Sheppo /* delete a console */ 139*1ae08745Sheppo void 140*1ae08745Sheppo vntsd_delete_cons(vntsd_t *vntsdp) 141*1ae08745Sheppo { 142*1ae08745Sheppo vntsd_group_t *groupp; 143*1ae08745Sheppo vntsd_cons_t *consp; 144*1ae08745Sheppo 145*1ae08745Sheppo for (; ; ) { 146*1ae08745Sheppo /* get the group contains deleted console */ 147*1ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 148*1ae08745Sheppo groupp = vntsd_que_walk(vntsdp->grouppq, 149*1ae08745Sheppo (el_func_t)find_clean_cons_group); 150*1ae08745Sheppo if (groupp == NULL) { 151*1ae08745Sheppo /* no more group has console deleted */ 152*1ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 153*1ae08745Sheppo return; 154*1ae08745Sheppo } 155*1ae08745Sheppo groupp->status &= ~VNTSD_GROUP_CLEAN_CONS; 156*1ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 157*1ae08745Sheppo 158*1ae08745Sheppo for (; ; ) { 159*1ae08745Sheppo /* get the console to be deleted */ 160*1ae08745Sheppo (void) mutex_lock(&groupp->lock); 161*1ae08745Sheppo assert(groupp->conspq); 162*1ae08745Sheppo consp = vntsd_que_walk(groupp->conspq, 163*1ae08745Sheppo (el_func_t)find_clean_cons); 164*1ae08745Sheppo if (consp == NULL) { 165*1ae08745Sheppo /* no more cons to delete */ 166*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 167*1ae08745Sheppo break; 168*1ae08745Sheppo } 169*1ae08745Sheppo 170*1ae08745Sheppo /* remove console from the group */ 171*1ae08745Sheppo (void) vntsd_que_rm(&groupp->conspq, consp); 172*1ae08745Sheppo groupp->num_cons--; 173*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 174*1ae08745Sheppo 175*1ae08745Sheppo /* clean up the console */ 176*1ae08745Sheppo cleanup_cons(consp); 177*1ae08745Sheppo 178*1ae08745Sheppo /* delete group? */ 179*1ae08745Sheppo if (groupp->num_cons == 0) { 180*1ae08745Sheppo /* no more console delete it */ 181*1ae08745Sheppo assert(groupp->vntsd); 182*1ae08745Sheppo 183*1ae08745Sheppo (void) mutex_lock(&groupp->vntsd->lock); 184*1ae08745Sheppo (void) vntsd_que_rm(&groupp->vntsd->grouppq, 185*1ae08745Sheppo groupp); 186*1ae08745Sheppo (void) mutex_unlock(&groupp->vntsd->lock); 187*1ae08745Sheppo 188*1ae08745Sheppo /* clean up the group */ 189*1ae08745Sheppo vntsd_clean_group(groupp); 190*1ae08745Sheppo break; 191*1ae08745Sheppo } 192*1ae08745Sheppo } 193*1ae08745Sheppo } 194*1ae08745Sheppo } 195*1ae08745Sheppo 196*1ae08745Sheppo /* clean up a group */ 197*1ae08745Sheppo void 198*1ae08745Sheppo vntsd_clean_group(vntsd_group_t *groupp) 199*1ae08745Sheppo { 200*1ae08745Sheppo 201*1ae08745Sheppo timestruc_t to; 202*1ae08745Sheppo 203*1ae08745Sheppo D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(), 204*1ae08745Sheppo groupp->group_name, groupp->tcp_port); 205*1ae08745Sheppo 206*1ae08745Sheppo (void) mutex_lock(&groupp->lock); 207*1ae08745Sheppo 208*1ae08745Sheppo /* prevent from reentry */ 209*1ae08745Sheppo if (groupp->status & VNTSD_GROUP_CLEANUP) { 210*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 211*1ae08745Sheppo return; 212*1ae08745Sheppo } 213*1ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEANUP; 214*1ae08745Sheppo vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons); 215*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 216*1ae08745Sheppo 217*1ae08745Sheppo /* walk through no cons client queue */ 218*1ae08745Sheppo while (groupp->no_cons_clientpq != NULL) { 219*1ae08745Sheppo groupp->status |= VNTSD_GROUP_SIG_WAIT; 220*1ae08745Sheppo (void) vntsd_que_walk(groupp->no_cons_clientpq, 221*1ae08745Sheppo (el_func_t)vntsd_notify_client_cons_del); 222*1ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 223*1ae08745Sheppo to.tv_nsec = 0; 224*1ae08745Sheppo (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); 225*1ae08745Sheppo } 226*1ae08745Sheppo 227*1ae08745Sheppo if (groupp->listen_tid == thr_self()) { 228*1ae08745Sheppo /* listen thread is exiting */ 229*1ae08745Sheppo (void) mutex_lock(&(groupp->vntsd->lock)); 230*1ae08745Sheppo (void) vntsd_que_rm(&groupp->vntsd->grouppq, groupp); 231*1ae08745Sheppo (void) mutex_unlock(&groupp->vntsd->lock); 232*1ae08745Sheppo 233*1ae08745Sheppo (void) cond_destroy(&groupp->cvp); 234*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 235*1ae08745Sheppo (void) mutex_destroy(&groupp->lock); 236*1ae08745Sheppo free(groupp); 237*1ae08745Sheppo return; 238*1ae08745Sheppo } 239*1ae08745Sheppo 240*1ae08745Sheppo /* signal listen thread to exit */ 241*1ae08745Sheppo groupp->status |= VNTSD_GROUP_SIG_WAIT; 242*1ae08745Sheppo 243*1ae08745Sheppo while (groupp->status & VNTSD_GROUP_SIG_WAIT) { 244*1ae08745Sheppo (void) thr_kill(groupp->listen_tid, SIGUSR1); 245*1ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 246*1ae08745Sheppo to.tv_nsec = 0; 247*1ae08745Sheppo /* wait listen thread to exit */ 248*1ae08745Sheppo (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); 249*1ae08745Sheppo } 250*1ae08745Sheppo 251*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 252*1ae08745Sheppo (void) thr_join(groupp->listen_tid, NULL, NULL); 253*1ae08745Sheppo /* free group */ 254*1ae08745Sheppo (void) cond_destroy(&groupp->cvp); 255*1ae08745Sheppo (void) mutex_destroy(&groupp->lock); 256*1ae08745Sheppo free(groupp); 257*1ae08745Sheppo } 258*1ae08745Sheppo 259*1ae08745Sheppo /* allocate and initialize console structure */ 260*1ae08745Sheppo static vntsd_cons_t * 261*1ae08745Sheppo alloc_cons(vntsd_group_t *groupp, vcc_console_t *consolep) 262*1ae08745Sheppo { 263*1ae08745Sheppo vntsd_cons_t *consp; 264*1ae08745Sheppo int rv; 265*1ae08745Sheppo 266*1ae08745Sheppo /* allocate console */ 267*1ae08745Sheppo consp = (vntsd_cons_t *)malloc(sizeof (vntsd_cons_t)); 268*1ae08745Sheppo if (consp == NULL) { 269*1ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "alloc_cons"); 270*1ae08745Sheppo return (NULL); 271*1ae08745Sheppo } 272*1ae08745Sheppo 273*1ae08745Sheppo /* intialize console */ 274*1ae08745Sheppo bzero(consp, sizeof (vntsd_cons_t)); 275*1ae08745Sheppo 276*1ae08745Sheppo (void) mutex_init(&consp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 277*1ae08745Sheppo (void) cond_init(&consp->cvp, USYNC_THREAD, NULL); 278*1ae08745Sheppo 279*1ae08745Sheppo consp->cons_no = consolep->cons_no; 280*1ae08745Sheppo (void) strlcpy(consp->domain_name, consolep->domain_name, MAXPATHLEN); 281*1ae08745Sheppo (void) strlcpy(consp->dev_name, consolep->dev_name, MAXPATHLEN); 282*1ae08745Sheppo consp->wr_tid = (thread_t)-1; 283*1ae08745Sheppo consp->vcc_fd = (thread_t)-1; 284*1ae08745Sheppo 285*1ae08745Sheppo /* join the group */ 286*1ae08745Sheppo (void) mutex_lock(&groupp->lock); 287*1ae08745Sheppo 288*1ae08745Sheppo if ((rv = vntsd_que_append(&groupp->conspq, consp)) != 289*1ae08745Sheppo VNTSD_SUCCESS) { 290*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 291*1ae08745Sheppo vntsd_log(rv, "alloc_cons"); 292*1ae08745Sheppo free_cons(consp); 293*1ae08745Sheppo return (NULL); 294*1ae08745Sheppo } 295*1ae08745Sheppo groupp->num_cons++; 296*1ae08745Sheppo consp->group = groupp; 297*1ae08745Sheppo 298*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 299*1ae08745Sheppo 300*1ae08745Sheppo D1(stderr, "t@%d alloc_cons@%d %s %s\n", thr_self(), 301*1ae08745Sheppo consp->cons_no, consp->domain_name, consp->dev_name); 302*1ae08745Sheppo 303*1ae08745Sheppo return (consp); 304*1ae08745Sheppo } 305*1ae08745Sheppo 306*1ae08745Sheppo /* compare tcp with group->tcp */ 307*1ae08745Sheppo static boolean_t 308*1ae08745Sheppo grp_by_tcp(vntsd_group_t *groupp, uint64_t *tcp_port) 309*1ae08745Sheppo { 310*1ae08745Sheppo assert(groupp); 311*1ae08745Sheppo assert(tcp_port); 312*1ae08745Sheppo return (groupp->tcp_port == *tcp_port); 313*1ae08745Sheppo } 314*1ae08745Sheppo 315*1ae08745Sheppo /* allocate and initialize group */ 316*1ae08745Sheppo static vntsd_group_t * 317*1ae08745Sheppo alloc_group(vntsd_t *vntsdp, char *group_name, uint64_t tcp_port) 318*1ae08745Sheppo { 319*1ae08745Sheppo vntsd_group_t *groupp; 320*1ae08745Sheppo 321*1ae08745Sheppo /* allocate group */ 322*1ae08745Sheppo groupp = (vntsd_group_t *)malloc(sizeof (vntsd_group_t)); 323*1ae08745Sheppo if (groupp == NULL) { 324*1ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "alloc_group"); 325*1ae08745Sheppo return (NULL); 326*1ae08745Sheppo } 327*1ae08745Sheppo 328*1ae08745Sheppo /* initialize group */ 329*1ae08745Sheppo bzero(groupp, sizeof (vntsd_group_t)); 330*1ae08745Sheppo 331*1ae08745Sheppo (void) mutex_init(&groupp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 332*1ae08745Sheppo (void) cond_init(&groupp->cvp, USYNC_THREAD, NULL); 333*1ae08745Sheppo 334*1ae08745Sheppo if (group_name != NULL) { 335*1ae08745Sheppo (void) memcpy(groupp->group_name, group_name, MAXPATHLEN); 336*1ae08745Sheppo } 337*1ae08745Sheppo 338*1ae08745Sheppo groupp->tcp_port = tcp_port; 339*1ae08745Sheppo groupp->listen_tid = (thread_t)-1; 340*1ae08745Sheppo groupp->sockfd = (thread_t)-1; 341*1ae08745Sheppo groupp->vntsd = vntsdp; 342*1ae08745Sheppo 343*1ae08745Sheppo D1(stderr, "t@%d alloc_group@%lld:%s\n", thr_self(), groupp->tcp_port, 344*1ae08745Sheppo groupp->group_name); 345*1ae08745Sheppo 346*1ae08745Sheppo return (groupp); 347*1ae08745Sheppo } 348*1ae08745Sheppo 349*1ae08745Sheppo /* 350*1ae08745Sheppo * Initialize a console, if console is associated with with a 351*1ae08745Sheppo * new group, intialize the group. 352*1ae08745Sheppo */ 353*1ae08745Sheppo static int 354*1ae08745Sheppo alloc_cons_with_group(vntsd_t *vntsdp, vcc_console_t *consp, 355*1ae08745Sheppo vntsd_group_t **new_groupp) 356*1ae08745Sheppo { 357*1ae08745Sheppo vntsd_group_t *groupp = NULL; 358*1ae08745Sheppo int rv; 359*1ae08745Sheppo 360*1ae08745Sheppo *new_groupp = NULL; 361*1ae08745Sheppo 362*1ae08745Sheppo /* match group by tcp port */ 363*1ae08745Sheppo 364*1ae08745Sheppo 365*1ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 366*1ae08745Sheppo groupp = vntsd_que_find(vntsdp->grouppq, 367*1ae08745Sheppo (compare_func_t)grp_by_tcp, (void *)&(consp->tcp_port)); 368*1ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 369*1ae08745Sheppo 370*1ae08745Sheppo if (groupp != NULL) { 371*1ae08745Sheppo /* group with same tcp port found */ 372*1ae08745Sheppo 373*1ae08745Sheppo if (strcmp(groupp->group_name, consp->group_name)) { 374*1ae08745Sheppo /* conflict group name */ 375*1ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_GRP_NAME, 376*1ae08745Sheppo "group name is different from existing group"); 377*1ae08745Sheppo return (VNTSD_ERR_VCC_CTRL_DATA); 378*1ae08745Sheppo } 379*1ae08745Sheppo 380*1ae08745Sheppo } else { 381*1ae08745Sheppo /* new group */ 382*1ae08745Sheppo groupp = alloc_group(vntsdp, consp->group_name, 383*1ae08745Sheppo consp->tcp_port); 384*1ae08745Sheppo if (groupp == NULL) { 385*1ae08745Sheppo return (VNTSD_ERR_NO_MEM); 386*1ae08745Sheppo } 387*1ae08745Sheppo 388*1ae08745Sheppo assert(groupp->conspq == NULL); 389*1ae08745Sheppo /* queue group to vntsdp */ 390*1ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 391*1ae08745Sheppo rv = vntsd_que_append(&vntsdp->grouppq, groupp); 392*1ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 393*1ae08745Sheppo 394*1ae08745Sheppo if (rv != VNTSD_SUCCESS) { 395*1ae08745Sheppo return (rv); 396*1ae08745Sheppo } 397*1ae08745Sheppo 398*1ae08745Sheppo *new_groupp = groupp; 399*1ae08745Sheppo } 400*1ae08745Sheppo 401*1ae08745Sheppo /* intialize console */ 402*1ae08745Sheppo if (alloc_cons(groupp, consp) == NULL) { 403*1ae08745Sheppo /* no memory */ 404*1ae08745Sheppo if (new_groupp != NULL) { 405*1ae08745Sheppo /* clean up new group */ 406*1ae08745Sheppo (void) cond_destroy(&groupp->cvp); 407*1ae08745Sheppo (void) mutex_destroy(&groupp->lock); 408*1ae08745Sheppo free(groupp); 409*1ae08745Sheppo } 410*1ae08745Sheppo 411*1ae08745Sheppo return (VNTSD_ERR_NO_MEM); 412*1ae08745Sheppo } 413*1ae08745Sheppo 414*1ae08745Sheppo return (VNTSD_SUCCESS); 415*1ae08745Sheppo 416*1ae08745Sheppo } 417*1ae08745Sheppo 418*1ae08745Sheppo 419*1ae08745Sheppo /* create listen thread */ 420*1ae08745Sheppo static boolean_t 421*1ae08745Sheppo create_listen_thread(vntsd_group_t *groupp) 422*1ae08745Sheppo { 423*1ae08745Sheppo 424*1ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 425*1ae08745Sheppo int rv; 426*1ae08745Sheppo 427*1ae08745Sheppo assert(groupp); 428*1ae08745Sheppo 429*1ae08745Sheppo (void) mutex_lock(&groupp->lock); 430*1ae08745Sheppo assert(groupp->num_cons); 431*1ae08745Sheppo 432*1ae08745Sheppo D1(stderr, "t@%d create_listen:%lld\n", thr_self(), groupp->tcp_port); 433*1ae08745Sheppo 434*1ae08745Sheppo if ((rv = thr_create(NULL, 0, (thr_func_t)vntsd_listen_thread, 435*1ae08745Sheppo (void *)groupp, THR_DETACHED, &groupp->listen_tid)) 436*1ae08745Sheppo != 0) { 437*1ae08745Sheppo (void) (void) snprintf(err_msg, sizeof (err_msg), 438*1ae08745Sheppo "Can not create listen thread for" 439*1ae08745Sheppo "group %s tcp %llx\n", groupp->group_name, 440*1ae08745Sheppo groupp->tcp_port); 441*1ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); 442*1ae08745Sheppo 443*1ae08745Sheppo /* clean up group queue */ 444*1ae08745Sheppo vntsd_free_que(&groupp->conspq, (clean_func_t)free_cons); 445*1ae08745Sheppo groupp->listen_tid = (thread_t)-1; 446*1ae08745Sheppo } 447*1ae08745Sheppo 448*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 449*1ae08745Sheppo 450*1ae08745Sheppo return (rv != 0); 451*1ae08745Sheppo } 452*1ae08745Sheppo 453*1ae08745Sheppo /* delete a console if the console exists in the vntsd */ 454*1ae08745Sheppo static void 455*1ae08745Sheppo delete_cons_before_add(vntsd_t *vntsdp, uint64_t tcp_port, uint_t cons_no) 456*1ae08745Sheppo { 457*1ae08745Sheppo vntsd_group_t *groupp; 458*1ae08745Sheppo vntsd_cons_t *consp; 459*1ae08745Sheppo 460*1ae08745Sheppo /* group exists? */ 461*1ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 462*1ae08745Sheppo groupp = vntsd_que_find(vntsdp->grouppq, (compare_func_t)grp_by_tcp, 463*1ae08745Sheppo (void *)&(tcp_port)); 464*1ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 465*1ae08745Sheppo 466*1ae08745Sheppo if (groupp == NULL) { 467*1ae08745Sheppo /* no such group */ 468*1ae08745Sheppo return; 469*1ae08745Sheppo } 470*1ae08745Sheppo 471*1ae08745Sheppo /* group exists, if console exists? */ 472*1ae08745Sheppo (void) mutex_lock(&groupp->lock); 473*1ae08745Sheppo consp = vntsd_que_find(groupp->conspq, 474*1ae08745Sheppo (compare_func_t)vntsd_cons_by_consno, &cons_no); 475*1ae08745Sheppo 476*1ae08745Sheppo if (consp == NULL) { 477*1ae08745Sheppo /* no such console */ 478*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 479*1ae08745Sheppo return; 480*1ae08745Sheppo } 481*1ae08745Sheppo /* console exists - delete console */ 482*1ae08745Sheppo 483*1ae08745Sheppo (void) mutex_lock(&consp->lock); 484*1ae08745Sheppo 485*1ae08745Sheppo consp->status |= VNTSD_CONS_DELETED; 486*1ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEAN_CONS; 487*1ae08745Sheppo 488*1ae08745Sheppo (void) mutex_unlock(&consp->lock); 489*1ae08745Sheppo 490*1ae08745Sheppo (void) mutex_unlock(&groupp->lock); 491*1ae08745Sheppo 492*1ae08745Sheppo vntsd_delete_cons(vntsdp); 493*1ae08745Sheppo } 494*1ae08745Sheppo 495*1ae08745Sheppo /* add a console */ 496*1ae08745Sheppo static void 497*1ae08745Sheppo do_add_cons(vntsd_t *vntsdp, int cons_no) 498*1ae08745Sheppo { 499*1ae08745Sheppo vcc_console_t console; 500*1ae08745Sheppo vntsd_group_t *groupp; 501*1ae08745Sheppo int rv; 502*1ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 503*1ae08745Sheppo 504*1ae08745Sheppo 505*1ae08745Sheppo (void) snprintf(err_msg, sizeof (err_msg), 506*1ae08745Sheppo "do_add_cons():Can not add console=%d", cons_no); 507*1ae08745Sheppo 508*1ae08745Sheppo /* get console configuration from vcc */ 509*1ae08745Sheppo 510*1ae08745Sheppo if ((rv = vntsd_vcc_ioctl(VCC_CONS_INFO, cons_no, (void *)&console)) 511*1ae08745Sheppo != VNTSD_SUCCESS) { 512*1ae08745Sheppo vntsd_log(rv, err_msg); 513*1ae08745Sheppo return; 514*1ae08745Sheppo } 515*1ae08745Sheppo 516*1ae08745Sheppo /* clean up the console if console was deleted and added again */ 517*1ae08745Sheppo delete_cons_before_add(vntsdp, console.tcp_port, console.cons_no); 518*1ae08745Sheppo 519*1ae08745Sheppo /* initialize console */ 520*1ae08745Sheppo 521*1ae08745Sheppo if ((rv = alloc_cons_with_group(vntsdp, &console, &groupp)) != 522*1ae08745Sheppo VNTSD_SUCCESS) { 523*1ae08745Sheppo /* no memory to add this new console */ 524*1ae08745Sheppo vntsd_log(rv, err_msg); 525*1ae08745Sheppo return; 526*1ae08745Sheppo } 527*1ae08745Sheppo 528*1ae08745Sheppo if (groupp != NULL) { 529*1ae08745Sheppo /* new group */ 530*1ae08745Sheppo /* create listen thread for this console */ 531*1ae08745Sheppo if (create_listen_thread(groupp)) { 532*1ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); 533*1ae08745Sheppo (void) cond_destroy(&groupp->cvp); 534*1ae08745Sheppo (void) mutex_destroy(&groupp->lock); 535*1ae08745Sheppo free(groupp); 536*1ae08745Sheppo } 537*1ae08745Sheppo 538*1ae08745Sheppo } 539*1ae08745Sheppo } 540*1ae08745Sheppo 541*1ae08745Sheppo /* daemon wake up */ 542*1ae08745Sheppo void 543*1ae08745Sheppo vntsd_daemon_wakeup(vntsd_t *vntsdp) 544*1ae08745Sheppo { 545*1ae08745Sheppo 546*1ae08745Sheppo vcc_response_t inq_data; 547*1ae08745Sheppo 548*1ae08745Sheppo /* reason to wake up */ 549*1ae08745Sheppo if (vntsd_vcc_ioctl(VCC_INQUIRY, 0, (void *)&inq_data) != 550*1ae08745Sheppo VNTSD_SUCCESS) { 551*1ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, "vntsd_daemon_wakeup()"); 552*1ae08745Sheppo return; 553*1ae08745Sheppo } 554*1ae08745Sheppo 555*1ae08745Sheppo D1(stderr, "t@%d vntsd_daemon_wakup:msg %d port %x\n", thr_self(), 556*1ae08745Sheppo inq_data.reason, inq_data.cons_no); 557*1ae08745Sheppo 558*1ae08745Sheppo switch (inq_data.reason) { 559*1ae08745Sheppo 560*1ae08745Sheppo case VCC_CONS_ADDED: 561*1ae08745Sheppo do_add_cons(vntsdp, inq_data.cons_no); 562*1ae08745Sheppo break; 563*1ae08745Sheppo 564*1ae08745Sheppo default: 565*1ae08745Sheppo DERR(stderr, "t@%d daemon_wakeup:ioctl_unknown %d\n", 566*1ae08745Sheppo thr_self(), inq_data.reason); 567*1ae08745Sheppo vntsd_log(VNTSD_ERR_UNKNOWN_CMD, "from vcc\n"); 568*1ae08745Sheppo break; 569*1ae08745Sheppo } 570*1ae08745Sheppo } 571*1ae08745Sheppo 572*1ae08745Sheppo /* initial console configuration */ 573*1ae08745Sheppo void 574*1ae08745Sheppo vntsd_get_config(vntsd_t *vntsdp) 575*1ae08745Sheppo { 576*1ae08745Sheppo 577*1ae08745Sheppo int i; 578*1ae08745Sheppo int num_cons; 579*1ae08745Sheppo vcc_console_t *consp; 580*1ae08745Sheppo vntsd_group_t *groupp; 581*1ae08745Sheppo 582*1ae08745Sheppo /* num of consoles */ 583*1ae08745Sheppo num_cons = 0; 584*1ae08745Sheppo 585*1ae08745Sheppo if (vntsd_vcc_ioctl(VCC_NUM_CONSOLE, 0, (void *)&num_cons) != 586*1ae08745Sheppo VNTSD_SUCCESS) { 587*1ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, "VCC_NUM_CONSOLE failed\n"); 588*1ae08745Sheppo return; 589*1ae08745Sheppo } 590*1ae08745Sheppo 591*1ae08745Sheppo D3(stderr, "get_config:num_cons=%d", num_cons); 592*1ae08745Sheppo 593*1ae08745Sheppo if (num_cons == 0) { 594*1ae08745Sheppo return; 595*1ae08745Sheppo } 596*1ae08745Sheppo 597*1ae08745Sheppo /* allocate memory for all consoles */ 598*1ae08745Sheppo consp = malloc(num_cons*sizeof (vcc_console_t)); 599*1ae08745Sheppo 600*1ae08745Sheppo if (consp == NULL) { 601*1ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "for console table."); 602*1ae08745Sheppo return; 603*1ae08745Sheppo } 604*1ae08745Sheppo 605*1ae08745Sheppo /* get console table */ 606*1ae08745Sheppo if (vntsd_vcc_ioctl(VCC_CONS_TBL, 0, (void *)consp) != VNTSD_SUCCESS) { 607*1ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, " VCC_CONS_TBL " 608*1ae08745Sheppo "for console table\n"); 609*1ae08745Sheppo return; 610*1ae08745Sheppo } 611*1ae08745Sheppo 612*1ae08745Sheppo /* intialize groups and consoles */ 613*1ae08745Sheppo for (i = 0; i < num_cons; i++) { 614*1ae08745Sheppo if (alloc_cons_with_group(vntsdp, &consp[i], &groupp) 615*1ae08745Sheppo != VNTSD_SUCCESS) { 616*1ae08745Sheppo vntsd_log(VNTSD_ERR_ADD_CONS_FAILED, "get_config"); 617*1ae08745Sheppo } 618*1ae08745Sheppo } 619*1ae08745Sheppo 620*1ae08745Sheppo /* create listen thread for each group */ 621*1ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 622*1ae08745Sheppo 623*1ae08745Sheppo for (; ; ) { 624*1ae08745Sheppo groupp = vntsd_que_walk(vntsdp->grouppq, 625*1ae08745Sheppo (el_func_t)create_listen_thread); 626*1ae08745Sheppo if (groupp == NULL) { 627*1ae08745Sheppo break; 628*1ae08745Sheppo } 629*1ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, "get config()"); 630*1ae08745Sheppo } 631*1ae08745Sheppo 632*1ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 633*1ae08745Sheppo } 634