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 --- |