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 2004 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 if ((status = events_start_event_watcher()) != 0) { 656 return (status); 657 } 658 659 return (0); 660 } 661 662 static int 663 make_descriptors(int type) 664 { 665 int error; 666 667 if ((error = initialize()) != 0) { 668 return (error); 669 } 670 671 switch (type) { 672 case DM_DRIVE: 673 error = drive_make_descriptors(); 674 break; 675 case DM_BUS: 676 error = bus_make_descriptors(); 677 break; 678 case DM_CONTROLLER: 679 error = controller_make_descriptors(); 680 break; 681 case DM_PATH: 682 error = path_make_descriptors(); 683 break; 684 case DM_ALIAS: 685 error = alias_make_descriptors(); 686 break; 687 case DM_MEDIA: 688 error = media_make_descriptors(); 689 break; 690 case DM_PARTITION: 691 error = partition_make_descriptors(); 692 break; 693 case DM_SLICE: 694 error = slice_make_descriptors(); 695 break; 696 } 697 698 return (error); 699 } 700 701 static int 702 match_alias(alias_t *ap, alias_t *listp) 703 { 704 if (ap->alias == NULL) { 705 return (0); 706 } 707 708 while (listp != NULL) { 709 if (libdiskmgt_str_eq(ap->alias, listp->alias)) { 710 return (1); 711 } 712 listp = listp->next; 713 } 714 715 return (0); 716 } 717 718 static int 719 match_aliases(disk_t *d1p, disk_t *d2p) 720 { 721 alias_t *ap; 722 723 if (d1p->aliases == NULL || d2p->aliases == NULL) { 724 return (0); 725 } 726 727 ap = d1p->aliases; 728 while (ap != NULL) { 729 if (match_alias(ap, d2p->aliases)) { 730 return (1); 731 } 732 ap = ap->next; 733 } 734 735 return (0); 736 } 737 738 static int 739 match_disk(disk_t *oldp, disk_t *newp) 740 { 741 if (oldp->devid != NULL) { 742 if (newp->devid != NULL && 743 devid_compare(oldp->devid, newp->devid) == 0) { 744 return (1); 745 } 746 747 } else { 748 /* oldp device id is null */ 749 if (newp->devid == NULL) { 750 /* both disks have no device id, check aliases */ 751 if (match_aliases(oldp, newp)) { 752 return (1); 753 } 754 } 755 } 756 757 return (0); 758 } 759 760 static descriptor_t * 761 new_descriptor(dm_desc_type_t type, void *op, char *name, char *secondary_name) 762 { 763 descriptor_t *d; 764 765 if (name != NULL && name[0] == 0) { 766 name = NULL; 767 } 768 769 if (secondary_name != NULL && secondary_name[0] == 0) { 770 secondary_name = NULL; 771 } 772 773 d = (descriptor_t *)malloc(sizeof (descriptor_t)); 774 if (d == NULL) { 775 return (NULL); 776 } 777 d->type = type; 778 switch (type) { 779 case DM_CONTROLLER: 780 d->p.controller = op; 781 break; 782 case DM_BUS: 783 d->p.bus = op; 784 break; 785 default: 786 d->p.disk = op; 787 break; 788 } 789 if (name != NULL) { 790 d->name = strdup(name); 791 if (d->name == NULL) { 792 free(d); 793 return (NULL); 794 } 795 } else { 796 d->name = NULL; 797 } 798 799 if (type == DM_SLICE || type == DM_PARTITION) { 800 if (secondary_name != NULL) { 801 d->secondary_name = strdup(secondary_name); 802 if (d->secondary_name == NULL) { 803 free(d->name); 804 free(d); 805 return (NULL); 806 } 807 } else { 808 d->secondary_name = NULL; 809 } 810 } else { 811 d->secondary_name = NULL; 812 } 813 814 d->refcnt = 0; 815 816 /* add this descriptor to the head of the list */ 817 if (desc_listp != NULL) { 818 desc_listp->prev = d; 819 } 820 d->prev = NULL; 821 d->next = desc_listp; 822 desc_listp = d; 823 824 return (d); 825 } 826 827 static void 828 rewalk_tree() 829 { 830 struct search_args args; 831 disk_t *free_disklistp; 832 controller_t *free_controllerlistp; 833 bus_t *free_buslistp; 834 835 findevs(&args); 836 837 if (args.dev_walk_status == 0) { 838 descriptor_t *descp; 839 840 /* walk the existing descriptors and update the ptrs */ 841 descp = desc_listp; 842 while (descp != NULL) { 843 update_desc(descp, args.disk_listp, args.controller_listp, 844 args.bus_listp); 845 descp = descp->next; 846 } 847 848 /* update the cached object ptrs */ 849 free_disklistp = disk_listp; 850 free_controllerlistp = controller_listp; 851 free_buslistp = bus_listp; 852 disk_listp = args.disk_listp; 853 controller_listp = args.controller_listp; 854 bus_listp = args.bus_listp; 855 856 } else { 857 free_disklistp = args.disk_listp; 858 free_controllerlistp = args.controller_listp; 859 free_buslistp = args.bus_listp; 860 } 861 862 /* 863 * Free the memory from either the old cached objects or the failed 864 * update objects. 865 */ 866 while (free_disklistp != NULL) { 867 disk_t *nextp; 868 869 nextp = free_disklistp->next; 870 cache_free_disk(free_disklistp); 871 free_disklistp = nextp; 872 } 873 while (free_controllerlistp != NULL) { 874 controller_t *nextp; 875 876 nextp = free_controllerlistp->next; 877 cache_free_controller(free_controllerlistp); 878 free_controllerlistp = nextp; 879 } 880 while (free_buslistp != NULL) { 881 bus_t *nextp; 882 883 nextp = free_buslistp->next; 884 cache_free_bus(free_buslistp); 885 free_buslistp = nextp; 886 } 887 } 888 889 /* 890 * Walk the new set of cached objects and update the descriptor ptr to point 891 * to the correct new object. If there is no object any more, set the desc 892 * ptr to null. 893 */ 894 static void 895 update_desc(descriptor_t *descp, disk_t *newdisksp, controller_t *newctrlp, 896 bus_t *newbusp) 897 { 898 /* if the descriptor is already dead, we're done */ 899 if (descp->p.generic == NULL) { 900 return; 901 } 902 903 /* 904 * All descriptors use a disk ptr except for controller descriptors 905 * and path descriptors. 906 */ 907 908 switch (descp->type) { 909 case DM_BUS: 910 update_desc_busp(descp, newbusp); 911 break; 912 case DM_CONTROLLER: 913 update_desc_ctrlp(descp, newctrlp); 914 break; 915 case DM_PATH: 916 update_desc_pathp(descp, newctrlp); 917 break; 918 default: 919 update_desc_diskp(descp, newdisksp); 920 break; 921 } 922 } 923 924 static void 925 update_desc_busp(descriptor_t *descp, bus_t *busp) 926 { 927 /* walk the new objects and find the correct bus */ 928 for (; busp; busp = busp->next) { 929 if (libdiskmgt_str_eq(descp->p.bus->name, busp->name)) { 930 descp->p.bus = busp; 931 return; 932 } 933 } 934 935 /* we did not find the controller any more, clear the ptr in the desc */ 936 descp->p.bus = NULL; 937 } 938 939 static void 940 update_desc_ctrlp(descriptor_t *descp, controller_t *newctrlp) 941 { 942 /* walk the new objects and find the correct controller */ 943 for (; newctrlp; newctrlp = newctrlp->next) { 944 if (libdiskmgt_str_eq(descp->p.controller->name, newctrlp->name)) { 945 descp->p.controller = newctrlp; 946 return; 947 } 948 } 949 950 /* we did not find the controller any more, clear the ptr in the desc */ 951 descp->p.controller = NULL; 952 } 953 954 static void 955 update_desc_diskp(descriptor_t *descp, disk_t *newdisksp) 956 { 957 /* walk the new objects and find the correct disk */ 958 for (; newdisksp; newdisksp = newdisksp->next) { 959 if (match_disk(descp->p.disk, newdisksp)) { 960 descp->p.disk = newdisksp; 961 return; 962 } 963 } 964 965 /* we did not find the disk any more, clear the ptr in the descriptor */ 966 descp->p.disk = NULL; 967 } 968 969 static void 970 update_desc_pathp(descriptor_t *descp, controller_t *newctrlp) 971 { 972 /* walk the new objects and find the correct path */ 973 for (; newctrlp; newctrlp = newctrlp->next) { 974 path_t **pp; 975 976 pp = newctrlp->paths; 977 if (pp != NULL) { 978 int i; 979 980 for (i = 0; pp[i]; i++) { 981 if (libdiskmgt_str_eq(descp->p.path->name, pp[i]->name)) { 982 descp->p.path = pp[i]; 983 return; 984 } 985 } 986 } 987 } 988 989 /* we did not find the path any more, clear the ptr in the desc */ 990 descp->p.path = NULL; 991 } 992