11ae08745Sheppo /* 21ae08745Sheppo * CDDL HEADER START 31ae08745Sheppo * 41ae08745Sheppo * The contents of this file are subject to the terms of the 51ae08745Sheppo * Common Development and Distribution License (the "License"). 61ae08745Sheppo * You may not use this file except in compliance with the License. 71ae08745Sheppo * 81ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 101ae08745Sheppo * See the License for the specific language governing permissions 111ae08745Sheppo * and limitations under the License. 121ae08745Sheppo * 131ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 161ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181ae08745Sheppo * 191ae08745Sheppo * CDDL HEADER END 201ae08745Sheppo */ 211ae08745Sheppo /* 221ae08745Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 231ae08745Sheppo * Use is subject to license terms. 241ae08745Sheppo */ 251ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 261ae08745Sheppo 271ae08745Sheppo /* 281ae08745Sheppo * Configuration and setup interface to vcc driver. 291ae08745Sheppo * At intialization time, vntsd opens vcc ctrl port and read initial 301ae08745Sheppo * configuratioa. It manages console groups, creates the listen thread, 311ae08745Sheppo * dynamically adds and removes virtual console within a group. 321ae08745Sheppo */ 331ae08745Sheppo 341ae08745Sheppo 351ae08745Sheppo #include <syslog.h> 361ae08745Sheppo #include <stdio.h> 371ae08745Sheppo #include <sys/types.h> 381ae08745Sheppo #include <sys/ipc.h> 391ae08745Sheppo #include <stdlib.h> 401ae08745Sheppo #include <string.h> 411ae08745Sheppo #include <unistd.h> 421ae08745Sheppo #include <sys/socket.h> 431ae08745Sheppo #include <sys/ipc.h> 441ae08745Sheppo #include <sys/shm.h> 451ae08745Sheppo #include <sys/sem.h> 461ae08745Sheppo #include <wait.h> 471ae08745Sheppo #include <time.h> 481ae08745Sheppo #include <synch.h> 491ae08745Sheppo #include <netinet/in.h> 501ae08745Sheppo #include <thread.h> 511ae08745Sheppo #include <signal.h> 521ae08745Sheppo #include "vntsd.h" 531ae08745Sheppo 541ae08745Sheppo /* signal all clients that console has been deleted */ 551ae08745Sheppo boolean_t 561ae08745Sheppo vntsd_notify_client_cons_del(vntsd_client_t *clientp) 571ae08745Sheppo { 581ae08745Sheppo (void) mutex_lock(&clientp->lock); 591ae08745Sheppo clientp->status |= VNTSD_CLIENT_CONS_DELETED; 601ae08745Sheppo (void) thr_kill(clientp->cons_tid, SIGUSR1); 611ae08745Sheppo (void) mutex_unlock(&clientp->lock); 621ae08745Sheppo return (B_FALSE); 631ae08745Sheppo } 641ae08745Sheppo 651ae08745Sheppo /* free console structure */ 661ae08745Sheppo static void 671ae08745Sheppo free_cons(vntsd_cons_t *consp) 681ae08745Sheppo { 691ae08745Sheppo assert(consp); 701ae08745Sheppo (void) mutex_destroy(&consp->lock); 711ae08745Sheppo (void) cond_destroy(&consp->cvp); 721ae08745Sheppo free(consp); 731ae08745Sheppo } 741ae08745Sheppo 751ae08745Sheppo /* 761ae08745Sheppo * all clients connected to a console must disconnect before 771ae08745Sheppo * removing a console. 781ae08745Sheppo */ 791ae08745Sheppo static void 801ae08745Sheppo cleanup_cons(vntsd_cons_t *consp) 811ae08745Sheppo { 821ae08745Sheppo vntsd_group_t *groupp; 831ae08745Sheppo timestruc_t to; 841ae08745Sheppo 851ae08745Sheppo assert(consp); 861ae08745Sheppo D1(stderr, "t@%d vntsd_disconn_clients@%d\n", thr_self(), 871ae08745Sheppo consp->cons_no); 881ae08745Sheppo 891ae08745Sheppo groupp = consp->group; 901ae08745Sheppo assert(groupp); 911ae08745Sheppo 921ae08745Sheppo 931ae08745Sheppo (void) mutex_lock(&consp->lock); 941ae08745Sheppo 951ae08745Sheppo /* wait for all clients disconnect from the console */ 961ae08745Sheppo while (consp->clientpq != NULL) { 971ae08745Sheppo consp->status |= VNTSD_CONS_SIG_WAIT; 981ae08745Sheppo 991ae08745Sheppo /* signal client to disconnect the console */ 1001ae08745Sheppo (void) vntsd_que_walk(consp->clientpq, 1011ae08745Sheppo (el_func_t)vntsd_notify_client_cons_del); 1021ae08745Sheppo 1031ae08745Sheppo (void) thr_kill(consp->wr_tid, SIGUSR1); 1041ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 1051ae08745Sheppo to.tv_nsec = 0; 1061ae08745Sheppo 1071ae08745Sheppo /* wait for clients to disconnect */ 1081ae08745Sheppo (void) cond_reltimedwait(&consp->cvp, &consp->lock, &to); 1091ae08745Sheppo } 1101ae08745Sheppo 1111ae08745Sheppo (void) mutex_unlock(&consp->lock); 1121ae08745Sheppo 1131ae08745Sheppo free_cons(consp); 1141ae08745Sheppo } 1151ae08745Sheppo 1161ae08745Sheppo /* search for a group whose console is being deleted */ 1171ae08745Sheppo static boolean_t 1181ae08745Sheppo find_clean_cons_group(vntsd_group_t *groupp) 1191ae08745Sheppo { 1201ae08745Sheppo if (groupp->status & VNTSD_GROUP_CLEAN_CONS) { 1211ae08745Sheppo return (B_TRUE); 1221ae08745Sheppo } else { 1231ae08745Sheppo return (B_FALSE); 1241ae08745Sheppo } 1251ae08745Sheppo } 1261ae08745Sheppo 1271ae08745Sheppo /* search for a console that is being deleted */ 1281ae08745Sheppo static boolean_t 1291ae08745Sheppo find_clean_cons(vntsd_cons_t *consp) 1301ae08745Sheppo { 1311ae08745Sheppo if (consp->status & VNTSD_CONS_DELETED) { 1321ae08745Sheppo return (B_TRUE); 1331ae08745Sheppo } else { 1341ae08745Sheppo return (B_FALSE); 1351ae08745Sheppo } 1361ae08745Sheppo } 1371ae08745Sheppo 1381ae08745Sheppo /* delete a console */ 1391ae08745Sheppo void 1401ae08745Sheppo vntsd_delete_cons(vntsd_t *vntsdp) 1411ae08745Sheppo { 1421ae08745Sheppo vntsd_group_t *groupp; 1431ae08745Sheppo vntsd_cons_t *consp; 1441ae08745Sheppo 1451ae08745Sheppo for (; ; ) { 1461ae08745Sheppo /* get the group contains deleted console */ 1471ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 1481ae08745Sheppo groupp = vntsd_que_walk(vntsdp->grouppq, 1491ae08745Sheppo (el_func_t)find_clean_cons_group); 1501ae08745Sheppo if (groupp == NULL) { 1511ae08745Sheppo /* no more group has console deleted */ 1521ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 1531ae08745Sheppo return; 1541ae08745Sheppo } 155*7636cb21Slm (void) mutex_lock(&groupp->lock); 1561ae08745Sheppo groupp->status &= ~VNTSD_GROUP_CLEAN_CONS; 157*7636cb21Slm (void) mutex_unlock(&groupp->lock); 1581ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 1591ae08745Sheppo 1601ae08745Sheppo for (; ; ) { 1611ae08745Sheppo /* get the console to be deleted */ 1621ae08745Sheppo (void) mutex_lock(&groupp->lock); 1631ae08745Sheppo assert(groupp->conspq); 1641ae08745Sheppo consp = vntsd_que_walk(groupp->conspq, 1651ae08745Sheppo (el_func_t)find_clean_cons); 1661ae08745Sheppo if (consp == NULL) { 1671ae08745Sheppo /* no more cons to delete */ 1681ae08745Sheppo (void) mutex_unlock(&groupp->lock); 1691ae08745Sheppo break; 1701ae08745Sheppo } 1711ae08745Sheppo 1721ae08745Sheppo /* remove console from the group */ 1731ae08745Sheppo (void) vntsd_que_rm(&groupp->conspq, consp); 1741ae08745Sheppo groupp->num_cons--; 1751ae08745Sheppo (void) mutex_unlock(&groupp->lock); 1761ae08745Sheppo 1771ae08745Sheppo /* clean up the console */ 1781ae08745Sheppo cleanup_cons(consp); 1791ae08745Sheppo 1801ae08745Sheppo /* delete group? */ 1811ae08745Sheppo if (groupp->num_cons == 0) { 1821ae08745Sheppo /* no more console delete it */ 1831ae08745Sheppo assert(groupp->vntsd); 1841ae08745Sheppo 1851ae08745Sheppo (void) mutex_lock(&groupp->vntsd->lock); 1861ae08745Sheppo (void) vntsd_que_rm(&groupp->vntsd->grouppq, 1871ae08745Sheppo groupp); 1881ae08745Sheppo (void) mutex_unlock(&groupp->vntsd->lock); 1891ae08745Sheppo 1901ae08745Sheppo /* clean up the group */ 1911ae08745Sheppo vntsd_clean_group(groupp); 1921ae08745Sheppo break; 1931ae08745Sheppo } 1941ae08745Sheppo } 1951ae08745Sheppo } 1961ae08745Sheppo } 1971ae08745Sheppo 1981ae08745Sheppo /* clean up a group */ 1991ae08745Sheppo void 2001ae08745Sheppo vntsd_clean_group(vntsd_group_t *groupp) 2011ae08745Sheppo { 2021ae08745Sheppo 2031ae08745Sheppo timestruc_t to; 2041ae08745Sheppo 2051ae08745Sheppo D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(), 2061ae08745Sheppo groupp->group_name, groupp->tcp_port); 2071ae08745Sheppo 2081ae08745Sheppo (void) mutex_lock(&groupp->lock); 2091ae08745Sheppo 2101ae08745Sheppo /* prevent from reentry */ 2111ae08745Sheppo if (groupp->status & VNTSD_GROUP_CLEANUP) { 212*7636cb21Slm if (groupp->listen_tid == thr_self()) { 213*7636cb21Slm /* signal that the listen thread is exiting */ 214*7636cb21Slm groupp->status &= ~VNTSD_GROUP_SIG_WAIT; 215*7636cb21Slm (void) cond_signal(&groupp->cvp); 216*7636cb21Slm } 2171ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2181ae08745Sheppo return; 2191ae08745Sheppo } 2201ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEANUP; 2211ae08745Sheppo vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons); 2221ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2231ae08745Sheppo 2241ae08745Sheppo /* walk through no cons client queue */ 2251ae08745Sheppo while (groupp->no_cons_clientpq != NULL) { 2261ae08745Sheppo groupp->status |= VNTSD_GROUP_SIG_WAIT; 2271ae08745Sheppo (void) vntsd_que_walk(groupp->no_cons_clientpq, 2281ae08745Sheppo (el_func_t)vntsd_notify_client_cons_del); 2291ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 2301ae08745Sheppo to.tv_nsec = 0; 2311ae08745Sheppo (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); 2321ae08745Sheppo } 2331ae08745Sheppo 2341ae08745Sheppo if (groupp->listen_tid == thr_self()) { 2351ae08745Sheppo /* listen thread is exiting */ 2361ae08745Sheppo (void) mutex_lock(&(groupp->vntsd->lock)); 2371ae08745Sheppo (void) vntsd_que_rm(&groupp->vntsd->grouppq, groupp); 2381ae08745Sheppo (void) mutex_unlock(&groupp->vntsd->lock); 2391ae08745Sheppo 2401ae08745Sheppo (void) cond_destroy(&groupp->cvp); 2411ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2421ae08745Sheppo (void) mutex_destroy(&groupp->lock); 2431ae08745Sheppo free(groupp); 2441ae08745Sheppo return; 2451ae08745Sheppo } 2461ae08745Sheppo 2471ae08745Sheppo /* signal listen thread to exit */ 2481ae08745Sheppo groupp->status |= VNTSD_GROUP_SIG_WAIT; 2491ae08745Sheppo 2501ae08745Sheppo while (groupp->status & VNTSD_GROUP_SIG_WAIT) { 2511ae08745Sheppo (void) thr_kill(groupp->listen_tid, SIGUSR1); 2521ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 2531ae08745Sheppo to.tv_nsec = 0; 2541ae08745Sheppo /* wait listen thread to exit */ 2551ae08745Sheppo (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); 2561ae08745Sheppo } 2571ae08745Sheppo 2581ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2591ae08745Sheppo (void) thr_join(groupp->listen_tid, NULL, NULL); 2601ae08745Sheppo /* free group */ 2611ae08745Sheppo (void) cond_destroy(&groupp->cvp); 2621ae08745Sheppo (void) mutex_destroy(&groupp->lock); 2631ae08745Sheppo free(groupp); 2641ae08745Sheppo } 2651ae08745Sheppo 2661ae08745Sheppo /* allocate and initialize console structure */ 2671ae08745Sheppo static vntsd_cons_t * 2681ae08745Sheppo alloc_cons(vntsd_group_t *groupp, vcc_console_t *consolep) 2691ae08745Sheppo { 2701ae08745Sheppo vntsd_cons_t *consp; 2711ae08745Sheppo int rv; 2721ae08745Sheppo 2731ae08745Sheppo /* allocate console */ 2741ae08745Sheppo consp = (vntsd_cons_t *)malloc(sizeof (vntsd_cons_t)); 2751ae08745Sheppo if (consp == NULL) { 2761ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "alloc_cons"); 2771ae08745Sheppo return (NULL); 2781ae08745Sheppo } 2791ae08745Sheppo 2801ae08745Sheppo /* intialize console */ 2811ae08745Sheppo bzero(consp, sizeof (vntsd_cons_t)); 2821ae08745Sheppo 2831ae08745Sheppo (void) mutex_init(&consp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 2841ae08745Sheppo (void) cond_init(&consp->cvp, USYNC_THREAD, NULL); 2851ae08745Sheppo 2861ae08745Sheppo consp->cons_no = consolep->cons_no; 2871ae08745Sheppo (void) strlcpy(consp->domain_name, consolep->domain_name, MAXPATHLEN); 2881ae08745Sheppo (void) strlcpy(consp->dev_name, consolep->dev_name, MAXPATHLEN); 2891ae08745Sheppo consp->wr_tid = (thread_t)-1; 2901ae08745Sheppo consp->vcc_fd = (thread_t)-1; 2911ae08745Sheppo 2921ae08745Sheppo /* join the group */ 2931ae08745Sheppo (void) mutex_lock(&groupp->lock); 2941ae08745Sheppo 2951ae08745Sheppo if ((rv = vntsd_que_append(&groupp->conspq, consp)) != 2961ae08745Sheppo VNTSD_SUCCESS) { 2971ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2981ae08745Sheppo vntsd_log(rv, "alloc_cons"); 2991ae08745Sheppo free_cons(consp); 3001ae08745Sheppo return (NULL); 3011ae08745Sheppo } 3021ae08745Sheppo groupp->num_cons++; 3031ae08745Sheppo consp->group = groupp; 3041ae08745Sheppo 3051ae08745Sheppo (void) mutex_unlock(&groupp->lock); 3061ae08745Sheppo 3071ae08745Sheppo D1(stderr, "t@%d alloc_cons@%d %s %s\n", thr_self(), 3081ae08745Sheppo consp->cons_no, consp->domain_name, consp->dev_name); 3091ae08745Sheppo 3101ae08745Sheppo return (consp); 3111ae08745Sheppo } 3121ae08745Sheppo 3131ae08745Sheppo /* compare tcp with group->tcp */ 3141ae08745Sheppo static boolean_t 3151ae08745Sheppo grp_by_tcp(vntsd_group_t *groupp, uint64_t *tcp_port) 3161ae08745Sheppo { 3171ae08745Sheppo assert(groupp); 3181ae08745Sheppo assert(tcp_port); 3191ae08745Sheppo return (groupp->tcp_port == *tcp_port); 3201ae08745Sheppo } 3211ae08745Sheppo 3221ae08745Sheppo /* allocate and initialize group */ 3231ae08745Sheppo static vntsd_group_t * 3241ae08745Sheppo alloc_group(vntsd_t *vntsdp, char *group_name, uint64_t tcp_port) 3251ae08745Sheppo { 3261ae08745Sheppo vntsd_group_t *groupp; 3271ae08745Sheppo 3281ae08745Sheppo /* allocate group */ 3291ae08745Sheppo groupp = (vntsd_group_t *)malloc(sizeof (vntsd_group_t)); 3301ae08745Sheppo if (groupp == NULL) { 3311ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "alloc_group"); 3321ae08745Sheppo return (NULL); 3331ae08745Sheppo } 3341ae08745Sheppo 3351ae08745Sheppo /* initialize group */ 3361ae08745Sheppo bzero(groupp, sizeof (vntsd_group_t)); 3371ae08745Sheppo 3381ae08745Sheppo (void) mutex_init(&groupp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 3391ae08745Sheppo (void) cond_init(&groupp->cvp, USYNC_THREAD, NULL); 3401ae08745Sheppo 3411ae08745Sheppo if (group_name != NULL) { 3421ae08745Sheppo (void) memcpy(groupp->group_name, group_name, MAXPATHLEN); 3431ae08745Sheppo } 3441ae08745Sheppo 3451ae08745Sheppo groupp->tcp_port = tcp_port; 3461ae08745Sheppo groupp->listen_tid = (thread_t)-1; 3471ae08745Sheppo groupp->sockfd = (thread_t)-1; 3481ae08745Sheppo groupp->vntsd = vntsdp; 3491ae08745Sheppo 3501ae08745Sheppo D1(stderr, "t@%d alloc_group@%lld:%s\n", thr_self(), groupp->tcp_port, 3511ae08745Sheppo groupp->group_name); 3521ae08745Sheppo 3531ae08745Sheppo return (groupp); 3541ae08745Sheppo } 3551ae08745Sheppo 3561ae08745Sheppo /* 3571ae08745Sheppo * Initialize a console, if console is associated with with a 3581ae08745Sheppo * new group, intialize the group. 3591ae08745Sheppo */ 3601ae08745Sheppo static int 3611ae08745Sheppo alloc_cons_with_group(vntsd_t *vntsdp, vcc_console_t *consp, 3621ae08745Sheppo vntsd_group_t **new_groupp) 3631ae08745Sheppo { 3641ae08745Sheppo vntsd_group_t *groupp = NULL; 3651ae08745Sheppo int rv; 3661ae08745Sheppo 3671ae08745Sheppo *new_groupp = NULL; 3681ae08745Sheppo 3691ae08745Sheppo /* match group by tcp port */ 3701ae08745Sheppo 3711ae08745Sheppo 3721ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 3731ae08745Sheppo groupp = vntsd_que_find(vntsdp->grouppq, 3741ae08745Sheppo (compare_func_t)grp_by_tcp, (void *)&(consp->tcp_port)); 3751ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 3761ae08745Sheppo 3771ae08745Sheppo if (groupp != NULL) { 3781ae08745Sheppo /* group with same tcp port found */ 3791ae08745Sheppo 3801ae08745Sheppo if (strcmp(groupp->group_name, consp->group_name)) { 3811ae08745Sheppo /* conflict group name */ 3821ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_GRP_NAME, 3831ae08745Sheppo "group name is different from existing group"); 3841ae08745Sheppo return (VNTSD_ERR_VCC_CTRL_DATA); 3851ae08745Sheppo } 3861ae08745Sheppo 3871ae08745Sheppo } else { 3881ae08745Sheppo /* new group */ 3891ae08745Sheppo groupp = alloc_group(vntsdp, consp->group_name, 3901ae08745Sheppo consp->tcp_port); 3911ae08745Sheppo if (groupp == NULL) { 3921ae08745Sheppo return (VNTSD_ERR_NO_MEM); 3931ae08745Sheppo } 3941ae08745Sheppo 3951ae08745Sheppo assert(groupp->conspq == NULL); 3961ae08745Sheppo /* queue group to vntsdp */ 3971ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 3981ae08745Sheppo rv = vntsd_que_append(&vntsdp->grouppq, groupp); 3991ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 4001ae08745Sheppo 4011ae08745Sheppo if (rv != VNTSD_SUCCESS) { 4021ae08745Sheppo return (rv); 4031ae08745Sheppo } 4041ae08745Sheppo 4051ae08745Sheppo *new_groupp = groupp; 4061ae08745Sheppo } 4071ae08745Sheppo 4081ae08745Sheppo /* intialize console */ 4091ae08745Sheppo if (alloc_cons(groupp, consp) == NULL) { 4101ae08745Sheppo /* no memory */ 4111ae08745Sheppo if (new_groupp != NULL) { 4121ae08745Sheppo /* clean up new group */ 4131ae08745Sheppo (void) cond_destroy(&groupp->cvp); 4141ae08745Sheppo (void) mutex_destroy(&groupp->lock); 4151ae08745Sheppo free(groupp); 4161ae08745Sheppo } 4171ae08745Sheppo 4181ae08745Sheppo return (VNTSD_ERR_NO_MEM); 4191ae08745Sheppo } 4201ae08745Sheppo 4211ae08745Sheppo return (VNTSD_SUCCESS); 4221ae08745Sheppo 4231ae08745Sheppo } 4241ae08745Sheppo 4251ae08745Sheppo 4261ae08745Sheppo /* create listen thread */ 4271ae08745Sheppo static boolean_t 4281ae08745Sheppo create_listen_thread(vntsd_group_t *groupp) 4291ae08745Sheppo { 4301ae08745Sheppo 4311ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 4321ae08745Sheppo int rv; 4331ae08745Sheppo 4341ae08745Sheppo assert(groupp); 4351ae08745Sheppo 4361ae08745Sheppo (void) mutex_lock(&groupp->lock); 4371ae08745Sheppo assert(groupp->num_cons); 4381ae08745Sheppo 4391ae08745Sheppo D1(stderr, "t@%d create_listen:%lld\n", thr_self(), groupp->tcp_port); 4401ae08745Sheppo 4411ae08745Sheppo if ((rv = thr_create(NULL, 0, (thr_func_t)vntsd_listen_thread, 4421ae08745Sheppo (void *)groupp, THR_DETACHED, &groupp->listen_tid)) 4431ae08745Sheppo != 0) { 4441ae08745Sheppo (void) (void) snprintf(err_msg, sizeof (err_msg), 4451ae08745Sheppo "Can not create listen thread for" 4461ae08745Sheppo "group %s tcp %llx\n", groupp->group_name, 4471ae08745Sheppo groupp->tcp_port); 4481ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); 4491ae08745Sheppo 4501ae08745Sheppo /* clean up group queue */ 4511ae08745Sheppo vntsd_free_que(&groupp->conspq, (clean_func_t)free_cons); 4521ae08745Sheppo groupp->listen_tid = (thread_t)-1; 4531ae08745Sheppo } 4541ae08745Sheppo 4551ae08745Sheppo (void) mutex_unlock(&groupp->lock); 4561ae08745Sheppo 4571ae08745Sheppo return (rv != 0); 4581ae08745Sheppo } 4591ae08745Sheppo 4601ae08745Sheppo /* delete a console if the console exists in the vntsd */ 4611ae08745Sheppo static void 4621ae08745Sheppo delete_cons_before_add(vntsd_t *vntsdp, uint64_t tcp_port, uint_t cons_no) 4631ae08745Sheppo { 4641ae08745Sheppo vntsd_group_t *groupp; 4651ae08745Sheppo vntsd_cons_t *consp; 4661ae08745Sheppo 4671ae08745Sheppo /* group exists? */ 4681ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 4691ae08745Sheppo groupp = vntsd_que_find(vntsdp->grouppq, (compare_func_t)grp_by_tcp, 4701ae08745Sheppo (void *)&(tcp_port)); 4711ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 4721ae08745Sheppo 4731ae08745Sheppo if (groupp == NULL) { 4741ae08745Sheppo /* no such group */ 4751ae08745Sheppo return; 4761ae08745Sheppo } 4771ae08745Sheppo 4781ae08745Sheppo /* group exists, if console exists? */ 4791ae08745Sheppo (void) mutex_lock(&groupp->lock); 4801ae08745Sheppo consp = vntsd_que_find(groupp->conspq, 4811ae08745Sheppo (compare_func_t)vntsd_cons_by_consno, &cons_no); 4821ae08745Sheppo 4831ae08745Sheppo if (consp == NULL) { 4841ae08745Sheppo /* no such console */ 4851ae08745Sheppo (void) mutex_unlock(&groupp->lock); 4861ae08745Sheppo return; 4871ae08745Sheppo } 4881ae08745Sheppo /* console exists - delete console */ 4891ae08745Sheppo 4901ae08745Sheppo (void) mutex_lock(&consp->lock); 4911ae08745Sheppo 4921ae08745Sheppo consp->status |= VNTSD_CONS_DELETED; 4931ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEAN_CONS; 4941ae08745Sheppo 4951ae08745Sheppo (void) mutex_unlock(&consp->lock); 4961ae08745Sheppo 4971ae08745Sheppo (void) mutex_unlock(&groupp->lock); 4981ae08745Sheppo 4991ae08745Sheppo vntsd_delete_cons(vntsdp); 5001ae08745Sheppo } 5011ae08745Sheppo 5021ae08745Sheppo /* add a console */ 5031ae08745Sheppo static void 5041ae08745Sheppo do_add_cons(vntsd_t *vntsdp, int cons_no) 5051ae08745Sheppo { 5061ae08745Sheppo vcc_console_t console; 5071ae08745Sheppo vntsd_group_t *groupp; 5081ae08745Sheppo int rv; 5091ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 5101ae08745Sheppo 5111ae08745Sheppo 5121ae08745Sheppo (void) snprintf(err_msg, sizeof (err_msg), 5131ae08745Sheppo "do_add_cons():Can not add console=%d", cons_no); 5141ae08745Sheppo 5151ae08745Sheppo /* get console configuration from vcc */ 5161ae08745Sheppo 5171ae08745Sheppo if ((rv = vntsd_vcc_ioctl(VCC_CONS_INFO, cons_no, (void *)&console)) 5181ae08745Sheppo != VNTSD_SUCCESS) { 5191ae08745Sheppo vntsd_log(rv, err_msg); 5201ae08745Sheppo return; 5211ae08745Sheppo } 5221ae08745Sheppo 5231ae08745Sheppo /* clean up the console if console was deleted and added again */ 5241ae08745Sheppo delete_cons_before_add(vntsdp, console.tcp_port, console.cons_no); 5251ae08745Sheppo 5261ae08745Sheppo /* initialize console */ 5271ae08745Sheppo 5281ae08745Sheppo if ((rv = alloc_cons_with_group(vntsdp, &console, &groupp)) != 5291ae08745Sheppo VNTSD_SUCCESS) { 5301ae08745Sheppo /* no memory to add this new console */ 5311ae08745Sheppo vntsd_log(rv, err_msg); 5321ae08745Sheppo return; 5331ae08745Sheppo } 5341ae08745Sheppo 5351ae08745Sheppo if (groupp != NULL) { 5361ae08745Sheppo /* new group */ 5371ae08745Sheppo /* create listen thread for this console */ 5381ae08745Sheppo if (create_listen_thread(groupp)) { 5391ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); 5401ae08745Sheppo (void) cond_destroy(&groupp->cvp); 5411ae08745Sheppo (void) mutex_destroy(&groupp->lock); 5421ae08745Sheppo free(groupp); 5431ae08745Sheppo } 5441ae08745Sheppo 5451ae08745Sheppo } 5461ae08745Sheppo } 5471ae08745Sheppo 5481ae08745Sheppo /* daemon wake up */ 5491ae08745Sheppo void 5501ae08745Sheppo vntsd_daemon_wakeup(vntsd_t *vntsdp) 5511ae08745Sheppo { 5521ae08745Sheppo 5531ae08745Sheppo vcc_response_t inq_data; 5541ae08745Sheppo 5551ae08745Sheppo /* reason to wake up */ 5561ae08745Sheppo if (vntsd_vcc_ioctl(VCC_INQUIRY, 0, (void *)&inq_data) != 5571ae08745Sheppo VNTSD_SUCCESS) { 5581ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, "vntsd_daemon_wakeup()"); 5591ae08745Sheppo return; 5601ae08745Sheppo } 5611ae08745Sheppo 5621ae08745Sheppo D1(stderr, "t@%d vntsd_daemon_wakup:msg %d port %x\n", thr_self(), 5631ae08745Sheppo inq_data.reason, inq_data.cons_no); 5641ae08745Sheppo 5651ae08745Sheppo switch (inq_data.reason) { 5661ae08745Sheppo 5671ae08745Sheppo case VCC_CONS_ADDED: 5681ae08745Sheppo do_add_cons(vntsdp, inq_data.cons_no); 5691ae08745Sheppo break; 5701ae08745Sheppo 571*7636cb21Slm case VCC_CONS_MISS_ADDED: 572*7636cb21Slm /* an added port was deleted before vntsd can process it */ 573*7636cb21Slm return; 574*7636cb21Slm 5751ae08745Sheppo default: 5761ae08745Sheppo DERR(stderr, "t@%d daemon_wakeup:ioctl_unknown %d\n", 5771ae08745Sheppo thr_self(), inq_data.reason); 5781ae08745Sheppo vntsd_log(VNTSD_ERR_UNKNOWN_CMD, "from vcc\n"); 5791ae08745Sheppo break; 5801ae08745Sheppo } 5811ae08745Sheppo } 5821ae08745Sheppo 5831ae08745Sheppo /* initial console configuration */ 5841ae08745Sheppo void 5851ae08745Sheppo vntsd_get_config(vntsd_t *vntsdp) 5861ae08745Sheppo { 5871ae08745Sheppo 5881ae08745Sheppo int i; 5891ae08745Sheppo int num_cons; 5901ae08745Sheppo vcc_console_t *consp; 5911ae08745Sheppo vntsd_group_t *groupp; 5921ae08745Sheppo 5931ae08745Sheppo /* num of consoles */ 5941ae08745Sheppo num_cons = 0; 5951ae08745Sheppo 5961ae08745Sheppo if (vntsd_vcc_ioctl(VCC_NUM_CONSOLE, 0, (void *)&num_cons) != 5971ae08745Sheppo VNTSD_SUCCESS) { 5981ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, "VCC_NUM_CONSOLE failed\n"); 5991ae08745Sheppo return; 6001ae08745Sheppo } 6011ae08745Sheppo 6021ae08745Sheppo D3(stderr, "get_config:num_cons=%d", num_cons); 6031ae08745Sheppo 6041ae08745Sheppo if (num_cons == 0) { 6051ae08745Sheppo return; 6061ae08745Sheppo } 6071ae08745Sheppo 6081ae08745Sheppo /* allocate memory for all consoles */ 6091ae08745Sheppo consp = malloc(num_cons*sizeof (vcc_console_t)); 6101ae08745Sheppo 6111ae08745Sheppo if (consp == NULL) { 6121ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "for console table."); 6131ae08745Sheppo return; 6141ae08745Sheppo } 6151ae08745Sheppo 6161ae08745Sheppo /* get console table */ 6171ae08745Sheppo if (vntsd_vcc_ioctl(VCC_CONS_TBL, 0, (void *)consp) != VNTSD_SUCCESS) { 6181ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, " VCC_CONS_TBL " 6191ae08745Sheppo "for console table\n"); 6201ae08745Sheppo return; 6211ae08745Sheppo } 6221ae08745Sheppo 6231ae08745Sheppo /* intialize groups and consoles */ 6241ae08745Sheppo for (i = 0; i < num_cons; i++) { 6251ae08745Sheppo if (alloc_cons_with_group(vntsdp, &consp[i], &groupp) 6261ae08745Sheppo != VNTSD_SUCCESS) { 6271ae08745Sheppo vntsd_log(VNTSD_ERR_ADD_CONS_FAILED, "get_config"); 6281ae08745Sheppo } 6291ae08745Sheppo } 6301ae08745Sheppo 6311ae08745Sheppo /* create listen thread for each group */ 6321ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 6331ae08745Sheppo 6341ae08745Sheppo for (; ; ) { 6351ae08745Sheppo groupp = vntsd_que_walk(vntsdp->grouppq, 6361ae08745Sheppo (el_func_t)create_listen_thread); 6371ae08745Sheppo if (groupp == NULL) { 6381ae08745Sheppo break; 6391ae08745Sheppo } 6401ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, "get config()"); 6411ae08745Sheppo } 6421ae08745Sheppo 6431ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 6441ae08745Sheppo } 645