vntsdvcc.c (3af08d828975d7e2581b6829e0eecff14d87a483) vntsdvcc.c (4d39be2b45b5ac811d28452e6eb629ac64aebfc4)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 55 unchanged lines hidden (view full) ---

64
65/* free console structure */
66static void
67free_cons(vntsd_cons_t *consp)
68{
69 assert(consp);
70 (void) mutex_destroy(&consp->lock);
71 (void) cond_destroy(&consp->cvp);
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 55 unchanged lines hidden (view full) ---

64
65/* free console structure */
66static void
67free_cons(vntsd_cons_t *consp)
68{
69 assert(consp);
70 (void) mutex_destroy(&consp->lock);
71 (void) cond_destroy(&consp->cvp);
72 if (consp->vcc_fd != -1)
73 (void) close(consp->vcc_fd);
72 free(consp);
73}
74
74 free(consp);
75}
76
77/* free group structure */
78static void
79free_group(vntsd_group_t *groupp)
80{
81 assert(groupp);
82 (void) mutex_destroy(&groupp->lock);
83 (void) cond_destroy(&groupp->cvp);
84 if (groupp->sockfd != -1)
85 (void) close(groupp->sockfd);
86 free(groupp);
87}
88
75/*
76 * all clients connected to a console must disconnect before
77 * removing a console.
78 */
79static void
80cleanup_cons(vntsd_cons_t *consp)
81{
82 vntsd_group_t *groupp;

--- 78 unchanged lines hidden (view full) ---

161 (void) mutex_lock(&groupp->lock);
162 groupp->status &= ~VNTSD_GROUP_CLEAN_CONS;
163 (void) mutex_unlock(&groupp->lock);
164 (void) mutex_unlock(&vntsdp->lock);
165
166 for (; ; ) {
167 /* get the console to be deleted */
168 (void) mutex_lock(&groupp->lock);
89/*
90 * all clients connected to a console must disconnect before
91 * removing a console.
92 */
93static void
94cleanup_cons(vntsd_cons_t *consp)
95{
96 vntsd_group_t *groupp;

--- 78 unchanged lines hidden (view full) ---

175 (void) mutex_lock(&groupp->lock);
176 groupp->status &= ~VNTSD_GROUP_CLEAN_CONS;
177 (void) mutex_unlock(&groupp->lock);
178 (void) mutex_unlock(&vntsdp->lock);
179
180 for (; ; ) {
181 /* get the console to be deleted */
182 (void) mutex_lock(&groupp->lock);
169 assert(groupp->conspq);
170 consp = vntsd_que_walk(groupp->conspq,
171 (el_func_t)find_clean_cons);
172 if (consp == NULL) {
173 /* no more cons to delete */
174 (void) mutex_unlock(&groupp->lock);
175 break;
176 }
177
183
178 /* remove console from the group */
179 (void) vntsd_que_rm(&groupp->conspq, consp);
180 (void) mutex_unlock(&groupp->lock);
184 /* clean up any deleted console in the group */
185 if (groupp->conspq != NULL) {
186 consp = vntsd_que_walk(groupp->conspq,
187 (el_func_t)find_clean_cons);
188 if (consp == NULL) {
189 /* no more cons to delete */
190 (void) mutex_unlock(&groupp->lock);
191 break;
192 }
181
193
182 /* clean up the console */
183 cleanup_cons(consp);
194 /* remove console from the group */
195 (void) vntsd_que_rm(&groupp->conspq, consp);
196 (void) mutex_unlock(&groupp->lock);
184
197
198 /* clean up the console */
199 cleanup_cons(consp);
200 }
201
185 /* delete group? */
202 /* delete group? */
186 if (groupp->num_cons == 0) {
187 /* no more console delete it */
203 if (groupp->conspq == NULL) {
204 /* no more console in the group delete group */
188 assert(groupp->vntsd);
189
190 (void) mutex_lock(&groupp->vntsd->lock);
191 (void) vntsd_que_rm(&groupp->vntsd->grouppq,
192 groupp);
193 (void) mutex_unlock(&groupp->vntsd->lock);
194
195 /* clean up the group */

--- 12 unchanged lines hidden (view full) ---

208 timestruc_t to;
209
210 D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(),
211 groupp->group_name, groupp->tcp_port);
212
213 (void) mutex_lock(&groupp->lock);
214
215 /* prevent from reentry */
205 assert(groupp->vntsd);
206
207 (void) mutex_lock(&groupp->vntsd->lock);
208 (void) vntsd_que_rm(&groupp->vntsd->grouppq,
209 groupp);
210 (void) mutex_unlock(&groupp->vntsd->lock);
211
212 /* clean up the group */

--- 12 unchanged lines hidden (view full) ---

225 timestruc_t to;
226
227 D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(),
228 groupp->group_name, groupp->tcp_port);
229
230 (void) mutex_lock(&groupp->lock);
231
232 /* prevent from reentry */
216 if (groupp->status & VNTSD_GROUP_CLEANUP) {
217 if (groupp->listen_tid == thr_self()) {
218 /* signal that the listen thread is exiting */
219 groupp->status &= ~VNTSD_GROUP_SIG_WAIT;
220 (void) cond_signal(&groupp->cvp);
221 }
233 if (groupp->status & VNTSD_GROUP_IN_CLEANUP) {
222 (void) mutex_unlock(&groupp->lock);
223 return;
224 }
234 (void) mutex_unlock(&groupp->lock);
235 return;
236 }
225 groupp->status |= VNTSD_GROUP_CLEANUP;
237 groupp->status |= VNTSD_GROUP_IN_CLEANUP;
238
239 /* mark group waiting for listen thread to exits */
240 groupp->status |= VNTSD_GROUP_SIG_WAIT;
226 (void) mutex_unlock(&groupp->lock);
227
228 vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons);
229
241 (void) mutex_unlock(&groupp->lock);
242
243 vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons);
244
245 (void) mutex_lock(&groupp->lock);
230 /* walk through no cons client queue */
231 while (groupp->no_cons_clientpq != NULL) {
246 /* walk through no cons client queue */
247 while (groupp->no_cons_clientpq != NULL) {
232 groupp->status |= VNTSD_GROUP_SIG_WAIT;
233 (void) vntsd_que_walk(groupp->no_cons_clientpq,
234 (el_func_t)vntsd_notify_client_cons_del);
235 to.tv_sec = VNTSD_CV_WAIT_DELTIME;
236 to.tv_nsec = 0;
237 (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to);
238 }
239
248 (void) vntsd_que_walk(groupp->no_cons_clientpq,
249 (el_func_t)vntsd_notify_client_cons_del);
250 to.tv_sec = VNTSD_CV_WAIT_DELTIME;
251 to.tv_nsec = 0;
252 (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to);
253 }
254
240 if (groupp->listen_tid == thr_self()) {
241 /* listen thread is exiting */
242 (void) mutex_lock(&(groupp->vntsd->lock));
243 (void) vntsd_que_rm(&groupp->vntsd->grouppq, groupp);
244 (void) mutex_unlock(&groupp->vntsd->lock);
245
246 (void) cond_destroy(&groupp->cvp);
247 (void) mutex_unlock(&groupp->lock);
248 (void) mutex_destroy(&groupp->lock);
249 free(groupp);
250 return;
251 }
252
253 /* signal listen thread to exit */
254 groupp->status |= VNTSD_GROUP_SIG_WAIT;
255
255 /* waiting for listen thread to exit */
256 while (groupp->status & VNTSD_GROUP_SIG_WAIT) {
256 while (groupp->status & VNTSD_GROUP_SIG_WAIT) {
257 /* signal listen thread to exit */
257 (void) thr_kill(groupp->listen_tid, SIGUSR1);
258 to.tv_sec = VNTSD_CV_WAIT_DELTIME;
259 to.tv_nsec = 0;
260 /* wait listen thread to exit */
261 (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to);
262 }
263
264 (void) mutex_unlock(&groupp->lock);
265 (void) thr_join(groupp->listen_tid, NULL, NULL);
266 /* free group */
258 (void) thr_kill(groupp->listen_tid, SIGUSR1);
259 to.tv_sec = VNTSD_CV_WAIT_DELTIME;
260 to.tv_nsec = 0;
261 /* wait listen thread to exit */
262 (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to);
263 }
264
265 (void) mutex_unlock(&groupp->lock);
266 (void) thr_join(groupp->listen_tid, NULL, NULL);
267 /* free group */
267 (void) cond_destroy(&groupp->cvp);
268 (void) mutex_destroy(&groupp->lock);
269 free(groupp);
268 free_group(groupp);
270}
271
272/* allocate and initialize console structure */
273static vntsd_cons_t *
274alloc_cons(vntsd_group_t *groupp, vcc_console_t *consolep)
275{
276 vntsd_cons_t *consp;
277 int rv;

--- 10 unchanged lines hidden (view full) ---

288
289 (void) mutex_init(&consp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL);
290 (void) cond_init(&consp->cvp, USYNC_THREAD, NULL);
291
292 consp->cons_no = consolep->cons_no;
293 (void) strlcpy(consp->domain_name, consolep->domain_name, MAXPATHLEN);
294 (void) strlcpy(consp->dev_name, consolep->dev_name, MAXPATHLEN);
295 consp->wr_tid = (thread_t)-1;
269}
270
271/* allocate and initialize console structure */
272static vntsd_cons_t *
273alloc_cons(vntsd_group_t *groupp, vcc_console_t *consolep)
274{
275 vntsd_cons_t *consp;
276 int rv;

--- 10 unchanged lines hidden (view full) ---

287
288 (void) mutex_init(&consp->lock, USYNC_THREAD|LOCK_ERRORCHECK, NULL);
289 (void) cond_init(&consp->cvp, USYNC_THREAD, NULL);
290
291 consp->cons_no = consolep->cons_no;
292 (void) strlcpy(consp->domain_name, consolep->domain_name, MAXPATHLEN);
293 (void) strlcpy(consp->dev_name, consolep->dev_name, MAXPATHLEN);
294 consp->wr_tid = (thread_t)-1;
296 consp->vcc_fd = (thread_t)-1;
295 consp->vcc_fd = -1;
297
298 /* join the group */
299 (void) mutex_lock(&groupp->lock);
300
301 if ((rv = vntsd_que_append(&groupp->conspq, consp)) !=
302 VNTSD_SUCCESS) {
303 (void) mutex_unlock(&groupp->lock);
304 vntsd_log(rv, "alloc_cons");

--- 40 unchanged lines hidden (view full) ---

345 (void) cond_init(&groupp->cvp, USYNC_THREAD, NULL);
346
347 if (group_name != NULL) {
348 (void) memcpy(groupp->group_name, group_name, MAXPATHLEN);
349 }
350
351 groupp->tcp_port = tcp_port;
352 groupp->listen_tid = (thread_t)-1;
296
297 /* join the group */
298 (void) mutex_lock(&groupp->lock);
299
300 if ((rv = vntsd_que_append(&groupp->conspq, consp)) !=
301 VNTSD_SUCCESS) {
302 (void) mutex_unlock(&groupp->lock);
303 vntsd_log(rv, "alloc_cons");

--- 40 unchanged lines hidden (view full) ---

344 (void) cond_init(&groupp->cvp, USYNC_THREAD, NULL);
345
346 if (group_name != NULL) {
347 (void) memcpy(groupp->group_name, group_name, MAXPATHLEN);
348 }
349
350 groupp->tcp_port = tcp_port;
351 groupp->listen_tid = (thread_t)-1;
353 groupp->sockfd = (thread_t)-1;
352 groupp->sockfd = -1;
354 groupp->vntsd = vntsdp;
355
356 D1(stderr, "t@%d alloc_group@%lld:%s\n", thr_self(), groupp->tcp_port,
357 groupp->group_name);
358
359 return (groupp);
360}
361
353 groupp->vntsd = vntsdp;
354
355 D1(stderr, "t@%d alloc_group@%lld:%s\n", thr_self(), groupp->tcp_port,
356 groupp->group_name);
357
358 return (groupp);
359}
360
361/* mark a deleted console */
362boolean_t
363vntsd_mark_deleted_cons(vntsd_cons_t *consp)
364{
365 (void) mutex_lock(&consp->lock);
366 consp->status |= VNTSD_CONS_DELETED;
367 (void) mutex_unlock(&consp->lock);
368 return (B_FALSE);
369}
370
362/*
363 * Initialize a console, if console is associated with with a
364 * new group, intialize the group.
365 */
366static int
367alloc_cons_with_group(vntsd_t *vntsdp, vcc_console_t *consp,
368 vntsd_group_t **new_groupp)
369{
370 vntsd_group_t *groupp = NULL;
371 int rv;
372
373 *new_groupp = NULL;
374
375 /* match group by tcp port */
376
377
378 (void) mutex_lock(&vntsdp->lock);
379 groupp = vntsd_que_find(vntsdp->grouppq,
380 (compare_func_t)grp_by_tcp, (void *)&(consp->tcp_port));
371/*
372 * Initialize a console, if console is associated with with a
373 * new group, intialize the group.
374 */
375static int
376alloc_cons_with_group(vntsd_t *vntsdp, vcc_console_t *consp,
377 vntsd_group_t **new_groupp)
378{
379 vntsd_group_t *groupp = NULL;
380 int rv;
381
382 *new_groupp = NULL;
383
384 /* match group by tcp port */
385
386
387 (void) mutex_lock(&vntsdp->lock);
388 groupp = vntsd_que_find(vntsdp->grouppq,
389 (compare_func_t)grp_by_tcp, (void *)&(consp->tcp_port));
390 if (groupp != NULL)
391 (void) mutex_lock(&groupp->lock);
392
381 (void) mutex_unlock(&vntsdp->lock);
382
383 if (groupp != NULL) {
393 (void) mutex_unlock(&vntsdp->lock);
394
395 if (groupp != NULL) {
384 /* group with same tcp port found */
396 /*
397 * group with same tcp port found.
398 * if there is no console in the group, the
399 * group should be removed and the tcp port can
400 * be used for tne new group.
401 * This is possible, when there is tight loop of
402 * creating/deleting domains. When a vcc port is
403 * removed, a read thread will have an I/O error because
404 * vcc has closed the port. The read thread then marks
405 * the console is removed and notify main thread to
406 * remove the console.
407 * Meanwhile, the same port and its group (with same
408 * tcp port and group name) is created. Vcc notify
409 * vntsd that new console is added.
410 * Main thread now have two events. If main thread polls
411 * out vcc notification first, it will find that there is
412 * a group has no console.
413 */
385
414
386 if (strcmp(groupp->group_name, consp->group_name)) {
415 if (vntsd_chk_group_total_cons(groupp) == 0) {
416
417 /* all consoles in the group have been removed */
418 (void) vntsd_que_walk(groupp->conspq,
419 (el_func_t)vntsd_mark_deleted_cons);
420 groupp->status |= VNTSD_GROUP_CLEAN_CONS;
421 (void) mutex_unlock(&groupp->lock);
422 groupp = NULL;
423
424 } else if (strcmp(groupp->group_name, consp->group_name)) {
387 /* conflict group name */
388 vntsd_log(VNTSD_ERR_VCC_GRP_NAME,
389 "group name is different from existing group");
425 /* conflict group name */
426 vntsd_log(VNTSD_ERR_VCC_GRP_NAME,
427 "group name is different from existing group");
428 (void) mutex_unlock(&groupp->lock);
390 return (VNTSD_ERR_VCC_CTRL_DATA);
429 return (VNTSD_ERR_VCC_CTRL_DATA);
430
431 } else {
432 /* group already existed */
433 (void) mutex_unlock(&groupp->lock);
391 }
392
434 }
435
393 } else {
436 }
437
438 if (groupp == NULL) {
394 /* new group */
395 groupp = alloc_group(vntsdp, consp->group_name,
396 consp->tcp_port);
397 if (groupp == NULL) {
398 return (VNTSD_ERR_NO_MEM);
399 }
400
401 assert(groupp->conspq == NULL);

--- 9 unchanged lines hidden (view full) ---

411 *new_groupp = groupp;
412 }
413
414 /* intialize console */
415 if (alloc_cons(groupp, consp) == NULL) {
416 /* no memory */
417 if (new_groupp != NULL) {
418 /* clean up new group */
439 /* new group */
440 groupp = alloc_group(vntsdp, consp->group_name,
441 consp->tcp_port);
442 if (groupp == NULL) {
443 return (VNTSD_ERR_NO_MEM);
444 }
445
446 assert(groupp->conspq == NULL);

--- 9 unchanged lines hidden (view full) ---

456 *new_groupp = groupp;
457 }
458
459 /* intialize console */
460 if (alloc_cons(groupp, consp) == NULL) {
461 /* no memory */
462 if (new_groupp != NULL) {
463 /* clean up new group */
419 (void) cond_destroy(&groupp->cvp);
420 (void) mutex_destroy(&groupp->lock);
421 free(groupp);
464 free_group(groupp);
422 }
423
424 return (VNTSD_ERR_NO_MEM);
425 }
426
427 return (VNTSD_SUCCESS);
428
429}

--- 28 unchanged lines hidden (view full) ---

458 groupp->listen_tid = (thread_t)-1;
459 }
460
461 (void) mutex_unlock(&groupp->lock);
462
463 return (rv != 0);
464}
465
465 }
466
467 return (VNTSD_ERR_NO_MEM);
468 }
469
470 return (VNTSD_SUCCESS);
471
472}

--- 28 unchanged lines hidden (view full) ---

501 groupp->listen_tid = (thread_t)-1;
502 }
503
504 (void) mutex_unlock(&groupp->lock);
505
506 return (rv != 0);
507}
508
509/* find deleted console by console no */
510static boolean_t
511deleted_cons_by_consno(vntsd_cons_t *consp, int *cons_no)
512{
513 vntsd_client_t *clientp;
514
515 assert(consp);
516
517 if (consp->cons_no != *cons_no)
518 return (B_FALSE);
519
520 /* has console marked as deleted? */
521 if ((consp->status & VNTSD_CONS_DELETED) == 0)
522 return (B_TRUE);
523
524 /* notify clients of console ? */
525 clientp = (vntsd_client_t *)consp->clientpq->handle;
526
527 if (clientp == NULL)
528 /* therre is no client for this console */
529 return (B_TRUE);
530
531 if (clientp->status & VNTSD_CLIENT_CONS_DELETED)
532 /* clients of console have notified */
533 return (B_FALSE);
534
535 return (B_TRUE);
536}
537
538/* find group structure from console no */
539static boolean_t
540find_cons_group_by_cons_no(vntsd_group_t *groupp, uint_t *cons_no)
541{
542 vntsd_cons_t *consp;
543
544 consp = vntsd_que_find(groupp->conspq,
545 (compare_func_t)deleted_cons_by_consno, cons_no);
546 return (consp != NULL);
547
548}
549
466/* delete a console if the console exists in the vntsd */
467static void
550/* delete a console if the console exists in the vntsd */
551static void
468delete_cons_before_add(vntsd_t *vntsdp, uint64_t tcp_port, uint_t cons_no)
552delete_cons_before_add(vntsd_t *vntsdp, uint_t cons_no)
469{
470 vntsd_group_t *groupp;
471 vntsd_cons_t *consp;
472
473 /* group exists? */
474 (void) mutex_lock(&vntsdp->lock);
553{
554 vntsd_group_t *groupp;
555 vntsd_cons_t *consp;
556
557 /* group exists? */
558 (void) mutex_lock(&vntsdp->lock);
475 groupp = vntsd_que_find(vntsdp->grouppq, (compare_func_t)grp_by_tcp,
476 (void *)&(tcp_port));
559 groupp = vntsd_que_find(vntsdp->grouppq,
560 (compare_func_t)find_cons_group_by_cons_no,
561 &cons_no);
477 (void) mutex_unlock(&vntsdp->lock);
478
479 if (groupp == NULL) {
480 /* no such group */
481 return;
482 }
483
484 /* group exists, if console exists? */
485 (void) mutex_lock(&groupp->lock);
486 consp = vntsd_que_find(groupp->conspq,
562 (void) mutex_unlock(&vntsdp->lock);
563
564 if (groupp == NULL) {
565 /* no such group */
566 return;
567 }
568
569 /* group exists, if console exists? */
570 (void) mutex_lock(&groupp->lock);
571 consp = vntsd_que_find(groupp->conspq,
487 (compare_func_t)vntsd_cons_by_consno, &cons_no);
572 (compare_func_t)deleted_cons_by_consno, &cons_no);
488
489 if (consp == NULL) {
490 /* no such console */
491 (void) mutex_unlock(&groupp->lock);
492 return;
493 }
494 /* console exists - delete console */
495

--- 26 unchanged lines hidden (view full) ---

522
523 if ((rv = vntsd_vcc_ioctl(VCC_CONS_INFO, cons_no, (void *)&console))
524 != VNTSD_SUCCESS) {
525 vntsd_log(rv, err_msg);
526 return;
527 }
528
529 /* clean up the console if console was deleted and added again */
573
574 if (consp == NULL) {
575 /* no such console */
576 (void) mutex_unlock(&groupp->lock);
577 return;
578 }
579 /* console exists - delete console */
580

--- 26 unchanged lines hidden (view full) ---

607
608 if ((rv = vntsd_vcc_ioctl(VCC_CONS_INFO, cons_no, (void *)&console))
609 != VNTSD_SUCCESS) {
610 vntsd_log(rv, err_msg);
611 return;
612 }
613
614 /* clean up the console if console was deleted and added again */
530 delete_cons_before_add(vntsdp, console.tcp_port, console.cons_no);
615 delete_cons_before_add(vntsdp, console.cons_no);
531
532 /* initialize console */
533
534 if ((rv = alloc_cons_with_group(vntsdp, &console, &groupp)) !=
535 VNTSD_SUCCESS) {
536 /* no memory to add this new console */
537 vntsd_log(rv, err_msg);
538 return;
539 }
540
541 if (groupp != NULL) {
542 /* new group */
543 /* create listen thread for this console */
544 if (create_listen_thread(groupp)) {
545 vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg);
616
617 /* initialize console */
618
619 if ((rv = alloc_cons_with_group(vntsdp, &console, &groupp)) !=
620 VNTSD_SUCCESS) {
621 /* no memory to add this new console */
622 vntsd_log(rv, err_msg);
623 return;
624 }
625
626 if (groupp != NULL) {
627 /* new group */
628 /* create listen thread for this console */
629 if (create_listen_thread(groupp)) {
630 vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg);
546 (void) cond_destroy(&groupp->cvp);
547 (void) mutex_destroy(&groupp->lock);
548 free(groupp);
631 free_group(groupp);
549 }
550
551 }
552}
553
554/* daemon wake up */
555void
556vntsd_daemon_wakeup(vntsd_t *vntsdp)

--- 94 unchanged lines hidden ---
632 }
633
634 }
635}
636
637/* daemon wake up */
638void
639vntsd_daemon_wakeup(vntsd_t *vntsdp)

--- 94 unchanged lines hidden ---