xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_getdevs.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * get dev_t list
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #include <meta.h>
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <sys/mhd.h>
36*0Sstevel@tonic-gate #include <strings.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate /*
39*0Sstevel@tonic-gate  * private version of minor(), able to handle 64 bit and 32 bit devices.
40*0Sstevel@tonic-gate  * print a warning out in case a 32 bit dev is specified.
41*0Sstevel@tonic-gate  */
42*0Sstevel@tonic-gate minor_t
43*0Sstevel@tonic-gate meta_getminor(md_dev64_t dev64)
44*0Sstevel@tonic-gate {
45*0Sstevel@tonic-gate 	/* check if it's a real 64 bit dev */
46*0Sstevel@tonic-gate 	if ((dev64 >> NBITSMAJOR64) > 0) {
47*0Sstevel@tonic-gate 		return ((minor_t)(dev64 & MAXMIN64));
48*0Sstevel@tonic-gate 	} else {
49*0Sstevel@tonic-gate 		if (getenv("META_DEBUG"))
50*0Sstevel@tonic-gate 			(void) printf(
51*0Sstevel@tonic-gate 			    "meta_getminor called with 32 bit dev: 0x%llx\n",
52*0Sstevel@tonic-gate 				dev64);
53*0Sstevel@tonic-gate 		return ((minor_t)(dev64 & MAXMIN32));
54*0Sstevel@tonic-gate 	}
55*0Sstevel@tonic-gate }
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate /*
58*0Sstevel@tonic-gate  * private version of major(), able to handle 64 bit and 32 bit devices.
59*0Sstevel@tonic-gate  * print a warning out in case a 32 bit dev is specified.
60*0Sstevel@tonic-gate  */
61*0Sstevel@tonic-gate major_t
62*0Sstevel@tonic-gate meta_getmajor(md_dev64_t dev64)
63*0Sstevel@tonic-gate {
64*0Sstevel@tonic-gate 	/* check if it's a real 64 bit dev */
65*0Sstevel@tonic-gate 	if ((dev64 >> NBITSMAJOR64) > 0) {
66*0Sstevel@tonic-gate 		return ((major_t)((dev64 >> NBITSMINOR64) & MAXMAJ64));
67*0Sstevel@tonic-gate 	} else {
68*0Sstevel@tonic-gate 		if (getenv("META_DEBUG"))
69*0Sstevel@tonic-gate 			(void) printf(
70*0Sstevel@tonic-gate 			    "meta_getmajor called with 32 bit dev: 0x%llx\n",
71*0Sstevel@tonic-gate 			dev64);
72*0Sstevel@tonic-gate 		return ((major_t)((dev64 >> NBITSMINOR32) & MAXMAJ32));
73*0Sstevel@tonic-gate 	}
74*0Sstevel@tonic-gate }
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate /*
77*0Sstevel@tonic-gate  * private version of cmpldev(), able to handle 64 bit and 32 bit devices.
78*0Sstevel@tonic-gate  */
79*0Sstevel@tonic-gate dev32_t
80*0Sstevel@tonic-gate meta_cmpldev(md_dev64_t dev64)
81*0Sstevel@tonic-gate {
82*0Sstevel@tonic-gate 	minor_t minor;
83*0Sstevel@tonic-gate 	major_t major;
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate 	major = (major_t)(dev64 >> NBITSMAJOR64);
86*0Sstevel@tonic-gate 	if (major == 0) {
87*0Sstevel@tonic-gate 		return ((dev32_t)dev64);
88*0Sstevel@tonic-gate 	}
89*0Sstevel@tonic-gate 	minor = (dev32_t)dev64 & MAXMIN32;
90*0Sstevel@tonic-gate 	return ((major << NBITSMINOR32) | minor);
91*0Sstevel@tonic-gate }
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate /*
94*0Sstevel@tonic-gate  * private version of expldev(), able to handle 64 bit and 32 bit devices.
95*0Sstevel@tonic-gate  */
96*0Sstevel@tonic-gate md_dev64_t
97*0Sstevel@tonic-gate meta_expldev(md_dev64_t dev64)
98*0Sstevel@tonic-gate {
99*0Sstevel@tonic-gate 	minor_t minor;
100*0Sstevel@tonic-gate 	major_t major;
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	major = (major_t)(dev64 >> NBITSMAJOR64);
103*0Sstevel@tonic-gate 	if (major > 0) { /* a 64 bit device was given, return unchanged */
104*0Sstevel@tonic-gate 		return (dev64);
105*0Sstevel@tonic-gate 	}
106*0Sstevel@tonic-gate 	minor = (minor_t)(dev64) & MAXMIN32;
107*0Sstevel@tonic-gate 	major = ((major_t)dev64 >> NBITSMINOR32) & MAXMAJ32;
108*0Sstevel@tonic-gate 	return (((md_dev64_t)major << NBITSMINOR64) | minor);
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate /*
112*0Sstevel@tonic-gate  * get underlying devices (recursively)
113*0Sstevel@tonic-gate  */
114*0Sstevel@tonic-gate int
115*0Sstevel@tonic-gate meta_getdevs(
116*0Sstevel@tonic-gate 	mdsetname_t		*sp,
117*0Sstevel@tonic-gate 	mdname_t		*namep,
118*0Sstevel@tonic-gate 	mdnamelist_t		**nlpp,
119*0Sstevel@tonic-gate 	md_error_t		*ep
120*0Sstevel@tonic-gate )
121*0Sstevel@tonic-gate {
122*0Sstevel@tonic-gate 	char			*miscname;
123*0Sstevel@tonic-gate 	md_dev64_t		*mydevs = NULL;
124*0Sstevel@tonic-gate 	md_getdevs_params_t	mgd;
125*0Sstevel@tonic-gate 	size_t			i;
126*0Sstevel@tonic-gate 	int			rval = -1;
127*0Sstevel@tonic-gate 	md_sys_error_t		*ip;
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 	/* must have local set */
130*0Sstevel@tonic-gate 	assert(sp != NULL);
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	/* just add regular devices */
133*0Sstevel@tonic-gate 	if (! metaismeta(namep)) {
134*0Sstevel@tonic-gate 		mdnamelist_t	*p;
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate 		/*
137*0Sstevel@tonic-gate 		 * If the dev_t is in the array already
138*0Sstevel@tonic-gate 		 * then let's continue.
139*0Sstevel@tonic-gate 		 */
140*0Sstevel@tonic-gate 		for (p = *nlpp; (p != NULL); p = p->next) {
141*0Sstevel@tonic-gate 			if (strcmp(namep->bname, p->namep->bname) == 0) {
142*0Sstevel@tonic-gate 				rval = 0;
143*0Sstevel@tonic-gate 				goto out;
144*0Sstevel@tonic-gate 			}
145*0Sstevel@tonic-gate 		}
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 		/* add to list */
148*0Sstevel@tonic-gate 		(void) metanamelist_append(nlpp, namep);
149*0Sstevel@tonic-gate 		rval = 0;
150*0Sstevel@tonic-gate 		goto out;
151*0Sstevel@tonic-gate 	}
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 	/* get MD misc module */
154*0Sstevel@tonic-gate 	if ((miscname = metagetmiscname(namep, ep)) == NULL)
155*0Sstevel@tonic-gate 		goto out;
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	/* get count of underlying devices */
158*0Sstevel@tonic-gate 	(void) memset(&mgd, '\0', sizeof (mgd));
159*0Sstevel@tonic-gate 	MD_SETDRIVERNAME(&mgd, miscname, sp->setno);
160*0Sstevel@tonic-gate 	mgd.mnum = meta_getminor(namep->dev);
161*0Sstevel@tonic-gate 	mgd.cnt = 0;
162*0Sstevel@tonic-gate 	mgd.devs = NULL;
163*0Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, namep->cname) != 0) {
164*0Sstevel@tonic-gate 		if (mgd.mde.info.errclass == MDEC_SYS) {
165*0Sstevel@tonic-gate 			ip = &mgd.mde.info.md_error_info_t_u.sys_error;
166*0Sstevel@tonic-gate 			if (ip->errnum == ENODEV) {
167*0Sstevel@tonic-gate 				rval = 0;
168*0Sstevel@tonic-gate 				goto out;
169*0Sstevel@tonic-gate 			}
170*0Sstevel@tonic-gate 		}
171*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &mgd.mde);
172*0Sstevel@tonic-gate 		goto out;
173*0Sstevel@tonic-gate 	} else if (mgd.cnt <= 0) {
174*0Sstevel@tonic-gate 		assert(mgd.cnt >= 0);
175*0Sstevel@tonic-gate 		rval = 0;
176*0Sstevel@tonic-gate 		goto out;
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	/* get underlying devices */
180*0Sstevel@tonic-gate 	mydevs = Zalloc(sizeof (*mydevs) * mgd.cnt);
181*0Sstevel@tonic-gate 	mgd.devs = (uintptr_t)mydevs;
182*0Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, namep->cname) != 0) {
183*0Sstevel@tonic-gate 		if (mgd.mde.info.errclass == MDEC_SYS) {
184*0Sstevel@tonic-gate 			ip = &mgd.mde.info.md_error_info_t_u.sys_error;
185*0Sstevel@tonic-gate 			if (ip->errnum == ENODEV) {
186*0Sstevel@tonic-gate 				rval = 0;
187*0Sstevel@tonic-gate 				goto out;
188*0Sstevel@tonic-gate 			}
189*0Sstevel@tonic-gate 		}
190*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &mgd.mde);
191*0Sstevel@tonic-gate 		goto out;
192*0Sstevel@tonic-gate 	} else if (mgd.cnt <= 0) {
193*0Sstevel@tonic-gate 		assert(mgd.cnt >= 0);
194*0Sstevel@tonic-gate 		rval = 0;
195*0Sstevel@tonic-gate 		goto out;
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate 	/* recurse */
198*0Sstevel@tonic-gate 	for (i = 0; (i < mgd.cnt); ++i) {
199*0Sstevel@tonic-gate 		mdname_t	*devnp;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 		if (mydevs[i] == NODEV64) {
202*0Sstevel@tonic-gate 			continue;
203*0Sstevel@tonic-gate 		}
204*0Sstevel@tonic-gate 		if ((devnp = metadevname(&sp, mydevs[i], ep)) == NULL) {
205*0Sstevel@tonic-gate 			goto out;
206*0Sstevel@tonic-gate 		}
207*0Sstevel@tonic-gate 		if (meta_getdevs(sp, devnp, nlpp, ep) != 0)
208*0Sstevel@tonic-gate 			goto out;
209*0Sstevel@tonic-gate 	}
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	/* success */
212*0Sstevel@tonic-gate 	rval = 0;
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate 	/* cleanup, return error */
215*0Sstevel@tonic-gate out:
216*0Sstevel@tonic-gate 	if (mydevs != NULL)
217*0Sstevel@tonic-gate 		Free(mydevs);
218*0Sstevel@tonic-gate 	return (rval);
219*0Sstevel@tonic-gate }
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate /*
222*0Sstevel@tonic-gate  * get all dev_t for a set
223*0Sstevel@tonic-gate  */
224*0Sstevel@tonic-gate int
225*0Sstevel@tonic-gate meta_getalldevs(
226*0Sstevel@tonic-gate 	mdsetname_t		*sp,		/* set to look in */
227*0Sstevel@tonic-gate 	mdnamelist_t		**nlpp,		/* returned devices */
228*0Sstevel@tonic-gate 	int			check_db,
229*0Sstevel@tonic-gate 	md_error_t		*ep
230*0Sstevel@tonic-gate )
231*0Sstevel@tonic-gate {
232*0Sstevel@tonic-gate 	md_replicalist_t	*rlp, *rp;
233*0Sstevel@tonic-gate 	mdnamelist_t		*nlp, *np;
234*0Sstevel@tonic-gate 	mdhspnamelist_t		*hspnlp, *hspp;
235*0Sstevel@tonic-gate 	int			rval = 0;
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	assert(sp != NULL);
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	/*
240*0Sstevel@tonic-gate 	 * Get a replica namelist,
241*0Sstevel@tonic-gate 	 * and then get all the devs within the replicas.
242*0Sstevel@tonic-gate 	 */
243*0Sstevel@tonic-gate 	if (check_db == TRUE) {
244*0Sstevel@tonic-gate 		rlp = NULL;
245*0Sstevel@tonic-gate 		if (metareplicalist(sp, MD_BASICNAME_OK, &rlp, ep) < 0)
246*0Sstevel@tonic-gate 			rval = -1;
247*0Sstevel@tonic-gate 		for (rp = rlp; (rp != NULL); rp = rp->rl_next) {
248*0Sstevel@tonic-gate 			if (meta_getdevs(sp, rp->rl_repp->r_namep,
249*0Sstevel@tonic-gate 			    nlpp, ep) != 0)
250*0Sstevel@tonic-gate 				rval = -1;
251*0Sstevel@tonic-gate 		}
252*0Sstevel@tonic-gate 		metafreereplicalist(rlp);
253*0Sstevel@tonic-gate 	}
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	/*
256*0Sstevel@tonic-gate 	 * Get a stripe namelist,
257*0Sstevel@tonic-gate 	 * and then get all the devs within the stripes.
258*0Sstevel@tonic-gate 	 */
259*0Sstevel@tonic-gate 	nlp = NULL;
260*0Sstevel@tonic-gate 	if (meta_get_stripe_names(sp, &nlp, 0, ep) < 0)
261*0Sstevel@tonic-gate 		rval = -1;
262*0Sstevel@tonic-gate 	for (np = nlp; (np != NULL); np = np->next) {
263*0Sstevel@tonic-gate 		if (meta_getdevs(sp, np->namep, nlpp, ep) != 0)
264*0Sstevel@tonic-gate 			rval = -1;
265*0Sstevel@tonic-gate 	}
266*0Sstevel@tonic-gate 	metafreenamelist(nlp);
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate 	/*
269*0Sstevel@tonic-gate 	 * Get a mirror namelist,
270*0Sstevel@tonic-gate 	 * and then get all the devs within the mirrors.
271*0Sstevel@tonic-gate 	 */
272*0Sstevel@tonic-gate 	nlp = NULL;
273*0Sstevel@tonic-gate 	if (meta_get_mirror_names(sp, &nlp, 0, ep) < 0)
274*0Sstevel@tonic-gate 		rval = -1;
275*0Sstevel@tonic-gate 	for (np = nlp; (np != NULL); np = np->next) {
276*0Sstevel@tonic-gate 		if (meta_getdevs(sp, np->namep, nlpp, ep) != 0)
277*0Sstevel@tonic-gate 			rval = -1;
278*0Sstevel@tonic-gate 	}
279*0Sstevel@tonic-gate 	metafreenamelist(nlp);
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 	/*
282*0Sstevel@tonic-gate 	 * Get a trans namelist,
283*0Sstevel@tonic-gate 	 * and then get all the devs within the trans.
284*0Sstevel@tonic-gate 	 */
285*0Sstevel@tonic-gate 	nlp = NULL;
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 	if (meta_get_trans_names(sp, &nlp, 0, ep) < 0)
288*0Sstevel@tonic-gate 		rval = -1;
289*0Sstevel@tonic-gate 	for (np = nlp; (np != NULL); np = np->next) {
290*0Sstevel@tonic-gate 		if (meta_getdevs(sp, np->namep, nlpp, ep) != 0)
291*0Sstevel@tonic-gate 			rval = -1;
292*0Sstevel@tonic-gate 	}
293*0Sstevel@tonic-gate 	metafreenamelist(nlp);
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 	/*
296*0Sstevel@tonic-gate 	 * Get a hot spare pool namelist,
297*0Sstevel@tonic-gate 	 * and then get all the devs within the hot spare pools.
298*0Sstevel@tonic-gate 	 */
299*0Sstevel@tonic-gate 	hspnlp = NULL;
300*0Sstevel@tonic-gate 	if (meta_get_hsp_names(sp, &hspnlp, 0, ep) < 0)
301*0Sstevel@tonic-gate 		rval = -1;
302*0Sstevel@tonic-gate 	for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) {
303*0Sstevel@tonic-gate 		md_hsp_t	*hsp;
304*0Sstevel@tonic-gate 		uint_t		i;
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 		if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL)
307*0Sstevel@tonic-gate 			rval = -1;
308*0Sstevel@tonic-gate 		else for (i = 0; (i < hsp->hotspares.hotspares_len); ++i) {
309*0Sstevel@tonic-gate 			md_hs_t	*hs = &hsp->hotspares.hotspares_val[i];
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 			if (meta_getdevs(sp, hs->hsnamep, nlpp, ep) != 0)
312*0Sstevel@tonic-gate 				rval = -1;
313*0Sstevel@tonic-gate 		}
314*0Sstevel@tonic-gate 	}
315*0Sstevel@tonic-gate 	metafreehspnamelist(hspnlp);
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	/*
318*0Sstevel@tonic-gate 	 * Get a raid namelist,
319*0Sstevel@tonic-gate 	 * and then get all the devs within the raids.
320*0Sstevel@tonic-gate 	 */
321*0Sstevel@tonic-gate 	nlp = NULL;
322*0Sstevel@tonic-gate 	if (meta_get_raid_names(sp, &nlp, 0, ep) < 0)
323*0Sstevel@tonic-gate 		rval = -1;
324*0Sstevel@tonic-gate 	for (np = nlp; (np != NULL); np = np->next) {
325*0Sstevel@tonic-gate 		if (meta_getdevs(sp, np->namep, nlpp, ep) != 0)
326*0Sstevel@tonic-gate 			rval = -1;
327*0Sstevel@tonic-gate 	}
328*0Sstevel@tonic-gate 	metafreenamelist(nlp);
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	/*
331*0Sstevel@tonic-gate 	 * Get a soft partition namelist,
332*0Sstevel@tonic-gate 	 * and then get all the devs within the softpartitions
333*0Sstevel@tonic-gate 	 */
334*0Sstevel@tonic-gate 	nlp = NULL;
335*0Sstevel@tonic-gate 	if (meta_get_sp_names(sp, &nlp, 0, ep) < 0)
336*0Sstevel@tonic-gate 		rval = -1;
337*0Sstevel@tonic-gate 	for (np = nlp; (np != NULL); np = np->next) {
338*0Sstevel@tonic-gate 		if (meta_getdevs(sp, np->namep, nlpp, ep) != 0)
339*0Sstevel@tonic-gate 			rval = -1;
340*0Sstevel@tonic-gate 	}
341*0Sstevel@tonic-gate 	metafreenamelist(nlp);
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	return (rval);
344*0Sstevel@tonic-gate }
345*0Sstevel@tonic-gate 
346*0Sstevel@tonic-gate /*
347*0Sstevel@tonic-gate  * get vtoc from a device already opened.
348*0Sstevel@tonic-gate  * returns
349*0Sstevel@tonic-gate  *	0 on success,
350*0Sstevel@tonic-gate  *	-1 on error. If the error was  ENOTSUP, partno will be set to
351*0Sstevel@tonic-gate  *		VT_ENOTSUP if possible.
352*0Sstevel@tonic-gate  */
353*0Sstevel@tonic-gate int
354*0Sstevel@tonic-gate meta_getvtoc(
355*0Sstevel@tonic-gate 	int		fd,		/* fd for named device */
356*0Sstevel@tonic-gate 	char		*devname,	/* name of device */
357*0Sstevel@tonic-gate 	struct vtoc	*vtocbufp,	/* vtoc buffer to fill */
358*0Sstevel@tonic-gate 	int		*partno,	/* return partno here */
359*0Sstevel@tonic-gate 	md_error_t	*ep
360*0Sstevel@tonic-gate )
361*0Sstevel@tonic-gate {
362*0Sstevel@tonic-gate 	int		part;
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	(void) memset(vtocbufp, 0, sizeof (*vtocbufp));
365*0Sstevel@tonic-gate 	if ((part = read_vtoc(fd, vtocbufp)) < 0) {
366*0Sstevel@tonic-gate 		int	err = errno;
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 		if (ioctl(fd, MHIOCSTATUS, NULL) == 1)
369*0Sstevel@tonic-gate 			err = EACCES;
370*0Sstevel@tonic-gate 		else if (part == VT_EINVAL)
371*0Sstevel@tonic-gate 			err = EINVAL;
372*0Sstevel@tonic-gate 		else if (part == VT_EIO)
373*0Sstevel@tonic-gate 			err = EIO;
374*0Sstevel@tonic-gate 		else if (part == VT_ENOTSUP) {
375*0Sstevel@tonic-gate 			if (partno) {
376*0Sstevel@tonic-gate 				*partno = VT_ENOTSUP;
377*0Sstevel@tonic-gate 				return (-1);
378*0Sstevel@tonic-gate 			}
379*0Sstevel@tonic-gate 		}
380*0Sstevel@tonic-gate 		return (mdsyserror(ep, err, devname));
381*0Sstevel@tonic-gate 	}
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 	/* Slice number for *p0 partition (whole disk on x86) is 16 */
384*0Sstevel@tonic-gate 	if (part >= V_NUMPAR)
385*0Sstevel@tonic-gate 		return (mdsyserror(ep, EINVAL, devname));
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate 	if (partno)
388*0Sstevel@tonic-gate 		*partno = part;
389*0Sstevel@tonic-gate 	return (0);
390*0Sstevel@tonic-gate }
391*0Sstevel@tonic-gate /*
392*0Sstevel@tonic-gate  * set mdvtoc for a meta devices
393*0Sstevel@tonic-gate  */
394*0Sstevel@tonic-gate int
395*0Sstevel@tonic-gate meta_setmdvtoc(
396*0Sstevel@tonic-gate 	int		fd,		/* fd for named device */
397*0Sstevel@tonic-gate 	char		*devname,	/* name of device */
398*0Sstevel@tonic-gate 	mdvtoc_t	*mdvtocp,	/* mdvtoc buffer to fill */
399*0Sstevel@tonic-gate 	md_error_t	*ep
400*0Sstevel@tonic-gate )
401*0Sstevel@tonic-gate {
402*0Sstevel@tonic-gate 	uint_t i;
403*0Sstevel@tonic-gate 
404*0Sstevel@tonic-gate 	/*
405*0Sstevel@tonic-gate 	 * Sanity-check the mdvtoc
406*0Sstevel@tonic-gate 	 */
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 	if (mdvtocp->nparts > V_NUMPAR) {
409*0Sstevel@tonic-gate 		return (-1);
410*0Sstevel@tonic-gate 	}
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	/*
413*0Sstevel@tonic-gate 	 * since many drivers won't allow opening a device make sure
414*0Sstevel@tonic-gate 	 * all partitions aren't being set to zero. If all are zero then
415*0Sstevel@tonic-gate 	 * we have no way to set them to something else
416*0Sstevel@tonic-gate 	 */
417*0Sstevel@tonic-gate 
418*0Sstevel@tonic-gate 	for (i = 0; i < mdvtocp->nparts; i++)
419*0Sstevel@tonic-gate 		if (mdvtocp->parts[i].size > 0)
420*0Sstevel@tonic-gate 			break;
421*0Sstevel@tonic-gate 	if (i == mdvtocp->nparts)
422*0Sstevel@tonic-gate 		return (-1);
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate 	/*
425*0Sstevel@tonic-gate 	 * Write the mdvtoc
426*0Sstevel@tonic-gate 	 */
427*0Sstevel@tonic-gate 	if (ioctl(fd, DKIOCSVTOC, (caddr_t)mdvtocp) == -1) {
428*0Sstevel@tonic-gate 		return (mdsyserror(ep, errno, devname));
429*0Sstevel@tonic-gate 	}
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate 	return (0);
432*0Sstevel@tonic-gate }
433*0Sstevel@tonic-gate 
434*0Sstevel@tonic-gate /*
435*0Sstevel@tonic-gate  * set vtoc
436*0Sstevel@tonic-gate  */
437*0Sstevel@tonic-gate int
438*0Sstevel@tonic-gate meta_setvtoc(
439*0Sstevel@tonic-gate 	int		fd,		/* fd for named device */
440*0Sstevel@tonic-gate 	char		*devname,	/* name of device */
441*0Sstevel@tonic-gate 	struct vtoc	*vtocbufp,	/* vtoc buffer to fill */
442*0Sstevel@tonic-gate 	md_error_t	*ep
443*0Sstevel@tonic-gate )
444*0Sstevel@tonic-gate {
445*0Sstevel@tonic-gate 	int		part;
446*0Sstevel@tonic-gate 	int		err;
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 	if ((part = write_vtoc(fd, vtocbufp)) < 0) {
449*0Sstevel@tonic-gate 		if (part == VT_EINVAL)
450*0Sstevel@tonic-gate 			err = EINVAL;
451*0Sstevel@tonic-gate 		else if (part == VT_EIO)
452*0Sstevel@tonic-gate 			err = EIO;
453*0Sstevel@tonic-gate 		else
454*0Sstevel@tonic-gate 			err = errno;
455*0Sstevel@tonic-gate 		return (mdsyserror(ep, err, devname));
456*0Sstevel@tonic-gate 	}
457*0Sstevel@tonic-gate 
458*0Sstevel@tonic-gate 	return (0);
459*0Sstevel@tonic-gate }
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate /*
462*0Sstevel@tonic-gate  * FUNCTION:	meta_get_names()
463*0Sstevel@tonic-gate  * INPUT:	drivername - char string containing the driver name
464*0Sstevel@tonic-gate  *		sp	- the set name to get soft partitions from
465*0Sstevel@tonic-gate  *		options	- options from the command line
466*0Sstevel@tonic-gate  * OUTPUT:	nlpp	- list of all soft partition names
467*0Sstevel@tonic-gate  *		ep	- return error pointer
468*0Sstevel@tonic-gate  * RETURNS:	int	- -1 if error, 0 success
469*0Sstevel@tonic-gate  * PURPOSE:	returns a list of all specified devices in the metadb
470*0Sstevel@tonic-gate  *		for all devices in the specified set
471*0Sstevel@tonic-gate  */
472*0Sstevel@tonic-gate int
473*0Sstevel@tonic-gate meta_get_names(
474*0Sstevel@tonic-gate 	char		*drivername,
475*0Sstevel@tonic-gate 	mdsetname_t	*sp,
476*0Sstevel@tonic-gate 	mdnamelist_t	**nlpp,
477*0Sstevel@tonic-gate 	mdprtopts_t	options,
478*0Sstevel@tonic-gate 	md_error_t	*ep
479*0Sstevel@tonic-gate )
480*0Sstevel@tonic-gate {
481*0Sstevel@tonic-gate 	md_i_getnum_t	gn;		/* MD_IOCGET_NUM params */
482*0Sstevel@tonic-gate 	mdnamelist_t	**tailpp = nlpp;
483*0Sstevel@tonic-gate 	minor_t		*minors = NULL;
484*0Sstevel@tonic-gate 	minor_t		*m_ptr;
485*0Sstevel@tonic-gate 	int		i;
486*0Sstevel@tonic-gate 
487*0Sstevel@tonic-gate 	(void) memset(&gn, '\0', sizeof (gn));
488*0Sstevel@tonic-gate 	MD_SETDRIVERNAME(&gn, drivername, sp->setno);
489*0Sstevel@tonic-gate 
490*0Sstevel@tonic-gate 	/* get number of devices */
491*0Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET_NUM, &gn, &gn.mde, NULL) != 0) {
492*0Sstevel@tonic-gate 		if (mdiserror(&gn.mde, MDE_UNIT_NOT_FOUND)) {
493*0Sstevel@tonic-gate 			mdclrerror(&gn.mde);
494*0Sstevel@tonic-gate 		} else {
495*0Sstevel@tonic-gate 			(void) mdstealerror(ep, &gn.mde);
496*0Sstevel@tonic-gate 			return (-1);
497*0Sstevel@tonic-gate 		}
498*0Sstevel@tonic-gate 	}
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate 	if (gn.size > 0) {
501*0Sstevel@tonic-gate 		/* malloc minor number buffer to be filled by ioctl */
502*0Sstevel@tonic-gate 		if ((minors = (minor_t *)malloc(
503*0Sstevel@tonic-gate 				gn.size * sizeof (minor_t))) == 0) {
504*0Sstevel@tonic-gate 			return (ENOMEM);
505*0Sstevel@tonic-gate 		}
506*0Sstevel@tonic-gate 		gn.minors = (uintptr_t)minors;
507*0Sstevel@tonic-gate 		if (metaioctl(MD_IOCGET_NUM, &gn, &gn.mde, NULL) != 0) {
508*0Sstevel@tonic-gate 			(void) mdstealerror(ep, &gn.mde);
509*0Sstevel@tonic-gate 			free(minors);
510*0Sstevel@tonic-gate 			return (-1);
511*0Sstevel@tonic-gate 		}
512*0Sstevel@tonic-gate 		m_ptr = minors;
513*0Sstevel@tonic-gate 		for (i = 0; i < gn.size; i++) {
514*0Sstevel@tonic-gate 			mdname_t	*np;
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate 			/* get name */
517*0Sstevel@tonic-gate 			np = metamnumname(&sp, *m_ptr,
518*0Sstevel@tonic-gate 				((options & PRINT_FAST) ? 1 : 0), ep);
519*0Sstevel@tonic-gate 			if (np == NULL)
520*0Sstevel@tonic-gate 				goto out;
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate 			tailpp = meta_namelist_append_wrapper(
523*0Sstevel@tonic-gate 				tailpp, np);
524*0Sstevel@tonic-gate 
525*0Sstevel@tonic-gate 			/* next device */
526*0Sstevel@tonic-gate 			m_ptr++;
527*0Sstevel@tonic-gate 		}
528*0Sstevel@tonic-gate 		free(minors);
529*0Sstevel@tonic-gate 	}
530*0Sstevel@tonic-gate 	return (gn.size);
531*0Sstevel@tonic-gate 
532*0Sstevel@tonic-gate out:
533*0Sstevel@tonic-gate 	if (minors != NULL)
534*0Sstevel@tonic-gate 		free(minors);
535*0Sstevel@tonic-gate 	metafreenamelist(*nlpp);
536*0Sstevel@tonic-gate 	*nlpp = NULL;
537*0Sstevel@tonic-gate 	return (-1);
538*0Sstevel@tonic-gate }
539*0Sstevel@tonic-gate 
540*0Sstevel@tonic-gate /*
541*0Sstevel@tonic-gate  * Wrap lib/libdevid/devid_deviceid_to_nmlist.  We want to take the
542*0Sstevel@tonic-gate  * results from that function and filter out the c[t]dp style names that
543*0Sstevel@tonic-gate  * we typically see on x86 so that we never see them.
544*0Sstevel@tonic-gate  */
545*0Sstevel@tonic-gate int
546*0Sstevel@tonic-gate meta_deviceid_to_nmlist(char *search_path, ddi_devid_t devid, char *minor_name,
547*0Sstevel@tonic-gate 	devid_nmlist_t	**retlist)
548*0Sstevel@tonic-gate {
549*0Sstevel@tonic-gate 	int		res;
550*0Sstevel@tonic-gate 	devid_nmlist_t	*dp;
551*0Sstevel@tonic-gate 	devid_nmlist_t	*tmp_retlist;
552*0Sstevel@tonic-gate 	int		i = 1;
553*0Sstevel@tonic-gate 	devid_nmlist_t	*rp;
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 	res = devid_deviceid_to_nmlist(search_path, devid, minor_name, retlist);
556*0Sstevel@tonic-gate 	if (res != 0) {
557*0Sstevel@tonic-gate 		return (res);
558*0Sstevel@tonic-gate 	}
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 	/* first count the number of non c[t]dp items in retlist */
562*0Sstevel@tonic-gate 	for (dp = *retlist; dp->dev != NODEV; dp++) {
563*0Sstevel@tonic-gate 		uint_t		s;
564*0Sstevel@tonic-gate 
565*0Sstevel@tonic-gate 		/* Check if this is a c[t]dp style name.  */
566*0Sstevel@tonic-gate 		if (parse_ctd(basename(dp->devname), &s) != 1) {
567*0Sstevel@tonic-gate 			i++;
568*0Sstevel@tonic-gate 		}
569*0Sstevel@tonic-gate 	}
570*0Sstevel@tonic-gate 
571*0Sstevel@tonic-gate 	/* create an array to hold the non c[t]dp items */
572*0Sstevel@tonic-gate 	tmp_retlist = Malloc(sizeof (devid_nmlist_t) * i);
573*0Sstevel@tonic-gate 	/* copy the non c[t]dp items to the array */
574*0Sstevel@tonic-gate 	for (dp = *retlist, rp = tmp_retlist; dp->dev != NODEV; dp++) {
575*0Sstevel@tonic-gate 		uint_t		s;
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate 		/* Check if this is a c[t]dp style name.  */
578*0Sstevel@tonic-gate 		if (parse_ctd(basename(dp->devname), &s) != 1) {
579*0Sstevel@tonic-gate 			/* nope, so copy and go to the next */
580*0Sstevel@tonic-gate 			rp->dev = dp->dev;
581*0Sstevel@tonic-gate 			rp->devname = Strdup(dp->devname);
582*0Sstevel@tonic-gate 			rp++;
583*0Sstevel@tonic-gate 		}
584*0Sstevel@tonic-gate 		/* if it is c[t]dp, just skip the element */
585*0Sstevel@tonic-gate 	}
586*0Sstevel@tonic-gate 	/* copy the list terminator */
587*0Sstevel@tonic-gate 	rp->dev = NODEV;
588*0Sstevel@tonic-gate 	rp->devname = NULL;
589*0Sstevel@tonic-gate 	devid_free_nmlist (*retlist);
590*0Sstevel@tonic-gate 	*retlist = tmp_retlist;
591*0Sstevel@tonic-gate 	return (res);
592*0Sstevel@tonic-gate }
593