示例#1
0
/* delete a console */
void
vntsd_delete_cons(vntsd_t *vntsdp)
{
	vntsd_group_t *groupp;
	vntsd_cons_t *consp;

	for (; ; ) {
		/* get the group contains deleted console */
		(void) mutex_lock(&vntsdp->lock);
		groupp = vntsd_que_walk(vntsdp->grouppq,
		    (el_func_t)find_clean_cons_group);
		if (groupp == NULL) {
			/* no more group has console deleted */
			(void) mutex_unlock(&vntsdp->lock);
			return;
		}
		groupp->status &= ~VNTSD_GROUP_CLEAN_CONS;
		(void) mutex_unlock(&vntsdp->lock);

		for (; ; ) {
			/* get the console to be deleted */
			(void) mutex_lock(&groupp->lock);
			assert(groupp->conspq);
			consp = vntsd_que_walk(groupp->conspq,
			    (el_func_t)find_clean_cons);
			if (consp == NULL) {
				/* no more cons to delete */
				(void) mutex_unlock(&groupp->lock);
				break;
			}

			/* remove console from the group */
			(void) vntsd_que_rm(&groupp->conspq, consp);
			groupp->num_cons--;
			(void) mutex_unlock(&groupp->lock);

			/* clean up the console */
			cleanup_cons(consp);

			/* delete group? */
			if (groupp->num_cons == 0) {
				/* no more console delete it */
				assert(groupp->vntsd);

				(void) mutex_lock(&groupp->vntsd->lock);
				(void) vntsd_que_rm(&groupp->vntsd->grouppq,
						    groupp);
				(void) mutex_unlock(&groupp->vntsd->lock);

				/* clean up the group */
				vntsd_clean_group(groupp);
				break;
			}
		}
	}
}
示例#2
0
/*
 *  all clients connected to a console must disconnect before
 *  removing a console.
 */
static void
cleanup_cons(vntsd_cons_t *consp)
{
	vntsd_group_t	*groupp;
	timestruc_t	to;

	assert(consp);
	D1(stderr, "t@%d vntsd_disconn_clients@%d\n", thr_self(),
	    consp->cons_no);

	groupp = consp->group;
	assert(groupp);


	(void) mutex_lock(&consp->lock);

	/* wait for all clients disconnect from the console */
	while (consp->clientpq != NULL) {
		consp->status |= VNTSD_CONS_SIG_WAIT;

		/* signal client to disconnect the console */
		(void) vntsd_que_walk(consp->clientpq,
		    (el_func_t)vntsd_notify_client_cons_del);

		(void) thr_kill(consp->wr_tid, SIGUSR1);
		to.tv_sec = VNTSD_CV_WAIT_DELTIME;
		to.tv_nsec = 0;

		/* wait for clients to disconnect  */
		(void) cond_reltimedwait(&consp->cvp, &consp->lock, &to);
	}

	(void) mutex_unlock(&consp->lock);

	free_cons(consp);
}
示例#3
0
/* initial console configuration */
void
vntsd_get_config(vntsd_t *vntsdp)
{

	int		i;
	int		num_cons;
	vcc_console_t	*consp;
	vntsd_group_t	*groupp;

	/* num of consoles */
	num_cons = 0;

	if (vntsd_vcc_ioctl(VCC_NUM_CONSOLE, 0, (void *)&num_cons) !=
	    VNTSD_SUCCESS) {
		vntsd_log(VNTSD_ERR_VCC_IOCTL, "VCC_NUM_CONSOLE failed\n");
		return;
	}

	D3(stderr, "get_config:num_cons=%d", num_cons);

	if (num_cons == 0) {
		return;
	}

	/* allocate memory for all consoles */
	consp = malloc(num_cons*sizeof (vcc_console_t));

	if (consp == NULL) {
		vntsd_log(VNTSD_ERR_NO_MEM, "for console table.");
		return;
	}

	/* get console table */
	if (vntsd_vcc_ioctl(VCC_CONS_TBL, 0, (void *)consp) != VNTSD_SUCCESS) {
		vntsd_log(VNTSD_ERR_VCC_IOCTL, " VCC_CONS_TBL "
		    "for console table\n");
		return;
	}

	/* intialize groups and consoles  */
	for (i = 0; i < num_cons; i++) {
		if (alloc_cons_with_group(vntsdp, &consp[i], &groupp)
		    != VNTSD_SUCCESS) {
			vntsd_log(VNTSD_ERR_ADD_CONS_FAILED, "get_config");
		}
	}

	/* create listen thread for each group */
	(void) mutex_lock(&vntsdp->lock);

	for (; ; ) {
		groupp = vntsd_que_walk(vntsdp->grouppq,
		    (el_func_t)create_listen_thread);
		if (groupp == NULL) {
			break;
		}
		vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, "get config()");
	}

	(void) mutex_unlock(&vntsdp->lock);
}
示例#4
0
/* clean up a group */
void
vntsd_clean_group(vntsd_group_t *groupp)
{

	timestruc_t	to;

	D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(),
	    groupp->group_name, groupp->tcp_port);

	(void) mutex_lock(&groupp->lock);

	/* prevent from reentry */
	if (groupp->status & VNTSD_GROUP_CLEANUP) {
		(void) mutex_unlock(&groupp->lock);
		return;
	}
	groupp->status |= VNTSD_GROUP_CLEANUP;
	vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons);
	(void) mutex_unlock(&groupp->lock);

	/* walk through no cons client queue */
	while (groupp->no_cons_clientpq != NULL) {
		groupp->status |= VNTSD_GROUP_SIG_WAIT;
		(void) vntsd_que_walk(groupp->no_cons_clientpq,
		    (el_func_t)vntsd_notify_client_cons_del);
		to.tv_sec = VNTSD_CV_WAIT_DELTIME;
		to.tv_nsec = 0;
		(void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to);
	}

	if (groupp->listen_tid == thr_self()) {
		/* listen thread is exiting */
		(void) mutex_lock(&(groupp->vntsd->lock));
		(void) vntsd_que_rm(&groupp->vntsd->grouppq, groupp);
		(void) mutex_unlock(&groupp->vntsd->lock);

		(void) cond_destroy(&groupp->cvp);
		(void) mutex_unlock(&groupp->lock);
		(void) mutex_destroy(&groupp->lock);
		free(groupp);
		return;
	}

	/* signal listen thread to exit  */
	groupp->status |= VNTSD_GROUP_SIG_WAIT;

	while (groupp->status & VNTSD_GROUP_SIG_WAIT) {
		(void) thr_kill(groupp->listen_tid, SIGUSR1);
		to.tv_sec = VNTSD_CV_WAIT_DELTIME;
		to.tv_nsec = 0;
		/* wait listen thread to exit  */
		(void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to);
	}

	(void) mutex_unlock(&groupp->lock);
	(void) thr_join(groupp->listen_tid, NULL, NULL);
	/* free group */
	(void) cond_destroy(&groupp->cvp);
	(void) mutex_destroy(&groupp->lock);
	free(groupp);
}
示例#5
0
/*
 * check the state of listen thread. exit if there is an fatal error
 * or the group is removed. Main thread will call free_group
 * to close group socket and free group structure.
 */
static void
listen_chk_status(vntsd_group_t *groupp, int status)
{
	char	    err_msg[VNTSD_LINE_LEN];


	D1(stderr, "t@%d listen_chk_status() status=%d group=%s "
	    "tcp=%lld group status = %x\n", thr_self(), status,
	    groupp->group_name, groupp->tcp_port, groupp->status);

	(void) snprintf(err_msg, sizeof (err_msg),
	    "Group:%s TCP port %lld status %x",
	    groupp->group_name, groupp->tcp_port, groupp->status);


	switch (status) {

	case VNTSD_SUCCESS:
		return;


	case VNTSD_STATUS_ACCEPT_ERR:
		return;

	case VNTSD_STATUS_INTR:
		assert(groupp->status & VNTSD_GROUP_SIG_WAIT);
		/*FALLTHRU*/
	case VNTSD_STATUS_NO_CONS:
	default:
		/* fatal error or no console in the group, remove the group. */

		(void) mutex_lock(&groupp->lock);

		if (groupp->status & VNTSD_GROUP_SIG_WAIT) {
			/*
			 * group is already being deleted, notify main
			 * thread and exit.
			 */
			groupp->status &= ~VNTSD_GROUP_SIG_WAIT;
			(void) cond_signal(&groupp->cvp);
			(void) mutex_unlock(&groupp->lock);
			thr_exit(0);
		}

		/*
		 * if there still is console(s) in the group,
		 * the console(s) could not be connected any more because of
		 * a fatal error. Therefore, mark the console and notify
		 * main thread to delete console and group.
		 */
		(void) vntsd_que_walk(groupp->conspq,
		    (el_func_t)vntsd_mark_deleted_cons);
		groupp->status |= VNTSD_GROUP_CLEAN_CONS;

		/* signal main thread to delete the group */
		(void) thr_kill(groupp->vntsd->tid, SIGUSR1);
		(void) mutex_unlock(&groupp->lock);

		/* log error */
		if (status != VNTSD_STATUS_NO_CONS)
			vntsd_log(status, err_msg);
		thr_exit(0);
	}
}