/* allocate and initialize console structure */ static vntsd_cons_t * alloc_cons(vntsd_group_t *groupp, vcc_console_t *consolep) { vntsd_cons_t *consp; int rv; /* allocate console */ consp = (vntsd_cons_t *)malloc(sizeof (vntsd_cons_t)); if (consp == NULL) { vntsd_log(VNTSD_ERR_NO_MEM, "alloc_cons"); return (NULL); } /* intialize console */ bzero(consp, sizeof (vntsd_cons_t)); (void) mutex_init(&consp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); (void) cond_init(&consp->cvp, USYNC_THREAD, NULL); consp->cons_no = consolep->cons_no; (void) strlcpy(consp->domain_name, consolep->domain_name, MAXPATHLEN); (void) strlcpy(consp->dev_name, consolep->dev_name, MAXPATHLEN); consp->wr_tid = (thread_t)-1; consp->vcc_fd = (thread_t)-1; /* join the group */ (void) mutex_lock(&groupp->lock); if ((rv = vntsd_que_append(&groupp->conspq, consp)) != VNTSD_SUCCESS) { (void) mutex_unlock(&groupp->lock); vntsd_log(rv, "alloc_cons"); free_cons(consp); return (NULL); } groupp->num_cons++; consp->group = groupp; (void) mutex_unlock(&groupp->lock); D1(stderr, "t@%d alloc_cons@%d %s %s\n", thr_self(), consp->cons_no, consp->domain_name, consp->dev_name); return (consp); }
/* * Initialize a console, if console is associated with with a * new group, intialize the group. */ static int alloc_cons_with_group(vntsd_t *vntsdp, vcc_console_t *consp, vntsd_group_t **new_groupp) { vntsd_group_t *groupp = NULL; int rv; *new_groupp = NULL; /* match group by tcp port */ (void) mutex_lock(&vntsdp->lock); groupp = vntsd_que_find(vntsdp->grouppq, (compare_func_t)grp_by_tcp, (void *)&(consp->tcp_port)); (void) mutex_unlock(&vntsdp->lock); if (groupp != NULL) { /* group with same tcp port found */ if (strcmp(groupp->group_name, consp->group_name)) { /* conflict group name */ vntsd_log(VNTSD_ERR_VCC_GRP_NAME, "group name is different from existing group"); return (VNTSD_ERR_VCC_CTRL_DATA); } } else { /* new group */ groupp = alloc_group(vntsdp, consp->group_name, consp->tcp_port); if (groupp == NULL) { return (VNTSD_ERR_NO_MEM); } assert(groupp->conspq == NULL); /* queue group to vntsdp */ (void) mutex_lock(&vntsdp->lock); rv = vntsd_que_append(&vntsdp->grouppq, groupp); (void) mutex_unlock(&vntsdp->lock); if (rv != VNTSD_SUCCESS) { return (rv); } *new_groupp = groupp; } /* intialize console */ if (alloc_cons(groupp, consp) == NULL) { /* no memory */ if (new_groupp != NULL) { /* clean up new group */ (void) cond_destroy(&groupp->cvp); (void) mutex_destroy(&groupp->lock); free(groupp); } return (VNTSD_ERR_NO_MEM); } return (VNTSD_SUCCESS); }
/* ceate console selection thread */ static int create_console_thread(vntsd_group_t *groupp, int sockfd) { vntsd_client_t *clientp; vntsd_thr_arg_t *thr_arg; int rv; assert(groupp); D1(stderr, "t@%d create_console_thread@%lld:client@%d\n", thr_self(), groupp->tcp_port, sockfd); /* allocate a new client */ clientp = (vntsd_client_t *)malloc(sizeof (vntsd_client_t)); if (clientp == NULL) { return (VNTSD_ERR_NO_MEM); } /* initialize the client */ bzero(clientp, sizeof (vntsd_client_t)); clientp->sockfd = sockfd; clientp->cons_tid = (thread_t)-1; (void) mutex_init(&clientp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL); /* append client to group */ (void) mutex_lock(&groupp->lock); /* check if the group is [being] removed */ if (groupp->status & VNTSD_GROUP_IN_CLEANUP) { (void) mutex_unlock(&groupp->lock); vntsd_free_client(clientp); return (VNTSD_STATUS_NO_CONS); } if ((rv = vntsd_que_append(&groupp->no_cons_clientpq, clientp)) != VNTSD_SUCCESS) { (void) mutex_unlock(&groupp->lock); vntsd_free_client(clientp); return (rv); } (void) mutex_unlock(&groupp->lock); /* * allocate thr_arg from heap for console thread so * that thr_arg is still valid after this function exits. * console thread will free thr_arg. */ thr_arg = (vntsd_thr_arg_t *)malloc(sizeof (vntsd_thr_arg_t)); if (thr_arg == NULL) { vntsd_free_client(clientp); return (VNTSD_ERR_NO_MEM); } thr_arg->handle = groupp; thr_arg->arg = clientp; (void) mutex_lock(&clientp->lock); /* create console selection thread */ if (thr_create(NULL, 0, (thr_func_t)vntsd_console_thread, thr_arg, THR_DETACHED, &clientp->cons_tid)) { free(thr_arg); (void) mutex_unlock(&clientp->lock); (void) mutex_lock(&groupp->lock); (void) vntsd_que_rm(&groupp->no_cons_clientpq, clientp); (void) mutex_unlock(&groupp->lock); vntsd_free_client(clientp); return (VNTSD_ERR_CREATE_CONS_THR); } (void) mutex_unlock(&clientp->lock); return (VNTSD_SUCCESS); }