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 /*
24*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25*0Sstevel@tonic-gate  * Use is subject to license terms.
26*0Sstevel@tonic-gate  */
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate /*
31*0Sstevel@tonic-gate  * initialize metadevices
32*0Sstevel@tonic-gate  */
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <meta.h>
35*0Sstevel@tonic-gate #include <libdevinfo.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate int
39*0Sstevel@tonic-gate parse_interlace(
40*0Sstevel@tonic-gate 	char		*uname,		/* Meta Device name (eg d0) */
41*0Sstevel@tonic-gate 	char		*str,		/* String to Parse		 */
42*0Sstevel@tonic-gate 	diskaddr_t	*interlacep,
43*0Sstevel@tonic-gate 	md_error_t	*ep
44*0Sstevel@tonic-gate )
45*0Sstevel@tonic-gate {
46*0Sstevel@tonic-gate 	diskaddr_t	num;
47*0Sstevel@tonic-gate 	char		c;
48*0Sstevel@tonic-gate 	int		cnt;
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate 	/* parse interlace */
51*0Sstevel@tonic-gate 	if ((cnt = sscanf(str, "%llu%c", &num, &c)) < 1) {
52*0Sstevel@tonic-gate 		return (meta_cook_syntax(ep, MDE_BAD_INTERLACE,
53*0Sstevel@tonic-gate 		    uname, 1, &str));
54*0Sstevel@tonic-gate 	} else if (cnt == 1) {
55*0Sstevel@tonic-gate 		if (num & (DEV_BSIZE - 1)) {
56*0Sstevel@tonic-gate 			return (meta_cook_syntax(ep, MDE_BAD_INTERLACE,
57*0Sstevel@tonic-gate 			    uname, 1, &str));
58*0Sstevel@tonic-gate 		}
59*0Sstevel@tonic-gate 		num = lbtodb(num);
60*0Sstevel@tonic-gate 	} else switch (c) {
61*0Sstevel@tonic-gate 	case 'b':
62*0Sstevel@tonic-gate 	case 'B':
63*0Sstevel@tonic-gate 		num *= DEV_BSIZE / DEV_BSIZE;
64*0Sstevel@tonic-gate 		break;
65*0Sstevel@tonic-gate 	case 'k':
66*0Sstevel@tonic-gate 	case 'K':
67*0Sstevel@tonic-gate 		num *= 1024 / DEV_BSIZE;
68*0Sstevel@tonic-gate 		break;
69*0Sstevel@tonic-gate 	case 'm':
70*0Sstevel@tonic-gate 	case 'M':
71*0Sstevel@tonic-gate 		num *= 1024 * 1024 / DEV_BSIZE;
72*0Sstevel@tonic-gate 		break;
73*0Sstevel@tonic-gate 	default:
74*0Sstevel@tonic-gate 		return (meta_cook_syntax(ep, MDE_BAD_INTERLACE,
75*0Sstevel@tonic-gate 		    NULL, 1, &str));
76*0Sstevel@tonic-gate 	}
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 	/* return success */
79*0Sstevel@tonic-gate 	*interlacep = num;
80*0Sstevel@tonic-gate 	return (0);
81*0Sstevel@tonic-gate }
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate /*
84*0Sstevel@tonic-gate  * cook up syntax error
85*0Sstevel@tonic-gate  */
86*0Sstevel@tonic-gate int
87*0Sstevel@tonic-gate meta_cook_syntax(
88*0Sstevel@tonic-gate 	md_error_t	*ep,
89*0Sstevel@tonic-gate 	md_void_errno_t	errcode,
90*0Sstevel@tonic-gate 	char		*uname,
91*0Sstevel@tonic-gate 	int		argc,
92*0Sstevel@tonic-gate 	char		*argv[]
93*0Sstevel@tonic-gate )
94*0Sstevel@tonic-gate {
95*0Sstevel@tonic-gate 	int		rval;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	/* if we have a token, concat it to uname */
98*0Sstevel@tonic-gate 	if ((argc > 0) && (argv[0] != NULL) && (argv[0][0] != '\0')) {
99*0Sstevel@tonic-gate 		char	*p;
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 		if ((uname != NULL) && (uname[0] != '\0')) {
102*0Sstevel@tonic-gate 			p = Malloc(strlen(uname) + 2
103*0Sstevel@tonic-gate 			    + 1 + strlen(argv[0]) + 1 + 1);
104*0Sstevel@tonic-gate 			(void) strcpy(p, uname);
105*0Sstevel@tonic-gate 			(void) strcat(p, ": ");
106*0Sstevel@tonic-gate 		} else {
107*0Sstevel@tonic-gate 			p = Malloc(1 + strlen(argv[0]) + 1 + 1);
108*0Sstevel@tonic-gate 			p[0] = '\0';
109*0Sstevel@tonic-gate 		}
110*0Sstevel@tonic-gate 		(void) strcat(p, "\"");
111*0Sstevel@tonic-gate 		(void) strcat(p, argv[0]);
112*0Sstevel@tonic-gate 		(void) strcat(p, "\"");
113*0Sstevel@tonic-gate 		rval = mderror(ep, errcode, p);
114*0Sstevel@tonic-gate 		Free(p);
115*0Sstevel@tonic-gate 	} else {
116*0Sstevel@tonic-gate 		rval = mderror(ep, errcode, uname);
117*0Sstevel@tonic-gate 	}
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	return (rval);
120*0Sstevel@tonic-gate }
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate int
123*0Sstevel@tonic-gate meta_check_devicesize(
124*0Sstevel@tonic-gate 	diskaddr_t	total_blocks
125*0Sstevel@tonic-gate )
126*0Sstevel@tonic-gate {
127*0Sstevel@tonic-gate 	int	rval = MD_CRO_32BIT;
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	if (total_blocks > MD_MAX_BLKS_FOR_SMALL_DEVS) {
131*0Sstevel@tonic-gate 		rval = MD_CRO_64BIT;
132*0Sstevel@tonic-gate 	}
133*0Sstevel@tonic-gate 	return (rval);
134*0Sstevel@tonic-gate }
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate /*
138*0Sstevel@tonic-gate  * setup metadevice geometry
139*0Sstevel@tonic-gate  */
140*0Sstevel@tonic-gate /*ARGSUSED*/
141*0Sstevel@tonic-gate int
142*0Sstevel@tonic-gate meta_setup_geom(
143*0Sstevel@tonic-gate 	md_unit_t	*md,
144*0Sstevel@tonic-gate 	mdname_t	*np,
145*0Sstevel@tonic-gate 	mdgeom_t	*geomp,
146*0Sstevel@tonic-gate 	uint_t		write_reinstruct,
147*0Sstevel@tonic-gate 	uint_t		read_reinstruct,
148*0Sstevel@tonic-gate 	uint_t		round_cyl,
149*0Sstevel@tonic-gate 	md_error_t	*ep
150*0Sstevel@tonic-gate )
151*0Sstevel@tonic-gate {
152*0Sstevel@tonic-gate 	diskaddr_t	cylsize = geomp->nhead * geomp->nsect;
153*0Sstevel@tonic-gate 	diskaddr_t	total_blocks;
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 	if (round_cyl) {
156*0Sstevel@tonic-gate 		total_blocks = rounddown(md->c.un_actual_tb, cylsize);
157*0Sstevel@tonic-gate 	} else {
158*0Sstevel@tonic-gate 		total_blocks = md->c.un_actual_tb;
159*0Sstevel@tonic-gate 	}
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 	md->c.un_total_blocks = total_blocks;
162*0Sstevel@tonic-gate 	md->c.un_nhead = geomp->nhead;
163*0Sstevel@tonic-gate 	md->c.un_nsect = geomp->nsect;
164*0Sstevel@tonic-gate 	md->c.un_rpm = geomp->rpm;
165*0Sstevel@tonic-gate 	md->c.un_wr_reinstruct = write_reinstruct;
166*0Sstevel@tonic-gate 	md->c.un_rd_reinstruct = read_reinstruct;
167*0Sstevel@tonic-gate 	return (0);
168*0Sstevel@tonic-gate }
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate /*
171*0Sstevel@tonic-gate  * adjust metadevice geometry
172*0Sstevel@tonic-gate  */
173*0Sstevel@tonic-gate /*ARGSUSED*/
174*0Sstevel@tonic-gate int
175*0Sstevel@tonic-gate meta_adjust_geom(
176*0Sstevel@tonic-gate 	md_unit_t	*md,
177*0Sstevel@tonic-gate 	mdname_t	*np,
178*0Sstevel@tonic-gate 	uint_t		write_reinstruct,
179*0Sstevel@tonic-gate 	uint_t		read_reinstruct,
180*0Sstevel@tonic-gate 	uint_t		round_cyl,
181*0Sstevel@tonic-gate 	md_error_t	*ep
182*0Sstevel@tonic-gate )
183*0Sstevel@tonic-gate {
184*0Sstevel@tonic-gate 	diskaddr_t	cylsize = md->c.un_nhead * md->c.un_nsect;
185*0Sstevel@tonic-gate 	diskaddr_t	total_blocks;
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 	if (round_cyl) {
188*0Sstevel@tonic-gate 		total_blocks = rounddown(md->c.un_actual_tb, cylsize);
189*0Sstevel@tonic-gate 	} else {
190*0Sstevel@tonic-gate 		total_blocks = md->c.un_actual_tb;
191*0Sstevel@tonic-gate 	}
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	md->c.un_total_blocks = total_blocks;
194*0Sstevel@tonic-gate 	if (write_reinstruct > md->c.un_wr_reinstruct)
195*0Sstevel@tonic-gate 		md->c.un_wr_reinstruct = write_reinstruct;
196*0Sstevel@tonic-gate 	if (read_reinstruct > md->c.un_rd_reinstruct)
197*0Sstevel@tonic-gate 		md->c.un_rd_reinstruct = read_reinstruct;
198*0Sstevel@tonic-gate 	return (0);
199*0Sstevel@tonic-gate }
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate /*
202*0Sstevel@tonic-gate  * Function: meta_init_make_device
203*0Sstevel@tonic-gate  * Purpose:
204*0Sstevel@tonic-gate  * 	Create the device node <uname> by constructing the necessary
205*0Sstevel@tonic-gate  * 	md_mkdev_params_t structure. We have to handle relative names
206*0Sstevel@tonic-gate  *	(e.g. "d80") and fully-qualified names (e.g. "/dev/md/red/dsk/d80").
207*0Sstevel@tonic-gate  *	The field that we need is the unit number of the metadevice (80 in
208*0Sstevel@tonic-gate  *	the above examples).
209*0Sstevel@tonic-gate  * Input:	spp	set structure
210*0Sstevel@tonic-gate  *		uname	unit-name (fully qualified or relative)
211*0Sstevel@tonic-gate  * Output:	ep	error return structure
212*0Sstevel@tonic-gate  * Returns:	0	success
213*0Sstevel@tonic-gate  *		-1	Error. <ep> contains error reason
214*0Sstevel@tonic-gate  */
215*0Sstevel@tonic-gate int
216*0Sstevel@tonic-gate meta_init_make_device(
217*0Sstevel@tonic-gate 	mdsetname_t	**spp,
218*0Sstevel@tonic-gate 	char		*uname,
219*0Sstevel@tonic-gate 	md_error_t	*ep
220*0Sstevel@tonic-gate )
221*0Sstevel@tonic-gate {
222*0Sstevel@tonic-gate 	di_devlink_handle_t	hdl;
223*0Sstevel@tonic-gate 	md_mkdev_params_t	params;
224*0Sstevel@tonic-gate 	int			rval = 0;
225*0Sstevel@tonic-gate 	char			*p, *e = uname;
226*0Sstevel@tonic-gate 	size_t			len = strlen(uname);
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate 	e += len;
229*0Sstevel@tonic-gate 	(void) memset(&params, 0, sizeof (params));
230*0Sstevel@tonic-gate 	MD_SETDRIVERNAME(&params, "md", (*spp)->setno);
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	/*
233*0Sstevel@tonic-gate 	 * Find the start of the unit within <uname>.
234*0Sstevel@tonic-gate 	 */
235*0Sstevel@tonic-gate 	p = strrchr(uname, '/');
236*0Sstevel@tonic-gate 	if (p == NULL) {
237*0Sstevel@tonic-gate 		/* Relative name (e.g. d80) */
238*0Sstevel@tonic-gate 		p = &uname[1];
239*0Sstevel@tonic-gate 	} else {
240*0Sstevel@tonic-gate 		/* qualified name (e.g. /dev/md/dsk/d80) */
241*0Sstevel@tonic-gate 		p += 2;
242*0Sstevel@tonic-gate 		if (p >= e) {
243*0Sstevel@tonic-gate 			/* Invalid drive name */
244*0Sstevel@tonic-gate 			p = Malloc(len + 3);
245*0Sstevel@tonic-gate 			(void) snprintf(p, len + 3, "\"%s\"", uname);
246*0Sstevel@tonic-gate 			rval = mderror(ep, MDE_NOT_DRIVENAME, p);
247*0Sstevel@tonic-gate 			Free(p);
248*0Sstevel@tonic-gate 			return (rval);
249*0Sstevel@tonic-gate 		}
250*0Sstevel@tonic-gate 	}
251*0Sstevel@tonic-gate 	e = NULL;
252*0Sstevel@tonic-gate 	params.mnum = strtoul(p, &e, 10);
253*0Sstevel@tonic-gate 	if (e == p) {
254*0Sstevel@tonic-gate 		/* Invalid drive name */
255*0Sstevel@tonic-gate 		p = Malloc(len + 3);
256*0Sstevel@tonic-gate 		(void) snprintf(p, len + 3, "\"%s\"", uname);
257*0Sstevel@tonic-gate 		rval = mderror(ep, MDE_NOT_DRIVENAME, p);
258*0Sstevel@tonic-gate 		Free(p);
259*0Sstevel@tonic-gate 		return (rval);
260*0Sstevel@tonic-gate 	}
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate 	if (metaioctl(MD_IOCMAKE_DEV, &params, &params.mde, NULL) != 0) {
263*0Sstevel@tonic-gate 		return (mdstealerror(ep, &params.mde));
264*0Sstevel@tonic-gate 	}
265*0Sstevel@tonic-gate 	/*
266*0Sstevel@tonic-gate 	 * Wait until device appears in namespace. di_devlink_init() returns
267*0Sstevel@tonic-gate 	 * once the /dev links have been created. If NULL is returned the
268*0Sstevel@tonic-gate 	 * link operation failed and we haven't got a device to use.
269*0Sstevel@tonic-gate 	 * NOTE: This will take a _long_ time for large numbers of metadevices.
270*0Sstevel@tonic-gate 	 *	 Change to use the enhanced di_devlink_init() interface when
271*0Sstevel@tonic-gate 	 *	 available.
272*0Sstevel@tonic-gate 	 */
273*0Sstevel@tonic-gate 	hdl = di_devlink_init("md", DI_MAKE_LINK);
274*0Sstevel@tonic-gate 	if (hdl != NULL) {
275*0Sstevel@tonic-gate 		(void) di_devlink_fini(&hdl);
276*0Sstevel@tonic-gate 	} else {
277*0Sstevel@tonic-gate 		p = Malloc(len + 3);
278*0Sstevel@tonic-gate 		(void) snprintf(p, len + 3, "\"%s\"", uname);
279*0Sstevel@tonic-gate 		rval = mderror(ep, MDE_UNIT_NOT_FOUND, p);
280*0Sstevel@tonic-gate 		Free(p);
281*0Sstevel@tonic-gate 	}
282*0Sstevel@tonic-gate 	return (rval);
283*0Sstevel@tonic-gate }
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate /*
286*0Sstevel@tonic-gate  * FUNCTION:	is_metadb_cmd()
287*0Sstevel@tonic-gate  * INPUT:	argc	- number of command line arguments
288*0Sstevel@tonic-gate  *		argv	- pointer to array of command line arguments
289*0Sstevel@tonic-gate  * OUTPUT:	none
290*0Sstevel@tonic-gate  * RETURNS:	TRUE if a metadb is to be created, FALSE otherwise
291*0Sstevel@tonic-gate  * PURPOSE:	parses enough of the command line to determine if a metadb
292*0Sstevel@tonic-gate  *		create is being attempted
293*0Sstevel@tonic-gate  */
294*0Sstevel@tonic-gate static boolean_t
295*0Sstevel@tonic-gate is_metadb_cmd(
296*0Sstevel@tonic-gate 	int	argc,
297*0Sstevel@tonic-gate 	char	*argv[]
298*0Sstevel@tonic-gate )
299*0Sstevel@tonic-gate {
300*0Sstevel@tonic-gate 	ulong_t	num;
301*0Sstevel@tonic-gate 	int	len;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	/* look for match */
304*0Sstevel@tonic-gate 	if (argc > 0 && (sscanf(argv[0], "mddb%lu%n", &num, &len) == 1) &&
305*0Sstevel@tonic-gate 		    (strlen(argv[0]) == len) && ((long)num >= 0)) {
306*0Sstevel@tonic-gate 		return (B_TRUE);
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	return (B_FALSE);
310*0Sstevel@tonic-gate }
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate /*
313*0Sstevel@tonic-gate  * FUNCTION:	is_stripe_cmd()
314*0Sstevel@tonic-gate  * INPUT:	argc	- number of command line arguments
315*0Sstevel@tonic-gate  *		argv	- pointer to array of command line arguments
316*0Sstevel@tonic-gate  * OUTPUT:	none
317*0Sstevel@tonic-gate  * RETURNS:	TRUE if a stripe is to be created, FALSE otherwise
318*0Sstevel@tonic-gate  * PURPOSE:	parses enough of the command line to determine if a stripe
319*0Sstevel@tonic-gate  *		create is being attempted
320*0Sstevel@tonic-gate  */
321*0Sstevel@tonic-gate static boolean_t
322*0Sstevel@tonic-gate is_stripe_cmd(
323*0Sstevel@tonic-gate 	int	argc,
324*0Sstevel@tonic-gate 	char	*argv[]
325*0Sstevel@tonic-gate )
326*0Sstevel@tonic-gate {
327*0Sstevel@tonic-gate 	uint_t	nrow;
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate 	if (argc > 1 && (sscanf(argv[1], "%u", &nrow) != 1) || ((int)nrow < 0))
330*0Sstevel@tonic-gate 		return (B_FALSE);
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 	return (B_TRUE);
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate /*
336*0Sstevel@tonic-gate  * FUNCTION:	meta_get_init_type()
337*0Sstevel@tonic-gate  * INPUT:	argc	- number of command line arguments
338*0Sstevel@tonic-gate  *		argv	- pointer to array of command line arguments
339*0Sstevel@tonic-gate  * OUTPUT:	none
340*0Sstevel@tonic-gate  * RETURNS:	type of metadevice or hot spare pools being initialized
341*0Sstevel@tonic-gate  * PURPOSE:	parses enough of the command line to determine what type
342*0Sstevel@tonic-gate  *		of metainit is being attempted
343*0Sstevel@tonic-gate  */
344*0Sstevel@tonic-gate mdinittypes_t
345*0Sstevel@tonic-gate meta_get_init_type(
346*0Sstevel@tonic-gate 	int 	argc,
347*0Sstevel@tonic-gate 	char	*argv[]
348*0Sstevel@tonic-gate )
349*0Sstevel@tonic-gate {
350*0Sstevel@tonic-gate 	char		*arg = argv[1];
351*0Sstevel@tonic-gate 	mdinittypes_t	init_type;
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 	if (argc == 1) /* must be a hot spare pool w/o devices */
354*0Sstevel@tonic-gate 		return (TAB_HSP);
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 	init_type = TAB_UNKNOWN;
357*0Sstevel@tonic-gate 	if (arg != NULL) {
358*0Sstevel@tonic-gate 		if (strcmp(arg, "-m") == 0) {
359*0Sstevel@tonic-gate 			init_type = TAB_MIRROR;
360*0Sstevel@tonic-gate 		} else if (strcmp(arg, "-r") == 0) {
361*0Sstevel@tonic-gate 			init_type = TAB_RAID;
362*0Sstevel@tonic-gate 		} else if (strcmp(arg, "-p") == 0) {
363*0Sstevel@tonic-gate 			init_type = TAB_SP;
364*0Sstevel@tonic-gate 		} else if (strcmp(arg, "-t") == 0) {
365*0Sstevel@tonic-gate 			init_type = TAB_TRANS;
366*0Sstevel@tonic-gate 		} else if (is_metadb_cmd(argc, argv)) {
367*0Sstevel@tonic-gate 			init_type = TAB_MDDB;
368*0Sstevel@tonic-gate 		} else if (is_stripe_cmd(argc, argv)) {
369*0Sstevel@tonic-gate 			init_type = TAB_STRIPE;
370*0Sstevel@tonic-gate 		} else { /* assume that it is a hsp */
371*0Sstevel@tonic-gate 			init_type = TAB_HSP;
372*0Sstevel@tonic-gate 		}
373*0Sstevel@tonic-gate 	}
374*0Sstevel@tonic-gate 	return (init_type);
375*0Sstevel@tonic-gate }
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate /*
378*0Sstevel@tonic-gate  * initialize named device or hotspare pool
379*0Sstevel@tonic-gate  */
380*0Sstevel@tonic-gate int
381*0Sstevel@tonic-gate meta_init_name(
382*0Sstevel@tonic-gate 	mdsetname_t	**spp,
383*0Sstevel@tonic-gate 	int		argc,
384*0Sstevel@tonic-gate 	char		*argv[],
385*0Sstevel@tonic-gate 	mdcmdopts_t	options,
386*0Sstevel@tonic-gate 	md_error_t	*ep
387*0Sstevel@tonic-gate )
388*0Sstevel@tonic-gate {
389*0Sstevel@tonic-gate 	mdinittypes_t	init_type;
390*0Sstevel@tonic-gate 	char		*p;
391*0Sstevel@tonic-gate 	int		rval;
392*0Sstevel@tonic-gate 	char		*uname = argv[0];
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 	assert(argc > 0);
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate 	/* determine type of metadevice or hot spare pool being created */
397*0Sstevel@tonic-gate 	init_type = meta_get_init_type(argc, argv);
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate 	/* hotspare pool */
400*0Sstevel@tonic-gate 	if (init_type == TAB_HSP)
401*0Sstevel@tonic-gate 		return (meta_init_hsp(spp, argc, argv, options, ep));
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate 	/* metadevice */
404*0Sstevel@tonic-gate 	if (argc >= 2 && init_type != TAB_UNKNOWN) {
405*0Sstevel@tonic-gate 		md_error_t	t_e = mdnullerror;
406*0Sstevel@tonic-gate 		char	*cname;
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 		/*
409*0Sstevel@tonic-gate 		 * We need to create the device node if the specified metadevice
410*0Sstevel@tonic-gate 		 * does not already exist in the database. The actual creation
411*0Sstevel@tonic-gate 		 * is undertaken by the md driver and the links propagated by
412*0Sstevel@tonic-gate 		 * devfsadm.
413*0Sstevel@tonic-gate 		 */
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate 		/* initialize the spp properly */
416*0Sstevel@tonic-gate 		if ((cname = meta_name_getname(spp, uname, &t_e)) != NULL)
417*0Sstevel@tonic-gate 			Free(cname);
418*0Sstevel@tonic-gate 		if (! mdisok(&t_e))
419*0Sstevel@tonic-gate 			return (mdstealerror(ep, &t_e));
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 		/* Create device node */
422*0Sstevel@tonic-gate 		if (meta_init_make_device(spp, uname, &t_e) != 0) {
423*0Sstevel@tonic-gate 			return (mdstealerror(ep, &t_e));
424*0Sstevel@tonic-gate 		}
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 		switch (init_type) {
427*0Sstevel@tonic-gate 		case TAB_MIRROR:
428*0Sstevel@tonic-gate 			return (meta_init_mirror(spp, argc, argv, options, ep));
429*0Sstevel@tonic-gate 			break;
430*0Sstevel@tonic-gate 		case TAB_RAID:
431*0Sstevel@tonic-gate 			return (meta_init_raid(spp, argc, argv, options, ep));
432*0Sstevel@tonic-gate 			break;
433*0Sstevel@tonic-gate 		case TAB_SP:
434*0Sstevel@tonic-gate 			return (meta_init_sp(spp, argc, argv, options, ep));
435*0Sstevel@tonic-gate 			break;
436*0Sstevel@tonic-gate 		case TAB_TRANS:
437*0Sstevel@tonic-gate 			return (mderror(ep, MDE_EOF_TRANS, NULL));
438*0Sstevel@tonic-gate 			break;
439*0Sstevel@tonic-gate 		case TAB_STRIPE:
440*0Sstevel@tonic-gate 			return (meta_init_stripe(spp, argc, argv, options, ep));
441*0Sstevel@tonic-gate 			break;
442*0Sstevel@tonic-gate 		}
443*0Sstevel@tonic-gate 	}
444*0Sstevel@tonic-gate 
445*0Sstevel@tonic-gate 	/* unknown type */
446*0Sstevel@tonic-gate 	p = Malloc(1 + strlen(uname) + 1 + 1);
447*0Sstevel@tonic-gate 	(void) strcpy(p, "\"");
448*0Sstevel@tonic-gate 	(void) strcat(p, uname);
449*0Sstevel@tonic-gate 	(void) strcat(p, "\"");
450*0Sstevel@tonic-gate 	rval = mderror(ep, MDE_SYNTAX, p);
451*0Sstevel@tonic-gate 	Free(p);
452*0Sstevel@tonic-gate 	return (rval);
453*0Sstevel@tonic-gate }
454