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
vntsd_notify_client_cons_del(vntsd_client_t * clientp)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
free_cons(vntsd_cons_t * consp)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
free_group(vntsd_group_t * groupp)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
cleanup_cons(vntsd_cons_t * consp)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
find_clean_cons_group(vntsd_group_t * groupp)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
find_clean_cons(vntsd_cons_t * consp)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
vntsd_delete_cons(vntsd_t * vntsdp)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
vntsd_clean_group(vntsd_group_t * groupp)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 *
alloc_cons(vntsd_group_t * groupp,vcc_console_t * consolep)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
grp_by_tcp(vntsd_group_t * groupp,uint64_t * tcp_port)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 *
alloc_group(vntsd_t * vntsdp,char * group_name,uint64_t tcp_port)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
vntsd_mark_deleted_cons(vntsd_cons_t * consp)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
alloc_cons_with_group(vntsd_t * vntsdp,vcc_console_t * consp,vntsd_group_t ** new_groupp)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
create_listen_thread(vntsd_group_t * groupp)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
deleted_cons_by_consno(vntsd_cons_t * consp,int * cons_no)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
find_cons_group_by_cons_no(vntsd_group_t * groupp,uint_t * cons_no)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
delete_cons_before_add(vntsd_t * vntsdp,uint_t cons_no)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
do_add_cons(vntsd_t * vntsdp,int cons_no)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
vntsd_daemon_wakeup(vntsd_t * vntsdp)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
vntsd_get_config(vntsd_t * vntsdp)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