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 111*3af08d82Slm66018 /* reduce console count in the group */ 112*3af08d82Slm66018 (void) mutex_lock(&groupp->lock); 113*3af08d82Slm66018 assert(groupp->num_cons > 0); 114*3af08d82Slm66018 groupp->num_cons--; 115*3af08d82Slm66018 (void) mutex_unlock(&groupp->lock); 116*3af08d82Slm66018 1171ae08745Sheppo (void) mutex_unlock(&consp->lock); 1181ae08745Sheppo 1191ae08745Sheppo free_cons(consp); 1201ae08745Sheppo } 1211ae08745Sheppo 1221ae08745Sheppo /* search for a group whose console is being deleted */ 1231ae08745Sheppo static boolean_t 1241ae08745Sheppo find_clean_cons_group(vntsd_group_t *groupp) 1251ae08745Sheppo { 1261ae08745Sheppo if (groupp->status & VNTSD_GROUP_CLEAN_CONS) { 1271ae08745Sheppo return (B_TRUE); 1281ae08745Sheppo } else { 1291ae08745Sheppo return (B_FALSE); 1301ae08745Sheppo } 1311ae08745Sheppo } 1321ae08745Sheppo 1331ae08745Sheppo /* search for a console that is being deleted */ 1341ae08745Sheppo static boolean_t 1351ae08745Sheppo find_clean_cons(vntsd_cons_t *consp) 1361ae08745Sheppo { 1371ae08745Sheppo if (consp->status & VNTSD_CONS_DELETED) { 1381ae08745Sheppo return (B_TRUE); 1391ae08745Sheppo } else { 1401ae08745Sheppo return (B_FALSE); 1411ae08745Sheppo } 1421ae08745Sheppo } 1431ae08745Sheppo 1441ae08745Sheppo /* delete a console */ 1451ae08745Sheppo void 1461ae08745Sheppo vntsd_delete_cons(vntsd_t *vntsdp) 1471ae08745Sheppo { 1481ae08745Sheppo vntsd_group_t *groupp; 1491ae08745Sheppo vntsd_cons_t *consp; 1501ae08745Sheppo 1511ae08745Sheppo for (; ; ) { 1521ae08745Sheppo /* get the group contains deleted console */ 1531ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 1541ae08745Sheppo groupp = vntsd_que_walk(vntsdp->grouppq, 1551ae08745Sheppo (el_func_t)find_clean_cons_group); 1561ae08745Sheppo if (groupp == NULL) { 1571ae08745Sheppo /* no more group has console deleted */ 1581ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 1591ae08745Sheppo return; 1601ae08745Sheppo } 1617636cb21Slm66018 (void) mutex_lock(&groupp->lock); 1621ae08745Sheppo groupp->status &= ~VNTSD_GROUP_CLEAN_CONS; 1637636cb21Slm66018 (void) mutex_unlock(&groupp->lock); 1641ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 1651ae08745Sheppo 1661ae08745Sheppo for (; ; ) { 1671ae08745Sheppo /* get the console to be deleted */ 1681ae08745Sheppo (void) mutex_lock(&groupp->lock); 1691ae08745Sheppo assert(groupp->conspq); 1701ae08745Sheppo consp = vntsd_que_walk(groupp->conspq, 1711ae08745Sheppo (el_func_t)find_clean_cons); 1721ae08745Sheppo if (consp == NULL) { 1731ae08745Sheppo /* no more cons to delete */ 1741ae08745Sheppo (void) mutex_unlock(&groupp->lock); 1751ae08745Sheppo break; 1761ae08745Sheppo } 1771ae08745Sheppo 1781ae08745Sheppo /* remove console from the group */ 1791ae08745Sheppo (void) vntsd_que_rm(&groupp->conspq, consp); 1801ae08745Sheppo (void) mutex_unlock(&groupp->lock); 1811ae08745Sheppo 1821ae08745Sheppo /* clean up the console */ 1831ae08745Sheppo cleanup_cons(consp); 1841ae08745Sheppo 1851ae08745Sheppo /* delete group? */ 1861ae08745Sheppo if (groupp->num_cons == 0) { 1871ae08745Sheppo /* no more console delete it */ 1881ae08745Sheppo assert(groupp->vntsd); 1891ae08745Sheppo 1901ae08745Sheppo (void) mutex_lock(&groupp->vntsd->lock); 1911ae08745Sheppo (void) vntsd_que_rm(&groupp->vntsd->grouppq, 1921ae08745Sheppo groupp); 1931ae08745Sheppo (void) mutex_unlock(&groupp->vntsd->lock); 1941ae08745Sheppo 1951ae08745Sheppo /* clean up the group */ 1961ae08745Sheppo vntsd_clean_group(groupp); 1971ae08745Sheppo break; 1981ae08745Sheppo } 1991ae08745Sheppo } 2001ae08745Sheppo } 2011ae08745Sheppo } 2021ae08745Sheppo 2031ae08745Sheppo /* clean up a group */ 2041ae08745Sheppo void 2051ae08745Sheppo vntsd_clean_group(vntsd_group_t *groupp) 2061ae08745Sheppo { 2071ae08745Sheppo 2081ae08745Sheppo timestruc_t to; 2091ae08745Sheppo 2101ae08745Sheppo D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(), 2111ae08745Sheppo groupp->group_name, groupp->tcp_port); 2121ae08745Sheppo 2131ae08745Sheppo (void) mutex_lock(&groupp->lock); 2141ae08745Sheppo 2151ae08745Sheppo /* prevent from reentry */ 2161ae08745Sheppo if (groupp->status & VNTSD_GROUP_CLEANUP) { 2177636cb21Slm66018 if (groupp->listen_tid == thr_self()) { 2187636cb21Slm66018 /* signal that the listen thread is exiting */ 2197636cb21Slm66018 groupp->status &= ~VNTSD_GROUP_SIG_WAIT; 2207636cb21Slm66018 (void) cond_signal(&groupp->cvp); 2217636cb21Slm66018 } 2221ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2231ae08745Sheppo return; 2241ae08745Sheppo } 2251ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEANUP; 2261ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2271ae08745Sheppo 228*3af08d82Slm66018 vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons); 229*3af08d82Slm66018 2301ae08745Sheppo /* walk through no cons client queue */ 2311ae08745Sheppo while (groupp->no_cons_clientpq != NULL) { 2321ae08745Sheppo groupp->status |= VNTSD_GROUP_SIG_WAIT; 2331ae08745Sheppo (void) vntsd_que_walk(groupp->no_cons_clientpq, 2341ae08745Sheppo (el_func_t)vntsd_notify_client_cons_del); 2351ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 2361ae08745Sheppo to.tv_nsec = 0; 2371ae08745Sheppo (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); 2381ae08745Sheppo } 2391ae08745Sheppo 2401ae08745Sheppo if (groupp->listen_tid == thr_self()) { 2411ae08745Sheppo /* listen thread is exiting */ 2421ae08745Sheppo (void) mutex_lock(&(groupp->vntsd->lock)); 2431ae08745Sheppo (void) vntsd_que_rm(&groupp->vntsd->grouppq, groupp); 2441ae08745Sheppo (void) mutex_unlock(&groupp->vntsd->lock); 2451ae08745Sheppo 2461ae08745Sheppo (void) cond_destroy(&groupp->cvp); 2471ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2481ae08745Sheppo (void) mutex_destroy(&groupp->lock); 2491ae08745Sheppo free(groupp); 2501ae08745Sheppo return; 2511ae08745Sheppo } 2521ae08745Sheppo 2531ae08745Sheppo /* signal listen thread to exit */ 2541ae08745Sheppo groupp->status |= VNTSD_GROUP_SIG_WAIT; 2551ae08745Sheppo 2561ae08745Sheppo while (groupp->status & VNTSD_GROUP_SIG_WAIT) { 2571ae08745Sheppo (void) thr_kill(groupp->listen_tid, SIGUSR1); 2581ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 2591ae08745Sheppo to.tv_nsec = 0; 2601ae08745Sheppo /* wait listen thread to exit */ 2611ae08745Sheppo (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); 2621ae08745Sheppo } 2631ae08745Sheppo 2641ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2651ae08745Sheppo (void) thr_join(groupp->listen_tid, NULL, NULL); 2661ae08745Sheppo /* free group */ 2671ae08745Sheppo (void) cond_destroy(&groupp->cvp); 2681ae08745Sheppo (void) mutex_destroy(&groupp->lock); 2691ae08745Sheppo free(groupp); 2701ae08745Sheppo } 2711ae08745Sheppo 2721ae08745Sheppo /* allocate and initialize console structure */ 2731ae08745Sheppo static vntsd_cons_t * 2741ae08745Sheppo alloc_cons(vntsd_group_t *groupp, vcc_console_t *consolep) 2751ae08745Sheppo { 2761ae08745Sheppo vntsd_cons_t *consp; 2771ae08745Sheppo int rv; 2781ae08745Sheppo 2791ae08745Sheppo /* allocate console */ 2801ae08745Sheppo consp = (vntsd_cons_t *)malloc(sizeof (vntsd_cons_t)); 2811ae08745Sheppo if (consp == NULL) { 2821ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "alloc_cons"); 2831ae08745Sheppo return (NULL); 2841ae08745Sheppo } 2851ae08745Sheppo 2861ae08745Sheppo /* intialize console */ 2871ae08745Sheppo bzero(consp, sizeof (vntsd_cons_t)); 2881ae08745Sheppo 2891ae08745Sheppo (void) mutex_init(&consp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 2901ae08745Sheppo (void) cond_init(&consp->cvp, USYNC_THREAD, NULL); 2911ae08745Sheppo 2921ae08745Sheppo consp->cons_no = consolep->cons_no; 2931ae08745Sheppo (void) strlcpy(consp->domain_name, consolep->domain_name, MAXPATHLEN); 2941ae08745Sheppo (void) strlcpy(consp->dev_name, consolep->dev_name, MAXPATHLEN); 2951ae08745Sheppo consp->wr_tid = (thread_t)-1; 2961ae08745Sheppo consp->vcc_fd = (thread_t)-1; 2971ae08745Sheppo 2981ae08745Sheppo /* join the group */ 2991ae08745Sheppo (void) mutex_lock(&groupp->lock); 3001ae08745Sheppo 3011ae08745Sheppo if ((rv = vntsd_que_append(&groupp->conspq, consp)) != 3021ae08745Sheppo VNTSD_SUCCESS) { 3031ae08745Sheppo (void) mutex_unlock(&groupp->lock); 3041ae08745Sheppo vntsd_log(rv, "alloc_cons"); 3051ae08745Sheppo free_cons(consp); 3061ae08745Sheppo return (NULL); 3071ae08745Sheppo } 3081ae08745Sheppo groupp->num_cons++; 3091ae08745Sheppo consp->group = groupp; 3101ae08745Sheppo 3111ae08745Sheppo (void) mutex_unlock(&groupp->lock); 3121ae08745Sheppo 3131ae08745Sheppo D1(stderr, "t@%d alloc_cons@%d %s %s\n", thr_self(), 3141ae08745Sheppo consp->cons_no, consp->domain_name, consp->dev_name); 3151ae08745Sheppo 3161ae08745Sheppo return (consp); 3171ae08745Sheppo } 3181ae08745Sheppo 3191ae08745Sheppo /* compare tcp with group->tcp */ 3201ae08745Sheppo static boolean_t 3211ae08745Sheppo grp_by_tcp(vntsd_group_t *groupp, uint64_t *tcp_port) 3221ae08745Sheppo { 3231ae08745Sheppo assert(groupp); 3241ae08745Sheppo assert(tcp_port); 3251ae08745Sheppo return (groupp->tcp_port == *tcp_port); 3261ae08745Sheppo } 3271ae08745Sheppo 3281ae08745Sheppo /* allocate and initialize group */ 3291ae08745Sheppo static vntsd_group_t * 3301ae08745Sheppo alloc_group(vntsd_t *vntsdp, char *group_name, uint64_t tcp_port) 3311ae08745Sheppo { 3321ae08745Sheppo vntsd_group_t *groupp; 3331ae08745Sheppo 3341ae08745Sheppo /* allocate group */ 3351ae08745Sheppo groupp = (vntsd_group_t *)malloc(sizeof (vntsd_group_t)); 3361ae08745Sheppo if (groupp == NULL) { 3371ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "alloc_group"); 3381ae08745Sheppo return (NULL); 3391ae08745Sheppo } 3401ae08745Sheppo 3411ae08745Sheppo /* initialize group */ 3421ae08745Sheppo bzero(groupp, sizeof (vntsd_group_t)); 3431ae08745Sheppo 3441ae08745Sheppo (void) mutex_init(&groupp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 3451ae08745Sheppo (void) cond_init(&groupp->cvp, USYNC_THREAD, NULL); 3461ae08745Sheppo 3471ae08745Sheppo if (group_name != NULL) { 3481ae08745Sheppo (void) memcpy(groupp->group_name, group_name, MAXPATHLEN); 3491ae08745Sheppo } 3501ae08745Sheppo 3511ae08745Sheppo groupp->tcp_port = tcp_port; 3521ae08745Sheppo groupp->listen_tid = (thread_t)-1; 3531ae08745Sheppo groupp->sockfd = (thread_t)-1; 3541ae08745Sheppo groupp->vntsd = vntsdp; 3551ae08745Sheppo 3561ae08745Sheppo D1(stderr, "t@%d alloc_group@%lld:%s\n", thr_self(), groupp->tcp_port, 3571ae08745Sheppo groupp->group_name); 3581ae08745Sheppo 3591ae08745Sheppo return (groupp); 3601ae08745Sheppo } 3611ae08745Sheppo 3621ae08745Sheppo /* 3631ae08745Sheppo * Initialize a console, if console is associated with with a 3641ae08745Sheppo * new group, intialize the group. 3651ae08745Sheppo */ 3661ae08745Sheppo static int 3671ae08745Sheppo alloc_cons_with_group(vntsd_t *vntsdp, vcc_console_t *consp, 3681ae08745Sheppo vntsd_group_t **new_groupp) 3691ae08745Sheppo { 3701ae08745Sheppo vntsd_group_t *groupp = NULL; 3711ae08745Sheppo int rv; 3721ae08745Sheppo 3731ae08745Sheppo *new_groupp = NULL; 3741ae08745Sheppo 3751ae08745Sheppo /* match group by tcp port */ 3761ae08745Sheppo 3771ae08745Sheppo 3781ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 3791ae08745Sheppo groupp = vntsd_que_find(vntsdp->grouppq, 3801ae08745Sheppo (compare_func_t)grp_by_tcp, (void *)&(consp->tcp_port)); 3811ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 3821ae08745Sheppo 3831ae08745Sheppo if (groupp != NULL) { 3841ae08745Sheppo /* group with same tcp port found */ 3851ae08745Sheppo 3861ae08745Sheppo if (strcmp(groupp->group_name, consp->group_name)) { 3871ae08745Sheppo /* conflict group name */ 3881ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_GRP_NAME, 3891ae08745Sheppo "group name is different from existing group"); 3901ae08745Sheppo return (VNTSD_ERR_VCC_CTRL_DATA); 3911ae08745Sheppo } 3921ae08745Sheppo 3931ae08745Sheppo } else { 3941ae08745Sheppo /* new group */ 3951ae08745Sheppo groupp = alloc_group(vntsdp, consp->group_name, 3961ae08745Sheppo consp->tcp_port); 3971ae08745Sheppo if (groupp == NULL) { 3981ae08745Sheppo return (VNTSD_ERR_NO_MEM); 3991ae08745Sheppo } 4001ae08745Sheppo 4011ae08745Sheppo assert(groupp->conspq == NULL); 4021ae08745Sheppo /* queue group to vntsdp */ 4031ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 4041ae08745Sheppo rv = vntsd_que_append(&vntsdp->grouppq, groupp); 4051ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 4061ae08745Sheppo 4071ae08745Sheppo if (rv != VNTSD_SUCCESS) { 4081ae08745Sheppo return (rv); 4091ae08745Sheppo } 4101ae08745Sheppo 4111ae08745Sheppo *new_groupp = groupp; 4121ae08745Sheppo } 4131ae08745Sheppo 4141ae08745Sheppo /* intialize console */ 4151ae08745Sheppo if (alloc_cons(groupp, consp) == NULL) { 4161ae08745Sheppo /* no memory */ 4171ae08745Sheppo if (new_groupp != NULL) { 4181ae08745Sheppo /* clean up new group */ 4191ae08745Sheppo (void) cond_destroy(&groupp->cvp); 4201ae08745Sheppo (void) mutex_destroy(&groupp->lock); 4211ae08745Sheppo free(groupp); 4221ae08745Sheppo } 4231ae08745Sheppo 4241ae08745Sheppo return (VNTSD_ERR_NO_MEM); 4251ae08745Sheppo } 4261ae08745Sheppo 4271ae08745Sheppo return (VNTSD_SUCCESS); 4281ae08745Sheppo 4291ae08745Sheppo } 4301ae08745Sheppo 4311ae08745Sheppo 4321ae08745Sheppo /* create listen thread */ 4331ae08745Sheppo static boolean_t 4341ae08745Sheppo create_listen_thread(vntsd_group_t *groupp) 4351ae08745Sheppo { 4361ae08745Sheppo 4371ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 4381ae08745Sheppo int rv; 4391ae08745Sheppo 4401ae08745Sheppo assert(groupp); 4411ae08745Sheppo 4421ae08745Sheppo (void) mutex_lock(&groupp->lock); 4431ae08745Sheppo assert(groupp->num_cons); 4441ae08745Sheppo 4451ae08745Sheppo D1(stderr, "t@%d create_listen:%lld\n", thr_self(), groupp->tcp_port); 4461ae08745Sheppo 4471ae08745Sheppo if ((rv = thr_create(NULL, 0, (thr_func_t)vntsd_listen_thread, 4481ae08745Sheppo (void *)groupp, THR_DETACHED, &groupp->listen_tid)) 4491ae08745Sheppo != 0) { 4501ae08745Sheppo (void) (void) snprintf(err_msg, sizeof (err_msg), 4511ae08745Sheppo "Can not create listen thread for" 4521ae08745Sheppo "group %s tcp %llx\n", groupp->group_name, 4531ae08745Sheppo groupp->tcp_port); 4541ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); 4551ae08745Sheppo 4561ae08745Sheppo /* clean up group queue */ 4571ae08745Sheppo vntsd_free_que(&groupp->conspq, (clean_func_t)free_cons); 4581ae08745Sheppo groupp->listen_tid = (thread_t)-1; 4591ae08745Sheppo } 4601ae08745Sheppo 4611ae08745Sheppo (void) mutex_unlock(&groupp->lock); 4621ae08745Sheppo 4631ae08745Sheppo return (rv != 0); 4641ae08745Sheppo } 4651ae08745Sheppo 4661ae08745Sheppo /* delete a console if the console exists in the vntsd */ 4671ae08745Sheppo static void 4681ae08745Sheppo delete_cons_before_add(vntsd_t *vntsdp, uint64_t tcp_port, uint_t cons_no) 4691ae08745Sheppo { 4701ae08745Sheppo vntsd_group_t *groupp; 4711ae08745Sheppo vntsd_cons_t *consp; 4721ae08745Sheppo 4731ae08745Sheppo /* group exists? */ 4741ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 4751ae08745Sheppo groupp = vntsd_que_find(vntsdp->grouppq, (compare_func_t)grp_by_tcp, 4761ae08745Sheppo (void *)&(tcp_port)); 4771ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 4781ae08745Sheppo 4791ae08745Sheppo if (groupp == NULL) { 4801ae08745Sheppo /* no such group */ 4811ae08745Sheppo return; 4821ae08745Sheppo } 4831ae08745Sheppo 4841ae08745Sheppo /* group exists, if console exists? */ 4851ae08745Sheppo (void) mutex_lock(&groupp->lock); 4861ae08745Sheppo consp = vntsd_que_find(groupp->conspq, 4871ae08745Sheppo (compare_func_t)vntsd_cons_by_consno, &cons_no); 4881ae08745Sheppo 4891ae08745Sheppo if (consp == NULL) { 4901ae08745Sheppo /* no such console */ 4911ae08745Sheppo (void) mutex_unlock(&groupp->lock); 4921ae08745Sheppo return; 4931ae08745Sheppo } 4941ae08745Sheppo /* console exists - delete console */ 4951ae08745Sheppo 4961ae08745Sheppo (void) mutex_lock(&consp->lock); 4971ae08745Sheppo 4981ae08745Sheppo consp->status |= VNTSD_CONS_DELETED; 4991ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEAN_CONS; 5001ae08745Sheppo 5011ae08745Sheppo (void) mutex_unlock(&consp->lock); 5021ae08745Sheppo 5031ae08745Sheppo (void) mutex_unlock(&groupp->lock); 5041ae08745Sheppo 5051ae08745Sheppo vntsd_delete_cons(vntsdp); 5061ae08745Sheppo } 5071ae08745Sheppo 5081ae08745Sheppo /* add a console */ 5091ae08745Sheppo static void 5101ae08745Sheppo do_add_cons(vntsd_t *vntsdp, int cons_no) 5111ae08745Sheppo { 5121ae08745Sheppo vcc_console_t console; 5131ae08745Sheppo vntsd_group_t *groupp; 5141ae08745Sheppo int rv; 5151ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 5161ae08745Sheppo 5171ae08745Sheppo 5181ae08745Sheppo (void) snprintf(err_msg, sizeof (err_msg), 5191ae08745Sheppo "do_add_cons():Can not add console=%d", cons_no); 5201ae08745Sheppo 5211ae08745Sheppo /* get console configuration from vcc */ 5221ae08745Sheppo 5231ae08745Sheppo if ((rv = vntsd_vcc_ioctl(VCC_CONS_INFO, cons_no, (void *)&console)) 5241ae08745Sheppo != VNTSD_SUCCESS) { 5251ae08745Sheppo vntsd_log(rv, err_msg); 5261ae08745Sheppo return; 5271ae08745Sheppo } 5281ae08745Sheppo 5291ae08745Sheppo /* clean up the console if console was deleted and added again */ 5301ae08745Sheppo delete_cons_before_add(vntsdp, console.tcp_port, console.cons_no); 5311ae08745Sheppo 5321ae08745Sheppo /* initialize console */ 5331ae08745Sheppo 5341ae08745Sheppo if ((rv = alloc_cons_with_group(vntsdp, &console, &groupp)) != 5351ae08745Sheppo VNTSD_SUCCESS) { 5361ae08745Sheppo /* no memory to add this new console */ 5371ae08745Sheppo vntsd_log(rv, err_msg); 5381ae08745Sheppo return; 5391ae08745Sheppo } 5401ae08745Sheppo 5411ae08745Sheppo if (groupp != NULL) { 5421ae08745Sheppo /* new group */ 5431ae08745Sheppo /* create listen thread for this console */ 5441ae08745Sheppo if (create_listen_thread(groupp)) { 5451ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); 5461ae08745Sheppo (void) cond_destroy(&groupp->cvp); 5471ae08745Sheppo (void) mutex_destroy(&groupp->lock); 5481ae08745Sheppo free(groupp); 5491ae08745Sheppo } 5501ae08745Sheppo 5511ae08745Sheppo } 5521ae08745Sheppo } 5531ae08745Sheppo 5541ae08745Sheppo /* daemon wake up */ 5551ae08745Sheppo void 5561ae08745Sheppo vntsd_daemon_wakeup(vntsd_t *vntsdp) 5571ae08745Sheppo { 5581ae08745Sheppo 5591ae08745Sheppo vcc_response_t inq_data; 5601ae08745Sheppo 5611ae08745Sheppo /* reason to wake up */ 5621ae08745Sheppo if (vntsd_vcc_ioctl(VCC_INQUIRY, 0, (void *)&inq_data) != 5631ae08745Sheppo VNTSD_SUCCESS) { 5641ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, "vntsd_daemon_wakeup()"); 5651ae08745Sheppo return; 5661ae08745Sheppo } 5671ae08745Sheppo 5681ae08745Sheppo D1(stderr, "t@%d vntsd_daemon_wakup:msg %d port %x\n", thr_self(), 5691ae08745Sheppo inq_data.reason, inq_data.cons_no); 5701ae08745Sheppo 5711ae08745Sheppo switch (inq_data.reason) { 5721ae08745Sheppo 5731ae08745Sheppo case VCC_CONS_ADDED: 5741ae08745Sheppo do_add_cons(vntsdp, inq_data.cons_no); 5751ae08745Sheppo break; 5761ae08745Sheppo 5777636cb21Slm66018 case VCC_CONS_MISS_ADDED: 5787636cb21Slm66018 /* an added port was deleted before vntsd can process it */ 5797636cb21Slm66018 return; 5807636cb21Slm66018 5811ae08745Sheppo default: 5821ae08745Sheppo DERR(stderr, "t@%d daemon_wakeup:ioctl_unknown %d\n", 5831ae08745Sheppo thr_self(), inq_data.reason); 5841ae08745Sheppo vntsd_log(VNTSD_ERR_UNKNOWN_CMD, "from vcc\n"); 5851ae08745Sheppo break; 5861ae08745Sheppo } 5871ae08745Sheppo } 5881ae08745Sheppo 5891ae08745Sheppo /* initial console configuration */ 5901ae08745Sheppo void 5911ae08745Sheppo vntsd_get_config(vntsd_t *vntsdp) 5921ae08745Sheppo { 5931ae08745Sheppo 5941ae08745Sheppo int i; 5951ae08745Sheppo int num_cons; 5961ae08745Sheppo vcc_console_t *consp; 5971ae08745Sheppo vntsd_group_t *groupp; 5981ae08745Sheppo 5991ae08745Sheppo /* num of consoles */ 6001ae08745Sheppo num_cons = 0; 6011ae08745Sheppo 6021ae08745Sheppo if (vntsd_vcc_ioctl(VCC_NUM_CONSOLE, 0, (void *)&num_cons) != 6031ae08745Sheppo VNTSD_SUCCESS) { 6041ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, "VCC_NUM_CONSOLE failed\n"); 6051ae08745Sheppo return; 6061ae08745Sheppo } 6071ae08745Sheppo 6081ae08745Sheppo D3(stderr, "get_config:num_cons=%d", num_cons); 6091ae08745Sheppo 6101ae08745Sheppo if (num_cons == 0) { 6111ae08745Sheppo return; 6121ae08745Sheppo } 6131ae08745Sheppo 6141ae08745Sheppo /* allocate memory for all consoles */ 6151ae08745Sheppo consp = malloc(num_cons*sizeof (vcc_console_t)); 6161ae08745Sheppo 6171ae08745Sheppo if (consp == NULL) { 6181ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "for console table."); 6191ae08745Sheppo return; 6201ae08745Sheppo } 6211ae08745Sheppo 6221ae08745Sheppo /* get console table */ 6231ae08745Sheppo if (vntsd_vcc_ioctl(VCC_CONS_TBL, 0, (void *)consp) != VNTSD_SUCCESS) { 6241ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, " VCC_CONS_TBL " 6251ae08745Sheppo "for console table\n"); 6261ae08745Sheppo return; 6271ae08745Sheppo } 6281ae08745Sheppo 6291ae08745Sheppo /* intialize groups and consoles */ 6301ae08745Sheppo for (i = 0; i < num_cons; i++) { 6311ae08745Sheppo if (alloc_cons_with_group(vntsdp, &consp[i], &groupp) 6321ae08745Sheppo != VNTSD_SUCCESS) { 6331ae08745Sheppo vntsd_log(VNTSD_ERR_ADD_CONS_FAILED, "get_config"); 6341ae08745Sheppo } 6351ae08745Sheppo } 6361ae08745Sheppo 6371ae08745Sheppo /* create listen thread for each group */ 6381ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 6391ae08745Sheppo 6401ae08745Sheppo for (; ; ) { 6411ae08745Sheppo groupp = vntsd_que_walk(vntsdp->grouppq, 6421ae08745Sheppo (el_func_t)create_listen_thread); 6431ae08745Sheppo if (groupp == NULL) { 6441ae08745Sheppo break; 6451ae08745Sheppo } 6461ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, "get config()"); 6471ae08745Sheppo } 6481ae08745Sheppo 6491ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 6501ae08745Sheppo } 651