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