dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libdiskmgt / common / cache.c
blob922847aa084c65eb96b2487fec731a338efa0aa8
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
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>
40 #include "libdiskmgt.h"
41 #include "disks_private.h"
42 #include "partition.h"
44 #define ALIASES 0
45 #define DEVPATHS 1
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.
53 int dm_debug = 0;
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;
62 descriptor_t *desc_listp = NULL;
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);
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.
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.
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.
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.
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.
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.
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}
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.
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).
153 void
154 cache_free_alias(alias_t *aliasp)
156 slice_t *dp;
158 free(aliasp->alias);
159 free(aliasp->kstat_name);
160 free(aliasp->wwn);
162 /* free devpaths */
163 dp = aliasp->devpaths;
164 while (dp != NULL) {
165 slice_t *nextp;
167 nextp = dp->next;
168 free(dp->devpath);
169 free(dp);
170 dp = nextp;
173 /* free orig_paths */
174 dp = aliasp->orig_paths;
175 while (dp != NULL) {
176 slice_t *nextp;
178 nextp = dp->next;
179 free(dp->devpath);
180 free(dp);
181 dp = nextp;
184 free(aliasp);
187 void
188 cache_free_bus(bus_t *bp)
190 free(bp->name);
191 free(bp->btype);
192 free(bp->kstat_name);
193 free(bp->pname);
194 free(bp->controllers);
195 free(bp);
198 void
199 cache_free_controller(controller_t *cp)
201 free(cp->name);
202 free(cp->kstat_name);
203 free(cp->disks);
204 if (cp->paths != NULL) {
205 int i;
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]);
211 free(cp->paths);
214 free(cp);
217 void
218 cache_free_descriptor(descriptor_t *desc)
220 if (!cache_is_valid_desc(desc)) {
221 return;
224 desc->refcnt--;
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;
235 if (desc->next != NULL) {
236 desc->next->prev = desc->prev;
238 free(desc);
242 void
243 cache_free_descriptors(descriptor_t **desc_list)
245 int i;
247 for (i = 0; desc_list[i]; i++) {
248 cache_free_descriptor(desc_list[i]);
251 free(desc_list);
254 void
255 cache_free_disk(disk_t *dp)
257 alias_t *ap;
259 free(dp->device_id);
260 if (dp->devid != NULL) {
261 devid_free(dp->devid);
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;
273 nextp = ap->next;
274 cache_free_alias(ap);
275 ap = nextp;
278 free(dp);
281 void
282 cache_free_path(path_t *pp)
284 free(pp->name);
285 free(pp->disks);
286 free(pp->states);
288 if (pp->wwns) {
289 int i;
291 for (i = 0; pp->wwns[i]; i++) {
292 free(pp->wwns[i]);
294 free(pp->wwns);
297 free(pp);
300 bus_t *
301 cache_get_buslist()
303 if (initialize() != 0) {
304 return (NULL);
307 return (bus_listp);
310 controller_t *
311 cache_get_controllerlist()
313 if (initialize() != 0) {
314 return (NULL);
317 return (controller_listp);
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.
326 descriptor_t *
327 cache_get_desc(int type, void *gp, char *name, char *secondary_name, int *errp)
329 descriptor_t *dp;
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;
340 if (dp != NULL) {
341 dp->refcnt++;
344 return (dp);
347 descriptor_t **
348 cache_get_descriptors(int type, int *errp)
350 descriptor_t **descs;
351 descriptor_t *descp;
352 int cnt = 0;
353 int pos;
355 if ((*errp = make_descriptors(type)) != 0) {
356 return (NULL);
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++;
365 descp = descp->next;
368 descs = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
369 if (descs == NULL) {
370 *errp = ENOMEM;
371 return (NULL);
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;
382 descp = descp->next;
384 descs[pos] = NULL;
386 *errp = 0;
387 return (descs);
390 disk_t *
391 cache_get_disklist()
393 if (initialize() != 0) {
394 return (NULL);
397 return (disk_listp);
401 cache_is_valid_desc(descriptor_t *d)
403 descriptor_t *descp;
405 for (descp = desc_listp; descp != NULL; descp = descp->next) {
406 if (descp == d) {
407 return (1);
411 return (0);
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.
420 void
421 cache_load_desc(int type, void *gp, char *name, char *secondary_name, int *errp)
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;
432 void
433 cache_rlock()
435 (void) rw_rdlock(&cache_lock);
438 void
439 cache_unlock()
441 (void) rw_unlock(&cache_lock);
445 * This function is called when we get a devtree event. Type is either add
446 * or delete of a drive.
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.
451 void
452 cache_update(dm_event_type_t ev_type, char *devname)
454 char *orig_name;
456 cache_wlock();
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;
472 cache_unlock();
475 void
476 cache_wlock()
478 (void) rw_wrlock(&cache_lock);
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.
488 static void
489 clear_descriptors(void *gp)
491 descriptor_t *descp;
493 for (descp = desc_listp; descp != NULL; descp = descp->next) {
494 if (descp->p.generic == gp) {
495 /* clear descriptor */
496 descp->p.generic = NULL;
501 /* remove the ptr from the controller to the specified disk */
502 static void
503 clr_ctrl_disk_ptr(controller_t *cp, disk_t *dp)
505 int i;
507 for (i = 0; cp->disks[i]; i++) {
508 if (dp == cp->disks[i]) {
509 int j;
511 for (j = i; cp->disks[j]; j++) {
512 cp->disks[j] = cp->disks[j + 1];
514 return;
519 /* remove the ptr from the path to the specified disk */
520 static void
521 clr_path_disk_ptr(path_t *pp, disk_t *dp)
523 int i;
525 for (i = 0; pp->disks[i]; i++) {
526 if (dp == pp->disks[i]) {
527 int j;
529 for (j = i; pp->disks[j]; j++) {
530 pp->disks[j] = pp->disks[j + 1];
532 return;
537 static void
538 del_drive(disk_t *dp)
540 int i;
541 disk_t *listp;
542 disk_t *prev = NULL;
544 clear_descriptors(dp);
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);
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);
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;
569 break;
572 if (prev == NULL) {
573 prev = disk_listp;
574 } else {
575 prev = prev->next;
579 cache_free_disk(dp);
583 * Delete cached drive info when we get a devtree drive delete event.
585 static void
586 del_drive_by_name(char *name)
588 disk_t *listp;
590 for (listp = disk_listp; listp != NULL; listp = listp->next) {
591 alias_t *ap;
593 for (ap = listp->aliases; ap; ap = ap->next) {
594 if (libdiskmgt_str_eq(name, ap->alias)) {
595 del_drive(listp);
596 return;
602 static descriptor_t *
603 have_desc(int type, void *gp, char *name, char *secondary_name)
605 descriptor_t *descp;
607 if (name != NULL && name[0] == 0) {
608 name = NULL;
611 if (secondary_name != NULL && secondary_name[0] == 0) {
612 secondary_name = NULL;
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);
625 } else {
626 return (descp);
629 descp = descp->next;
632 return (NULL);
635 static int
636 initialize()
638 struct search_args args;
640 if (cache_loaded) {
641 return (0);
644 libdiskmgt_init_debug();
646 findevs(&args);
648 if (args.dev_walk_status != 0) {
649 return (args.dev_walk_status);
652 disk_listp = args.disk_listp;
653 controller_listp = args.controller_listp;
654 bus_listp = args.bus_listp;
656 cache_loaded = 1;
659 * Only start the event thread if we are not doing an install
661 if (getenv("_LIBDISKMGT_INSTALL") == NULL) {
662 if (events_start_event_watcher() != 0) {
664 * Log a message about the failure to start
665 * sysevents and continue on.
667 syslog(LOG_WARNING, dgettext(TEXT_DOMAIN,
668 "libdiskmgt: sysevent thread for cache "
669 "events failed to start\n"));
672 return (0);
675 static int
676 make_descriptors(int type)
678 int error;
680 if ((error = initialize()) != 0) {
681 return (error);
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;
711 return (error);
714 static int
715 match_alias(alias_t *ap, alias_t *listp)
717 if (ap->alias == NULL) {
718 return (0);
721 while (listp != NULL) {
722 if (libdiskmgt_str_eq(ap->alias, listp->alias)) {
723 return (1);
725 listp = listp->next;
728 return (0);
731 static int
732 match_aliases(disk_t *d1p, disk_t *d2p)
734 alias_t *ap;
736 if (d1p->aliases == NULL || d2p->aliases == NULL) {
737 return (0);
740 ap = d1p->aliases;
741 while (ap != NULL) {
742 if (match_alias(ap, d2p->aliases)) {
743 return (1);
745 ap = ap->next;
748 return (0);
751 static int
752 match_disk(disk_t *oldp, disk_t *newp)
754 if (oldp->devid != NULL) {
755 if (newp->devid != NULL &&
756 devid_compare(oldp->devid, newp->devid) == 0) {
757 return (1);
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);
770 return (0);
773 static descriptor_t *
774 new_descriptor(dm_desc_type_t type, void *op, char *name, char *secondary_name)
776 descriptor_t *d;
778 if (name != NULL && name[0] == 0) {
779 name = NULL;
782 if (secondary_name != NULL && secondary_name[0] == 0) {
783 secondary_name = NULL;
786 d = (descriptor_t *)malloc(sizeof (descriptor_t));
787 if (d == NULL) {
788 return (NULL);
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;
802 if (name != NULL) {
803 d->name = strdup(name);
804 if (d->name == NULL) {
805 free(d);
806 return (NULL);
808 } else {
809 d->name = NULL;
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);
820 } else {
821 d->secondary_name = NULL;
823 } else {
824 d->secondary_name = NULL;
827 d->refcnt = 0;
829 /* add this descriptor to the head of the list */
830 if (desc_listp != NULL) {
831 desc_listp->prev = d;
833 d->prev = NULL;
834 d->next = desc_listp;
835 desc_listp = d;
837 return (d);
840 static void
841 rewalk_tree()
843 struct search_args args;
844 disk_t *free_disklistp;
845 controller_t *free_controllerlistp;
846 bus_t *free_buslistp;
848 findevs(&args);
850 if (args.dev_walk_status == 0) {
851 descriptor_t *descp;
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;
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;
869 } else {
870 free_disklistp = args.disk_listp;
871 free_controllerlistp = args.controller_listp;
872 free_buslistp = args.bus_listp;
876 * Free the memory from either the old cached objects or the failed
877 * update objects.
879 while (free_disklistp != NULL) {
880 disk_t *nextp;
882 nextp = free_disklistp->next;
883 cache_free_disk(free_disklistp);
884 free_disklistp = nextp;
886 while (free_controllerlistp != NULL) {
887 controller_t *nextp;
889 nextp = free_controllerlistp->next;
890 cache_free_controller(free_controllerlistp);
891 free_controllerlistp = nextp;
893 while (free_buslistp != NULL) {
894 bus_t *nextp;
896 nextp = free_buslistp->next;
897 cache_free_bus(free_buslistp);
898 free_buslistp = nextp;
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.
907 static void
908 update_desc(descriptor_t *descp, disk_t *newdisksp, controller_t *newctrlp,
909 bus_t *newbusp)
911 /* if the descriptor is already dead, we're done */
912 if (descp->p.generic == NULL) {
913 return;
917 * All descriptors use a disk ptr except for controller descriptors
918 * and path descriptors.
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;
937 static void
938 update_desc_busp(descriptor_t *descp, bus_t *busp)
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;
948 /* we did not find the controller any more, clear the ptr in the desc */
949 descp->p.bus = NULL;
952 static void
953 update_desc_ctrlp(descriptor_t *descp, controller_t *newctrlp)
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;
964 /* we did not find the controller any more, clear the ptr in the desc */
965 descp->p.controller = NULL;
968 static void
969 update_desc_diskp(descriptor_t *descp, disk_t *newdisksp)
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;
979 /* we did not find the disk any more, clear the ptr in the descriptor */
980 descp->p.disk = NULL;
983 static void
984 update_desc_pathp(descriptor_t *descp, controller_t *newctrlp)
986 /* walk the new objects and find the correct path */
987 for (; newctrlp; newctrlp = newctrlp->next) {
988 path_t **pp;
990 pp = newctrlp->paths;
991 if (pp != NULL) {
992 int i;
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;
1004 /* we did not find the path any more, clear the ptr in the desc */
1005 descp->p.path = NULL;