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