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 <libintl.h> 35 #include <synch.h> 36 #include <sys/sunddi.h> 37 #include <sys/types.h> 38 #include <libgen.h> 39 #include <syslog.h> 40 41 #include "libdiskmgt.h" 42 #include "disks_private.h" 43 #include "partition.h" 44 45 #define ALIASES 0 46 #define DEVPATHS 1 47 48 /* 49 * Set DM_LIBDISKMGT_DEBUG in the environment. Two levels of debugging: 50 * 1 - errors, warnings and minimal tracing information 51 * 2 - verbose information 52 * All output prints on stderr. 53 */ 54 int dm_debug = 0; 55 56 /* Lock protecting the cached data */ 57 static rwlock_t cache_lock = DEFAULTRWLOCK; 58 static disk_t *disk_listp = NULL; 59 static controller_t *controller_listp = NULL; 60 static bus_t *bus_listp = NULL; 61 static int cache_loaded = 0; 62 63 descriptor_t *desc_listp = NULL; 64 65 static void clear_descriptors(void *gp); 66 static void clr_ctrl_disk_ptr(controller_t *cp, disk_t *dp); 67 static void clr_path_disk_ptr(path_t *pp, disk_t *dp); 68 static void del_drive(disk_t *dp); 69 static void del_drive_by_name(char *name); 70 static descriptor_t *have_desc(int type, void *gp, char *name, char *mname); 71 static int initialize(); 72 static int make_descriptors(int type); 73 static int match_disk(disk_t *oldp, disk_t *newp); 74 static int match_aliases(disk_t *d1p, disk_t *d2p); 75 static int match_alias(alias_t *ap, alias_t *listp); 76 static descriptor_t *new_descriptor(dm_desc_type_t type, void *op, 77 char *name, char *mname); 78 static void rewalk_tree(); 79 static void update_desc(descriptor_t *descp, disk_t *newdisksp, 80 controller_t *newctrlp, bus_t *newbusp); 81 static void update_desc_busp(descriptor_t *descp, bus_t *busp); 82 static void update_desc_ctrlp(descriptor_t *descp, 83 controller_t *newstrlp); 84 static void update_desc_diskp(descriptor_t *descp, 85 disk_t *newdisksp); 86 static void update_desc_pathp(descriptor_t *descp, 87 controller_t *newctrlp); 88 89 /* 90 * We only cache some of the data that we can obtain. For much of the data 91 * (e.g. slices & disks getting repartitioned) there are no events which would 92 * enable us to cache. As more events are added we can cache more information. 93 * 94 * Currently we cache the information we get from the dev tree walk. This is 95 * basically the information about the drives, aliases, devpaths, controllers 96 * and paths. We do not cache any information related to media, partitions 97 * or slices. 98 * 99 * A fundamental part of the API design is that the application can hold on 100 * to a set of descriptors for an indeterminate amount of time. Even if the 101 * application does not hold descriptors there is a window of time between the 102 * call that gets the descriptor and the use of the descriptor to get more 103 * information. Because of this, the cache design must work even if the object 104 * that the descriptor refers to no longer exists. 105 * 106 * Given this requirement, the code implements a two level cache. The 107 * descriptors that the application gets are really pointers into the first 108 * level of the cache. This first level contains the actual descriptors. 109 * These descriptors in turn refer to the objects we build from the dev tree 110 * walk which represent the drives and controllers. This is the second level 111 * in the cache. 112 * 113 * When we update the second level of the cache (the drives and controllers) 114 * we go through the first level (the descriptors) and update the pointers 115 * in those descriptors to refer to the new objects in the second level. If 116 * the object that the descriptor referred to is no longer in existence, we 117 * just null out the pointer in the descriptor. In this way the code that 118 * uses the descriptors knows that the object referred to by the descriptor 119 * no longer exists. 120 * 121 * We keep a reference count in the descriptors. This is incremented when 122 * we hand out a pointer to the descriptor and decremented when the application 123 * frees the descriptor it has. When the reference count goes to 0 we garbage 124 * collect the descriptors. In this way we only have to update active 125 * descriptors when we refresh the cache after an event. 126 * 127 * An example of the flow when we create descriptors: 128 * dm_get_descriptors libdiskmgt.c 129 * drive_get_descriptors drive.c 130 * cache_get_descriptors cache.c 131 * make_descriptors cache.c 132 * drive_make_descriptors drive.c 133 * cache_load_desc cache.c 134 * {update refcnts on descriptors & return them} 135 * 136 * The idea behind cache_get_descriptors and cache_load_desc is that we 137 * seperate the act of making the descriptor within the cache (which requires 138 * us to call back out to one of the object functions - drive_make_descriptors) 139 * from the act of handing out the descriptor (which requires us to increment 140 * the refcnt). In this way we keep all of the refcnt handling centralized 141 * in one function instead of forcing each object to ensure it replicates 142 * the refcnt handling correctly. 143 * 144 * Descriptors use two different kinds of indrection to refer to their 145 * corresponding object. For objects we cache (controllers, paths & drives) 146 * the descriptor keeps a pointer to that object. For objects that we 147 * dynamically build, the descriptor uses a combination of a pointer to the 148 * base object (usually the drive) along with a name (e.g. the media name or 149 * the alias). For objects that are based on media (e.g. a slice) we actually 150 * have to maintain a pointer (to the disk) and two names (e.g. the slice name 151 * and the media name which is the secondary name). 152 */ 153 154 void 155 cache_free_alias(alias_t *aliasp) 156 { 157 slice_t *dp; 158 159 free(aliasp->alias); 160 free(aliasp->kstat_name); 161 free(aliasp->wwn); 162 163 /* free devpaths */ 164 dp = aliasp->devpaths; 165 while (dp != NULL) { 166 slice_t *nextp; 167 168 nextp = dp->next; 169 free(dp->devpath); 170 free(dp); 171 dp = nextp; 172 } 173 174 /* free orig_paths */ 175 dp = aliasp->orig_paths; 176 while (dp != NULL) { 177 slice_t *nextp; 178 179 nextp = dp->next; 180 free(dp->devpath); 181 free(dp); 182 dp = nextp; 183 } 184 185 free(aliasp); 186 } 187 188 void 189 cache_free_bus(bus_t *bp) 190 { 191 free(bp->name); 192 free(bp->btype); 193 free(bp->kstat_name); 194 free(bp->pname); 195 free(bp->controllers); 196 free(bp); 197 } 198 199 void 200 cache_free_controller(controller_t *cp) 201 { 202 free(cp->name); 203 free(cp->kstat_name); 204 free(cp->disks); 205 if (cp->paths != NULL) { 206 int i; 207 208 for (i = 0; cp->paths[i]; i++) { 209 /* free the path since it can't exist w/o the controller */ 210 cache_free_path(cp->paths[i]); 211 } 212 free(cp->paths); 213 } 214 215 free(cp); 216 } 217 218 void 219 cache_free_descriptor(descriptor_t *desc) 220 { 221 if (!cache_is_valid_desc(desc)) { 222 return; 223 } 224 225 desc->refcnt--; 226 227 if (desc->refcnt <= 0) { 228 free(desc->name); 229 free(desc->secondary_name); 230 if (desc->prev == NULL) { 231 /* this is the first descriptor, update head ptr */ 232 desc_listp = desc->next; 233 } else { 234 desc->prev->next = desc->next; 235 } 236 if (desc->next != NULL) { 237 desc->next->prev = desc->prev; 238 } 239 free(desc); 240 } 241 } 242 243 void 244 cache_free_descriptors(descriptor_t **desc_list) 245 { 246 int i; 247 248 for (i = 0; desc_list[i]; i++) { 249 cache_free_descriptor(desc_list[i]); 250 } 251 252 free(desc_list); 253 } 254 255 void 256 cache_free_disk(disk_t *dp) 257 { 258 alias_t *ap; 259 260 free(dp->device_id); 261 if (dp->devid != NULL) { 262 devid_free(dp->devid); 263 } 264 free(dp->kernel_name); 265 free(dp->product_id); 266 free(dp->vendor_id); 267 free(dp->controllers); 268 /* the path objects are freed when we free the controller */ 269 free(dp->paths); 270 ap = dp->aliases; 271 while (ap != NULL) { 272 alias_t *nextp; 273 274 nextp = ap->next; 275 cache_free_alias(ap); 276 ap = nextp; 277 } 278 279 free(dp); 280 } 281 282 void 283 cache_free_path(path_t *pp) 284 { 285 int i; 286 287 free(pp->name); 288 free(pp->disks); 289 free(pp->states); 290 291 for (i = 0; pp->wwns[i]; i++) { 292 free(pp->wwns[i]); 293 } 294 free(pp->wwns); 295 296 free(pp); 297 } 298 299 bus_t * 300 cache_get_buslist() 301 { 302 if (initialize() != 0) { 303 return (NULL); 304 } 305 306 return (bus_listp); 307 } 308 309 controller_t * 310 cache_get_controllerlist() 311 { 312 if (initialize() != 0) { 313 return (NULL); 314 } 315 316 return (controller_listp); 317 } 318 319 /* 320 * This routine will either get the existing descriptor from the descriptor 321 * cache or make make a new descriptor and put it in the descriptor cache and 322 * return a pointer to that descriptor. We increment the refcnt when we hand 323 * out the descriptor. 324 */ 325 descriptor_t * 326 cache_get_desc(int type, void *gp, char *name, char *secondary_name, int *errp) 327 { 328 descriptor_t *dp; 329 330 *errp = 0; 331 if ((dp = have_desc(type, gp, name, secondary_name)) == NULL) { 332 /* make a new desc */ 333 if ((dp = new_descriptor(type, gp, name, secondary_name)) == 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, args.controller_listp, 855 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, newctrlp->name)) { 956 descp->p.controller = newctrlp; 957 return; 958 } 959 } 960 961 /* we did not find the controller any more, clear the ptr in the desc */ 962 descp->p.controller = NULL; 963 } 964 965 static void 966 update_desc_diskp(descriptor_t *descp, disk_t *newdisksp) 967 { 968 /* walk the new objects and find the correct disk */ 969 for (; newdisksp; newdisksp = newdisksp->next) { 970 if (match_disk(descp->p.disk, newdisksp)) { 971 descp->p.disk = newdisksp; 972 return; 973 } 974 } 975 976 /* we did not find the disk any more, clear the ptr in the descriptor */ 977 descp->p.disk = NULL; 978 } 979 980 static void 981 update_desc_pathp(descriptor_t *descp, controller_t *newctrlp) 982 { 983 /* walk the new objects and find the correct path */ 984 for (; newctrlp; newctrlp = newctrlp->next) { 985 path_t **pp; 986 987 pp = newctrlp->paths; 988 if (pp != NULL) { 989 int i; 990 991 for (i = 0; pp[i]; i++) { 992 if (libdiskmgt_str_eq(descp->p.path->name, pp[i]->name)) { 993 descp->p.path = pp[i]; 994 return; 995 } 996 } 997 } 998 } 999 1000 /* we did not find the path any more, clear the ptr in the desc */ 1001 descp->p.path = NULL; 1002 } 1003