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 /* 22*3c96341aSnarayan * Copyright 2007 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); 724d39be2bSsg70180 if (consp->vcc_fd != -1) 734d39be2bSsg70180 (void) close(consp->vcc_fd); 741ae08745Sheppo free(consp); 751ae08745Sheppo } 761ae08745Sheppo 774d39be2bSsg70180 /* free group structure */ 784d39be2bSsg70180 static void 794d39be2bSsg70180 free_group(vntsd_group_t *groupp) 804d39be2bSsg70180 { 814d39be2bSsg70180 assert(groupp); 824d39be2bSsg70180 (void) mutex_destroy(&groupp->lock); 834d39be2bSsg70180 (void) cond_destroy(&groupp->cvp); 844d39be2bSsg70180 if (groupp->sockfd != -1) 854d39be2bSsg70180 (void) close(groupp->sockfd); 864d39be2bSsg70180 free(groupp); 874d39be2bSsg70180 } 884d39be2bSsg70180 891ae08745Sheppo /* 901ae08745Sheppo * all clients connected to a console must disconnect before 911ae08745Sheppo * removing a console. 921ae08745Sheppo */ 931ae08745Sheppo static void 941ae08745Sheppo cleanup_cons(vntsd_cons_t *consp) 951ae08745Sheppo { 961ae08745Sheppo vntsd_group_t *groupp; 971ae08745Sheppo timestruc_t to; 981ae08745Sheppo 991ae08745Sheppo assert(consp); 1001ae08745Sheppo D1(stderr, "t@%d vntsd_disconn_clients@%d\n", thr_self(), 1011ae08745Sheppo consp->cons_no); 1021ae08745Sheppo 1031ae08745Sheppo groupp = consp->group; 1041ae08745Sheppo assert(groupp); 1051ae08745Sheppo 1061ae08745Sheppo 1071ae08745Sheppo (void) mutex_lock(&consp->lock); 1081ae08745Sheppo 1091ae08745Sheppo /* wait for all clients disconnect from the console */ 1101ae08745Sheppo while (consp->clientpq != NULL) { 1111ae08745Sheppo consp->status |= VNTSD_CONS_SIG_WAIT; 1121ae08745Sheppo 1131ae08745Sheppo /* signal client to disconnect the console */ 1141ae08745Sheppo (void) vntsd_que_walk(consp->clientpq, 1151ae08745Sheppo (el_func_t)vntsd_notify_client_cons_del); 1161ae08745Sheppo 1171ae08745Sheppo (void) thr_kill(consp->wr_tid, SIGUSR1); 1181ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 1191ae08745Sheppo to.tv_nsec = 0; 1201ae08745Sheppo 1211ae08745Sheppo /* wait for clients to disconnect */ 1221ae08745Sheppo (void) cond_reltimedwait(&consp->cvp, &consp->lock, &to); 1231ae08745Sheppo } 1241ae08745Sheppo 1253af08d82Slm66018 /* reduce console count in the group */ 1263af08d82Slm66018 (void) mutex_lock(&groupp->lock); 1273af08d82Slm66018 assert(groupp->num_cons > 0); 1283af08d82Slm66018 groupp->num_cons--; 1293af08d82Slm66018 (void) mutex_unlock(&groupp->lock); 1303af08d82Slm66018 1311ae08745Sheppo (void) mutex_unlock(&consp->lock); 1321ae08745Sheppo 1331ae08745Sheppo free_cons(consp); 1341ae08745Sheppo } 1351ae08745Sheppo 1361ae08745Sheppo /* search for a group whose console is being deleted */ 1371ae08745Sheppo static boolean_t 1381ae08745Sheppo find_clean_cons_group(vntsd_group_t *groupp) 1391ae08745Sheppo { 1401ae08745Sheppo if (groupp->status & VNTSD_GROUP_CLEAN_CONS) { 1411ae08745Sheppo return (B_TRUE); 1421ae08745Sheppo } else { 1431ae08745Sheppo return (B_FALSE); 1441ae08745Sheppo } 1451ae08745Sheppo } 1461ae08745Sheppo 1471ae08745Sheppo /* search for a console that is being deleted */ 1481ae08745Sheppo static boolean_t 1491ae08745Sheppo find_clean_cons(vntsd_cons_t *consp) 1501ae08745Sheppo { 1511ae08745Sheppo if (consp->status & VNTSD_CONS_DELETED) { 1521ae08745Sheppo return (B_TRUE); 1531ae08745Sheppo } else { 1541ae08745Sheppo return (B_FALSE); 1551ae08745Sheppo } 1561ae08745Sheppo } 1571ae08745Sheppo 1581ae08745Sheppo /* delete a console */ 1591ae08745Sheppo void 1601ae08745Sheppo vntsd_delete_cons(vntsd_t *vntsdp) 1611ae08745Sheppo { 1621ae08745Sheppo vntsd_group_t *groupp; 1631ae08745Sheppo vntsd_cons_t *consp; 1641ae08745Sheppo 1651ae08745Sheppo for (; ; ) { 1661ae08745Sheppo /* get the group contains deleted console */ 1671ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 1681ae08745Sheppo groupp = vntsd_que_walk(vntsdp->grouppq, 1691ae08745Sheppo (el_func_t)find_clean_cons_group); 1701ae08745Sheppo if (groupp == NULL) { 1711ae08745Sheppo /* no more group has console deleted */ 1721ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 1731ae08745Sheppo return; 1741ae08745Sheppo } 1757636cb21Slm66018 (void) mutex_lock(&groupp->lock); 1761ae08745Sheppo groupp->status &= ~VNTSD_GROUP_CLEAN_CONS; 1777636cb21Slm66018 (void) mutex_unlock(&groupp->lock); 1781ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 1791ae08745Sheppo 1801ae08745Sheppo for (; ; ) { 1811ae08745Sheppo /* get the console to be deleted */ 1821ae08745Sheppo (void) mutex_lock(&groupp->lock); 1834d39be2bSsg70180 1844d39be2bSsg70180 /* clean up any deleted console in the group */ 1854d39be2bSsg70180 if (groupp->conspq != NULL) { 1861ae08745Sheppo consp = vntsd_que_walk(groupp->conspq, 1871ae08745Sheppo (el_func_t)find_clean_cons); 1881ae08745Sheppo if (consp == NULL) { 1891ae08745Sheppo /* no more cons to delete */ 1901ae08745Sheppo (void) mutex_unlock(&groupp->lock); 1911ae08745Sheppo break; 1921ae08745Sheppo } 1931ae08745Sheppo 1941ae08745Sheppo /* remove console from the group */ 1951ae08745Sheppo (void) vntsd_que_rm(&groupp->conspq, consp); 1961ae08745Sheppo (void) mutex_unlock(&groupp->lock); 1971ae08745Sheppo 1981ae08745Sheppo /* clean up the console */ 1991ae08745Sheppo cleanup_cons(consp); 2004d39be2bSsg70180 } 2011ae08745Sheppo 2021ae08745Sheppo /* delete group? */ 2034d39be2bSsg70180 if (groupp->conspq == NULL) { 2044d39be2bSsg70180 /* no more console in the group delete group */ 2051ae08745Sheppo assert(groupp->vntsd); 2061ae08745Sheppo 2071ae08745Sheppo (void) mutex_lock(&groupp->vntsd->lock); 2081ae08745Sheppo (void) vntsd_que_rm(&groupp->vntsd->grouppq, 2091ae08745Sheppo groupp); 2101ae08745Sheppo (void) mutex_unlock(&groupp->vntsd->lock); 2111ae08745Sheppo 2121ae08745Sheppo /* clean up the group */ 2131ae08745Sheppo vntsd_clean_group(groupp); 2141ae08745Sheppo break; 2151ae08745Sheppo } 2161ae08745Sheppo } 2171ae08745Sheppo } 2181ae08745Sheppo } 2191ae08745Sheppo 2201ae08745Sheppo /* clean up a group */ 2211ae08745Sheppo void 2221ae08745Sheppo vntsd_clean_group(vntsd_group_t *groupp) 2231ae08745Sheppo { 2241ae08745Sheppo 2251ae08745Sheppo timestruc_t to; 2261ae08745Sheppo 2271ae08745Sheppo D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(), 2281ae08745Sheppo groupp->group_name, groupp->tcp_port); 2291ae08745Sheppo 2301ae08745Sheppo (void) mutex_lock(&groupp->lock); 2311ae08745Sheppo 2321ae08745Sheppo /* prevent from reentry */ 2334d39be2bSsg70180 if (groupp->status & VNTSD_GROUP_IN_CLEANUP) { 2341ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2351ae08745Sheppo return; 2361ae08745Sheppo } 2374d39be2bSsg70180 groupp->status |= VNTSD_GROUP_IN_CLEANUP; 2384d39be2bSsg70180 2394d39be2bSsg70180 /* mark group waiting for listen thread to exits */ 2404d39be2bSsg70180 groupp->status |= VNTSD_GROUP_SIG_WAIT; 2411ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2421ae08745Sheppo 2433af08d82Slm66018 vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons); 2443af08d82Slm66018 2454d39be2bSsg70180 (void) mutex_lock(&groupp->lock); 2461ae08745Sheppo /* walk through no cons client queue */ 2471ae08745Sheppo while (groupp->no_cons_clientpq != NULL) { 2481ae08745Sheppo (void) vntsd_que_walk(groupp->no_cons_clientpq, 2491ae08745Sheppo (el_func_t)vntsd_notify_client_cons_del); 2501ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 2511ae08745Sheppo to.tv_nsec = 0; 2521ae08745Sheppo (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); 2531ae08745Sheppo } 2541ae08745Sheppo 2554d39be2bSsg70180 /* waiting for listen thread to exit */ 2561ae08745Sheppo while (groupp->status & VNTSD_GROUP_SIG_WAIT) { 2574d39be2bSsg70180 /* signal listen thread to exit */ 2581ae08745Sheppo (void) thr_kill(groupp->listen_tid, SIGUSR1); 2591ae08745Sheppo to.tv_sec = VNTSD_CV_WAIT_DELTIME; 2601ae08745Sheppo to.tv_nsec = 0; 2611ae08745Sheppo /* wait listen thread to exit */ 2621ae08745Sheppo (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); 2631ae08745Sheppo } 2641ae08745Sheppo 2651ae08745Sheppo (void) mutex_unlock(&groupp->lock); 2661ae08745Sheppo (void) thr_join(groupp->listen_tid, NULL, NULL); 2671ae08745Sheppo /* free group */ 2684d39be2bSsg70180 free_group(groupp); 2691ae08745Sheppo } 2701ae08745Sheppo 2711ae08745Sheppo /* allocate and initialize console structure */ 2721ae08745Sheppo static vntsd_cons_t * 2731ae08745Sheppo alloc_cons(vntsd_group_t *groupp, vcc_console_t *consolep) 2741ae08745Sheppo { 2751ae08745Sheppo vntsd_cons_t *consp; 2761ae08745Sheppo int rv; 2771ae08745Sheppo 2781ae08745Sheppo /* allocate console */ 2791ae08745Sheppo consp = (vntsd_cons_t *)malloc(sizeof (vntsd_cons_t)); 2801ae08745Sheppo if (consp == NULL) { 2811ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "alloc_cons"); 2821ae08745Sheppo return (NULL); 2831ae08745Sheppo } 2841ae08745Sheppo 2851ae08745Sheppo /* intialize console */ 2861ae08745Sheppo bzero(consp, sizeof (vntsd_cons_t)); 2871ae08745Sheppo 2881ae08745Sheppo (void) mutex_init(&consp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 2891ae08745Sheppo (void) cond_init(&consp->cvp, USYNC_THREAD, NULL); 2901ae08745Sheppo 2911ae08745Sheppo consp->cons_no = consolep->cons_no; 2921ae08745Sheppo (void) strlcpy(consp->domain_name, consolep->domain_name, MAXPATHLEN); 2931ae08745Sheppo (void) strlcpy(consp->dev_name, consolep->dev_name, MAXPATHLEN); 2941ae08745Sheppo consp->wr_tid = (thread_t)-1; 2954d39be2bSsg70180 consp->vcc_fd = -1; 2961ae08745Sheppo 2971ae08745Sheppo /* join the group */ 2981ae08745Sheppo (void) mutex_lock(&groupp->lock); 2991ae08745Sheppo 3001ae08745Sheppo if ((rv = vntsd_que_append(&groupp->conspq, consp)) != 3011ae08745Sheppo VNTSD_SUCCESS) { 3021ae08745Sheppo (void) mutex_unlock(&groupp->lock); 3031ae08745Sheppo vntsd_log(rv, "alloc_cons"); 3041ae08745Sheppo free_cons(consp); 3051ae08745Sheppo return (NULL); 3061ae08745Sheppo } 3071ae08745Sheppo groupp->num_cons++; 3081ae08745Sheppo consp->group = groupp; 3091ae08745Sheppo 3101ae08745Sheppo (void) mutex_unlock(&groupp->lock); 3111ae08745Sheppo 3121ae08745Sheppo D1(stderr, "t@%d alloc_cons@%d %s %s\n", thr_self(), 3131ae08745Sheppo consp->cons_no, consp->domain_name, consp->dev_name); 3141ae08745Sheppo 3151ae08745Sheppo return (consp); 3161ae08745Sheppo } 3171ae08745Sheppo 3181ae08745Sheppo /* compare tcp with group->tcp */ 3191ae08745Sheppo static boolean_t 3201ae08745Sheppo grp_by_tcp(vntsd_group_t *groupp, uint64_t *tcp_port) 3211ae08745Sheppo { 3221ae08745Sheppo assert(groupp); 3231ae08745Sheppo assert(tcp_port); 3241ae08745Sheppo return (groupp->tcp_port == *tcp_port); 3251ae08745Sheppo } 3261ae08745Sheppo 3271ae08745Sheppo /* allocate and initialize group */ 3281ae08745Sheppo static vntsd_group_t * 3291ae08745Sheppo alloc_group(vntsd_t *vntsdp, char *group_name, uint64_t tcp_port) 3301ae08745Sheppo { 3311ae08745Sheppo vntsd_group_t *groupp; 3321ae08745Sheppo 3331ae08745Sheppo /* allocate group */ 3341ae08745Sheppo groupp = (vntsd_group_t *)malloc(sizeof (vntsd_group_t)); 3351ae08745Sheppo if (groupp == NULL) { 3361ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "alloc_group"); 3371ae08745Sheppo return (NULL); 3381ae08745Sheppo } 3391ae08745Sheppo 3401ae08745Sheppo /* initialize group */ 3411ae08745Sheppo bzero(groupp, sizeof (vntsd_group_t)); 3421ae08745Sheppo 3431ae08745Sheppo (void) mutex_init(&groupp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); 3441ae08745Sheppo (void) cond_init(&groupp->cvp, USYNC_THREAD, NULL); 3451ae08745Sheppo 3461ae08745Sheppo if (group_name != NULL) { 3471ae08745Sheppo (void) memcpy(groupp->group_name, group_name, MAXPATHLEN); 3481ae08745Sheppo } 3491ae08745Sheppo 3501ae08745Sheppo groupp->tcp_port = tcp_port; 3511ae08745Sheppo groupp->listen_tid = (thread_t)-1; 3524d39be2bSsg70180 groupp->sockfd = -1; 3531ae08745Sheppo groupp->vntsd = vntsdp; 3541ae08745Sheppo 3551ae08745Sheppo D1(stderr, "t@%d alloc_group@%lld:%s\n", thr_self(), groupp->tcp_port, 3561ae08745Sheppo groupp->group_name); 3571ae08745Sheppo 3581ae08745Sheppo return (groupp); 3591ae08745Sheppo } 3601ae08745Sheppo 3614d39be2bSsg70180 /* mark a deleted console */ 3624d39be2bSsg70180 boolean_t 3634d39be2bSsg70180 vntsd_mark_deleted_cons(vntsd_cons_t *consp) 3644d39be2bSsg70180 { 3654d39be2bSsg70180 (void) mutex_lock(&consp->lock); 3664d39be2bSsg70180 consp->status |= VNTSD_CONS_DELETED; 3674d39be2bSsg70180 (void) mutex_unlock(&consp->lock); 3684d39be2bSsg70180 return (B_FALSE); 3694d39be2bSsg70180 } 3704d39be2bSsg70180 3711ae08745Sheppo /* 3721ae08745Sheppo * Initialize a console, if console is associated with with a 3731ae08745Sheppo * new group, intialize the group. 3741ae08745Sheppo */ 3751ae08745Sheppo static int 3761ae08745Sheppo alloc_cons_with_group(vntsd_t *vntsdp, vcc_console_t *consp, 3771ae08745Sheppo vntsd_group_t **new_groupp) 3781ae08745Sheppo { 3791ae08745Sheppo vntsd_group_t *groupp = NULL; 3801ae08745Sheppo int rv; 3811ae08745Sheppo 3821ae08745Sheppo *new_groupp = NULL; 3831ae08745Sheppo 3841ae08745Sheppo /* match group by tcp port */ 3851ae08745Sheppo 3861ae08745Sheppo 3871ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 3881ae08745Sheppo groupp = vntsd_que_find(vntsdp->grouppq, 3891ae08745Sheppo (compare_func_t)grp_by_tcp, (void *)&(consp->tcp_port)); 3904d39be2bSsg70180 if (groupp != NULL) 3914d39be2bSsg70180 (void) mutex_lock(&groupp->lock); 3924d39be2bSsg70180 3931ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 3941ae08745Sheppo 3951ae08745Sheppo if (groupp != NULL) { 3964d39be2bSsg70180 /* 3974d39be2bSsg70180 * group with same tcp port found. 3984d39be2bSsg70180 * if there is no console in the group, the 3994d39be2bSsg70180 * group should be removed and the tcp port can 4004d39be2bSsg70180 * be used for tne new group. 4014d39be2bSsg70180 * This is possible, when there is tight loop of 4024d39be2bSsg70180 * creating/deleting domains. When a vcc port is 4034d39be2bSsg70180 * removed, a read thread will have an I/O error because 4044d39be2bSsg70180 * vcc has closed the port. The read thread then marks 4054d39be2bSsg70180 * the console is removed and notify main thread to 4064d39be2bSsg70180 * remove the console. 4074d39be2bSsg70180 * Meanwhile, the same port and its group (with same 4084d39be2bSsg70180 * tcp port and group name) is created. Vcc notify 4094d39be2bSsg70180 * vntsd that new console is added. 4104d39be2bSsg70180 * Main thread now have two events. If main thread polls 4114d39be2bSsg70180 * out vcc notification first, it will find that there is 4124d39be2bSsg70180 * a group has no console. 4134d39be2bSsg70180 */ 4141ae08745Sheppo 4154d39be2bSsg70180 if (vntsd_chk_group_total_cons(groupp) == 0) { 4164d39be2bSsg70180 4174d39be2bSsg70180 /* all consoles in the group have been removed */ 4184d39be2bSsg70180 (void) vntsd_que_walk(groupp->conspq, 4194d39be2bSsg70180 (el_func_t)vntsd_mark_deleted_cons); 4204d39be2bSsg70180 groupp->status |= VNTSD_GROUP_CLEAN_CONS; 4214d39be2bSsg70180 (void) mutex_unlock(&groupp->lock); 4224d39be2bSsg70180 groupp = NULL; 4234d39be2bSsg70180 4244d39be2bSsg70180 } else if (strcmp(groupp->group_name, consp->group_name)) { 4251ae08745Sheppo /* conflict group name */ 4261ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_GRP_NAME, 4271ae08745Sheppo "group name is different from existing group"); 4284d39be2bSsg70180 (void) mutex_unlock(&groupp->lock); 4291ae08745Sheppo return (VNTSD_ERR_VCC_CTRL_DATA); 4301ae08745Sheppo 4311ae08745Sheppo } else { 4324d39be2bSsg70180 /* group already existed */ 4334d39be2bSsg70180 (void) mutex_unlock(&groupp->lock); 4344d39be2bSsg70180 } 4354d39be2bSsg70180 4364d39be2bSsg70180 } 4374d39be2bSsg70180 4384d39be2bSsg70180 if (groupp == NULL) { 4391ae08745Sheppo /* new group */ 4401ae08745Sheppo groupp = alloc_group(vntsdp, consp->group_name, 4411ae08745Sheppo consp->tcp_port); 4421ae08745Sheppo if (groupp == NULL) { 4431ae08745Sheppo return (VNTSD_ERR_NO_MEM); 4441ae08745Sheppo } 4451ae08745Sheppo 4461ae08745Sheppo assert(groupp->conspq == NULL); 4471ae08745Sheppo /* queue group to vntsdp */ 4481ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 4491ae08745Sheppo rv = vntsd_que_append(&vntsdp->grouppq, groupp); 4501ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 4511ae08745Sheppo 4521ae08745Sheppo if (rv != VNTSD_SUCCESS) { 4531ae08745Sheppo return (rv); 4541ae08745Sheppo } 4551ae08745Sheppo 4561ae08745Sheppo *new_groupp = groupp; 4571ae08745Sheppo } 4581ae08745Sheppo 4591ae08745Sheppo /* intialize console */ 4601ae08745Sheppo if (alloc_cons(groupp, consp) == NULL) { 4611ae08745Sheppo /* no memory */ 4621ae08745Sheppo if (new_groupp != NULL) { 4631ae08745Sheppo /* clean up new group */ 4644d39be2bSsg70180 free_group(groupp); 4651ae08745Sheppo } 4661ae08745Sheppo 4671ae08745Sheppo return (VNTSD_ERR_NO_MEM); 4681ae08745Sheppo } 4691ae08745Sheppo 4701ae08745Sheppo return (VNTSD_SUCCESS); 4711ae08745Sheppo 4721ae08745Sheppo } 4731ae08745Sheppo 4741ae08745Sheppo 4751ae08745Sheppo /* create listen thread */ 4761ae08745Sheppo static boolean_t 4771ae08745Sheppo create_listen_thread(vntsd_group_t *groupp) 4781ae08745Sheppo { 4791ae08745Sheppo 4801ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 4811ae08745Sheppo int rv; 4821ae08745Sheppo 4831ae08745Sheppo assert(groupp); 4841ae08745Sheppo 4851ae08745Sheppo (void) mutex_lock(&groupp->lock); 4861ae08745Sheppo assert(groupp->num_cons); 4871ae08745Sheppo 4881ae08745Sheppo D1(stderr, "t@%d create_listen:%lld\n", thr_self(), groupp->tcp_port); 4891ae08745Sheppo 4901ae08745Sheppo if ((rv = thr_create(NULL, 0, (thr_func_t)vntsd_listen_thread, 4911ae08745Sheppo (void *)groupp, THR_DETACHED, &groupp->listen_tid)) 4921ae08745Sheppo != 0) { 4931ae08745Sheppo (void) (void) snprintf(err_msg, sizeof (err_msg), 4941ae08745Sheppo "Can not create listen thread for" 4951ae08745Sheppo "group %s tcp %llx\n", groupp->group_name, 4961ae08745Sheppo groupp->tcp_port); 4971ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); 4981ae08745Sheppo 4991ae08745Sheppo /* clean up group queue */ 5001ae08745Sheppo vntsd_free_que(&groupp->conspq, (clean_func_t)free_cons); 5011ae08745Sheppo groupp->listen_tid = (thread_t)-1; 5021ae08745Sheppo } 5031ae08745Sheppo 5041ae08745Sheppo (void) mutex_unlock(&groupp->lock); 5051ae08745Sheppo 5061ae08745Sheppo return (rv != 0); 5071ae08745Sheppo } 5081ae08745Sheppo 5094d39be2bSsg70180 /* find deleted console by console no */ 5104d39be2bSsg70180 static boolean_t 5114d39be2bSsg70180 deleted_cons_by_consno(vntsd_cons_t *consp, int *cons_no) 5124d39be2bSsg70180 { 5134d39be2bSsg70180 vntsd_client_t *clientp; 5144d39be2bSsg70180 5154d39be2bSsg70180 assert(consp); 5164d39be2bSsg70180 5174d39be2bSsg70180 if (consp->cons_no != *cons_no) 5184d39be2bSsg70180 return (B_FALSE); 5194d39be2bSsg70180 5204d39be2bSsg70180 /* has console marked as deleted? */ 5214d39be2bSsg70180 if ((consp->status & VNTSD_CONS_DELETED) == 0) 5224d39be2bSsg70180 return (B_TRUE); 5234d39be2bSsg70180 524*3c96341aSnarayan if (consp->clientpq == NULL) 525*3c96341aSnarayan /* there is no client for this console */ 5264d39be2bSsg70180 return (B_TRUE); 5274d39be2bSsg70180 528*3c96341aSnarayan /* need to notify clients of console ? */ 529*3c96341aSnarayan clientp = (vntsd_client_t *)consp->clientpq->handle; 530*3c96341aSnarayan 5314d39be2bSsg70180 if (clientp->status & VNTSD_CLIENT_CONS_DELETED) 5324d39be2bSsg70180 /* clients of console have notified */ 5334d39be2bSsg70180 return (B_FALSE); 5344d39be2bSsg70180 5354d39be2bSsg70180 return (B_TRUE); 5364d39be2bSsg70180 } 5374d39be2bSsg70180 5384d39be2bSsg70180 /* find group structure from console no */ 5394d39be2bSsg70180 static boolean_t 5404d39be2bSsg70180 find_cons_group_by_cons_no(vntsd_group_t *groupp, uint_t *cons_no) 5414d39be2bSsg70180 { 5424d39be2bSsg70180 vntsd_cons_t *consp; 5434d39be2bSsg70180 5444d39be2bSsg70180 consp = vntsd_que_find(groupp->conspq, 5454d39be2bSsg70180 (compare_func_t)deleted_cons_by_consno, cons_no); 5464d39be2bSsg70180 return (consp != NULL); 5474d39be2bSsg70180 5484d39be2bSsg70180 } 5494d39be2bSsg70180 5501ae08745Sheppo /* delete a console if the console exists in the vntsd */ 5511ae08745Sheppo static void 5524d39be2bSsg70180 delete_cons_before_add(vntsd_t *vntsdp, uint_t cons_no) 5531ae08745Sheppo { 5541ae08745Sheppo vntsd_group_t *groupp; 5551ae08745Sheppo vntsd_cons_t *consp; 5561ae08745Sheppo 5571ae08745Sheppo /* group exists? */ 5581ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 5594d39be2bSsg70180 groupp = vntsd_que_find(vntsdp->grouppq, 5604d39be2bSsg70180 (compare_func_t)find_cons_group_by_cons_no, 5614d39be2bSsg70180 &cons_no); 5621ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 5631ae08745Sheppo 5641ae08745Sheppo if (groupp == NULL) { 5651ae08745Sheppo /* no such group */ 5661ae08745Sheppo return; 5671ae08745Sheppo } 5681ae08745Sheppo 5691ae08745Sheppo /* group exists, if console exists? */ 5701ae08745Sheppo (void) mutex_lock(&groupp->lock); 5711ae08745Sheppo consp = vntsd_que_find(groupp->conspq, 5724d39be2bSsg70180 (compare_func_t)deleted_cons_by_consno, &cons_no); 5731ae08745Sheppo 5741ae08745Sheppo if (consp == NULL) { 5751ae08745Sheppo /* no such console */ 5761ae08745Sheppo (void) mutex_unlock(&groupp->lock); 5771ae08745Sheppo return; 5781ae08745Sheppo } 5791ae08745Sheppo 580*3c96341aSnarayan /* console exists - mark console for main thread to delete it */ 5811ae08745Sheppo (void) mutex_lock(&consp->lock); 5821ae08745Sheppo 583*3c96341aSnarayan if (consp->status & VNTSD_CONS_DELETED) { 584*3c96341aSnarayan /* already marked */ 585*3c96341aSnarayan (void) mutex_unlock(&consp->lock); 586*3c96341aSnarayan (void) mutex_unlock(&groupp->lock); 587*3c96341aSnarayan return; 588*3c96341aSnarayan } 589*3c96341aSnarayan 5901ae08745Sheppo consp->status |= VNTSD_CONS_DELETED; 5911ae08745Sheppo groupp->status |= VNTSD_GROUP_CLEAN_CONS; 5921ae08745Sheppo 5931ae08745Sheppo (void) mutex_unlock(&consp->lock); 5941ae08745Sheppo (void) mutex_unlock(&groupp->lock); 5951ae08745Sheppo 5961ae08745Sheppo } 5971ae08745Sheppo 5981ae08745Sheppo /* add a console */ 5991ae08745Sheppo static void 6001ae08745Sheppo do_add_cons(vntsd_t *vntsdp, int cons_no) 6011ae08745Sheppo { 6021ae08745Sheppo vcc_console_t console; 6031ae08745Sheppo vntsd_group_t *groupp; 6041ae08745Sheppo int rv; 6051ae08745Sheppo char err_msg[VNTSD_LINE_LEN]; 6061ae08745Sheppo 6071ae08745Sheppo 6081ae08745Sheppo (void) snprintf(err_msg, sizeof (err_msg), 6091ae08745Sheppo "do_add_cons():Can not add console=%d", cons_no); 6101ae08745Sheppo 6111ae08745Sheppo /* get console configuration from vcc */ 6121ae08745Sheppo 6131ae08745Sheppo if ((rv = vntsd_vcc_ioctl(VCC_CONS_INFO, cons_no, (void *)&console)) 6141ae08745Sheppo != VNTSD_SUCCESS) { 6151ae08745Sheppo vntsd_log(rv, err_msg); 6161ae08745Sheppo return; 6171ae08745Sheppo } 6181ae08745Sheppo 6191ae08745Sheppo /* clean up the console if console was deleted and added again */ 6204d39be2bSsg70180 delete_cons_before_add(vntsdp, console.cons_no); 6211ae08745Sheppo 6221ae08745Sheppo /* initialize console */ 6231ae08745Sheppo 6241ae08745Sheppo if ((rv = alloc_cons_with_group(vntsdp, &console, &groupp)) != 6251ae08745Sheppo VNTSD_SUCCESS) { 6261ae08745Sheppo /* no memory to add this new console */ 6271ae08745Sheppo vntsd_log(rv, err_msg); 6281ae08745Sheppo return; 6291ae08745Sheppo } 6301ae08745Sheppo 6311ae08745Sheppo if (groupp != NULL) { 6321ae08745Sheppo /* new group */ 6331ae08745Sheppo /* create listen thread for this console */ 6341ae08745Sheppo if (create_listen_thread(groupp)) { 6351ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); 6364d39be2bSsg70180 free_group(groupp); 6371ae08745Sheppo } 6381ae08745Sheppo 6391ae08745Sheppo } 6401ae08745Sheppo } 6411ae08745Sheppo 6421ae08745Sheppo /* daemon wake up */ 6431ae08745Sheppo void 6441ae08745Sheppo vntsd_daemon_wakeup(vntsd_t *vntsdp) 6451ae08745Sheppo { 6461ae08745Sheppo 6471ae08745Sheppo vcc_response_t inq_data; 6481ae08745Sheppo 6491ae08745Sheppo /* reason to wake up */ 6501ae08745Sheppo if (vntsd_vcc_ioctl(VCC_INQUIRY, 0, (void *)&inq_data) != 6511ae08745Sheppo VNTSD_SUCCESS) { 6521ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, "vntsd_daemon_wakeup()"); 6531ae08745Sheppo return; 6541ae08745Sheppo } 6551ae08745Sheppo 6561ae08745Sheppo D1(stderr, "t@%d vntsd_daemon_wakup:msg %d port %x\n", thr_self(), 6571ae08745Sheppo inq_data.reason, inq_data.cons_no); 6581ae08745Sheppo 6591ae08745Sheppo switch (inq_data.reason) { 6601ae08745Sheppo 6611ae08745Sheppo case VCC_CONS_ADDED: 6621ae08745Sheppo do_add_cons(vntsdp, inq_data.cons_no); 6631ae08745Sheppo break; 6641ae08745Sheppo 6657636cb21Slm66018 case VCC_CONS_MISS_ADDED: 6667636cb21Slm66018 /* an added port was deleted before vntsd can process it */ 6677636cb21Slm66018 return; 6687636cb21Slm66018 6691ae08745Sheppo default: 6701ae08745Sheppo DERR(stderr, "t@%d daemon_wakeup:ioctl_unknown %d\n", 6711ae08745Sheppo thr_self(), inq_data.reason); 6721ae08745Sheppo vntsd_log(VNTSD_ERR_UNKNOWN_CMD, "from vcc\n"); 6731ae08745Sheppo break; 6741ae08745Sheppo } 6751ae08745Sheppo } 6761ae08745Sheppo 6771ae08745Sheppo /* initial console configuration */ 6781ae08745Sheppo void 6791ae08745Sheppo vntsd_get_config(vntsd_t *vntsdp) 6801ae08745Sheppo { 6811ae08745Sheppo 6821ae08745Sheppo int i; 6831ae08745Sheppo int num_cons; 6841ae08745Sheppo vcc_console_t *consp; 6851ae08745Sheppo vntsd_group_t *groupp; 6861ae08745Sheppo 6871ae08745Sheppo /* num of consoles */ 6881ae08745Sheppo num_cons = 0; 6891ae08745Sheppo 6901ae08745Sheppo if (vntsd_vcc_ioctl(VCC_NUM_CONSOLE, 0, (void *)&num_cons) != 6911ae08745Sheppo VNTSD_SUCCESS) { 6921ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, "VCC_NUM_CONSOLE failed\n"); 6931ae08745Sheppo return; 6941ae08745Sheppo } 6951ae08745Sheppo 6961ae08745Sheppo D3(stderr, "get_config:num_cons=%d", num_cons); 6971ae08745Sheppo 6981ae08745Sheppo if (num_cons == 0) { 6991ae08745Sheppo return; 7001ae08745Sheppo } 7011ae08745Sheppo 7021ae08745Sheppo /* allocate memory for all consoles */ 7031ae08745Sheppo consp = malloc(num_cons*sizeof (vcc_console_t)); 7041ae08745Sheppo 7051ae08745Sheppo if (consp == NULL) { 7061ae08745Sheppo vntsd_log(VNTSD_ERR_NO_MEM, "for console table."); 7071ae08745Sheppo return; 7081ae08745Sheppo } 7091ae08745Sheppo 7101ae08745Sheppo /* get console table */ 7111ae08745Sheppo if (vntsd_vcc_ioctl(VCC_CONS_TBL, 0, (void *)consp) != VNTSD_SUCCESS) { 7121ae08745Sheppo vntsd_log(VNTSD_ERR_VCC_IOCTL, " VCC_CONS_TBL " 7131ae08745Sheppo "for console table\n"); 7141ae08745Sheppo return; 7151ae08745Sheppo } 7161ae08745Sheppo 7171ae08745Sheppo /* intialize groups and consoles */ 7181ae08745Sheppo for (i = 0; i < num_cons; i++) { 7191ae08745Sheppo if (alloc_cons_with_group(vntsdp, &consp[i], &groupp) 7201ae08745Sheppo != VNTSD_SUCCESS) { 7211ae08745Sheppo vntsd_log(VNTSD_ERR_ADD_CONS_FAILED, "get_config"); 7221ae08745Sheppo } 7231ae08745Sheppo } 7241ae08745Sheppo 7251ae08745Sheppo /* create listen thread for each group */ 7261ae08745Sheppo (void) mutex_lock(&vntsdp->lock); 7271ae08745Sheppo 7281ae08745Sheppo for (; ; ) { 7291ae08745Sheppo groupp = vntsd_que_walk(vntsdp->grouppq, 7301ae08745Sheppo (el_func_t)create_listen_thread); 7311ae08745Sheppo if (groupp == NULL) { 7321ae08745Sheppo break; 7331ae08745Sheppo } 7341ae08745Sheppo vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, "get config()"); 7351ae08745Sheppo } 7361ae08745Sheppo 7371ae08745Sheppo (void) mutex_unlock(&vntsdp->lock); 7381ae08745Sheppo } 739