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