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 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <fcntl.h> 29 #include <libdevinfo.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <libintl.h> 34 #include <synch.h> 35 #include <sys/sunddi.h> 36 #include <sys/types.h> 37 #include <libgen.h> 38 #include <syslog.h> 39 40 #include "libdiskmgt.h" 41 #include "disks_private.h" 42 #include "partition.h" 43 44 #define ALIASES 0 45 #define DEVPATHS 1 46 47 /* 48 * Set DM_LIBDISKMGT_DEBUG in the environment. Two levels of debugging: 49 * 1 - errors, warnings and minimal tracing information 50 * 2 - verbose information 51 * All output prints on stderr. 52 */ 53 int dm_debug = 0; 54 55 /* Lock protecting the cached data */ 56 static rwlock_t cache_lock = DEFAULTRWLOCK; 57 static disk_t *disk_listp = NULL; 58 static controller_t *controller_listp = NULL; 59 static bus_t *bus_listp = NULL; 60 static int cache_loaded = 0; 61 62 descriptor_t *desc_listp = NULL; 63 64 static void clear_descriptors(void *gp); 65 static void clr_ctrl_disk_ptr(controller_t *cp, disk_t *dp); 66 static void clr_path_disk_ptr(path_t *pp, disk_t *dp); 67 static void del_drive(disk_t *dp); 68 static void del_drive_by_name(char *name); 69 static descriptor_t *have_desc(int type, void *gp, char *name, char *mname); 70 static int initialize(); 71 static int make_descriptors(int type); 72 static int match_disk(disk_t *oldp, disk_t *newp); 73 static int match_aliases(disk_t *d1p, disk_t *d2p); 74 static int match_alias(alias_t *ap, alias_t *listp); 75 static descriptor_t *new_descriptor(dm_desc_type_t type, void *op, 76 char *name, char *mname); 77 static void rewalk_tree(); 78 static void update_desc(descriptor_t *descp, disk_t *newdisksp, 79 controller_t *newctrlp, bus_t *newbusp); 80 static void update_desc_busp(descriptor_t *descp, bus_t *busp); 81 static void update_desc_ctrlp(descriptor_t *descp, 82 controller_t *newstrlp); 83 static void update_desc_diskp(descriptor_t *descp, 84 disk_t *newdisksp); 85 static void update_desc_pathp(descriptor_t *descp, 86 controller_t *newctrlp); 87 88 /* 89 * We only cache some of the data that we can obtain. For much of the data 90 * (e.g. slices & disks getting repartitioned) there are no events which would 91 * enable us to cache. As more events are added we can cache more information. 92 * 93 * Currently we cache the information we get from the dev tree walk. This is 94 * basically the information about the drives, aliases, devpaths, controllers 95 * and paths. We do not cache any information related to media, partitions 96 * or slices. 97 * 98 * A fundamental part of the API design is that the application can hold on 99 * to a set of descriptors for an indeterminate amount of time. Even if the 100 * application does not hold descriptors there is a window of time between the 101 * call that gets the descriptor and the use of the descriptor to get more 102 * information. Because of this, the cache design must work even if the object 103 * that the descriptor refers to no longer exists. 104 * 105 * Given this requirement, the code implements a two level cache. The 106 * descriptors that the application gets are really pointers into the first 107 * level of the cache. This first level contains the actual descriptors. 108 * These descriptors in turn refer to the objects we build from the dev tree 109 * walk which represent the drives and controllers. This is the second level 110 * in the cache. 111 * 112 * When we update the second level of the cache (the drives and controllers) 113 * we go through the first level (the descriptors) and update the pointers 114 * in those descriptors to refer to the new objects in the second level. If 115 * the object that the descriptor referred to is no longer in existence, we 116 * just null out the pointer in the descriptor. In this way the code that 117 * uses the descriptors knows that the object referred to by the descriptor 118 * no longer exists. 119 * 120 * We keep a reference count in the descriptors. This is incremented when 121 * we hand out a pointer to the descriptor and decremented when the application 122 * frees the descriptor it has. When the reference count goes to 0 we garbage 123 * collect the descriptors. In this way we only have to update active 124 * descriptors when we refresh the cache after an event. 125 * 126 * An example of the flow when we create descriptors: 127 * dm_get_descriptors libdiskmgt.c 128 * drive_get_descriptors drive.c 129 * cache_get_descriptors cache.c 130 * make_descriptors cache.c 131 * drive_make_descriptors drive.c 132 * cache_load_desc cache.c 133 * {update refcnts on descriptors & return them} 134 * 135 * The idea behind cache_get_descriptors and cache_load_desc is that we 136 * seperate the act of making the descriptor within the cache (which requires 137 * us to call back out to one of the object functions - drive_make_descriptors) 138 * from the act of handing out the descriptor (which requires us to increment 139 * the refcnt). In this way we keep all of the refcnt handling centralized 140 * in one function instead of forcing each object to ensure it replicates 141 * the refcnt handling correctly. 142 * 143 * Descriptors use two different kinds of indrection to refer to their 144 * corresponding object. For objects we cache (controllers, paths & drives) 145 * the descriptor keeps a pointer to that object. For objects that we 146 * dynamically build, the descriptor uses a combination of a pointer to the 147 * base object (usually the drive) along with a name (e.g. the media name or 148 * the alias). For objects that are based on media (e.g. a slice) we actually 149 * have to maintain a pointer (to the disk) and two names (e.g. the slice name 150 * and the media name which is the secondary name). 151 */ 152 153 void 154 cache_free_alias(alias_t *aliasp) 155 { 156 slice_t *dp; 157 158 free(aliasp->alias); 159 free(aliasp->kstat_name); 160 free(aliasp->wwn); 161 162 /* free devpaths */ 163 dp = aliasp->devpaths; 164 while (dp != NULL) { 165 slice_t *nextp; 166 167 nextp = dp->next; 168 free(dp->devpath); 169 free(dp); 170 dp = nextp; 171 } 172 173 /* free orig_paths */ 174 dp = aliasp->orig_paths; 175 while (dp != NULL) { 176 slice_t *nextp; 177 178 nextp = dp->next; 179 free(dp->devpath); 180 free(dp); 181 dp = nextp; 182 } 183 184 free(aliasp); 185 } 186 187 void 188 cache_free_bus(bus_t *bp) 189 { 190 free(bp->name); 191 free(bp->btype); 192 free(bp->kstat_name); 193 free(bp->pname); 194 free(bp->controllers); 195 free(bp); 196 } 197 198 void 199 cache_free_controller(controller_t *cp) 200 { 201 free(cp->name); 202 free(cp->kstat_name); 203 free(cp->disks); 204 if (cp->paths != NULL) { 205 int i; 206 207 for (i = 0; cp->paths[i]; i++) { 208 /* free the path since it can't exist w/o the ctrlr */ 209 cache_free_path(cp->paths[i]); 210 } 211 free(cp->paths); 212 } 213 214 free(cp); 215 } 216 217 void 218 cache_free_descriptor(descriptor_t *desc) 219 { 220 if (!cache_is_valid_desc(desc)) { 221 return; 222 } 223 224 desc->refcnt--; 225 226 if (desc->refcnt <= 0) { 227 free(desc->name); 228 free(desc->secondary_name); 229 if (desc->prev == NULL) { 230 /* this is the first descriptor, update head ptr */ 231 desc_listp = desc->next; 232 } else { 233 desc->prev->next = desc->next; 234 } 235 if (desc->next != NULL) { 236 desc->next->prev = desc->prev; 237 } 238 free(desc); 239 } 240 } 241 242 void 243 cache_free_descriptors(descriptor_t **desc_list) 244 { 245 int i; 246 247 for (i = 0; desc_list[i]; i++) { 248 cache_free_descriptor(desc_list[i]); 249 } 250 251 free(desc_list); 252 } 253 254 void 255 cache_free_disk(disk_t *dp) 256 { 257 alias_t *ap; 258 259 free(dp->device_id); 260 if (dp->devid != NULL) { 261 devid_free(dp->devid); 262 } 263 free(dp->kernel_name); 264 free(dp->product_id); 265 free(dp->vendor_id); 266 free(dp->controllers); 267 /* the path objects are freed when we free the controller */ 268 free(dp->paths); 269 ap = dp->aliases; 270 while (ap != NULL) { 271 alias_t *nextp; 272 273 nextp = ap->next; 274 cache_free_alias(ap); 275 ap = nextp; 276 } 277 278 free(dp); 279 } 280 281 void 282 cache_free_path(path_t *pp) 283 { 284 free(pp->name); 285 free(pp->disks); 286 free(pp->states); 287 288 if (pp->wwns) { 289 int i; 290 291 for (i = 0; pp->wwns[i]; i++) { 292 free(pp->wwns[i]); 293 } 294 free(pp->wwns); 295 } 296 297 free(pp); 298 } 299 300 bus_t * 301 cache_get_buslist() 302 { 303 if (initialize() != 0) { 304 return (NULL); 305 } 306 307 return (bus_listp); 308 } 309 310 controller_t * 311 cache_get_controllerlist() 312 { 313 if (initialize() != 0) { 314 return (NULL); 315 } 316 317 return (controller_listp); 318 } 319 320 /* 321 * This routine will either get the existing descriptor from the descriptor 322 * cache or make make a new descriptor and put it in the descriptor cache and 323 * return a pointer to that descriptor. We increment the refcnt when we hand 324 * out the descriptor. 325 */ 326 descriptor_t * 327 cache_get_desc(int type, void *gp, char *name, char *secondary_name, int *errp) 328 { 329 descriptor_t *dp; 330 331 *errp = 0; 332 if ((dp = have_desc(type, gp, name, secondary_name)) == NULL) { 333 /* make a new desc */ 334 if ((dp = new_descriptor(type, gp, name, secondary_name)) 335 == NULL) { 336 *errp = ENOMEM; 337 } 338 } 339 340 if (dp != NULL) { 341 dp->refcnt++; 342 } 343 344 return (dp); 345 } 346 347 descriptor_t ** 348 cache_get_descriptors(int type, int *errp) 349 { 350 descriptor_t **descs; 351 descriptor_t *descp; 352 int cnt = 0; 353 int pos; 354 355 if ((*errp = make_descriptors(type)) != 0) { 356 return (NULL); 357 } 358 359 /* count the number of active descriptors in the descriptor cache */ 360 descp = desc_listp; 361 while (descp != NULL) { 362 if (descp->type == type && descp->p.generic != NULL) { 363 cnt++; 364 } 365 descp = descp->next; 366 } 367 368 descs = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *)); 369 if (descs == NULL) { 370 *errp = ENOMEM; 371 return (NULL); 372 } 373 374 pos = 0; 375 descp = desc_listp; 376 while (descp != NULL) { 377 if (descp->type == type && descp->p.generic != NULL) { 378 /* update refcnts before handing out the descriptors */ 379 descp->refcnt++; 380 descs[pos++] = descp; 381 } 382 descp = descp->next; 383 } 384 descs[pos] = NULL; 385 386 *errp = 0; 387 return (descs); 388 } 389 390 disk_t * 391 cache_get_disklist() 392 { 393 if (initialize() != 0) { 394 return (NULL); 395 } 396 397 return (disk_listp); 398 } 399 400 int 401 cache_is_valid_desc(descriptor_t *d) 402 { 403 descriptor_t *descp; 404 405 for (descp = desc_listp; descp != NULL; descp = descp->next) { 406 if (descp == d) { 407 return (1); 408 } 409 } 410 411 return (0); 412 } 413 414 /* 415 * This function is called by the *_make_descriptors function 416 * (e.g. drive_make_descriptors) within each of the objects. This function 417 * makes sure that the descriptor is built in the descriptor cache but 418 * it does not hand out the descriptors, so the refcnt is never incremented. 419 */ 420 void 421 cache_load_desc(int type, void *gp, char *name, char *secondary_name, int *errp) 422 { 423 *errp = 0; 424 if (have_desc(type, gp, name, secondary_name) == NULL) { 425 /* make a new desc */ 426 if (new_descriptor(type, gp, name, secondary_name) == NULL) { 427 *errp = ENOMEM; 428 } 429 } 430 } 431 432 void 433 cache_rlock() 434 { 435 (void) rw_rdlock(&cache_lock); 436 } 437 438 void 439 cache_unlock() 440 { 441 (void) rw_unlock(&cache_lock); 442 } 443 444 /* 445 * This function is called when we get a devtree event. Type is either add 446 * or delete of a drive. 447 * 448 * For delete, we need to clean up the 2nd level structures and clean up 449 * the pointers between the them. We also clear the descriptor ptr. 450 */ 451 void 452 cache_update(dm_event_type_t ev_type, char *devname) 453 { 454 char *orig_name; 455 456 cache_wlock(); 457 458 /* update the cache */ 459 switch (ev_type) { 460 case DM_EV_DISK_ADD: 461 rewalk_tree(); 462 events_new_event(devname, DM_DRIVE, DM_EV_TADD); 463 break; 464 case DM_EV_DISK_DELETE: 465 orig_name = devname; 466 devname = basename(devname); 467 del_drive_by_name(devname); 468 events_new_event(orig_name, DM_DRIVE, DM_EV_TREMOVE); 469 break; 470 } 471 472 cache_unlock(); 473 } 474 475 void 476 cache_wlock() 477 { 478 (void) rw_wrlock(&cache_lock); 479 } 480 481 /* 482 * Clear any descriptors that point at the specified cached object. 483 * We must go through the whole list since there can be multiple descriptors 484 * referencing the same object (i.e. drive/media/slice descriptors all point 485 * to the same drive object). The list is usually small (0 size) so this 486 * is not a big deal. 487 */ 488 static void 489 clear_descriptors(void *gp) 490 { 491 descriptor_t *descp; 492 493 for (descp = desc_listp; descp != NULL; descp = descp->next) { 494 if (descp->p.generic == gp) { 495 /* clear descriptor */ 496 descp->p.generic = NULL; 497 } 498 } 499 } 500 501 /* remove the ptr from the controller to the specified disk */ 502 static void 503 clr_ctrl_disk_ptr(controller_t *cp, disk_t *dp) 504 { 505 int i; 506 507 for (i = 0; cp->disks[i]; i++) { 508 if (dp == cp->disks[i]) { 509 int j; 510 511 for (j = i; cp->disks[j]; j++) { 512 cp->disks[j] = cp->disks[j + 1]; 513 } 514 return; 515 } 516 } 517 } 518 519 /* remove the ptr from the path to the specified disk */ 520 static void 521 clr_path_disk_ptr(path_t *pp, disk_t *dp) 522 { 523 int i; 524 525 for (i = 0; pp->disks[i]; i++) { 526 if (dp == pp->disks[i]) { 527 int j; 528 529 for (j = i; pp->disks[j]; j++) { 530 pp->disks[j] = pp->disks[j + 1]; 531 } 532 return; 533 } 534 } 535 } 536 537 static void 538 del_drive(disk_t *dp) 539 { 540 int i; 541 disk_t *listp; 542 disk_t *prev = NULL; 543 544 clear_descriptors(dp); 545 546 /* clear any ptrs from controllers to this drive */ 547 if (dp->controllers != NULL) { 548 for (i = 0; dp->controllers[i]; i++) { 549 clr_ctrl_disk_ptr(dp->controllers[i], dp); 550 } 551 } 552 553 /* clear any ptrs from paths to this drive */ 554 if (dp->paths != NULL) { 555 for (i = 0; dp->paths[i]; i++) { 556 clr_path_disk_ptr(dp->paths[i], dp); 557 } 558 } 559 560 /* clear drive from disk list */ 561 for (listp = disk_listp; listp != NULL; listp = listp->next) { 562 if (dp == listp) { 563 if (prev == NULL) { 564 disk_listp = dp->next; 565 } else { 566 prev->next = dp->next; 567 } 568 569 break; 570 } 571 572 if (prev == NULL) { 573 prev = disk_listp; 574 } else { 575 prev = prev->next; 576 } 577 } 578 579 cache_free_disk(dp); 580 } 581 582 /* 583 * Delete cached drive info when we get a devtree drive delete event. 584 */ 585 static void 586 del_drive_by_name(char *name) 587 { 588 disk_t *listp; 589 590 for (listp = disk_listp; listp != NULL; listp = listp->next) { 591 alias_t *ap; 592 593 for (ap = listp->aliases; ap; ap = ap->next) { 594 if (libdiskmgt_str_eq(name, ap->alias)) { 595 del_drive(listp); 596 return; 597 } 598 } 599 } 600 } 601 602 static descriptor_t * 603 have_desc(int type, void *gp, char *name, char *secondary_name) 604 { 605 descriptor_t *descp; 606 607 if (name != NULL && name[0] == 0) { 608 name = NULL; 609 } 610 611 if (secondary_name != NULL && secondary_name[0] == 0) { 612 secondary_name = NULL; 613 } 614 615 descp = desc_listp; 616 while (descp != NULL) { 617 if (descp->type == type && descp->p.generic == gp && 618 libdiskmgt_str_eq(descp->name, name)) { 619 if (type == DM_SLICE || type == DM_PARTITION || 620 type == DM_PATH) { 621 if (libdiskmgt_str_eq(descp->secondary_name, 622 secondary_name)) { 623 return (descp); 624 } 625 } else { 626 return (descp); 627 } 628 } 629 descp = descp->next; 630 } 631 632 return (NULL); 633 } 634 635 static int 636 initialize() 637 { 638 struct search_args args; 639 640 if (cache_loaded) { 641 return (0); 642 } 643 644 libdiskmgt_init_debug(); 645 646 findevs(&args); 647 648 if (args.dev_walk_status != 0) { 649 return (args.dev_walk_status); 650 } 651 652 disk_listp = args.disk_listp; 653 controller_listp = args.controller_listp; 654 bus_listp = args.bus_listp; 655 656 cache_loaded = 1; 657 658 /* 659 * Only start the event thread if we are not doing an install 660 */ 661 if (getenv("_LIBDISKMGT_INSTALL") == NULL) { 662 if (events_start_event_watcher() != 0) { 663 /* 664 * Log a message about the failure to start 665 * sysevents and continue on. 666 */ 667 syslog(LOG_WARNING, dgettext(TEXT_DOMAIN, 668 "libdiskmgt: sysevent thread for cache " 669 "events failed to start\n")); 670 } 671 } 672 return (0); 673 } 674 675 static int 676 make_descriptors(int type) 677 { 678 int error; 679 680 if ((error = initialize()) != 0) { 681 return (error); 682 } 683 684 switch (type) { 685 case DM_DRIVE: 686 error = drive_make_descriptors(); 687 break; 688 case DM_BUS: 689 error = bus_make_descriptors(); 690 break; 691 case DM_CONTROLLER: 692 error = controller_make_descriptors(); 693 break; 694 case DM_PATH: 695 error = path_make_descriptors(); 696 break; 697 case DM_ALIAS: 698 error = alias_make_descriptors(); 699 break; 700 case DM_MEDIA: 701 error = media_make_descriptors(); 702 break; 703 case DM_PARTITION: 704 error = partition_make_descriptors(); 705 break; 706 case DM_SLICE: 707 error = slice_make_descriptors(); 708 break; 709 } 710 711 return (error); 712 } 713 714 static int 715 match_alias(alias_t *ap, alias_t *listp) 716 { 717 if (ap->alias == NULL) { 718 return (0); 719 } 720 721 while (listp != NULL) { 722 if (libdiskmgt_str_eq(ap->alias, listp->alias)) { 723 return (1); 724 } 725 listp = listp->next; 726 } 727 728 return (0); 729 } 730 731 static int 732 match_aliases(disk_t *d1p, disk_t *d2p) 733 { 734 alias_t *ap; 735 736 if (d1p->aliases == NULL || d2p->aliases == NULL) { 737 return (0); 738 } 739 740 ap = d1p->aliases; 741 while (ap != NULL) { 742 if (match_alias(ap, d2p->aliases)) { 743 return (1); 744 } 745 ap = ap->next; 746 } 747 748 return (0); 749 } 750 751 static int 752 match_disk(disk_t *oldp, disk_t *newp) 753 { 754 if (oldp->devid != NULL) { 755 if (newp->devid != NULL && 756 devid_compare(oldp->devid, newp->devid) == 0) { 757 return (1); 758 } 759 760 } else { 761 /* oldp device id is null */ 762 if (newp->devid == NULL) { 763 /* both disks have no device id, check aliases */ 764 if (match_aliases(oldp, newp)) { 765 return (1); 766 } 767 } 768 } 769 770 return (0); 771 } 772 773 static descriptor_t * 774 new_descriptor(dm_desc_type_t type, void *op, char *name, char *secondary_name) 775 { 776 descriptor_t *d; 777 778 if (name != NULL && name[0] == 0) { 779 name = NULL; 780 } 781 782 if (secondary_name != NULL && secondary_name[0] == 0) { 783 secondary_name = NULL; 784 } 785 786 d = (descriptor_t *)malloc(sizeof (descriptor_t)); 787 if (d == NULL) { 788 return (NULL); 789 } 790 d->type = type; 791 switch (type) { 792 case DM_CONTROLLER: 793 d->p.controller = op; 794 break; 795 case DM_BUS: 796 d->p.bus = op; 797 break; 798 default: 799 d->p.disk = op; 800 break; 801 } 802 if (name != NULL) { 803 d->name = strdup(name); 804 if (d->name == NULL) { 805 free(d); 806 return (NULL); 807 } 808 } else { 809 d->name = NULL; 810 } 811 812 if (type == DM_SLICE || type == DM_PARTITION) { 813 if (secondary_name != NULL) { 814 d->secondary_name = strdup(secondary_name); 815 if (d->secondary_name == NULL) { 816 free(d->name); 817 free(d); 818 return (NULL); 819 } 820 } else { 821 d->secondary_name = NULL; 822 } 823 } else { 824 d->secondary_name = NULL; 825 } 826 827 d->refcnt = 0; 828 829 /* add this descriptor to the head of the list */ 830 if (desc_listp != NULL) { 831 desc_listp->prev = d; 832 } 833 d->prev = NULL; 834 d->next = desc_listp; 835 desc_listp = d; 836 837 return (d); 838 } 839 840 static void 841 rewalk_tree() 842 { 843 struct search_args args; 844 disk_t *free_disklistp; 845 controller_t *free_controllerlistp; 846 bus_t *free_buslistp; 847 848 findevs(&args); 849 850 if (args.dev_walk_status == 0) { 851 descriptor_t *descp; 852 853 /* walk the existing descriptors and update the ptrs */ 854 descp = desc_listp; 855 while (descp != NULL) { 856 update_desc(descp, args.disk_listp, 857 args.controller_listp, args.bus_listp); 858 descp = descp->next; 859 } 860 861 /* update the cached object ptrs */ 862 free_disklistp = disk_listp; 863 free_controllerlistp = controller_listp; 864 free_buslistp = bus_listp; 865 disk_listp = args.disk_listp; 866 controller_listp = args.controller_listp; 867 bus_listp = args.bus_listp; 868 869 } else { 870 free_disklistp = args.disk_listp; 871 free_controllerlistp = args.controller_listp; 872 free_buslistp = args.bus_listp; 873 } 874 875 /* 876 * Free the memory from either the old cached objects or the failed 877 * update objects. 878 */ 879 while (free_disklistp != NULL) { 880 disk_t *nextp; 881 882 nextp = free_disklistp->next; 883 cache_free_disk(free_disklistp); 884 free_disklistp = nextp; 885 } 886 while (free_controllerlistp != NULL) { 887 controller_t *nextp; 888 889 nextp = free_controllerlistp->next; 890 cache_free_controller(free_controllerlistp); 891 free_controllerlistp = nextp; 892 } 893 while (free_buslistp != NULL) { 894 bus_t *nextp; 895 896 nextp = free_buslistp->next; 897 cache_free_bus(free_buslistp); 898 free_buslistp = nextp; 899 } 900 } 901 902 /* 903 * Walk the new set of cached objects and update the descriptor ptr to point 904 * to the correct new object. If there is no object any more, set the desc 905 * ptr to null. 906 */ 907 static void 908 update_desc(descriptor_t *descp, disk_t *newdisksp, controller_t *newctrlp, 909 bus_t *newbusp) 910 { 911 /* if the descriptor is already dead, we're done */ 912 if (descp->p.generic == NULL) { 913 return; 914 } 915 916 /* 917 * All descriptors use a disk ptr except for controller descriptors 918 * and path descriptors. 919 */ 920 921 switch (descp->type) { 922 case DM_BUS: 923 update_desc_busp(descp, newbusp); 924 break; 925 case DM_CONTROLLER: 926 update_desc_ctrlp(descp, newctrlp); 927 break; 928 case DM_PATH: 929 update_desc_pathp(descp, newctrlp); 930 break; 931 default: 932 update_desc_diskp(descp, newdisksp); 933 break; 934 } 935 } 936 937 static void 938 update_desc_busp(descriptor_t *descp, bus_t *busp) 939 { 940 /* walk the new objects and find the correct bus */ 941 for (; busp; busp = busp->next) { 942 if (libdiskmgt_str_eq(descp->p.bus->name, busp->name)) { 943 descp->p.bus = busp; 944 return; 945 } 946 } 947 948 /* we did not find the controller any more, clear the ptr in the desc */ 949 descp->p.bus = NULL; 950 } 951 952 static void 953 update_desc_ctrlp(descriptor_t *descp, controller_t *newctrlp) 954 { 955 /* walk the new objects and find the correct controller */ 956 for (; newctrlp; newctrlp = newctrlp->next) { 957 if (libdiskmgt_str_eq(descp->p.controller->name, 958 newctrlp->name)) { 959 descp->p.controller = newctrlp; 960 return; 961 } 962 } 963 964 /* we did not find the controller any more, clear the ptr in the desc */ 965 descp->p.controller = NULL; 966 } 967 968 static void 969 update_desc_diskp(descriptor_t *descp, disk_t *newdisksp) 970 { 971 /* walk the new objects and find the correct disk */ 972 for (; newdisksp; newdisksp = newdisksp->next) { 973 if (match_disk(descp->p.disk, newdisksp)) { 974 descp->p.disk = newdisksp; 975 return; 976 } 977 } 978 979 /* we did not find the disk any more, clear the ptr in the descriptor */ 980 descp->p.disk = NULL; 981 } 982 983 static void 984 update_desc_pathp(descriptor_t *descp, controller_t *newctrlp) 985 { 986 /* walk the new objects and find the correct path */ 987 for (; newctrlp; newctrlp = newctrlp->next) { 988 path_t **pp; 989 990 pp = newctrlp->paths; 991 if (pp != NULL) { 992 int i; 993 994 for (i = 0; pp[i]; i++) { 995 if (libdiskmgt_str_eq(descp->p.path->name, 996 pp[i]->name)) { 997 descp->p.path = pp[i]; 998 return; 999 } 1000 } 1001 } 1002 } 1003 1004 /* we did not find the path any more, clear the ptr in the desc */ 1005 descp->p.path = NULL; 1006 } 1007