xref: /titanic_53/usr/src/cmd/vntsd/vntsdvcc.c (revision 3af08d828975d7e2581b6829e0eecff14d87a483)
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