xref: /titanic_50/usr/src/cmd/vntsd/vntsdvcc.c (revision 1ae0874509b6811fdde1dfd46f0d93fd09867a3f)
1*1ae08745Sheppo /*
2*1ae08745Sheppo  * CDDL HEADER START
3*1ae08745Sheppo  *
4*1ae08745Sheppo  * The contents of this file are subject to the terms of the
5*1ae08745Sheppo  * Common Development and Distribution License (the "License").
6*1ae08745Sheppo  * You may not use this file except in compliance with the License.
7*1ae08745Sheppo  *
8*1ae08745Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1ae08745Sheppo  * or http://www.opensolaris.org/os/licensing.
10*1ae08745Sheppo  * See the License for the specific language governing permissions
11*1ae08745Sheppo  * and limitations under the License.
12*1ae08745Sheppo  *
13*1ae08745Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
14*1ae08745Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1ae08745Sheppo  * If applicable, add the following below this CDDL HEADER, with the
16*1ae08745Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
17*1ae08745Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1ae08745Sheppo  *
19*1ae08745Sheppo  * CDDL HEADER END
20*1ae08745Sheppo  */
21*1ae08745Sheppo /*
22*1ae08745Sheppo  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*1ae08745Sheppo  * Use is subject to license terms.
24*1ae08745Sheppo  */
25*1ae08745Sheppo #pragma ident	"%Z%%M%	%I%	%E% SMI"
26*1ae08745Sheppo 
27*1ae08745Sheppo /*
28*1ae08745Sheppo  * Configuration and setup interface to vcc driver.
29*1ae08745Sheppo  * At intialization time, vntsd opens vcc ctrl port and read initial
30*1ae08745Sheppo  * configuratioa. It manages console groups, creates the listen thread,
31*1ae08745Sheppo  * dynamically adds and removes virtual console within a group.
32*1ae08745Sheppo  */
33*1ae08745Sheppo 
34*1ae08745Sheppo 
35*1ae08745Sheppo #include <syslog.h>
36*1ae08745Sheppo #include <stdio.h>
37*1ae08745Sheppo #include <sys/types.h>
38*1ae08745Sheppo #include <sys/ipc.h>
39*1ae08745Sheppo #include <stdlib.h>
40*1ae08745Sheppo #include <string.h>
41*1ae08745Sheppo #include <unistd.h>
42*1ae08745Sheppo #include <sys/socket.h>
43*1ae08745Sheppo #include <sys/ipc.h>
44*1ae08745Sheppo #include <sys/shm.h>
45*1ae08745Sheppo #include <sys/sem.h>
46*1ae08745Sheppo #include <wait.h>
47*1ae08745Sheppo #include <time.h>
48*1ae08745Sheppo #include <synch.h>
49*1ae08745Sheppo #include <netinet/in.h>
50*1ae08745Sheppo #include <thread.h>
51*1ae08745Sheppo #include <signal.h>
52*1ae08745Sheppo #include "vntsd.h"
53*1ae08745Sheppo 
54*1ae08745Sheppo /* signal all clients that console has been deleted */
55*1ae08745Sheppo boolean_t
56*1ae08745Sheppo vntsd_notify_client_cons_del(vntsd_client_t *clientp)
57*1ae08745Sheppo {
58*1ae08745Sheppo 	(void) mutex_lock(&clientp->lock);
59*1ae08745Sheppo 	clientp->status |= VNTSD_CLIENT_CONS_DELETED;
60*1ae08745Sheppo 	(void) thr_kill(clientp->cons_tid, SIGUSR1);
61*1ae08745Sheppo 	(void) mutex_unlock(&clientp->lock);
62*1ae08745Sheppo 	return (B_FALSE);
63*1ae08745Sheppo }
64*1ae08745Sheppo 
65*1ae08745Sheppo /* free console  structure */
66*1ae08745Sheppo static void
67*1ae08745Sheppo free_cons(vntsd_cons_t *consp)
68*1ae08745Sheppo {
69*1ae08745Sheppo 	assert(consp);
70*1ae08745Sheppo 	(void) mutex_destroy(&consp->lock);
71*1ae08745Sheppo 	(void) cond_destroy(&consp->cvp);
72*1ae08745Sheppo 	free(consp);
73*1ae08745Sheppo }
74*1ae08745Sheppo 
75*1ae08745Sheppo /*
76*1ae08745Sheppo  *  all clients connected to a console must disconnect before
77*1ae08745Sheppo  *  removing a console.
78*1ae08745Sheppo  */
79*1ae08745Sheppo static void
80*1ae08745Sheppo cleanup_cons(vntsd_cons_t *consp)
81*1ae08745Sheppo {
82*1ae08745Sheppo 	vntsd_group_t	*groupp;
83*1ae08745Sheppo 	timestruc_t	to;
84*1ae08745Sheppo 
85*1ae08745Sheppo 	assert(consp);
86*1ae08745Sheppo 	D1(stderr, "t@%d vntsd_disconn_clients@%d\n", thr_self(),
87*1ae08745Sheppo 	    consp->cons_no);
88*1ae08745Sheppo 
89*1ae08745Sheppo 	groupp = consp->group;
90*1ae08745Sheppo 	assert(groupp);
91*1ae08745Sheppo 
92*1ae08745Sheppo 
93*1ae08745Sheppo 	(void) mutex_lock(&consp->lock);
94*1ae08745Sheppo 
95*1ae08745Sheppo 	/* wait for all clients disconnect from the console */
96*1ae08745Sheppo 	while (consp->clientpq != NULL) {
97*1ae08745Sheppo 		consp->status |= VNTSD_CONS_SIG_WAIT;
98*1ae08745Sheppo 
99*1ae08745Sheppo 		/* signal client to disconnect the console */
100*1ae08745Sheppo 		(void) vntsd_que_walk(consp->clientpq,
101*1ae08745Sheppo 		    (el_func_t)vntsd_notify_client_cons_del);
102*1ae08745Sheppo 
103*1ae08745Sheppo 		(void) thr_kill(consp->wr_tid, SIGUSR1);
104*1ae08745Sheppo 		to.tv_sec = VNTSD_CV_WAIT_DELTIME;
105*1ae08745Sheppo 		to.tv_nsec = 0;
106*1ae08745Sheppo 
107*1ae08745Sheppo 		/* wait for clients to disconnect  */
108*1ae08745Sheppo 		(void) cond_reltimedwait(&consp->cvp, &consp->lock, &to);
109*1ae08745Sheppo 	}
110*1ae08745Sheppo 
111*1ae08745Sheppo 	(void) mutex_unlock(&consp->lock);
112*1ae08745Sheppo 
113*1ae08745Sheppo 	free_cons(consp);
114*1ae08745Sheppo }
115*1ae08745Sheppo 
116*1ae08745Sheppo /* search for a group whose console is being deleted */
117*1ae08745Sheppo static boolean_t
118*1ae08745Sheppo find_clean_cons_group(vntsd_group_t *groupp)
119*1ae08745Sheppo {
120*1ae08745Sheppo 	if (groupp->status & VNTSD_GROUP_CLEAN_CONS) {
121*1ae08745Sheppo 		return (B_TRUE);
122*1ae08745Sheppo 	} else {
123*1ae08745Sheppo 		return (B_FALSE);
124*1ae08745Sheppo 	}
125*1ae08745Sheppo }
126*1ae08745Sheppo 
127*1ae08745Sheppo /* search for a console that is being deleted */
128*1ae08745Sheppo static boolean_t
129*1ae08745Sheppo find_clean_cons(vntsd_cons_t *consp)
130*1ae08745Sheppo {
131*1ae08745Sheppo 	if (consp->status & VNTSD_CONS_DELETED) {
132*1ae08745Sheppo 		return (B_TRUE);
133*1ae08745Sheppo 	} else {
134*1ae08745Sheppo 		return (B_FALSE);
135*1ae08745Sheppo 	}
136*1ae08745Sheppo }
137*1ae08745Sheppo 
138*1ae08745Sheppo /* delete a console */
139*1ae08745Sheppo void
140*1ae08745Sheppo vntsd_delete_cons(vntsd_t *vntsdp)
141*1ae08745Sheppo {
142*1ae08745Sheppo 	vntsd_group_t *groupp;
143*1ae08745Sheppo 	vntsd_cons_t *consp;
144*1ae08745Sheppo 
145*1ae08745Sheppo 	for (; ; ) {
146*1ae08745Sheppo 		/* get the group contains deleted console */
147*1ae08745Sheppo 		(void) mutex_lock(&vntsdp->lock);
148*1ae08745Sheppo 		groupp = vntsd_que_walk(vntsdp->grouppq,
149*1ae08745Sheppo 		    (el_func_t)find_clean_cons_group);
150*1ae08745Sheppo 		if (groupp == NULL) {
151*1ae08745Sheppo 			/* no more group has console deleted */
152*1ae08745Sheppo 			(void) mutex_unlock(&vntsdp->lock);
153*1ae08745Sheppo 			return;
154*1ae08745Sheppo 		}
155*1ae08745Sheppo 		groupp->status &= ~VNTSD_GROUP_CLEAN_CONS;
156*1ae08745Sheppo 		(void) mutex_unlock(&vntsdp->lock);
157*1ae08745Sheppo 
158*1ae08745Sheppo 		for (; ; ) {
159*1ae08745Sheppo 			/* get the console to be deleted */
160*1ae08745Sheppo 			(void) mutex_lock(&groupp->lock);
161*1ae08745Sheppo 			assert(groupp->conspq);
162*1ae08745Sheppo 			consp = vntsd_que_walk(groupp->conspq,
163*1ae08745Sheppo 			    (el_func_t)find_clean_cons);
164*1ae08745Sheppo 			if (consp == NULL) {
165*1ae08745Sheppo 				/* no more cons to delete */
166*1ae08745Sheppo 				(void) mutex_unlock(&groupp->lock);
167*1ae08745Sheppo 				break;
168*1ae08745Sheppo 			}
169*1ae08745Sheppo 
170*1ae08745Sheppo 			/* remove console from the group */
171*1ae08745Sheppo 			(void) vntsd_que_rm(&groupp->conspq, consp);
172*1ae08745Sheppo 			groupp->num_cons--;
173*1ae08745Sheppo 			(void) mutex_unlock(&groupp->lock);
174*1ae08745Sheppo 
175*1ae08745Sheppo 			/* clean up the console */
176*1ae08745Sheppo 			cleanup_cons(consp);
177*1ae08745Sheppo 
178*1ae08745Sheppo 			/* delete group? */
179*1ae08745Sheppo 			if (groupp->num_cons == 0) {
180*1ae08745Sheppo 				/* no more console delete it */
181*1ae08745Sheppo 				assert(groupp->vntsd);
182*1ae08745Sheppo 
183*1ae08745Sheppo 				(void) mutex_lock(&groupp->vntsd->lock);
184*1ae08745Sheppo 				(void) vntsd_que_rm(&groupp->vntsd->grouppq,
185*1ae08745Sheppo 						    groupp);
186*1ae08745Sheppo 				(void) mutex_unlock(&groupp->vntsd->lock);
187*1ae08745Sheppo 
188*1ae08745Sheppo 				/* clean up the group */
189*1ae08745Sheppo 				vntsd_clean_group(groupp);
190*1ae08745Sheppo 				break;
191*1ae08745Sheppo 			}
192*1ae08745Sheppo 		}
193*1ae08745Sheppo 	}
194*1ae08745Sheppo }
195*1ae08745Sheppo 
196*1ae08745Sheppo /* clean up a group */
197*1ae08745Sheppo void
198*1ae08745Sheppo vntsd_clean_group(vntsd_group_t *groupp)
199*1ae08745Sheppo {
200*1ae08745Sheppo 
201*1ae08745Sheppo 	timestruc_t	to;
202*1ae08745Sheppo 
203*1ae08745Sheppo 	D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(),
204*1ae08745Sheppo 	    groupp->group_name, groupp->tcp_port);
205*1ae08745Sheppo 
206*1ae08745Sheppo 	(void) mutex_lock(&groupp->lock);
207*1ae08745Sheppo 
208*1ae08745Sheppo 	/* prevent from reentry */
209*1ae08745Sheppo 	if (groupp->status & VNTSD_GROUP_CLEANUP) {
210*1ae08745Sheppo 		(void) mutex_unlock(&groupp->lock);
211*1ae08745Sheppo 		return;
212*1ae08745Sheppo 	}
213*1ae08745Sheppo 	groupp->status |= VNTSD_GROUP_CLEANUP;
214*1ae08745Sheppo 	vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons);
215*1ae08745Sheppo 	(void) mutex_unlock(&groupp->lock);
216*1ae08745Sheppo 
217*1ae08745Sheppo 	/* walk through no cons client queue */
218*1ae08745Sheppo 	while (groupp->no_cons_clientpq != NULL) {
219*1ae08745Sheppo 		groupp->status |= VNTSD_GROUP_SIG_WAIT;
220*1ae08745Sheppo 		(void) vntsd_que_walk(groupp->no_cons_clientpq,
221*1ae08745Sheppo 		    (el_func_t)vntsd_notify_client_cons_del);
222*1ae08745Sheppo 		to.tv_sec = VNTSD_CV_WAIT_DELTIME;
223*1ae08745Sheppo 		to.tv_nsec = 0;
224*1ae08745Sheppo 		(void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to);
225*1ae08745Sheppo 	}
226*1ae08745Sheppo 
227*1ae08745Sheppo 	if (groupp->listen_tid == thr_self()) {
228*1ae08745Sheppo 		/* listen thread is exiting */
229*1ae08745Sheppo 		(void) mutex_lock(&(groupp->vntsd->lock));
230*1ae08745Sheppo 		(void) vntsd_que_rm(&groupp->vntsd->grouppq, groupp);
231*1ae08745Sheppo 		(void) mutex_unlock(&groupp->vntsd->lock);
232*1ae08745Sheppo 
233*1ae08745Sheppo 		(void) cond_destroy(&groupp->cvp);
234*1ae08745Sheppo 		(void) mutex_unlock(&groupp->lock);
235*1ae08745Sheppo 		(void) mutex_destroy(&groupp->lock);
236*1ae08745Sheppo 		free(groupp);
237*1ae08745Sheppo 		return;
238*1ae08745Sheppo 	}
239*1ae08745Sheppo 
240*1ae08745Sheppo 	/* signal listen thread to exit  */
241*1ae08745Sheppo 	groupp->status |= VNTSD_GROUP_SIG_WAIT;
242*1ae08745Sheppo 
243*1ae08745Sheppo 	while (groupp->status & VNTSD_GROUP_SIG_WAIT) {
244*1ae08745Sheppo 		(void) thr_kill(groupp->listen_tid, SIGUSR1);
245*1ae08745Sheppo 		to.tv_sec = VNTSD_CV_WAIT_DELTIME;
246*1ae08745Sheppo 		to.tv_nsec = 0;
247*1ae08745Sheppo 		/* wait listen thread to exit  */
248*1ae08745Sheppo 		(void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to);
249*1ae08745Sheppo 	}
250*1ae08745Sheppo 
251*1ae08745Sheppo 	(void) mutex_unlock(&groupp->lock);
252*1ae08745Sheppo 	(void) thr_join(groupp->listen_tid, NULL, NULL);
253*1ae08745Sheppo 	/* free group */
254*1ae08745Sheppo 	(void) cond_destroy(&groupp->cvp);
255*1ae08745Sheppo 	(void) mutex_destroy(&groupp->lock);
256*1ae08745Sheppo 	free(groupp);
257*1ae08745Sheppo }
258*1ae08745Sheppo 
259*1ae08745Sheppo /* allocate and initialize console structure */
260*1ae08745Sheppo static vntsd_cons_t *
261*1ae08745Sheppo alloc_cons(vntsd_group_t *groupp, vcc_console_t *consolep)
262*1ae08745Sheppo {
263*1ae08745Sheppo 	vntsd_cons_t *consp;
264*1ae08745Sheppo 	int	rv;
265*1ae08745Sheppo 
266*1ae08745Sheppo 	/* allocate console */
267*1ae08745Sheppo 	consp = (vntsd_cons_t *)malloc(sizeof (vntsd_cons_t));
268*1ae08745Sheppo 	if (consp == NULL) {
269*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_NO_MEM, "alloc_cons");
270*1ae08745Sheppo 		return (NULL);
271*1ae08745Sheppo 	}
272*1ae08745Sheppo 
273*1ae08745Sheppo 	/* intialize console */
274*1ae08745Sheppo 	bzero(consp, sizeof (vntsd_cons_t));
275*1ae08745Sheppo 
276*1ae08745Sheppo 	(void) mutex_init(&consp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL);
277*1ae08745Sheppo 	(void) cond_init(&consp->cvp, USYNC_THREAD, NULL);
278*1ae08745Sheppo 
279*1ae08745Sheppo 	consp->cons_no = consolep->cons_no;
280*1ae08745Sheppo 	(void) strlcpy(consp->domain_name, consolep->domain_name, MAXPATHLEN);
281*1ae08745Sheppo 	(void) strlcpy(consp->dev_name, consolep->dev_name, MAXPATHLEN);
282*1ae08745Sheppo 	consp->wr_tid = (thread_t)-1;
283*1ae08745Sheppo 	consp->vcc_fd = (thread_t)-1;
284*1ae08745Sheppo 
285*1ae08745Sheppo 	/* join the group */
286*1ae08745Sheppo 	(void) mutex_lock(&groupp->lock);
287*1ae08745Sheppo 
288*1ae08745Sheppo 	if ((rv = vntsd_que_append(&groupp->conspq, consp)) !=
289*1ae08745Sheppo 	    VNTSD_SUCCESS) {
290*1ae08745Sheppo 		(void) mutex_unlock(&groupp->lock);
291*1ae08745Sheppo 		vntsd_log(rv, "alloc_cons");
292*1ae08745Sheppo 		free_cons(consp);
293*1ae08745Sheppo 		return (NULL);
294*1ae08745Sheppo 	}
295*1ae08745Sheppo 	groupp->num_cons++;
296*1ae08745Sheppo 	consp->group = groupp;
297*1ae08745Sheppo 
298*1ae08745Sheppo 	(void) mutex_unlock(&groupp->lock);
299*1ae08745Sheppo 
300*1ae08745Sheppo 	D1(stderr, "t@%d alloc_cons@%d %s %s\n", thr_self(),
301*1ae08745Sheppo 	    consp->cons_no, consp->domain_name, consp->dev_name);
302*1ae08745Sheppo 
303*1ae08745Sheppo 	return (consp);
304*1ae08745Sheppo }
305*1ae08745Sheppo 
306*1ae08745Sheppo /* compare tcp with group->tcp */
307*1ae08745Sheppo static boolean_t
308*1ae08745Sheppo grp_by_tcp(vntsd_group_t *groupp, uint64_t *tcp_port)
309*1ae08745Sheppo {
310*1ae08745Sheppo 	assert(groupp);
311*1ae08745Sheppo 	assert(tcp_port);
312*1ae08745Sheppo 	return (groupp->tcp_port == *tcp_port);
313*1ae08745Sheppo }
314*1ae08745Sheppo 
315*1ae08745Sheppo /* allocate and initialize group */
316*1ae08745Sheppo static vntsd_group_t *
317*1ae08745Sheppo alloc_group(vntsd_t *vntsdp, char *group_name, uint64_t tcp_port)
318*1ae08745Sheppo {
319*1ae08745Sheppo 	vntsd_group_t *groupp;
320*1ae08745Sheppo 
321*1ae08745Sheppo 	/* allocate group */
322*1ae08745Sheppo 	groupp = (vntsd_group_t *)malloc(sizeof (vntsd_group_t));
323*1ae08745Sheppo 	if (groupp == NULL) {
324*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_NO_MEM, "alloc_group");
325*1ae08745Sheppo 		return (NULL);
326*1ae08745Sheppo 	}
327*1ae08745Sheppo 
328*1ae08745Sheppo 	/* initialize group */
329*1ae08745Sheppo 	bzero(groupp, sizeof (vntsd_group_t));
330*1ae08745Sheppo 
331*1ae08745Sheppo 	(void) mutex_init(&groupp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL);
332*1ae08745Sheppo 	(void) cond_init(&groupp->cvp, USYNC_THREAD, NULL);
333*1ae08745Sheppo 
334*1ae08745Sheppo 	if (group_name != NULL) {
335*1ae08745Sheppo 		(void) memcpy(groupp->group_name, group_name, MAXPATHLEN);
336*1ae08745Sheppo 	}
337*1ae08745Sheppo 
338*1ae08745Sheppo 	groupp->tcp_port = tcp_port;
339*1ae08745Sheppo 	groupp->listen_tid = (thread_t)-1;
340*1ae08745Sheppo 	groupp->sockfd = (thread_t)-1;
341*1ae08745Sheppo 	groupp->vntsd = vntsdp;
342*1ae08745Sheppo 
343*1ae08745Sheppo 	D1(stderr, "t@%d alloc_group@%lld:%s\n", thr_self(), groupp->tcp_port,
344*1ae08745Sheppo 	    groupp->group_name);
345*1ae08745Sheppo 
346*1ae08745Sheppo 	return (groupp);
347*1ae08745Sheppo }
348*1ae08745Sheppo 
349*1ae08745Sheppo /*
350*1ae08745Sheppo  * Initialize a console, if console is associated with with a
351*1ae08745Sheppo  * new group, intialize the group.
352*1ae08745Sheppo  */
353*1ae08745Sheppo static int
354*1ae08745Sheppo alloc_cons_with_group(vntsd_t *vntsdp, vcc_console_t *consp,
355*1ae08745Sheppo     vntsd_group_t **new_groupp)
356*1ae08745Sheppo {
357*1ae08745Sheppo 	vntsd_group_t	*groupp = NULL;
358*1ae08745Sheppo 	int		rv;
359*1ae08745Sheppo 
360*1ae08745Sheppo 	*new_groupp = NULL;
361*1ae08745Sheppo 
362*1ae08745Sheppo 	/* match group by tcp port */
363*1ae08745Sheppo 
364*1ae08745Sheppo 
365*1ae08745Sheppo 	(void) mutex_lock(&vntsdp->lock);
366*1ae08745Sheppo 	groupp = vntsd_que_find(vntsdp->grouppq,
367*1ae08745Sheppo 	    (compare_func_t)grp_by_tcp, (void *)&(consp->tcp_port));
368*1ae08745Sheppo 	(void) mutex_unlock(&vntsdp->lock);
369*1ae08745Sheppo 
370*1ae08745Sheppo 	if (groupp != NULL) {
371*1ae08745Sheppo 		/* group with same tcp port found */
372*1ae08745Sheppo 
373*1ae08745Sheppo 		if (strcmp(groupp->group_name, consp->group_name)) {
374*1ae08745Sheppo 			/* conflict group name */
375*1ae08745Sheppo 			vntsd_log(VNTSD_ERR_VCC_GRP_NAME,
376*1ae08745Sheppo 			    "group name is different from existing group");
377*1ae08745Sheppo 			return (VNTSD_ERR_VCC_CTRL_DATA);
378*1ae08745Sheppo 		}
379*1ae08745Sheppo 
380*1ae08745Sheppo 	} else {
381*1ae08745Sheppo 		/* new group */
382*1ae08745Sheppo 		groupp = alloc_group(vntsdp, consp->group_name,
383*1ae08745Sheppo 		    consp->tcp_port);
384*1ae08745Sheppo 		if (groupp == NULL) {
385*1ae08745Sheppo 			return (VNTSD_ERR_NO_MEM);
386*1ae08745Sheppo 		}
387*1ae08745Sheppo 
388*1ae08745Sheppo 		assert(groupp->conspq == NULL);
389*1ae08745Sheppo 		/* queue group to vntsdp */
390*1ae08745Sheppo 		(void) mutex_lock(&vntsdp->lock);
391*1ae08745Sheppo 		rv = vntsd_que_append(&vntsdp->grouppq, groupp);
392*1ae08745Sheppo 		(void) mutex_unlock(&vntsdp->lock);
393*1ae08745Sheppo 
394*1ae08745Sheppo 		if (rv != VNTSD_SUCCESS) {
395*1ae08745Sheppo 			return (rv);
396*1ae08745Sheppo 		}
397*1ae08745Sheppo 
398*1ae08745Sheppo 		*new_groupp = groupp;
399*1ae08745Sheppo 	}
400*1ae08745Sheppo 
401*1ae08745Sheppo 	/* intialize console */
402*1ae08745Sheppo 	if (alloc_cons(groupp, consp) == NULL) {
403*1ae08745Sheppo 		/* no memory */
404*1ae08745Sheppo 		if (new_groupp != NULL) {
405*1ae08745Sheppo 			/* clean up new group */
406*1ae08745Sheppo 			(void) cond_destroy(&groupp->cvp);
407*1ae08745Sheppo 			(void) mutex_destroy(&groupp->lock);
408*1ae08745Sheppo 			free(groupp);
409*1ae08745Sheppo 		}
410*1ae08745Sheppo 
411*1ae08745Sheppo 		return (VNTSD_ERR_NO_MEM);
412*1ae08745Sheppo 	}
413*1ae08745Sheppo 
414*1ae08745Sheppo 	return (VNTSD_SUCCESS);
415*1ae08745Sheppo 
416*1ae08745Sheppo }
417*1ae08745Sheppo 
418*1ae08745Sheppo 
419*1ae08745Sheppo /* create listen thread */
420*1ae08745Sheppo static boolean_t
421*1ae08745Sheppo create_listen_thread(vntsd_group_t *groupp)
422*1ae08745Sheppo {
423*1ae08745Sheppo 
424*1ae08745Sheppo 	char err_msg[VNTSD_LINE_LEN];
425*1ae08745Sheppo 	int rv;
426*1ae08745Sheppo 
427*1ae08745Sheppo 	assert(groupp);
428*1ae08745Sheppo 
429*1ae08745Sheppo 	(void) mutex_lock(&groupp->lock);
430*1ae08745Sheppo 	assert(groupp->num_cons);
431*1ae08745Sheppo 
432*1ae08745Sheppo 	D1(stderr, "t@%d create_listen:%lld\n", thr_self(), groupp->tcp_port);
433*1ae08745Sheppo 
434*1ae08745Sheppo 	if ((rv = thr_create(NULL, 0, (thr_func_t)vntsd_listen_thread,
435*1ae08745Sheppo 			    (void *)groupp, THR_DETACHED, &groupp->listen_tid))
436*1ae08745Sheppo 	    != 0) {
437*1ae08745Sheppo 		(void) (void) snprintf(err_msg, sizeof (err_msg),
438*1ae08745Sheppo 		    "Can not create listen thread for"
439*1ae08745Sheppo 		    "group %s tcp %llx\n", groupp->group_name,
440*1ae08745Sheppo 		    groupp->tcp_port);
441*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg);
442*1ae08745Sheppo 
443*1ae08745Sheppo 		/* clean up group queue */
444*1ae08745Sheppo 		vntsd_free_que(&groupp->conspq, (clean_func_t)free_cons);
445*1ae08745Sheppo 		groupp->listen_tid = (thread_t)-1;
446*1ae08745Sheppo 	}
447*1ae08745Sheppo 
448*1ae08745Sheppo 	(void) mutex_unlock(&groupp->lock);
449*1ae08745Sheppo 
450*1ae08745Sheppo 	return (rv != 0);
451*1ae08745Sheppo }
452*1ae08745Sheppo 
453*1ae08745Sheppo /* delete a console if the console exists in the vntsd */
454*1ae08745Sheppo static void
455*1ae08745Sheppo delete_cons_before_add(vntsd_t *vntsdp, uint64_t tcp_port, uint_t cons_no)
456*1ae08745Sheppo {
457*1ae08745Sheppo 	vntsd_group_t	    *groupp;
458*1ae08745Sheppo 	vntsd_cons_t	    *consp;
459*1ae08745Sheppo 
460*1ae08745Sheppo 	/* group exists? */
461*1ae08745Sheppo 	(void) mutex_lock(&vntsdp->lock);
462*1ae08745Sheppo 	groupp = vntsd_que_find(vntsdp->grouppq, (compare_func_t)grp_by_tcp,
463*1ae08745Sheppo 	    (void *)&(tcp_port));
464*1ae08745Sheppo 	(void) mutex_unlock(&vntsdp->lock);
465*1ae08745Sheppo 
466*1ae08745Sheppo 	if (groupp == NULL) {
467*1ae08745Sheppo 		/* no such group */
468*1ae08745Sheppo 		return;
469*1ae08745Sheppo 	}
470*1ae08745Sheppo 
471*1ae08745Sheppo 	/* group exists, if console exists? */
472*1ae08745Sheppo 	(void) mutex_lock(&groupp->lock);
473*1ae08745Sheppo 	consp = vntsd_que_find(groupp->conspq,
474*1ae08745Sheppo 	    (compare_func_t)vntsd_cons_by_consno, &cons_no);
475*1ae08745Sheppo 
476*1ae08745Sheppo 	if (consp == NULL) {
477*1ae08745Sheppo 		/* no such console */
478*1ae08745Sheppo 		(void) mutex_unlock(&groupp->lock);
479*1ae08745Sheppo 		return;
480*1ae08745Sheppo 	}
481*1ae08745Sheppo 	/* console exists - delete console */
482*1ae08745Sheppo 
483*1ae08745Sheppo 	(void) mutex_lock(&consp->lock);
484*1ae08745Sheppo 
485*1ae08745Sheppo 	consp->status |= VNTSD_CONS_DELETED;
486*1ae08745Sheppo 	groupp->status |= VNTSD_GROUP_CLEAN_CONS;
487*1ae08745Sheppo 
488*1ae08745Sheppo 	(void) mutex_unlock(&consp->lock);
489*1ae08745Sheppo 
490*1ae08745Sheppo 	(void) mutex_unlock(&groupp->lock);
491*1ae08745Sheppo 
492*1ae08745Sheppo 	vntsd_delete_cons(vntsdp);
493*1ae08745Sheppo }
494*1ae08745Sheppo 
495*1ae08745Sheppo /* add a console */
496*1ae08745Sheppo static void
497*1ae08745Sheppo do_add_cons(vntsd_t *vntsdp, int cons_no)
498*1ae08745Sheppo {
499*1ae08745Sheppo 	vcc_console_t	console;
500*1ae08745Sheppo 	vntsd_group_t	*groupp;
501*1ae08745Sheppo 	int		rv;
502*1ae08745Sheppo 	char		err_msg[VNTSD_LINE_LEN];
503*1ae08745Sheppo 
504*1ae08745Sheppo 
505*1ae08745Sheppo 	(void) snprintf(err_msg, sizeof (err_msg),
506*1ae08745Sheppo 	    "do_add_cons():Can not add console=%d", cons_no);
507*1ae08745Sheppo 
508*1ae08745Sheppo 	/* get console configuration from vcc */
509*1ae08745Sheppo 
510*1ae08745Sheppo 	if ((rv = vntsd_vcc_ioctl(VCC_CONS_INFO, cons_no, (void *)&console))
511*1ae08745Sheppo 	    != VNTSD_SUCCESS) {
512*1ae08745Sheppo 		vntsd_log(rv, err_msg);
513*1ae08745Sheppo 		return;
514*1ae08745Sheppo 	}
515*1ae08745Sheppo 
516*1ae08745Sheppo 	/* clean up the console if console was deleted and added again */
517*1ae08745Sheppo 	delete_cons_before_add(vntsdp, console.tcp_port, console.cons_no);
518*1ae08745Sheppo 
519*1ae08745Sheppo 	/* initialize console */
520*1ae08745Sheppo 
521*1ae08745Sheppo 	if ((rv = alloc_cons_with_group(vntsdp, &console, &groupp)) !=
522*1ae08745Sheppo 	    VNTSD_SUCCESS) {
523*1ae08745Sheppo 		/* no memory to add this new console */
524*1ae08745Sheppo 		vntsd_log(rv, err_msg);
525*1ae08745Sheppo 		return;
526*1ae08745Sheppo 	}
527*1ae08745Sheppo 
528*1ae08745Sheppo 	if (groupp != NULL) {
529*1ae08745Sheppo 		/* new group */
530*1ae08745Sheppo 		/* create listen thread for this console */
531*1ae08745Sheppo 		if (create_listen_thread(groupp)) {
532*1ae08745Sheppo 			vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg);
533*1ae08745Sheppo 			(void) cond_destroy(&groupp->cvp);
534*1ae08745Sheppo 			(void) mutex_destroy(&groupp->lock);
535*1ae08745Sheppo 			free(groupp);
536*1ae08745Sheppo 		}
537*1ae08745Sheppo 
538*1ae08745Sheppo 	}
539*1ae08745Sheppo }
540*1ae08745Sheppo 
541*1ae08745Sheppo /* daemon wake up */
542*1ae08745Sheppo void
543*1ae08745Sheppo vntsd_daemon_wakeup(vntsd_t *vntsdp)
544*1ae08745Sheppo {
545*1ae08745Sheppo 
546*1ae08745Sheppo 	vcc_response_t	inq_data;
547*1ae08745Sheppo 
548*1ae08745Sheppo 	/* reason to wake up  */
549*1ae08745Sheppo 	if (vntsd_vcc_ioctl(VCC_INQUIRY, 0, (void *)&inq_data) !=
550*1ae08745Sheppo 	    VNTSD_SUCCESS) {
551*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_VCC_IOCTL, "vntsd_daemon_wakeup()");
552*1ae08745Sheppo 		return;
553*1ae08745Sheppo 	}
554*1ae08745Sheppo 
555*1ae08745Sheppo 	D1(stderr, "t@%d vntsd_daemon_wakup:msg %d port %x\n", thr_self(),
556*1ae08745Sheppo 	    inq_data.reason, inq_data.cons_no);
557*1ae08745Sheppo 
558*1ae08745Sheppo 	switch (inq_data.reason) {
559*1ae08745Sheppo 
560*1ae08745Sheppo 	case VCC_CONS_ADDED:
561*1ae08745Sheppo 		do_add_cons(vntsdp, inq_data.cons_no);
562*1ae08745Sheppo 		break;
563*1ae08745Sheppo 
564*1ae08745Sheppo 	default:
565*1ae08745Sheppo 		DERR(stderr, "t@%d daemon_wakeup:ioctl_unknown %d\n",
566*1ae08745Sheppo 		    thr_self(), inq_data.reason);
567*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_UNKNOWN_CMD, "from vcc\n");
568*1ae08745Sheppo 		break;
569*1ae08745Sheppo 	}
570*1ae08745Sheppo }
571*1ae08745Sheppo 
572*1ae08745Sheppo /* initial console configuration */
573*1ae08745Sheppo void
574*1ae08745Sheppo vntsd_get_config(vntsd_t *vntsdp)
575*1ae08745Sheppo {
576*1ae08745Sheppo 
577*1ae08745Sheppo 	int		i;
578*1ae08745Sheppo 	int		num_cons;
579*1ae08745Sheppo 	vcc_console_t	*consp;
580*1ae08745Sheppo 	vntsd_group_t	*groupp;
581*1ae08745Sheppo 
582*1ae08745Sheppo 	/* num of consoles */
583*1ae08745Sheppo 	num_cons = 0;
584*1ae08745Sheppo 
585*1ae08745Sheppo 	if (vntsd_vcc_ioctl(VCC_NUM_CONSOLE, 0, (void *)&num_cons) !=
586*1ae08745Sheppo 	    VNTSD_SUCCESS) {
587*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_VCC_IOCTL, "VCC_NUM_CONSOLE failed\n");
588*1ae08745Sheppo 		return;
589*1ae08745Sheppo 	}
590*1ae08745Sheppo 
591*1ae08745Sheppo 	D3(stderr, "get_config:num_cons=%d", num_cons);
592*1ae08745Sheppo 
593*1ae08745Sheppo 	if (num_cons == 0) {
594*1ae08745Sheppo 		return;
595*1ae08745Sheppo 	}
596*1ae08745Sheppo 
597*1ae08745Sheppo 	/* allocate memory for all consoles */
598*1ae08745Sheppo 	consp = malloc(num_cons*sizeof (vcc_console_t));
599*1ae08745Sheppo 
600*1ae08745Sheppo 	if (consp == NULL) {
601*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_NO_MEM, "for console table.");
602*1ae08745Sheppo 		return;
603*1ae08745Sheppo 	}
604*1ae08745Sheppo 
605*1ae08745Sheppo 	/* get console table */
606*1ae08745Sheppo 	if (vntsd_vcc_ioctl(VCC_CONS_TBL, 0, (void *)consp) != VNTSD_SUCCESS) {
607*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_VCC_IOCTL, " VCC_CONS_TBL "
608*1ae08745Sheppo 		    "for console table\n");
609*1ae08745Sheppo 		return;
610*1ae08745Sheppo 	}
611*1ae08745Sheppo 
612*1ae08745Sheppo 	/* intialize groups and consoles  */
613*1ae08745Sheppo 	for (i = 0; i < num_cons; i++) {
614*1ae08745Sheppo 		if (alloc_cons_with_group(vntsdp, &consp[i], &groupp)
615*1ae08745Sheppo 		    != VNTSD_SUCCESS) {
616*1ae08745Sheppo 			vntsd_log(VNTSD_ERR_ADD_CONS_FAILED, "get_config");
617*1ae08745Sheppo 		}
618*1ae08745Sheppo 	}
619*1ae08745Sheppo 
620*1ae08745Sheppo 	/* create listen thread for each group */
621*1ae08745Sheppo 	(void) mutex_lock(&vntsdp->lock);
622*1ae08745Sheppo 
623*1ae08745Sheppo 	for (; ; ) {
624*1ae08745Sheppo 		groupp = vntsd_que_walk(vntsdp->grouppq,
625*1ae08745Sheppo 		    (el_func_t)create_listen_thread);
626*1ae08745Sheppo 		if (groupp == NULL) {
627*1ae08745Sheppo 			break;
628*1ae08745Sheppo 		}
629*1ae08745Sheppo 		vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, "get config()");
630*1ae08745Sheppo 	}
631*1ae08745Sheppo 
632*1ae08745Sheppo 	(void) mutex_unlock(&vntsdp->lock);
633*1ae08745Sheppo }
634