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