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