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
cache_free_alias(alias_t * aliasp)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
cache_free_bus(bus_t * bp)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
cache_free_controller(controller_t * cp)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
cache_free_descriptor(descriptor_t * desc)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
cache_free_descriptors(descriptor_t ** desc_list)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
cache_free_disk(disk_t * dp)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
cache_free_path(path_t * pp)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 *
cache_get_buslist()299 cache_get_buslist()
300 {
301 if (initialize() != 0) {
302 return (NULL);
303 }
304
305 return (bus_listp);
306 }
307
308 controller_t *
cache_get_controllerlist()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 *
cache_get_desc(int type,void * gp,char * name,char * secondary_name,int * errp)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 **
cache_get_descriptors(int type,int * errp)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 *
cache_get_disklist()389 cache_get_disklist()
390 {
391 if (initialize() != 0) {
392 return (NULL);
393 }
394
395 return (disk_listp);
396 }
397
398 int
cache_is_valid_desc(descriptor_t * d)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
cache_load_desc(int type,void * gp,char * name,char * secondary_name,int * errp)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
cache_rlock()431 cache_rlock()
432 {
433 (void) rw_rdlock(&cache_lock);
434 }
435
436 void
cache_unlock()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
cache_update(dm_event_type_t ev_type,char * devname)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
cache_wlock()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
clear_descriptors(void * gp)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
clr_ctrl_disk_ptr(controller_t * cp,disk_t * dp)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
clr_path_disk_ptr(path_t * pp,disk_t * dp)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
del_drive(disk_t * dp)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
del_drive_by_name(char * name)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 *
have_desc(int type,void * gp,char * name,char * secondary_name)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
initialize()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
make_descriptors(int type)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
match_alias(alias_t * ap,alias_t * listp)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
match_aliases(disk_t * d1p,disk_t * d2p)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
match_disk(disk_t * oldp,disk_t * newp)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 *
new_descriptor(dm_desc_type_t type,void * op,char * name,char * secondary_name)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
rewalk_tree()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
update_desc(descriptor_t * descp,disk_t * newdisksp,controller_t * newctrlp,bus_t * newbusp)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
update_desc_busp(descriptor_t * descp,bus_t * busp)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
update_desc_ctrlp(descriptor_t * descp,controller_t * newctrlp)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
update_desc_diskp(descriptor_t * descp,disk_t * newdisksp)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
update_desc_pathp(descriptor_t * descp,controller_t * newctrlp)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