10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5908Spetede  * Common Development and Distribution License (the "License").
6908Spetede  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*1623Stw21770  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <meta.h>
290Sstevel@tonic-gate #include <metad.h>
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <ctype.h>
320Sstevel@tonic-gate #include <string.h>
33*1623Stw21770 #include <sys/fs/ufs_fsdir.h>
340Sstevel@tonic-gate 
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate  * Just in case we're not in a build environment, make sure that
370Sstevel@tonic-gate  * TEXT_DOMAIN gets set to something.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
400Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
410Sstevel@tonic-gate #endif
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate  *	Macros to produce a quoted string containing the value of a
450Sstevel@tonic-gate  *	preprocessor macro. For example, if SIZE is defined to be 256,
460Sstevel@tonic-gate  *	VAL2STR(SIZE) is "256". This is used to construct format
470Sstevel@tonic-gate  *	strings for scanf-family functions below.
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate #define	QUOTE(x)	#x
500Sstevel@tonic-gate #define	VAL2STR(x)	QUOTE(x)
510Sstevel@tonic-gate 
520Sstevel@tonic-gate extern	char	*getfullblkname();
530Sstevel@tonic-gate extern	char	*getfullrawname();
540Sstevel@tonic-gate 
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate  * caches
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate static	mdsetnamelist_t		*setlistp = NULL;
590Sstevel@tonic-gate static	mddrivenamelist_t	*drivelistp = NULL;
600Sstevel@tonic-gate static	mdnamelist_t		*fastnmlp = NULL;
610Sstevel@tonic-gate static	mdhspnamelist_t		*hsplistp = NULL;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate /*
64*1623Stw21770  * Static definitions
65*1623Stw21770  */
66*1623Stw21770 static int chksetname(mdsetname_t **spp, char *sname, md_error_t *ep);
67*1623Stw21770 
68*1623Stw21770 /*
690Sstevel@tonic-gate  * leak proof name conversion
700Sstevel@tonic-gate  */
710Sstevel@tonic-gate static char *
720Sstevel@tonic-gate rawname(
730Sstevel@tonic-gate 	char	*uname
740Sstevel@tonic-gate )
750Sstevel@tonic-gate {
760Sstevel@tonic-gate 	char	*p;
770Sstevel@tonic-gate 	struct stat	sbuf1, sbuf2;
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	if ((p = getfullrawname(uname)) == NULL) {
800Sstevel@tonic-gate 		return (NULL);
810Sstevel@tonic-gate 	} else if (*p == '\0') {
820Sstevel@tonic-gate 		Free(p);
830Sstevel@tonic-gate 		return (NULL);
840Sstevel@tonic-gate 	} else {
850Sstevel@tonic-gate 		if (stat(uname, &sbuf1) != 0) {
860Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
870Sstevel@tonic-gate 			    "device to mount in /etc/vfstab is "
880Sstevel@tonic-gate 			    "invalid for device %s\n"), uname);
890Sstevel@tonic-gate 			exit(1);
900Sstevel@tonic-gate 		}
910Sstevel@tonic-gate 		if (stat(p, &sbuf2) != 0) {
920Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
930Sstevel@tonic-gate 			    "device to fsck in /etc/vfstab is "
940Sstevel@tonic-gate 			    "invalid for raw device %s\n"), p);
950Sstevel@tonic-gate 			exit(1);
960Sstevel@tonic-gate 		}
970Sstevel@tonic-gate 		if (sbuf1.st_rdev != sbuf2.st_rdev) {
980Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
990Sstevel@tonic-gate 			    "/etc/vfstab entries inconsistent on "
1000Sstevel@tonic-gate 			    "line containing device %s\n"), uname);
1010Sstevel@tonic-gate 			exit(1);
1020Sstevel@tonic-gate 		}
103871Scasper 		if (!S_ISCHR(sbuf2.st_mode)) {
1040Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
1050Sstevel@tonic-gate 			    "/etc/vfstab device to fsck is not a "
1060Sstevel@tonic-gate 			    "raw device for device %s\n"), p);
1070Sstevel@tonic-gate 			exit(1);
1080Sstevel@tonic-gate 		}
1090Sstevel@tonic-gate 		return (p);
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate char *
1140Sstevel@tonic-gate blkname(
1150Sstevel@tonic-gate 	char	*uname
1160Sstevel@tonic-gate )
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate 	char	*p;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	if ((p = getfullblkname(uname)) == NULL) {
1210Sstevel@tonic-gate 		return (NULL);
1220Sstevel@tonic-gate 	} else if (*p == '\0') {
1230Sstevel@tonic-gate 		Free(p);
1240Sstevel@tonic-gate 		return (NULL);
1250Sstevel@tonic-gate 	} else {
1260Sstevel@tonic-gate 		return (p);
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate /*
1310Sstevel@tonic-gate  * FUNCTION:	parse_device()
1320Sstevel@tonic-gate  * INPUT:	sp - pointer to setname struct
1330Sstevel@tonic-gate  *		uname - Name of either a hotspare pool or metadevice
1340Sstevel@tonic-gate  *			This can either be a fully qualified path or
1350Sstevel@tonic-gate  *			in the form [set name/]device
136*1623Stw21770  * OUTPUT:	snamep - name of the set that uname is in
137*1623Stw21770  *		fnamep - metadevice or hsp with path and set name info stripped
138*1623Stw21770  *		    This parameter is dynamically allocated and must be
139*1623Stw21770  *		    freed by the calling function.
1400Sstevel@tonic-gate  * PURPOSE:	Parse uname and sp into the set name and device name strings.
1410Sstevel@tonic-gate  *		If the set name is specified as part of uname then use that
1420Sstevel@tonic-gate  *		otherwise attempt to get the set name from sp.
1430Sstevel@tonic-gate  */
1440Sstevel@tonic-gate static void
1450Sstevel@tonic-gate parse_device(
1460Sstevel@tonic-gate 	mdsetname_t	*sp,
1470Sstevel@tonic-gate 	char		*uname,
148*1623Stw21770 	char		**fnamep, /* dynamically alloced - caller must free */
149*1623Stw21770 	char		**snamep  /* dynamically alloced - caller must free */
1500Sstevel@tonic-gate )
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 	char		setname[FILENAME_MAX+1];
153*1623Stw21770 	char		devname[FILENAME_MAX+1];
1540Sstevel@tonic-gate 	char		*tname = Malloc(strlen(uname) + 1);
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	int		len;
1570Sstevel@tonic-gate 	char *up;
1580Sstevel@tonic-gate 	char *tp;
1590Sstevel@tonic-gate 	int lcws;	/* last character was slash */
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	/* Now copy uname to tname by throwing away any duplicate '/' */
1620Sstevel@tonic-gate 	for (lcws = 0, tp = tname, up = uname; *up; up++) {
1630Sstevel@tonic-gate 		if (lcws) {
1640Sstevel@tonic-gate 			if (*up == '/') {
1650Sstevel@tonic-gate 				continue;
1660Sstevel@tonic-gate 			} else {
1670Sstevel@tonic-gate 				lcws = 0;
1680Sstevel@tonic-gate 			}
1690Sstevel@tonic-gate 		}
1700Sstevel@tonic-gate 		if (*up == '/') {
1710Sstevel@tonic-gate 			lcws = 1;
1720Sstevel@tonic-gate 		}
1730Sstevel@tonic-gate 		*tp++ = *up; /* ++ is done by for loop */
1740Sstevel@tonic-gate 	}
1750Sstevel@tonic-gate 	*tp = '\0';
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	/* fully-qualified  - local set */
1780Sstevel@tonic-gate 	if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
179*1623Stw21770 			devname, &len) == 1) && (strlen(tname) == len)) ||
1800Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
181*1623Stw21770 			devname, &len) == 1) && (strlen(tname) == len))) {
182*1623Stw21770 		*snamep = Strdup(MD_LOCAL_NAME);
183*1623Stw21770 		*fnamep = Strdup(devname);
1840Sstevel@tonic-gate 		Free(tname);
1850Sstevel@tonic-gate 		return;
1860Sstevel@tonic-gate 	}
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	/* with setname specified - either fully qualified and relative spec */
189*1623Stw21770 	if (((sscanf(tname, "%[^/]/%" VAL2STR(FILENAME_MAX) "s%n",
190*1623Stw21770 		setname, devname, &len) == 2) && (strlen(tname) == len)) ||
1910Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
192*1623Stw21770 		setname, devname, &len) == 2) && (strlen(tname) == len)) ||
1930Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
194*1623Stw21770 		setname, devname, &len) == 2) && (strlen(tname) == len))) {
195*1623Stw21770 
196*1623Stw21770 		*snamep = Strdup(setname);
197*1623Stw21770 		*fnamep = Strdup(devname);
1980Sstevel@tonic-gate 		Free(tname);
1990Sstevel@tonic-gate 		return;
2000Sstevel@tonic-gate 	}
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	/* without setname specified */
203*1623Stw21770 	*fnamep = tname;
204*1623Stw21770 	if (sp != NULL && !metaislocalset(sp))
205*1623Stw21770 		*snamep = Strdup(sp->setname);
206*1623Stw21770 	else
207*1623Stw21770 		*snamep = NULL;
208*1623Stw21770 }
209*1623Stw21770 
210*1623Stw21770 /*
211*1623Stw21770  * check for "all"
212*1623Stw21770  */
213*1623Stw21770 int
214*1623Stw21770 meta_is_all(char *s)
215*1623Stw21770 {
216*1623Stw21770 	if ((strcoll(s, gettext("all")) == 0) ||
217*1623Stw21770 	    (strcoll(s, gettext("ALL")) == 0))
218*1623Stw21770 		return (1);
219*1623Stw21770 	return (0);
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate /*
223*1623Stw21770  * check for "none"
2240Sstevel@tonic-gate  */
225*1623Stw21770 int
226*1623Stw21770 meta_is_none(char *s)
227*1623Stw21770 {
228*1623Stw21770 	if ((strcoll(s, gettext("none")) == 0) ||
229*1623Stw21770 	    (strcoll(s, gettext("NONE")) == 0))
230*1623Stw21770 		return (1);
231*1623Stw21770 	return (0);
232*1623Stw21770 }
233*1623Stw21770 
2340Sstevel@tonic-gate static int
235*1623Stw21770 valid_name_syntax(char *uname)
2360Sstevel@tonic-gate {
237*1623Stw21770 	int	i;
238*1623Stw21770 	int	uname_len;
239*1623Stw21770 
240*1623Stw21770 	if (uname == NULL || !isalpha(uname[0]))
241*1623Stw21770 		return (0);
242*1623Stw21770 
243*1623Stw21770 	uname_len = strlen(uname);
244*1623Stw21770 	if (uname_len > MAXNAMLEN)
2450Sstevel@tonic-gate 		return (0);
246*1623Stw21770 
247*1623Stw21770 	/* 'all' and 'none' are reserved */
248*1623Stw21770 	if (meta_is_all(uname) || meta_is_none(uname))
249*1623Stw21770 		return (0);
250*1623Stw21770 
251*1623Stw21770 	for (i = 1; i < uname_len; i++) {
252*1623Stw21770 		if ((isalnum(uname[i]) || uname[i] == '-' ||
253*1623Stw21770 		    uname[i] == '_' || uname[i] == '.'))
254*1623Stw21770 			continue;
255*1623Stw21770 		break;
2560Sstevel@tonic-gate 	}
2570Sstevel@tonic-gate 
258*1623Stw21770 	if (i < uname_len)
2590Sstevel@tonic-gate 		return (0);
260*1623Stw21770 
261*1623Stw21770 	return (1);
262*1623Stw21770 
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate /*
266*1623Stw21770  * canonicalize name
2670Sstevel@tonic-gate  */
2680Sstevel@tonic-gate char *
2690Sstevel@tonic-gate meta_canonicalize(
2700Sstevel@tonic-gate 	mdsetname_t	*sp,
2710Sstevel@tonic-gate 	char		*uname
2720Sstevel@tonic-gate )
2730Sstevel@tonic-gate {
2740Sstevel@tonic-gate 	char	*sname = NULL;
275*1623Stw21770 	char	*tname = NULL;
2760Sstevel@tonic-gate 	char	*cname;
2770Sstevel@tonic-gate 
278*1623Stw21770 	/* return the dev name and set name */
279*1623Stw21770 	parse_device(sp, uname, &tname, &sname);
280*1623Stw21770 
281*1623Stw21770 	if (!valid_name_syntax(tname)) {
282*1623Stw21770 		Free(tname);
283*1623Stw21770 		if (sname != NULL)
284*1623Stw21770 		    Free(sname);
285*1623Stw21770 		return (NULL);
286*1623Stw21770 	}
287*1623Stw21770 
288*1623Stw21770 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
289*1623Stw21770 		cname = tname;
2900Sstevel@tonic-gate 	else {
2910Sstevel@tonic-gate 		size_t	cname_len;
2920Sstevel@tonic-gate 
293*1623Stw21770 		cname_len = strlen(tname) + strlen(sname) + 2;
2940Sstevel@tonic-gate 		cname = Malloc(cname_len);
2950Sstevel@tonic-gate 		(void) snprintf(
296*1623Stw21770 		    cname, cname_len, "%s/%s", sname, tname);
297*1623Stw21770 		Free(tname);
298*1623Stw21770 	}
299*1623Stw21770 
300*1623Stw21770 	if (sname != NULL)
301*1623Stw21770 	    Free(sname);
302*1623Stw21770 
303*1623Stw21770 	return (cname);
304*1623Stw21770 }
305*1623Stw21770 
306*1623Stw21770 /*
307*1623Stw21770  * canonicalize name and check the set
308*1623Stw21770  */
309*1623Stw21770 char *
310*1623Stw21770 meta_canonicalize_check_set(
311*1623Stw21770 	mdsetname_t	**spp,
312*1623Stw21770 	char		*uname,
313*1623Stw21770 	md_error_t	*ep
314*1623Stw21770 )
315*1623Stw21770 {
316*1623Stw21770 	char		*sname = NULL;
317*1623Stw21770 	char		*tname = NULL;
318*1623Stw21770 	char		*cname;
319*1623Stw21770 
320*1623Stw21770 	/* return the dev name and set name */
321*1623Stw21770 	parse_device(*spp, uname, &tname, &sname);
322*1623Stw21770 
323*1623Stw21770 	if (!valid_name_syntax(tname)) {
324*1623Stw21770 		(void) mderror(ep, MDE_NAME_ILLEGAL, tname);
325*1623Stw21770 		if (sname != NULL)
326*1623Stw21770 			Free(sname);
327*1623Stw21770 		Free(tname);
328*1623Stw21770 		return (NULL);
329*1623Stw21770 	}
330*1623Stw21770 
331*1623Stw21770 	/* check the set name returned from the name for validity */
332*1623Stw21770 	if (chksetname(spp, sname, ep) != 0) {
333*1623Stw21770 		Free(tname);
334*1623Stw21770 		if (sname != NULL)
335*1623Stw21770 		    Free(sname);
336*1623Stw21770 		return (NULL);
337*1623Stw21770 	}
338*1623Stw21770 
339*1623Stw21770 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
340*1623Stw21770 		cname = tname;
341*1623Stw21770 	else {
342*1623Stw21770 		size_t	cname_len;
343*1623Stw21770 
344*1623Stw21770 		cname_len = strlen(tname) + strlen(sname) + 2;
345*1623Stw21770 		cname = Malloc(cname_len);
346*1623Stw21770 		(void) snprintf(
347*1623Stw21770 		    cname, cname_len, "%s/%s", sname, tname);
348*1623Stw21770 		Free(tname);
349*1623Stw21770 	}
350*1623Stw21770 
351*1623Stw21770 	if (sname != NULL)
352*1623Stw21770 	    Free(sname);
353*1623Stw21770 
354*1623Stw21770 	return (cname);
355*1623Stw21770 }
356*1623Stw21770 
357*1623Stw21770 /*
358*1623Stw21770  * Verify that the name is a valid hsp/metadevice name
359*1623Stw21770  */
360*1623Stw21770 static int
361*1623Stw21770 parse_meta_hsp_name(char *uname)
362*1623Stw21770 {
363*1623Stw21770 	char	*sname = NULL;
364*1623Stw21770 	char	*tname = NULL;
365*1623Stw21770 	int	ret;
366*1623Stw21770 
367*1623Stw21770 	/* return the dev name and set name */
368*1623Stw21770 	parse_device(NULL, uname, &tname, &sname);
369*1623Stw21770 
370*1623Stw21770 	ret = valid_name_syntax(tname);
371*1623Stw21770 	if (sname != NULL)
3720Sstevel@tonic-gate 		Free(sname);
373*1623Stw21770 	Free(tname);
374*1623Stw21770 	return (ret);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate /*
3780Sstevel@tonic-gate  * check that name is a metadevice
3790Sstevel@tonic-gate  */
3800Sstevel@tonic-gate int
3810Sstevel@tonic-gate is_metaname(
3820Sstevel@tonic-gate 	char	*uname
3830Sstevel@tonic-gate )
3840Sstevel@tonic-gate {
385*1623Stw21770 	return (parse_meta_hsp_name(uname));
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate /*
3890Sstevel@tonic-gate  * check that name is a hotspare pool
3900Sstevel@tonic-gate  */
3910Sstevel@tonic-gate int
3920Sstevel@tonic-gate is_hspname(
3930Sstevel@tonic-gate 	char	*uname
3940Sstevel@tonic-gate )
3950Sstevel@tonic-gate {
396*1623Stw21770 	return (parse_meta_hsp_name(uname));
397*1623Stw21770 }
398*1623Stw21770 
399*1623Stw21770 /*
400*1623Stw21770  * check to verify that name is an existing metadevice
401*1623Stw21770  */
402*1623Stw21770 int
403*1623Stw21770 is_existing_metadevice(
404*1623Stw21770 	mdsetname_t	*sp,
405*1623Stw21770 	char		*uname
406*1623Stw21770 )
407*1623Stw21770 {
408*1623Stw21770 	char		*raw_name;
409*1623Stw21770 	char		*set_name;
410*1623Stw21770 	char		*full_path;
411*1623Stw21770 	char		*fname = NULL;
412*1623Stw21770 	int		pathlen;
413*1623Stw21770 	int		retval = 0;
414*1623Stw21770 
415*1623Stw21770 	assert(uname != NULL);
416*1623Stw21770 	/*
417*1623Stw21770 	 * If it is an absolute name of a metadevice, then just call rawname
418*1623Stw21770 	 * on the input
419*1623Stw21770 	 */
420*1623Stw21770 	if (uname[0] == '/') {
421*1623Stw21770 		if (strncmp("/dev/md", uname, strlen("/dev/md")) == 0 &&
422*1623Stw21770 			(raw_name = rawname(uname)) != NULL) {
423*1623Stw21770 		    Free(raw_name);
424*1623Stw21770 		    return (1);
425*1623Stw21770 		}
426*1623Stw21770 		return (0);
427*1623Stw21770 	}
428*1623Stw21770 
429*1623Stw21770 	/* create a fully specified path from the parsed string */
430*1623Stw21770 	parse_device(sp, uname, &fname, &set_name);
431*1623Stw21770 
432*1623Stw21770 	if ((set_name == NULL) || (strcmp(set_name, MD_LOCAL_NAME) == 0)) {
433*1623Stw21770 		pathlen = strlen("/dev/md/rdsk/") + strlen(fname) + 1;
434*1623Stw21770 		full_path = Zalloc(pathlen);
435*1623Stw21770 		(void) snprintf(full_path, pathlen, "/dev/md/rdsk/%s", fname);
436*1623Stw21770 	} else {
437*1623Stw21770 		pathlen = strlen("/dev/md//rdsk/") + strlen(fname) +
438*1623Stw21770 		    strlen(set_name) + 1;
439*1623Stw21770 		full_path = Zalloc(pathlen);
440*1623Stw21770 		(void) snprintf(full_path, pathlen, "/dev/md/%s/rdsk/%s",
441*1623Stw21770 		    set_name, fname);
442*1623Stw21770 	}
443*1623Stw21770 
444*1623Stw21770 	if ((raw_name = rawname(full_path)) != NULL) {
445*1623Stw21770 	    Free(raw_name);
446*1623Stw21770 	    retval = 1;
447*1623Stw21770 	}
448*1623Stw21770 
449*1623Stw21770 	if (set_name != NULL)
450*1623Stw21770 		Free(set_name);
451*1623Stw21770 
452*1623Stw21770 	Free(fname);
453*1623Stw21770 	Free(full_path);
454*1623Stw21770 	return (retval);
455*1623Stw21770 }
456*1623Stw21770 
457*1623Stw21770 /*
458*1623Stw21770  * check to verify that name is an existing hsp
459*1623Stw21770  */
460*1623Stw21770 int
461*1623Stw21770 is_existing_hsp(
462*1623Stw21770 	mdsetname_t	*sp,
463*1623Stw21770 	char		*uname
464*1623Stw21770 )
465*1623Stw21770 {
466*1623Stw21770 	md_error_t	status = mdnullerror;
467*1623Stw21770 	hsp_t		hsp;
468*1623Stw21770 	set_t		cur_set;
469*1623Stw21770 
470*1623Stw21770 	if (sp != NULL)
471*1623Stw21770 		cur_set = sp->setno;
472*1623Stw21770 	else
473*1623Stw21770 		cur_set = 0;
474*1623Stw21770 
475*1623Stw21770 	hsp = meta_gethspnmentbyname(cur_set, MD_SIDEWILD, uname, &status);
476*1623Stw21770 
477*1623Stw21770 	if (hsp == MD_HSP_NONE) {
478*1623Stw21770 		mdclrerror(&status);
479*1623Stw21770 		return (0);
480*1623Stw21770 	}
481*1623Stw21770 	return (1);
482*1623Stw21770 }
483*1623Stw21770 
484*1623Stw21770 /*
485*1623Stw21770  * check to verify that name is an existing metadevice or hotspare pool
486*1623Stw21770  */
487*1623Stw21770 int
488*1623Stw21770 is_existing_meta_hsp(
489*1623Stw21770 	mdsetname_t	*sp,
490*1623Stw21770 	char		*uname
491*1623Stw21770 )
492*1623Stw21770 {
493*1623Stw21770 	if (is_existing_metadevice(sp, uname) ||
494*1623Stw21770 	    is_existing_hsp(sp, uname))
4950Sstevel@tonic-gate 		return (1);
496*1623Stw21770 
497*1623Stw21770 	return (0);
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate /*
5010Sstevel@tonic-gate  *	mdsetname_t stuff
5020Sstevel@tonic-gate  */
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate /*
5050Sstevel@tonic-gate  * initialize setname
5060Sstevel@tonic-gate  */
5070Sstevel@tonic-gate static void
5080Sstevel@tonic-gate metainitsetname(
5090Sstevel@tonic-gate 	mdsetname_t	*sp
5100Sstevel@tonic-gate )
5110Sstevel@tonic-gate {
5120Sstevel@tonic-gate 	(void) memset(sp, '\0', sizeof (*sp));
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate static void
5160Sstevel@tonic-gate metafreesetdesc(md_set_desc *sd)
5170Sstevel@tonic-gate {
5180Sstevel@tonic-gate 	md_mnnode_desc	*nd;
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
5210Sstevel@tonic-gate 		nd = sd->sd_nodelist;
5220Sstevel@tonic-gate 		while (nd) {
5230Sstevel@tonic-gate 			sd->sd_nodelist = nd->nd_next;
5240Sstevel@tonic-gate 			Free(nd);
5250Sstevel@tonic-gate 			nd = sd->sd_nodelist;
5260Sstevel@tonic-gate 		}
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 	metafreedrivedesc(&sd->sd_drvs);
5290Sstevel@tonic-gate 	Free(sd);
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate /*
5330Sstevel@tonic-gate  * free allocated setname
5340Sstevel@tonic-gate  */
5350Sstevel@tonic-gate static void
5360Sstevel@tonic-gate metafreesetname(
5370Sstevel@tonic-gate 	mdsetname_t	*sp
5380Sstevel@tonic-gate )
5390Sstevel@tonic-gate {
5400Sstevel@tonic-gate 	if (sp->setname != NULL)
5410Sstevel@tonic-gate 		Free(sp->setname);
5420Sstevel@tonic-gate 	if (sp->setdesc != NULL)
5430Sstevel@tonic-gate 		metafreesetdesc(sp->setdesc);
5440Sstevel@tonic-gate 	metainitsetname(sp);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate  * flush the setname cache
5490Sstevel@tonic-gate  */
5500Sstevel@tonic-gate static void
5510Sstevel@tonic-gate metaflushsetnames()
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate 	mdsetnamelist_t		*p, *n;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	for (p = setlistp, n = NULL; (p != NULL); p = n) {
5560Sstevel@tonic-gate 		n = p->next;
5570Sstevel@tonic-gate 		metafreesetname(p->sp);
5580Sstevel@tonic-gate 		Free(p->sp);
5590Sstevel@tonic-gate 		Free(p);
5600Sstevel@tonic-gate 	}
5610Sstevel@tonic-gate 	setlistp = NULL;
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate /*
5650Sstevel@tonic-gate  * get set number
5660Sstevel@tonic-gate  */
5670Sstevel@tonic-gate static int
5680Sstevel@tonic-gate getsetno(
5690Sstevel@tonic-gate 	char		*sname,
5700Sstevel@tonic-gate 	set_t		*setnop,
5710Sstevel@tonic-gate 	md_error_t	*ep
5720Sstevel@tonic-gate )
5730Sstevel@tonic-gate {
5740Sstevel@tonic-gate 	md_set_record	*sr;
5750Sstevel@tonic-gate 	size_t		len;
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	/* local set */
5780Sstevel@tonic-gate 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
5790Sstevel@tonic-gate 		*setnop = 0;
5800Sstevel@tonic-gate 		return (0);
5810Sstevel@tonic-gate 	}
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	/* shared set */
5840Sstevel@tonic-gate 	if ((sr = getsetbyname(sname, ep)) == NULL) {
5850Sstevel@tonic-gate 		if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) {
5860Sstevel@tonic-gate 			char	*p;
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 			len = strlen(sname) + 30;
5890Sstevel@tonic-gate 			p = Malloc(len);
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 			(void) snprintf(p, len, "setname \"%s\"", sname);
5920Sstevel@tonic-gate 			(void) mderror(ep, MDE_NO_SET, p);
5930Sstevel@tonic-gate 			Free(p);
5940Sstevel@tonic-gate 		}
5950Sstevel@tonic-gate 		return (-1);
5960Sstevel@tonic-gate 	}
5970Sstevel@tonic-gate 	*setnop = sr->sr_setno;
5980Sstevel@tonic-gate 	free_sr(sr);
5990Sstevel@tonic-gate 	return (0);
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate /*
6030Sstevel@tonic-gate  * find setname from name
6040Sstevel@tonic-gate  */
6050Sstevel@tonic-gate mdsetname_t *
6060Sstevel@tonic-gate metasetname(
6070Sstevel@tonic-gate 	char		*sname,
6080Sstevel@tonic-gate 	md_error_t	*ep
6090Sstevel@tonic-gate )
6100Sstevel@tonic-gate {
6110Sstevel@tonic-gate 	mdsetnamelist_t	**tail;
6120Sstevel@tonic-gate 	set_t		setno;
6130Sstevel@tonic-gate 	mdsetname_t	*sp;
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	/* look for cached value first */
6160Sstevel@tonic-gate 	assert(sname != NULL);
6170Sstevel@tonic-gate 	for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) {
6180Sstevel@tonic-gate 		sp = (*tail)->sp;
6190Sstevel@tonic-gate 		if (strcmp(sp->setname, sname) == 0) {
6200Sstevel@tonic-gate 			return (sp);
6210Sstevel@tonic-gate 		}
6220Sstevel@tonic-gate 	}
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 	/* setup set */
6250Sstevel@tonic-gate 	if (getsetno(sname, &setno, ep) != 0)
6260Sstevel@tonic-gate 		return (NULL);
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	/* allocate new list element and setname */
6290Sstevel@tonic-gate 	*tail = Zalloc(sizeof (**tail));
6300Sstevel@tonic-gate 	sp = (*tail)->sp = Zalloc(sizeof (*sp));
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	sp->setname = Strdup(sname);
6330Sstevel@tonic-gate 	sp->setno = setno;
6340Sstevel@tonic-gate 	sp->lockfd = MD_NO_LOCK;
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	return (sp);
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate /*
6400Sstevel@tonic-gate  * find setname from setno
6410Sstevel@tonic-gate  */
6420Sstevel@tonic-gate mdsetname_t *
6430Sstevel@tonic-gate metasetnosetname(
6440Sstevel@tonic-gate 	set_t		setno,
6450Sstevel@tonic-gate 	md_error_t	*ep
6460Sstevel@tonic-gate )
6470Sstevel@tonic-gate {
6480Sstevel@tonic-gate 	mdsetnamelist_t	*slp;
6490Sstevel@tonic-gate 	mdsetname_t	*sp;
6500Sstevel@tonic-gate 	md_set_record	*sr;
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 	/* look for cached value first */
6530Sstevel@tonic-gate 	for (slp = setlistp; (slp != NULL); slp = slp->next) {
6540Sstevel@tonic-gate 		sp = slp->sp;
6550Sstevel@tonic-gate 		if (sp->setno == setno)
6560Sstevel@tonic-gate 			return (sp);
6570Sstevel@tonic-gate 	}
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 	/* local set */
6600Sstevel@tonic-gate 	if (setno == MD_LOCAL_SET)
6610Sstevel@tonic-gate 		return (metasetname(MD_LOCAL_NAME, ep));
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	/* shared set */
6640Sstevel@tonic-gate 	if ((sr = getsetbynum(setno, ep)) == NULL)
6650Sstevel@tonic-gate 		return (NULL);
6660Sstevel@tonic-gate 	sp = metasetname(sr->sr_setname, ep);
6670Sstevel@tonic-gate 	free_sr(sr);
6680Sstevel@tonic-gate 	return (sp);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate mdsetname_t *
6720Sstevel@tonic-gate metafakesetname(
6730Sstevel@tonic-gate 	set_t		setno,
6740Sstevel@tonic-gate 	char		*sname
6750Sstevel@tonic-gate )
6760Sstevel@tonic-gate {
6770Sstevel@tonic-gate 	mdsetnamelist_t	**tail;
6780Sstevel@tonic-gate 	mdsetname_t	*sp;
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 	/* look for cached value first */
6810Sstevel@tonic-gate 	for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) {
6820Sstevel@tonic-gate 		sp = (*tail)->sp;
6830Sstevel@tonic-gate 		if (sp->setno == setno) {
6840Sstevel@tonic-gate 			if ((sp->setname == NULL) && (sname != NULL))
6850Sstevel@tonic-gate 				sp->setname = Strdup(sname);
6860Sstevel@tonic-gate 			return (sp);
6870Sstevel@tonic-gate 		}
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	/* allocate new list element and setname */
6910Sstevel@tonic-gate 	*tail = Zalloc(sizeof (**tail));
6920Sstevel@tonic-gate 	sp = (*tail)->sp = Zalloc(sizeof (*sp));
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	if (sname != NULL)
6950Sstevel@tonic-gate 		sp->setname = Strdup(sname);
6960Sstevel@tonic-gate 	sp->setno = setno;
6970Sstevel@tonic-gate 	sp->lockfd = MD_NO_LOCK;
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	return (sp);
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate /*
7040Sstevel@tonic-gate  * setup set record (sr) and cache it in the mdsetname_t struct
7050Sstevel@tonic-gate  */
7060Sstevel@tonic-gate md_set_desc *
7070Sstevel@tonic-gate sr2setdesc(
7080Sstevel@tonic-gate 	md_set_record	*sr
7090Sstevel@tonic-gate )
7100Sstevel@tonic-gate {
7110Sstevel@tonic-gate 	md_set_desc	*sd;
7120Sstevel@tonic-gate 	int		i;
7130Sstevel@tonic-gate 	md_mnset_record	*mnsr;
7140Sstevel@tonic-gate 	md_mnnode_desc	*nd, *nd_prev = 0;
7150Sstevel@tonic-gate 	md_mnnode_record	*nr;
7160Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
7170Sstevel@tonic-gate 	md_error_t	*ep = &status;
7180Sstevel@tonic-gate 	int		nodecnt, nrcnt;
7190Sstevel@tonic-gate 	mndiskset_membershiplist_t *nl, *nl2;
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	sd = Zalloc(sizeof (*sd));
7220Sstevel@tonic-gate 	sd->sd_ctime = sr->sr_ctime;
7230Sstevel@tonic-gate 	sd->sd_genid = sr->sr_genid;
7240Sstevel@tonic-gate 	sd->sd_setno = sr->sr_setno;
7250Sstevel@tonic-gate 	sd->sd_flags = sr->sr_flags;
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
7280Sstevel@tonic-gate 		mnsr = (md_mnset_record *)sr;
7290Sstevel@tonic-gate 		(void) strlcpy(sd->sd_mn_master_nodenm,
7300Sstevel@tonic-gate 		    mnsr->sr_master_nodenm, sizeof (sd->sd_mn_master_nodenm));
7310Sstevel@tonic-gate 		sd->sd_mn_master_nodeid = mnsr->sr_master_nodeid;
7320Sstevel@tonic-gate 		if (strcmp(mnsr->sr_master_nodenm, mynode()) == 0) {
7330Sstevel@tonic-gate 			sd->sd_mn_am_i_master = 1;
7340Sstevel@tonic-gate 		}
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 		/*
7370Sstevel@tonic-gate 		 * Get membershiplist from API routine.  If there's
7380Sstevel@tonic-gate 		 * an error, just use a NULL nodelist.
7390Sstevel@tonic-gate 		 */
7400Sstevel@tonic-gate 		if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
7410Sstevel@tonic-gate 			nodecnt = 0;  /* no nodes are alive */
7420Sstevel@tonic-gate 			nl = NULL;
7430Sstevel@tonic-gate 		}
7440Sstevel@tonic-gate 		nr = mnsr->sr_nodechain;
7450Sstevel@tonic-gate 		nrcnt = 0;
7460Sstevel@tonic-gate 		/*
7470Sstevel@tonic-gate 		 * Node descriptor node list must be built in
7480Sstevel@tonic-gate 		 * ascending order of nodeid.  The nodechain
7490Sstevel@tonic-gate 		 * in the mnset record is in ascending order,
7500Sstevel@tonic-gate 		 * so just make them the same.
7510Sstevel@tonic-gate 		 */
7520Sstevel@tonic-gate 		while (nr) {
7530Sstevel@tonic-gate 			nd = Zalloc(sizeof (*nd));
7540Sstevel@tonic-gate 			if (nd_prev) {
7550Sstevel@tonic-gate 				nd_prev->nd_next = nd;
7560Sstevel@tonic-gate 			} else {
7570Sstevel@tonic-gate 				sd->sd_nodelist = nd;
7580Sstevel@tonic-gate 			}
7590Sstevel@tonic-gate 			nd->nd_ctime = nr->nr_ctime;
7600Sstevel@tonic-gate 			nd->nd_genid = nr->nr_genid;
7610Sstevel@tonic-gate 			nd->nd_flags = nr->nr_flags;
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 			(void) strlcpy(nd->nd_nodename, nr->nr_nodename,
7640Sstevel@tonic-gate 			    sizeof (nd->nd_nodename));
7650Sstevel@tonic-gate 			nd->nd_nodeid = nr->nr_nodeid;
7660Sstevel@tonic-gate 			if (strcmp(nd->nd_nodename, mynode()) == 0) {
7670Sstevel@tonic-gate 				sd->sd_mn_mynode = nd;
7680Sstevel@tonic-gate 			}
7690Sstevel@tonic-gate 			if (nd->nd_nodeid == sd->sd_mn_master_nodeid) {
7700Sstevel@tonic-gate 				sd->sd_mn_masternode = nd;
7710Sstevel@tonic-gate 			}
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 			/*
7740Sstevel@tonic-gate 			 * If node is marked ALIVE, then set priv_ic
7750Sstevel@tonic-gate 			 * from membership list.  During the early part
7760Sstevel@tonic-gate 			 * of a reconfig cycle, the membership list may
7770Sstevel@tonic-gate 			 * have been changed, (a node entering or leaving
7780Sstevel@tonic-gate 			 * the cluster), but rpc.metad hasn't flushed
7790Sstevel@tonic-gate 			 * its data yet.  So, if node is marked alive, but
7800Sstevel@tonic-gate 			 * is no longer in the membership list (node has
7810Sstevel@tonic-gate 			 * left the cluster) then just leave priv_ic to NULL.
7820Sstevel@tonic-gate 			 */
7830Sstevel@tonic-gate 			if (nd->nd_flags & MD_MN_NODE_ALIVE) {
7840Sstevel@tonic-gate 				nl2 = nl;
7850Sstevel@tonic-gate 				while (nl2) {
7860Sstevel@tonic-gate 					if (nl2->msl_node_id == nd->nd_nodeid) {
7870Sstevel@tonic-gate 						(void) strlcpy(nd->nd_priv_ic,
7880Sstevel@tonic-gate 						    nl2->msl_node_addr,
7890Sstevel@tonic-gate 						    sizeof (nd->nd_priv_ic));
7900Sstevel@tonic-gate 						break;
7910Sstevel@tonic-gate 					}
7920Sstevel@tonic-gate 					nl2 = nl2->next;
7930Sstevel@tonic-gate 				}
7940Sstevel@tonic-gate 			}
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 			nr = nr->nr_next;
7970Sstevel@tonic-gate 			nrcnt++;
7980Sstevel@tonic-gate 			nd_prev = nd;
7990Sstevel@tonic-gate 		}
8000Sstevel@tonic-gate 		sd->sd_mn_numnodes = nrcnt;
8010Sstevel@tonic-gate 		if (nodecnt)
8020Sstevel@tonic-gate 			meta_free_nodelist(nl);
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 		/* Just copying to keep consistent view between sr & sd */
8050Sstevel@tonic-gate 		(void) strlcpy(sd->sd_nodes[0], mnsr->sr_nodes_bw_compat[0],
8060Sstevel@tonic-gate 		    sizeof (sd->sd_nodes[0]));
8070Sstevel@tonic-gate 	} else {
8080Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++)
8090Sstevel@tonic-gate 			(void) strlcpy(sd->sd_nodes[i], sr->sr_nodes[i],
8100Sstevel@tonic-gate 			    sizeof (sd->sd_nodes[i]));
8110Sstevel@tonic-gate 	}
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 	sd->sd_med = sr->sr_med;		/* structure assignment */
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	return (sd);
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate md_set_desc *
8190Sstevel@tonic-gate metaget_setdesc(
8200Sstevel@tonic-gate 	mdsetname_t	*sp,
8210Sstevel@tonic-gate 	md_error_t	*ep
8220Sstevel@tonic-gate )
8230Sstevel@tonic-gate {
8240Sstevel@tonic-gate 	md_set_record	*sr;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	if (sp->setdesc != NULL)
8270Sstevel@tonic-gate 		return (sp->setdesc);
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	if (sp->setname != NULL) {
8300Sstevel@tonic-gate 		if ((sr = getsetbyname(sp->setname, ep)) != NULL) {
8310Sstevel@tonic-gate 			sp->setdesc = sr2setdesc(sr);
8320Sstevel@tonic-gate 			free_sr(sr);
8330Sstevel@tonic-gate 			return (sp->setdesc);
8340Sstevel@tonic-gate 		}
8350Sstevel@tonic-gate 	}
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate 	if (sp->setno > 0) {
8380Sstevel@tonic-gate 		if ((sr = getsetbynum(sp->setno, ep)) != NULL) {
8390Sstevel@tonic-gate 			sp->setdesc = sr2setdesc(sr);
8400Sstevel@tonic-gate 			free_sr(sr);
8410Sstevel@tonic-gate 			return (sp->setdesc);
8420Sstevel@tonic-gate 		}
8430Sstevel@tonic-gate 	}
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 	return (NULL);
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate void
8490Sstevel@tonic-gate metaflushsetname(mdsetname_t *sp)
8500Sstevel@tonic-gate {
8510Sstevel@tonic-gate 	if (sp == NULL)
8520Sstevel@tonic-gate 		return;
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	if (sp->setdesc == NULL)
8550Sstevel@tonic-gate 		return;
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 	metafreesetdesc(sp->setdesc);
8580Sstevel@tonic-gate 	sp->setdesc = NULL;
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate /*
8620Sstevel@tonic-gate  * check for local set
8630Sstevel@tonic-gate  */
8640Sstevel@tonic-gate int
8650Sstevel@tonic-gate metaislocalset(
8660Sstevel@tonic-gate 	mdsetname_t	*sp
8670Sstevel@tonic-gate )
8680Sstevel@tonic-gate {
8690Sstevel@tonic-gate 	assert(sp->setname != NULL);
8700Sstevel@tonic-gate 	if (strcmp(sp->setname, MD_LOCAL_NAME) == 0) {
8710Sstevel@tonic-gate 		assert(sp->setno == MD_LOCAL_SET);
8720Sstevel@tonic-gate 		return (1);
8730Sstevel@tonic-gate 	} else {
8740Sstevel@tonic-gate 		assert(sp->setno != MD_LOCAL_SET);
8750Sstevel@tonic-gate 		return (0);
8760Sstevel@tonic-gate 	}
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate /*
8800Sstevel@tonic-gate  * check for same set
8810Sstevel@tonic-gate  */
8820Sstevel@tonic-gate int
8830Sstevel@tonic-gate metaissameset(
8840Sstevel@tonic-gate 	mdsetname_t	*sp1,
8850Sstevel@tonic-gate 	mdsetname_t	*sp2
8860Sstevel@tonic-gate )
8870Sstevel@tonic-gate {
8880Sstevel@tonic-gate 	if (strcmp(sp1->setname, sp2->setname) == 0) {
8890Sstevel@tonic-gate 		assert(sp1->setno == sp2->setno);
8900Sstevel@tonic-gate 		return (1);
8910Sstevel@tonic-gate 	} else {
8920Sstevel@tonic-gate 		assert(sp1->setno != sp2->setno);
8930Sstevel@tonic-gate 		return (0);
8940Sstevel@tonic-gate 	}
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate /*
8980Sstevel@tonic-gate  * check to see if set changed
8990Sstevel@tonic-gate  */
9000Sstevel@tonic-gate static int
9010Sstevel@tonic-gate chkset(
9020Sstevel@tonic-gate 	mdsetname_t	**spp,
9030Sstevel@tonic-gate 	char		*sname,
9040Sstevel@tonic-gate 	md_error_t	*ep
9050Sstevel@tonic-gate )
9060Sstevel@tonic-gate {
9070Sstevel@tonic-gate 	/* if we already have a set, make sure it's the same */
908*1623Stw21770 	if (*spp != NULL && !metaislocalset(*spp)) {
9090Sstevel@tonic-gate 		if ((*spp)->setname != sname &&
9100Sstevel@tonic-gate 				strcmp((*spp)->setname, sname) != 0) {
9110Sstevel@tonic-gate 			return (mderror(ep, MDE_SET_DIFF, sname));
9120Sstevel@tonic-gate 		}
9130Sstevel@tonic-gate 		return (0);
9140Sstevel@tonic-gate 	}
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	/* otherwise store new set name and number */
9170Sstevel@tonic-gate 	if ((*spp = metasetname(sname, ep)) == NULL) {
9180Sstevel@tonic-gate 		return (-1);
9190Sstevel@tonic-gate 	}
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	/* return success */
9220Sstevel@tonic-gate 	return (0);
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate /*
9260Sstevel@tonic-gate  * check to see if set changed from default
9270Sstevel@tonic-gate  */
9280Sstevel@tonic-gate static int
9290Sstevel@tonic-gate chksetname(
9300Sstevel@tonic-gate 	mdsetname_t	**spp,
9310Sstevel@tonic-gate 	char		*sname,
9320Sstevel@tonic-gate 	md_error_t	*ep
9330Sstevel@tonic-gate )
9340Sstevel@tonic-gate {
9350Sstevel@tonic-gate 	/* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */
9360Sstevel@tonic-gate 	if (sname == NULL) {
9370Sstevel@tonic-gate 		if (*spp) {
938*1623Stw21770 			return (0);
9390Sstevel@tonic-gate 		} else {
9400Sstevel@tonic-gate 			sname = MD_LOCAL_NAME;
9410Sstevel@tonic-gate 		}
9420Sstevel@tonic-gate 	}
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 	/* see if changed */
9450Sstevel@tonic-gate 	return (chkset(spp, sname, ep));
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate /*
9490Sstevel@tonic-gate  * check setname from setno
9500Sstevel@tonic-gate  */
9510Sstevel@tonic-gate static int
9520Sstevel@tonic-gate chksetno(
9530Sstevel@tonic-gate 	mdsetname_t	**spp,
9540Sstevel@tonic-gate 	set_t		setno,
9550Sstevel@tonic-gate 	md_error_t	*ep
9560Sstevel@tonic-gate )
9570Sstevel@tonic-gate {
9580Sstevel@tonic-gate 	md_set_record	*sr;
9590Sstevel@tonic-gate 	int		rval;
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate 	/* local set */
9620Sstevel@tonic-gate 	if (setno == 0)
9630Sstevel@tonic-gate 		return (chkset(spp, MD_LOCAL_NAME, ep));
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 	/* shared set */
9660Sstevel@tonic-gate 	if ((sr = getsetbynum(setno, ep)) == NULL)
9670Sstevel@tonic-gate 		return (-1);
9680Sstevel@tonic-gate 	rval = chkset(spp, sr->sr_setname, ep);
9690Sstevel@tonic-gate 	free_sr(sr);
9700Sstevel@tonic-gate 	return (rval);
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate /*
9740Sstevel@tonic-gate  *	mddrivename_t stuff
9750Sstevel@tonic-gate  */
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate /*
9780Sstevel@tonic-gate  * initialize name
9790Sstevel@tonic-gate  */
9800Sstevel@tonic-gate static void
9810Sstevel@tonic-gate metainitname(
9820Sstevel@tonic-gate 	mdname_t	*np
9830Sstevel@tonic-gate )
9840Sstevel@tonic-gate {
9850Sstevel@tonic-gate 	(void) memset(np, 0, sizeof (*np));
9860Sstevel@tonic-gate 	np->dev = NODEV64;
9870Sstevel@tonic-gate 	np->key = MD_KEYBAD;
9880Sstevel@tonic-gate 	np->end_blk = -1;
9890Sstevel@tonic-gate 	np->start_blk = -1;
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate 
9920Sstevel@tonic-gate /*
9930Sstevel@tonic-gate  * free allocated name
9940Sstevel@tonic-gate  */
9950Sstevel@tonic-gate static void
9960Sstevel@tonic-gate metafreename(
9970Sstevel@tonic-gate 	mdname_t	*np
9980Sstevel@tonic-gate )
9990Sstevel@tonic-gate {
10000Sstevel@tonic-gate 	if (np->cname != NULL)
10010Sstevel@tonic-gate 		Free(np->cname);
10020Sstevel@tonic-gate 	if (np->bname != NULL)
10030Sstevel@tonic-gate 		Free(np->bname);
10040Sstevel@tonic-gate 	if (np->rname != NULL)
10050Sstevel@tonic-gate 		Free(np->rname);
10060Sstevel@tonic-gate 	if (np->devicesname != NULL)
10070Sstevel@tonic-gate 		Free(np->devicesname);
10080Sstevel@tonic-gate 	metainitname(np);
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate /*
10120Sstevel@tonic-gate  * initialize drive name
10130Sstevel@tonic-gate  */
10140Sstevel@tonic-gate static void
10150Sstevel@tonic-gate metainitdrivename(
10160Sstevel@tonic-gate 	mddrivename_t	*dnp
10170Sstevel@tonic-gate )
10180Sstevel@tonic-gate {
10190Sstevel@tonic-gate 	(void) memset(dnp, 0, sizeof (*dnp));
10200Sstevel@tonic-gate 	dnp->side_names_key = MD_KEYBAD;
10210Sstevel@tonic-gate }
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate /*
10240Sstevel@tonic-gate  * flush side names
10250Sstevel@tonic-gate  */
10260Sstevel@tonic-gate void
10270Sstevel@tonic-gate metaflushsidenames(
10280Sstevel@tonic-gate 	mddrivename_t	*dnp
10290Sstevel@tonic-gate )
10300Sstevel@tonic-gate {
10310Sstevel@tonic-gate 	mdsidenames_t	*p, *n;
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 	for (p = dnp->side_names, n = NULL; (p != NULL); p = n) {
10340Sstevel@tonic-gate 		n = p->next;
10350Sstevel@tonic-gate 		if (p->dname != NULL)
10360Sstevel@tonic-gate 			Free(p->dname);
10370Sstevel@tonic-gate 		if (p->cname != NULL)
10380Sstevel@tonic-gate 			Free(p->cname);
10390Sstevel@tonic-gate 		Free(p);
10400Sstevel@tonic-gate 	}
10410Sstevel@tonic-gate 	dnp->side_names = NULL;
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate 
10440Sstevel@tonic-gate /*
10450Sstevel@tonic-gate  * free drive name
10460Sstevel@tonic-gate  */
10470Sstevel@tonic-gate void
10480Sstevel@tonic-gate metafreedrivename(
10490Sstevel@tonic-gate 	mddrivename_t	*dnp
10500Sstevel@tonic-gate )
10510Sstevel@tonic-gate {
10520Sstevel@tonic-gate 	uint_t		slice;
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 	if (dnp->cname != NULL)
10550Sstevel@tonic-gate 		Free(dnp->cname);
10560Sstevel@tonic-gate 	if (dnp->rname != NULL)
10570Sstevel@tonic-gate 		Free(dnp->rname);
10580Sstevel@tonic-gate 	metafreevtoc(&dnp->vtoc);
10590Sstevel@tonic-gate 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice)
10600Sstevel@tonic-gate 		metafreename(&dnp->parts.parts_val[slice]);
10610Sstevel@tonic-gate 	if (dnp->parts.parts_val != NULL)
10620Sstevel@tonic-gate 		Free(dnp->parts.parts_val);
10630Sstevel@tonic-gate 	metaflushsidenames(dnp);
10640Sstevel@tonic-gate 	if (dnp->miscname != NULL)
10650Sstevel@tonic-gate 		Free(dnp->miscname);
10660Sstevel@tonic-gate 	meta_free_unit(dnp);
10670Sstevel@tonic-gate 	metainitdrivename(dnp);
10680Sstevel@tonic-gate }
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate /*
10710Sstevel@tonic-gate  * flush the drive name cache
10720Sstevel@tonic-gate  */
10730Sstevel@tonic-gate static void
10740Sstevel@tonic-gate metaflushdrivenames()
10750Sstevel@tonic-gate {
10760Sstevel@tonic-gate 	mddrivenamelist_t	*p, *n;
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate 	for (p = drivelistp, n = NULL; (p != NULL); p = n) {
10790Sstevel@tonic-gate 		n = p->next;
10800Sstevel@tonic-gate 		metafreedrivename(p->drivenamep);
10810Sstevel@tonic-gate 		Free(p->drivenamep);
10820Sstevel@tonic-gate 		Free(p);
10830Sstevel@tonic-gate 	}
10840Sstevel@tonic-gate 	drivelistp = NULL;
10850Sstevel@tonic-gate }
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate /*
10880Sstevel@tonic-gate  * peel off s%u from name
10890Sstevel@tonic-gate  */
10900Sstevel@tonic-gate char *
10910Sstevel@tonic-gate metadiskname(
10920Sstevel@tonic-gate 	char	*name
10930Sstevel@tonic-gate )
10940Sstevel@tonic-gate {
10950Sstevel@tonic-gate 	char	*p, *e;
10960Sstevel@tonic-gate 	char	onmb[BUFSIZ+1], cnmb[BUFSIZ];
10970Sstevel@tonic-gate 	uint_t	d = 0;
10980Sstevel@tonic-gate 	int	l = 0;
10990Sstevel@tonic-gate 	int	cl = strlen(name);
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate 	/*
11020Sstevel@tonic-gate 	 * Handle old style names, which are of the form /dev/rXXNN[a-h].
11030Sstevel@tonic-gate 	 */
11040Sstevel@tonic-gate 	if (sscanf(name, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n",
11050Sstevel@tonic-gate 	    onmb, &d, &l) == 2 && l == cl) {
11060Sstevel@tonic-gate 		(void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u", onmb, d);
11070Sstevel@tonic-gate 		return (Strdup(cnmb));
11080Sstevel@tonic-gate 	}
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 	/*
11110Sstevel@tonic-gate 	 * Handle old style names, which are of the form /dev/XXNN[a-h].
11120Sstevel@tonic-gate 	 */
11130Sstevel@tonic-gate 	if (sscanf(name, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n",
11140Sstevel@tonic-gate 	    onmb, &d, &l) == 2 && l == cl) {
11150Sstevel@tonic-gate 		(void) snprintf(cnmb, sizeof (cnmb), "/dev/%s%u", onmb, d);
11160Sstevel@tonic-gate 		return (Strdup(cnmb));
11170Sstevel@tonic-gate 	}
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	/* gobble number and 's' */
11200Sstevel@tonic-gate 	p = e = name + strlen(name) - 1;
11210Sstevel@tonic-gate 	for (; (p > name); --p) {
11220Sstevel@tonic-gate 		if (!isdigit(*p))
11230Sstevel@tonic-gate 			break;
11240Sstevel@tonic-gate 	}
11250Sstevel@tonic-gate 	if ((p == e) || (p <= name))
11260Sstevel@tonic-gate 		return (Strdup(name));
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	if (*p != 's' && strchr("dt", *p) == NULL)
11290Sstevel@tonic-gate 		return (Strdup(name));
11300Sstevel@tonic-gate 	else if (strchr("dt", *p) != NULL)
11310Sstevel@tonic-gate 		return (Strdup(name));
11320Sstevel@tonic-gate 	p--;
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 	if ((p <= name) || (!isdigit(*p)))
11350Sstevel@tonic-gate 		return (Strdup(name));
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	*(++p) = '\0';
11380Sstevel@tonic-gate 	e = Strdup(name);
11390Sstevel@tonic-gate 	*p = 's';
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	return (e);
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate /*
11450Sstevel@tonic-gate  * free list of drivenames
11460Sstevel@tonic-gate  */
11470Sstevel@tonic-gate void
11480Sstevel@tonic-gate metafreedrivenamelist(
11490Sstevel@tonic-gate 	mddrivenamelist_t	*dnlp
11500Sstevel@tonic-gate )
11510Sstevel@tonic-gate {
11520Sstevel@tonic-gate 	mddrivenamelist_t	*next = NULL;
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	for (/* void */; (dnlp != NULL); dnlp = next) {
11550Sstevel@tonic-gate 		next = dnlp->next;
11560Sstevel@tonic-gate 		Free(dnlp);
11570Sstevel@tonic-gate 	}
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate /*
11610Sstevel@tonic-gate  * build list of drivenames
11620Sstevel@tonic-gate  */
11630Sstevel@tonic-gate int
11640Sstevel@tonic-gate metadrivenamelist(
11650Sstevel@tonic-gate 	mdsetname_t		**spp,
11660Sstevel@tonic-gate 	mddrivenamelist_t	**dnlpp,
11670Sstevel@tonic-gate 	int			argc,
11680Sstevel@tonic-gate 	char			*argv[],
11690Sstevel@tonic-gate 	md_error_t		*ep
11700Sstevel@tonic-gate )
11710Sstevel@tonic-gate {
11720Sstevel@tonic-gate 	mddrivenamelist_t	**tailpp = dnlpp;
11730Sstevel@tonic-gate 	int			count = 0;
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 	for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
11760Sstevel@tonic-gate 		mddrivenamelist_t	*dnlp = Zalloc(sizeof (*dnlp));
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate 		if ((dnlp->drivenamep = metadrivename(spp, argv[0],
11790Sstevel@tonic-gate 		    ep)) == NULL) {
11800Sstevel@tonic-gate 			metafreedrivenamelist(*dnlpp);
11810Sstevel@tonic-gate 			*dnlpp = NULL;
11820Sstevel@tonic-gate 			return (-1);
11830Sstevel@tonic-gate 		}
11840Sstevel@tonic-gate 		*tailpp = dnlp;
11850Sstevel@tonic-gate 		tailpp = &dnlp->next;
11860Sstevel@tonic-gate 	}
11870Sstevel@tonic-gate 	return (count);
11880Sstevel@tonic-gate }
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate /*
11910Sstevel@tonic-gate  * append to end of drivename list
11920Sstevel@tonic-gate  */
11930Sstevel@tonic-gate mddrivename_t *
11940Sstevel@tonic-gate metadrivenamelist_append(
11950Sstevel@tonic-gate 	mddrivenamelist_t	**dnlpp,
11960Sstevel@tonic-gate 	mddrivename_t		*dnp
11970Sstevel@tonic-gate )
11980Sstevel@tonic-gate {
11990Sstevel@tonic-gate 	mddrivenamelist_t	*dnlp;
12000Sstevel@tonic-gate 
12010Sstevel@tonic-gate 	/* run to end of list */
12020Sstevel@tonic-gate 	for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next)
12030Sstevel@tonic-gate 		;
12040Sstevel@tonic-gate 
12050Sstevel@tonic-gate 	/* allocate new list element */
12060Sstevel@tonic-gate 	dnlp = *dnlpp = Zalloc(sizeof (*dnlp));
12070Sstevel@tonic-gate 
12080Sstevel@tonic-gate 	/* append drivename */
12090Sstevel@tonic-gate 	dnlp->drivenamep = dnp;
12100Sstevel@tonic-gate 	return (dnp);
12110Sstevel@tonic-gate }
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate /*
12140Sstevel@tonic-gate  * FUNCTION:	meta_drivenamelist_append_wrapper()
12150Sstevel@tonic-gate  * INPUT:	tailpp	- pointer to the list tail pointer
12160Sstevel@tonic-gate  *		dnp	- name node to be appended to list
12170Sstevel@tonic-gate  * OUTPUT:	none
12180Sstevel@tonic-gate  * RETURNS:	mddrivenamelist_t * - new tail of the list.
12190Sstevel@tonic-gate  * PURPOSE:	wrapper to meta_namelist_append for performance.
12200Sstevel@tonic-gate  *		metanamelist_append finds the tail each time which slows
12210Sstevel@tonic-gate  *		down long lists.  By keeping track of the tail ourselves
12220Sstevel@tonic-gate  *		we can change metadrivenamelist_append into a
12230Sstevel@tonic-gate  *		constant time operation.
12240Sstevel@tonic-gate  */
12250Sstevel@tonic-gate mddrivenamelist_t **
12260Sstevel@tonic-gate meta_drivenamelist_append_wrapper(
12270Sstevel@tonic-gate 	mddrivenamelist_t	**tailpp,
12280Sstevel@tonic-gate 	mddrivename_t	*dnp
12290Sstevel@tonic-gate )
12300Sstevel@tonic-gate {
12310Sstevel@tonic-gate 	(void) metadrivenamelist_append(tailpp, dnp);
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate 	/* If it's the first item in the list, return it instead of the next */
12340Sstevel@tonic-gate 	if ((*tailpp)->next == NULL)
12350Sstevel@tonic-gate 		return (tailpp);
12360Sstevel@tonic-gate 
12370Sstevel@tonic-gate 	return (&(*tailpp)->next);
12380Sstevel@tonic-gate }
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate /*
12420Sstevel@tonic-gate  *	mdname_t stuff
12430Sstevel@tonic-gate  */
12440Sstevel@tonic-gate 
12450Sstevel@tonic-gate /*
12460Sstevel@tonic-gate  * check set and get comparison name
1247*1623Stw21770  *
1248*1623Stw21770  * NOTE: This function has a side effect of setting *spp if the setname
1249*1623Stw21770  * has been specified and *spp is not already set.
12500Sstevel@tonic-gate  */
12510Sstevel@tonic-gate char *
12520Sstevel@tonic-gate meta_name_getname(
1253*1623Stw21770 	mdsetname_t		**spp,
1254*1623Stw21770 	char			*uname,
1255*1623Stw21770 	meta_device_type_t	uname_type,
1256*1623Stw21770 	md_error_t		*ep
12570Sstevel@tonic-gate )
12580Sstevel@tonic-gate {
1259*1623Stw21770 	if (uname_type == META_DEVICE || uname_type == HSP_DEVICE ||
1260*1623Stw21770 	    (uname_type == UNKNOWN && is_existing_metadevice(*spp, uname))) {
1261*1623Stw21770 
1262*1623Stw21770 		/*
1263*1623Stw21770 		 * if the setname is specified in uname, *spp is set,
1264*1623Stw21770 		 * and the set names don't agree then canonical name will be
1265*1623Stw21770 		 * returned as NULL
1266*1623Stw21770 		 */
1267*1623Stw21770 		return (meta_canonicalize_check_set(spp, uname, ep));
1268*1623Stw21770 	}
1269*1623Stw21770 
1270*1623Stw21770 	/* if it is not a meta/hsp and *spp is not set then set it to local */
1271*1623Stw21770 	if (chksetname(spp, NULL, ep) != 0)
12720Sstevel@tonic-gate 		return (NULL);
1273*1623Stw21770 
1274*1623Stw21770 	/* if it is not a meta/hsp name then just return uname */
1275*1623Stw21770 	return (Strdup(uname));
12760Sstevel@tonic-gate }
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate /*
12790Sstevel@tonic-gate  * FUNCTION:	getrname()
12800Sstevel@tonic-gate  * INPUT:	spp	- the setname struct
12810Sstevel@tonic-gate  *		uname	- the possibly unqualified device name
1282*1623Stw21770  *		type 	- ptr to the device type of uname
12830Sstevel@tonic-gate  * OUTPUT:	ep	- return error pointer
12840Sstevel@tonic-gate  * RETURNS:	char*	- character string containing the fully
12850Sstevel@tonic-gate  *			qualified raw device name
12860Sstevel@tonic-gate  * PURPOSE:	Create the fully qualified raw name for the possibly
12870Sstevel@tonic-gate  *		unqualified device name.  If uname is an absolute
12880Sstevel@tonic-gate  *		path the raw name is derived from the input string.
12890Sstevel@tonic-gate  *		Otherwise, an attempt is made to get the rawname by
1290*1623Stw21770  *		catting "/dev/md/rdsk" and "/dev/rdsk". If the input
1291*1623Stw21770  *		value of type is UNKNOWN and it can be successfully
1292*1623Stw21770  *		determined then update type to the correct value.
12930Sstevel@tonic-gate  */
1294*1623Stw21770 static	char *
1295*1623Stw21770 getrname(mdsetname_t **spp, char *uname,
1296*1623Stw21770     meta_device_type_t *type, md_error_t *ep)
12970Sstevel@tonic-gate {
1298*1623Stw21770 	char			*rname,
1299*1623Stw21770 				*fname;
1300*1623Stw21770 	int			i;
1301*1623Stw21770 	int 			rname_cnt = 0;
1302*1623Stw21770 	char			*rname_list[3];
1303*1623Stw21770 	meta_device_type_t	tmp_type;
13040Sstevel@tonic-gate 
13050Sstevel@tonic-gate 	assert(uname != NULL);
13060Sstevel@tonic-gate 	/* if it is an absolute name then just call rawname on the input */
13070Sstevel@tonic-gate 	if (uname[0] == '/') {
1308*1623Stw21770 	    if ((rname = rawname(uname)) != NULL) {
1309*1623Stw21770 		/*
1310*1623Stw21770 		 * If the returned rname does not match with
1311*1623Stw21770 		 * the specified uname type, we'll return null.
1312*1623Stw21770 		 */
1313*1623Stw21770 		if (strncmp(rname, "/dev/md", strlen("/dev/md")) == 0) {
1314*1623Stw21770 			if (*type == LOGICAL_DEVICE) {
1315*1623Stw21770 				(void) mdsyserror(ep, ENOENT, uname);
1316*1623Stw21770 				return (NULL);
1317*1623Stw21770 			}
1318*1623Stw21770 			*type = META_DEVICE;
1319*1623Stw21770 		} else {
1320*1623Stw21770 			if (*type == META_DEVICE) {
1321*1623Stw21770 				(void) mdsyserror(ep, ENOENT, uname);
1322*1623Stw21770 				return (NULL);
1323*1623Stw21770 			}
1324*1623Stw21770 			*type = LOGICAL_DEVICE;
1325*1623Stw21770 		}
13260Sstevel@tonic-gate 		return (rname);
1327*1623Stw21770 	    }
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate 	    /* out of luck */
13300Sstevel@tonic-gate 	    (void) mdsyserror(ep, ENOENT, uname);
13310Sstevel@tonic-gate 	    return (NULL);
13320Sstevel@tonic-gate 	}
13330Sstevel@tonic-gate 
13340Sstevel@tonic-gate 	/*
1335*1623Stw21770 	 * Get device that matches the requested type. If
1336*1623Stw21770 	 * a match is found, return immediately. If type is
1337*1623Stw21770 	 * UNKNOWN, save all the found devices in rname_list
1338*1623Stw21770 	 * so we can determine later whether the input uname
1339*1623Stw21770 	 * is ambiguous.
1340*1623Stw21770 	 *
13410Sstevel@tonic-gate 	 * Check for metadevice before physical device.
13420Sstevel@tonic-gate 	 * With the introduction of softpartitions it is more
13430Sstevel@tonic-gate 	 * likely to be a metadevice.
13440Sstevel@tonic-gate 	 */
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate 	/* metadevice short form */
1347*1623Stw21770 	if (*type == META_DEVICE || *type == UNKNOWN) {
1348*1623Stw21770 		if (metaislocalset(*spp)) {
1349*1623Stw21770 			fname = Malloc(strlen(uname) +
1350*1623Stw21770 			    strlen("/dev/md/rdsk/") + 1);
1351*1623Stw21770 			(void) strcpy(fname, "/dev/md/rdsk/");
1352*1623Stw21770 			(void) strcat(fname, uname);
13530Sstevel@tonic-gate 		} else {
1354*1623Stw21770 			char	*p;
1355*1623Stw21770 			size_t	len;
1356*1623Stw21770 
1357*1623Stw21770 			if ((p = strchr(uname, '/')) != NULL) {
1358*1623Stw21770 				++p;
1359*1623Stw21770 			} else {
1360*1623Stw21770 				p = uname;
1361*1623Stw21770 			}
1362*1623Stw21770 			len = strlen((*spp)->setname) + strlen(p) +
1363*1623Stw21770 			    strlen("/dev/md//rdsk/") + 1;
1364*1623Stw21770 			fname = Malloc(len);
1365*1623Stw21770 			(void) snprintf(fname, len, "/dev/md/%s/rdsk/%s",
1366*1623Stw21770 			    (*spp)->setname, p);
13670Sstevel@tonic-gate 		}
1368*1623Stw21770 		rname = rawname(fname);
1369*1623Stw21770 
1370*1623Stw21770 		if (*type == META_DEVICE) {
1371*1623Stw21770 			/*
1372*1623Stw21770 			 * Handle the case where we have a new metadevice
1373*1623Stw21770 			 * that does not yet exist in the name-space(e.g
1374*1623Stw21770 			 * metarecover in MN sets where /dev/md entry is
1375*1623Stw21770 			 * not yet created in the non-master nodes). In
1376*1623Stw21770 			 * this case we return the constructed metadevice
1377*1623Stw21770 			 * name as that will exist after the metainit call
1378*1623Stw21770 			 * has created it.
1379*1623Stw21770 			 */
1380*1623Stw21770 			if (rname == NULL) {
1381*1623Stw21770 				rname = Strdup(fname);
1382*1623Stw21770 			}
1383*1623Stw21770 
1384*1623Stw21770 			Free(fname);
1385*1623Stw21770 			return (rname);
1386*1623Stw21770 		}
1387*1623Stw21770 
1388*1623Stw21770 		Free(fname);
1389*1623Stw21770 		if ((rname != NULL) && (*type == UNKNOWN)) {
1390*1623Stw21770 			/* Save this result */
1391*1623Stw21770 			rname_list[rname_cnt] = rname;
1392*1623Stw21770 			rname_cnt ++;
1393*1623Stw21770 		}
13940Sstevel@tonic-gate 	}
1395*1623Stw21770 
1396*1623Stw21770 	if (*type == LOGICAL_DEVICE || *type == UNKNOWN) {
1397*1623Stw21770 		fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1);
1398*1623Stw21770 		(void) strcpy(fname, "/dev/rdsk/");
1399*1623Stw21770 		(void) strcat(fname, uname);
1400*1623Stw21770 		rname = rawname(fname);
1401*1623Stw21770 
1402*1623Stw21770 		Free(fname);
1403*1623Stw21770 		if (rname != NULL) {
1404*1623Stw21770 			/* Simply return if a logical device was requested */
1405*1623Stw21770 			if (*type == LOGICAL_DEVICE) {
1406*1623Stw21770 				return (rname);
1407*1623Stw21770 			} else {
1408*1623Stw21770 				rname_list[rname_cnt] = rname;
1409*1623Stw21770 				rname_cnt ++;
1410*1623Stw21770 			}
1411*1623Stw21770 		}
14120Sstevel@tonic-gate 	}
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate 	/*
14150Sstevel@tonic-gate 	 * If all else fails try the straight uname.
14160Sstevel@tonic-gate 	 * NOTE: This check was at the beginning of getrname instead
14170Sstevel@tonic-gate 	 * of here. It was moved to avoid a conflict with SC3.0. If
14180Sstevel@tonic-gate 	 * a diskset was mounted with the same name it would hang
14190Sstevel@tonic-gate 	 * the cluster in a loop. Example:
14200Sstevel@tonic-gate 	 *
14210Sstevel@tonic-gate 	 *	fubar/d10 -m fubar/d0 fubar/d1
14220Sstevel@tonic-gate 	 *	mount /dev/md/fubar/dsk/d10 /fubar
14230Sstevel@tonic-gate 	 *
1424*1623Stw21770 	 * When the system was booted SVM would try to take ownership
14250Sstevel@tonic-gate 	 * of diskset fubar. This would cause rawname("fubar/d10") to be
14260Sstevel@tonic-gate 	 * called. rawname() stats the string which caused the cluster
14270Sstevel@tonic-gate 	 * reservation code to try and take ownership which it was already
14280Sstevel@tonic-gate 	 * doing and a deadlock would occur. By moving this final attempt
14290Sstevel@tonic-gate 	 * at resolving the rawname to the end we avoid this deadlock.
14300Sstevel@tonic-gate 	 */
1431*1623Stw21770 	if (rname = rawname(uname)) {
1432*1623Stw21770 		/*
1433*1623Stw21770 		 * It's only possible to get a logical device from this
1434*1623Stw21770 		 * rawname call since a metadevice would have been
1435*1623Stw21770 		 * detected earlier.
1436*1623Stw21770 		 */
1437*1623Stw21770 		if (*type == LOGICAL_DEVICE &&
1438*1623Stw21770 		    (strncmp(rname, "/dev/md/", strlen("/dev/md"))) != 1)
1439*1623Stw21770 			return (rname);
1440*1623Stw21770 		else {
1441*1623Stw21770 			rname_list[rname_cnt] = rname;
1442*1623Stw21770 			rname_cnt++;
1443*1623Stw21770 		}
1444*1623Stw21770 	}
1445*1623Stw21770 
1446*1623Stw21770 	/*
1447*1623Stw21770 	 * At this point, we've searched /dev/md/rdsk, /dev/rdsk and
1448*1623Stw21770 	 * ./ for the specified device. rname_list contains all
1449*1623Stw21770 	 * the matches we've found and rname_cnt is the number of
1450*1623Stw21770 	 * matches.
1451*1623Stw21770 	 *
1452*1623Stw21770 	 * We know that either we don't have a match if a specific
1453*1623Stw21770 	 * type was given, in which case we simply return NULL or
1454*1623Stw21770 	 * we have an UNKNOWN device with 1-3 entries in rname_list.
1455*1623Stw21770 	 *
1456*1623Stw21770 	 * If we get 3 entries, rname_cnt == 3, it's ambiguous.
1457*1623Stw21770 	 * If we only get 1 entry, rname_cnt == 1, return rname_list[0].
1458*1623Stw21770 	 * If we get 2 entries that are not the same, it's ambigous.
1459*1623Stw21770 	 */
1460*1623Stw21770 	rname = NULL;
1461*1623Stw21770 	if (rname_cnt == 0 || *type != UNKNOWN) {
1462*1623Stw21770 		/* out of luck */
1463*1623Stw21770 		(void) mdsyserror(ep, ENOENT, uname);
1464*1623Stw21770 		return (NULL);
1465*1623Stw21770 	} else {
1466*1623Stw21770 		if (rname_cnt == 3) {
1467*1623Stw21770 			(void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
1468*1623Stw21770 			(void) printf(dgettext(TEXT_DOMAIN,
1469*1623Stw21770 			    "Error: ambiguous device name.\n%s %s %s\n\n"),
1470*1623Stw21770 			    rname_list[0], rname_list[1], rname_list[2]);
1471*1623Stw21770 			rname = NULL;
1472*1623Stw21770 		}
1473*1623Stw21770 
1474*1623Stw21770 		/* grab the type in case it is not ambiguous */
1475*1623Stw21770 		if (strncmp(rname_list[0], "/dev/md", strlen("/dev/md")) == 0)
1476*1623Stw21770 			tmp_type =  META_DEVICE;
1477*1623Stw21770 		else
1478*1623Stw21770 			tmp_type =  LOGICAL_DEVICE;
1479*1623Stw21770 
1480*1623Stw21770 		if (rname_cnt == 1) {
1481*1623Stw21770 			rname = Strdup(rname_list[0]);
1482*1623Stw21770 			*type = tmp_type;
1483*1623Stw21770 		} else {
1484*1623Stw21770 			/*
1485*1623Stw21770 			 * Prevent the case where the command is run in
1486*1623Stw21770 			 * either /dev/md/rdsk or /dev/rdsk so the both
1487*1623Stw21770 			 * rname_list[0] and rname_list[1] are the same.
1488*1623Stw21770 			 */
1489*1623Stw21770 			if (strcmp(rname_list[0], rname_list[1]) != 0) {
1490*1623Stw21770 				(void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
1491*1623Stw21770 				if (rname_cnt != 3) {
1492*1623Stw21770 					/*
1493*1623Stw21770 					 * For the rname_cnt == 3 case, the
1494*1623Stw21770 					 * error was printed above.
1495*1623Stw21770 					 */
1496*1623Stw21770 					(void) printf(dgettext(TEXT_DOMAIN,
1497*1623Stw21770 						"Error: ambiguous device "
1498*1623Stw21770 						"name.\n%s %s\n\n"),
1499*1623Stw21770 						rname_list[0], rname_list[1]);
1500*1623Stw21770 				}
1501*1623Stw21770 				rname = NULL;
1502*1623Stw21770 			} else {
1503*1623Stw21770 				rname = Strdup(rname_list[0]);
1504*1623Stw21770 				*type = tmp_type;
1505*1623Stw21770 			}
1506*1623Stw21770 		}
1507*1623Stw21770 		for (i = 0; i < rname_cnt; i++)
1508*1623Stw21770 			Free(rname_list[i]);
15090Sstevel@tonic-gate 		return (rname);
1510*1623Stw21770 	}
15110Sstevel@tonic-gate }
15120Sstevel@tonic-gate 
15130Sstevel@tonic-gate /*
15140Sstevel@tonic-gate  * get raw slice and drive names
15150Sstevel@tonic-gate  */
15160Sstevel@tonic-gate static char *
15170Sstevel@tonic-gate getrawnames(
1518*1623Stw21770 	mdsetname_t		**spp,
1519*1623Stw21770 	char			*uname,
1520*1623Stw21770 	char			**dnamep,
1521*1623Stw21770 	meta_device_type_t	*uname_type,
1522*1623Stw21770 	md_error_t		*ep
15230Sstevel@tonic-gate )
15240Sstevel@tonic-gate {
1525*1623Stw21770 	char		*rname = NULL;
15260Sstevel@tonic-gate 	size_t		len;
15270Sstevel@tonic-gate 
1528*1623Stw21770 	/*
1529*1623Stw21770 	 * Incorrect code path if type is HSP_DEVICE
1530*1623Stw21770 	 */
1531*1623Stw21770 	assert(*uname_type != HSP_DEVICE);
1532*1623Stw21770 
15330Sstevel@tonic-gate 	/* initialize */
15340Sstevel@tonic-gate 	*dnamep = NULL;
15350Sstevel@tonic-gate 
15360Sstevel@tonic-gate 	/* get slice name */
1537*1623Stw21770 	if ((rname = getrname(spp, uname, uname_type, ep)) != NULL) {
15380Sstevel@tonic-gate 		*dnamep = metadiskname(rname);
15390Sstevel@tonic-gate 		return (rname);
15400Sstevel@tonic-gate 	}
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 	/*
15430Sstevel@tonic-gate 	 * If name cannot be found, if may be because is is not accessible.
15440Sstevel@tonic-gate 	 * If it is an absolute name, try all possible disk name formats and
1545*1623Stw21770 	 * if it is device name, assume it is /dev/rdsk/..
1546*1623Stw21770 	 * Since the code below assumes logical devices, if the given
1547*1623Stw21770 	 * uname_type is META_DEVICE, there's nothing to do.
15480Sstevel@tonic-gate 	 */
1549*1623Stw21770 	if (mdissyserror(ep, ENOENT) && *uname_type != META_DEVICE) {
15500Sstevel@tonic-gate 		if (uname[0] == '/') {
15510Sstevel@tonic-gate 			/* Absolute name */
15520Sstevel@tonic-gate 			char			*p;
15530Sstevel@tonic-gate 			uint_t			d = 0;
15540Sstevel@tonic-gate 			int			l = 0;
15550Sstevel@tonic-gate 			char			onmb[BUFSIZ+1], snm[BUFSIZ+1];
15560Sstevel@tonic-gate 
15570Sstevel@tonic-gate 			/*
15580Sstevel@tonic-gate 			 * Handle old style raw names
15590Sstevel@tonic-gate 			 */
15600Sstevel@tonic-gate 			if (sscanf(uname,
15610Sstevel@tonic-gate 			    "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
15620Sstevel@tonic-gate 			    "%" VAL2STR(BUFSIZ) "[a-h]%n",
15630Sstevel@tonic-gate 			    onmb, &d, snm, &l) == 3 && l == strlen(uname)) {
15640Sstevel@tonic-gate 				mdclrerror(ep);
15650Sstevel@tonic-gate 				rname = Strdup(uname);
15660Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
1567*1623Stw21770 				*uname_type = LOGICAL_DEVICE;
15680Sstevel@tonic-gate 				return (rname);
15690Sstevel@tonic-gate 			}
15700Sstevel@tonic-gate 
15710Sstevel@tonic-gate 			/*
15720Sstevel@tonic-gate 			 * Handle old style block names
15730Sstevel@tonic-gate 			 */
15740Sstevel@tonic-gate 			if (sscanf(uname,
15750Sstevel@tonic-gate 			    "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u"
15760Sstevel@tonic-gate 			    "%" VAL2STR(BUFSIZ) "[a-h]%n",
15770Sstevel@tonic-gate 			    onmb, &d, snm, &l) == 3 && l == strlen(uname)) {
15780Sstevel@tonic-gate 				len = strlen(uname) + 1 + 1;
15790Sstevel@tonic-gate 				rname = Malloc(len);
15800Sstevel@tonic-gate 				(void) snprintf(rname, len, "/dev/r%s%u%s",
15810Sstevel@tonic-gate 				    onmb, d, snm);
15820Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
1583*1623Stw21770 				*uname_type = LOGICAL_DEVICE;
15840Sstevel@tonic-gate 				return (rname);
15850Sstevel@tonic-gate 			}
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate 			/* /.../dsk/... */
15880Sstevel@tonic-gate 			if ((p = strstr(uname, "/dsk/")) != NULL) {
15890Sstevel@tonic-gate 				mdclrerror(ep);
15900Sstevel@tonic-gate 				++p;
15910Sstevel@tonic-gate 				rname = Malloc(strlen(uname) + 1 + 1);
15920Sstevel@tonic-gate 				(void) strncpy(rname, uname, (p - uname));
15930Sstevel@tonic-gate 				rname[(p - uname)] = 'r';
15940Sstevel@tonic-gate 				(void) strcpy(&rname[(p - uname) + 1], p);
15950Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
1596*1623Stw21770 				*uname_type = LOGICAL_DEVICE;
15970Sstevel@tonic-gate 				return (rname);
15980Sstevel@tonic-gate 			}
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate 			/* /.../rdsk/... */
16010Sstevel@tonic-gate 			else if (strstr(uname, "/rdsk/") != NULL) {
16020Sstevel@tonic-gate 				mdclrerror(ep);
16030Sstevel@tonic-gate 				rname = Strdup(uname);
16040Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
1605*1623Stw21770 				*uname_type = LOGICAL_DEVICE;
16060Sstevel@tonic-gate 				return (rname);
16070Sstevel@tonic-gate 			}
16080Sstevel@tonic-gate 		} else {
16090Sstevel@tonic-gate 			/*
16100Sstevel@tonic-gate 			 * If it's not an absolute name but is a valid ctd name,
16110Sstevel@tonic-gate 			 * guess at /dev/rdsk/...
16120Sstevel@tonic-gate 			 */
16130Sstevel@tonic-gate 			uint_t	s;
16140Sstevel@tonic-gate 			if (parse_ctd(uname, &s) == 0) {
16150Sstevel@tonic-gate 				len = strlen(uname) + strlen("/dev/rdsk/") + 1;
16160Sstevel@tonic-gate 				rname = Malloc(len);
16170Sstevel@tonic-gate 				(void) snprintf(rname, len, "/dev/rdsk/%s",
16180Sstevel@tonic-gate 				    uname);
16190Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
1620*1623Stw21770 				*uname_type = LOGICAL_DEVICE;
16210Sstevel@tonic-gate 				return (rname);
16220Sstevel@tonic-gate 			}
16230Sstevel@tonic-gate 		}
16240Sstevel@tonic-gate 	}
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate 	/* out of luck */
1627*1623Stw21770 	if (!mdiserror(ep, MDE_AMBIGUOUS_DEV))
1628*1623Stw21770 		(void) mderror(ep, MDE_UNIT_NOT_FOUND, uname);
16290Sstevel@tonic-gate 	return (NULL);
16300Sstevel@tonic-gate }
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate /*
16330Sstevel@tonic-gate  * get number of slices for name
16340Sstevel@tonic-gate  */
16350Sstevel@tonic-gate static int
16360Sstevel@tonic-gate getnslice(
16370Sstevel@tonic-gate 	char		*rname,
16380Sstevel@tonic-gate 	char		*dname,
16390Sstevel@tonic-gate 	uint_t		*slicep
16400Sstevel@tonic-gate )
16410Sstevel@tonic-gate {
16420Sstevel@tonic-gate 	char		*srname;
16430Sstevel@tonic-gate 	uint_t		nslice;
16440Sstevel@tonic-gate 	size_t		dl = strlen(dname);
16450Sstevel@tonic-gate 	size_t		rl = strlen(rname);
16460Sstevel@tonic-gate 	size_t		l = 0;
16470Sstevel@tonic-gate 	size_t		len;
16480Sstevel@tonic-gate 
16490Sstevel@tonic-gate 	/*
16500Sstevel@tonic-gate 	 * get our slice number - works only with names that end in s%u -
16510Sstevel@tonic-gate 	 * all others return -1.
16520Sstevel@tonic-gate 	 */
16530Sstevel@tonic-gate 	if (dl >= rl ||
16540Sstevel@tonic-gate 	    sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl ||
16550Sstevel@tonic-gate 	    (int)*slicep < 0) {
16560Sstevel@tonic-gate 		return (-1);
16570Sstevel@tonic-gate 	}
16580Sstevel@tonic-gate 
16590Sstevel@tonic-gate 	/*
16600Sstevel@tonic-gate 	 * go find how many slices there really are
16610Sstevel@tonic-gate 	 */
16620Sstevel@tonic-gate 	len = strlen(dname) + 20 + 1;
16630Sstevel@tonic-gate 	srname = Malloc(len);
16640Sstevel@tonic-gate 	for (nslice = 0; /* void */; ++nslice) {
16650Sstevel@tonic-gate 		struct stat	statbuf;
16660Sstevel@tonic-gate 
16670Sstevel@tonic-gate 		/* build slice name */
16680Sstevel@tonic-gate 		(void) snprintf(srname, len, "%ss%u", dname, nslice);
16690Sstevel@tonic-gate 
16700Sstevel@tonic-gate 		/* see if it's there */
16710Sstevel@tonic-gate 		if ((meta_stat(srname, &statbuf) != 0) ||
16720Sstevel@tonic-gate 		    (! S_ISCHR(statbuf.st_mode))) {
16730Sstevel@tonic-gate 			break;
16740Sstevel@tonic-gate 		}
16750Sstevel@tonic-gate 	}
16760Sstevel@tonic-gate 	Free(srname);
16770Sstevel@tonic-gate 
16780Sstevel@tonic-gate 	/* Need to make sure that we at least have V_NUMPAR */
16790Sstevel@tonic-gate 	nslice = max(nslice, V_NUMPAR);
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate 	/* make sure we have at least our slice */
16820Sstevel@tonic-gate 	if (nslice < *slicep)
16830Sstevel@tonic-gate 		return (-1);
16840Sstevel@tonic-gate 
16850Sstevel@tonic-gate 	/* return number of slices */
16860Sstevel@tonic-gate 	return (nslice);
16870Sstevel@tonic-gate }
16880Sstevel@tonic-gate 
16890Sstevel@tonic-gate /*
16900Sstevel@tonic-gate  * Attempt to parse the input string as a c[t]ds specifier
16910Sstevel@tonic-gate  * The target can either be a SCSI target id or if the device
16920Sstevel@tonic-gate  * is in a fabric configuration in a fibre channel setup then
16930Sstevel@tonic-gate  * the target is a standard WWN (world wide name).
16940Sstevel@tonic-gate  *
16950Sstevel@tonic-gate  * if successful	return 0
16960Sstevel@tonic-gate  * if c[t]dp name	return 1
16970Sstevel@tonic-gate  * otherwise		return -1
16980Sstevel@tonic-gate  */
16990Sstevel@tonic-gate int
17000Sstevel@tonic-gate parse_ctd(
17010Sstevel@tonic-gate 	char	*uname,
17020Sstevel@tonic-gate 	uint_t	*slice)
17030Sstevel@tonic-gate {
17040Sstevel@tonic-gate 	uint_t	channel;
17050Sstevel@tonic-gate 	uint_t	target;
17060Sstevel@tonic-gate 	uint_t	device;
17070Sstevel@tonic-gate 	int	has_target = 1;
17080Sstevel@tonic-gate 	uint_t	cl;
17090Sstevel@tonic-gate 	uint_t	target_str_len;
17100Sstevel@tonic-gate 	char	*partial_ctd_str;
17110Sstevel@tonic-gate 	char	*target_str;
17120Sstevel@tonic-gate 	char	*device_start_pos;
17130Sstevel@tonic-gate 	int	l = -1;
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate 	/* pull off the channel spec and the 't' for the target */
17160Sstevel@tonic-gate 	if (sscanf(uname, "c%ut%n", &channel, &l) != 1 || l == -1) {
17170Sstevel@tonic-gate 		/* check for cds style name */
17180Sstevel@tonic-gate 		if (sscanf(uname, "c%ud%n", &channel, &l) != 1 || l == -1) {
17190Sstevel@tonic-gate 			return (-1);
17200Sstevel@tonic-gate 		} else {
17210Sstevel@tonic-gate 			l--;	/* we want to be on the 'd' */
17220Sstevel@tonic-gate 			has_target = 0;
17230Sstevel@tonic-gate 		}
17240Sstevel@tonic-gate 	}
17250Sstevel@tonic-gate 	partial_ctd_str = uname + l;
17260Sstevel@tonic-gate 
17270Sstevel@tonic-gate 	/* find the beginning of the device specifier */
17280Sstevel@tonic-gate 	device_start_pos = strrchr(partial_ctd_str, 'd');
17290Sstevel@tonic-gate 	if (device_start_pos == NULL) {
17300Sstevel@tonic-gate 		return (-1);
17310Sstevel@tonic-gate 	}
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate 	/* check to see if it is a ctd with a WWN or SCSI target */
17340Sstevel@tonic-gate 	if (has_target) {
17350Sstevel@tonic-gate 		/* pull off the target and see if it is a WWN */
17360Sstevel@tonic-gate 		target_str_len = device_start_pos - partial_ctd_str + 2;
17370Sstevel@tonic-gate 		target_str = (char *)Malloc(target_str_len+1);
17380Sstevel@tonic-gate 		(void) strcpy(target_str, "0X");
17390Sstevel@tonic-gate 		(void) strncpy(target_str+2, partial_ctd_str,
17400Sstevel@tonic-gate 		    target_str_len - 2);
17410Sstevel@tonic-gate 		target_str[target_str_len] = '\0';
17420Sstevel@tonic-gate 		if (sscanf(target_str, "%x%n", &target, &l) != 1 ||
17430Sstevel@tonic-gate 		    l != target_str_len) {
17440Sstevel@tonic-gate 			Free(target_str);
17450Sstevel@tonic-gate 			return (-1);
17460Sstevel@tonic-gate 		}
17470Sstevel@tonic-gate 		Free(target_str);
17480Sstevel@tonic-gate 	}
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate 	/* check the device and slice */
17510Sstevel@tonic-gate 	cl = strlen(device_start_pos);
17520Sstevel@tonic-gate 	if (sscanf(device_start_pos, "d%us%u%n", &device, slice, &l) != 2 ||
17530Sstevel@tonic-gate 			l != cl) {
17540Sstevel@tonic-gate 		/* check the device and partition */
17550Sstevel@tonic-gate 		if (sscanf(device_start_pos, "d%up%u%n", &device, slice, &l)
17560Sstevel@tonic-gate 		    == 2 && l == cl) {
17570Sstevel@tonic-gate 			return (1);
17580Sstevel@tonic-gate 		}
17590Sstevel@tonic-gate 		return (-1);
17600Sstevel@tonic-gate 	}
17610Sstevel@tonic-gate 
17620Sstevel@tonic-gate 	return (0);
17630Sstevel@tonic-gate }
17640Sstevel@tonic-gate 
17650Sstevel@tonic-gate 
17660Sstevel@tonic-gate /*
17670Sstevel@tonic-gate  * get number of slices for name
17680Sstevel@tonic-gate  */
17690Sstevel@tonic-gate static int
17700Sstevel@tonic-gate uname2sliceno(
1771*1623Stw21770 	char			*uname,
1772*1623Stw21770 	meta_device_type_t	uname_type,
1773*1623Stw21770 	uint_t			*slicep,
1774*1623Stw21770 	md_error_t		*ep
17750Sstevel@tonic-gate )
17760Sstevel@tonic-gate {
17770Sstevel@tonic-gate 	uint_t			c = 0, t = 0, d = 0;
17780Sstevel@tonic-gate 	int			l = 0, cl = 0;
17790Sstevel@tonic-gate 	int			fd;
17800Sstevel@tonic-gate 	struct dk_cinfo		cinfo;
17810Sstevel@tonic-gate 	char			*p;
17820Sstevel@tonic-gate 	char			*rname = NULL;
17830Sstevel@tonic-gate 
1784*1623Stw21770 
1785*1623Stw21770 	if (uname_type == META_DEVICE)
17860Sstevel@tonic-gate 		return (*slicep = 0);
17870Sstevel@tonic-gate 
17880Sstevel@tonic-gate 	if ((p = strrchr(uname, '/')) != NULL)
17890Sstevel@tonic-gate 		p++;
17900Sstevel@tonic-gate 	else
17910Sstevel@tonic-gate 		p = uname;
17920Sstevel@tonic-gate 
17930Sstevel@tonic-gate 	cl = strlen(p);
17940Sstevel@tonic-gate 
17950Sstevel@tonic-gate 	if (parse_ctd(p, slicep) == 0)
17960Sstevel@tonic-gate 		return (*slicep);
17970Sstevel@tonic-gate 	else if (sscanf(p, "mc%ut%ud%us%u%n", &c, &t, &d, slicep, &l) == 4 &&
17980Sstevel@tonic-gate 	    l == cl)
17990Sstevel@tonic-gate 		return (*slicep);
18000Sstevel@tonic-gate 	else if (sscanf(p, "d%us%u%n", &d, slicep, &l) == 2 && l == cl)
18010Sstevel@tonic-gate 		return (*slicep);
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate 	/*
18040Sstevel@tonic-gate 	 * If we can't get the slice from the name, then we have to do it the
18050Sstevel@tonic-gate 	 * hard and expensive way.
18060Sstevel@tonic-gate 	 */
18070Sstevel@tonic-gate 	if ((rname = rawname(uname)) == NULL)
18080Sstevel@tonic-gate 		return (-1);
18090Sstevel@tonic-gate 
18100Sstevel@tonic-gate 	/* get controller info */
18110Sstevel@tonic-gate 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
18120Sstevel@tonic-gate 		Free(rname);
18130Sstevel@tonic-gate 		return (-1);
18140Sstevel@tonic-gate 	}
18150Sstevel@tonic-gate 
18160Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &cinfo) != 0) {
18170Sstevel@tonic-gate 		int	save = errno;
18180Sstevel@tonic-gate 
18190Sstevel@tonic-gate 		if (save == ENOTTY)
18200Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname);
18210Sstevel@tonic-gate 		else
18220Sstevel@tonic-gate 			(void) mdsyserror(ep, save, rname);
18230Sstevel@tonic-gate 
18240Sstevel@tonic-gate 		Free(rname);
18250Sstevel@tonic-gate 		(void) close(fd);
18260Sstevel@tonic-gate 		return (-1);
18270Sstevel@tonic-gate 	}
18280Sstevel@tonic-gate 	(void) close(fd);	/* sd/ssd bug */
18290Sstevel@tonic-gate 
18300Sstevel@tonic-gate 	if (cinfo.dki_partition < V_NUMPAR) {
18310Sstevel@tonic-gate 		Free(rname);
18320Sstevel@tonic-gate 		return (*slicep = cinfo.dki_partition);
18330Sstevel@tonic-gate 	}
18340Sstevel@tonic-gate 
18350Sstevel@tonic-gate 	return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname));
18360Sstevel@tonic-gate }
18370Sstevel@tonic-gate 
18380Sstevel@tonic-gate /*
18390Sstevel@tonic-gate  * get partition info
18400Sstevel@tonic-gate  */
18410Sstevel@tonic-gate static int
18420Sstevel@tonic-gate getparts(
1843*1623Stw21770 	mddrivename_t		*dnp,
1844*1623Stw21770 	char			*rname,
1845*1623Stw21770 	char			*dname,
1846*1623Stw21770 	meta_device_type_t	uname_type,
1847*1623Stw21770 	uint_t			*npartsp,
1848*1623Stw21770 	uint_t			*partnop,
1849*1623Stw21770 	md_error_t		*ep
18500Sstevel@tonic-gate )
18510Sstevel@tonic-gate {
18520Sstevel@tonic-gate 	int		nparts;
18530Sstevel@tonic-gate 	uint_t		partno;
18540Sstevel@tonic-gate 	mdname_t	name;
18550Sstevel@tonic-gate 	mdvtoc_t	*vtocp;
18560Sstevel@tonic-gate 
18570Sstevel@tonic-gate 	/* metadevice */
1858*1623Stw21770 	if (uname_type == META_DEVICE) {
18590Sstevel@tonic-gate 		dnp->type = MDT_META;
18600Sstevel@tonic-gate 		nparts = 1;
18610Sstevel@tonic-gate 		partno = 0;
18620Sstevel@tonic-gate 		goto gotit;
18630Sstevel@tonic-gate 	}
18640Sstevel@tonic-gate 
18650Sstevel@tonic-gate 	/* see how many partitions in drive, this is really tricky */
18660Sstevel@tonic-gate 	metainitname(&name);
18670Sstevel@tonic-gate 	name.rname = rname;
18680Sstevel@tonic-gate 	name.drivenamep = dnp;
18690Sstevel@tonic-gate 	if ((vtocp = metagetvtoc(&name, TRUE, &partno, ep)) != NULL) {
18700Sstevel@tonic-gate 		dnp->type = MDT_COMP;
18710Sstevel@tonic-gate 		nparts = vtocp->nparts;
18720Sstevel@tonic-gate 		/* partno already setup */
18730Sstevel@tonic-gate 		/* dname already setup */
18740Sstevel@tonic-gate 		goto gotit;
18750Sstevel@tonic-gate 	}
18760Sstevel@tonic-gate 
18770Sstevel@tonic-gate 	if ((ep->info.errclass == MDEC_DEV) &&
18780Sstevel@tonic-gate 	    (ep->info.md_error_info_t_u.dev_error.errnum == MDE_TOO_MANY_PARTS))
18790Sstevel@tonic-gate 		return (-1);
18800Sstevel@tonic-gate 
18810Sstevel@tonic-gate 	/* fallback and try and guess (used to check for just EACCES here) */
18820Sstevel@tonic-gate 	if ((dname != NULL) &&
18830Sstevel@tonic-gate 	    ((nparts = getnslice(rname, dname, &partno)) > 0)) {
18840Sstevel@tonic-gate 		dnp->type = MDT_ACCES;
18850Sstevel@tonic-gate 		if (mdanysyserror(ep)) {
18860Sstevel@tonic-gate 			dnp->errnum =
18870Sstevel@tonic-gate 			    ep->info.md_error_info_t_u.sys_error.errnum;
18880Sstevel@tonic-gate 		} else {
18890Sstevel@tonic-gate 			dnp->errnum = ENOENT;
18900Sstevel@tonic-gate 		}
18910Sstevel@tonic-gate 		mdclrerror(ep);
18920Sstevel@tonic-gate 		/* nparts already setup */
18930Sstevel@tonic-gate 		/* partno already setup */
18940Sstevel@tonic-gate 		/* dname already setup */
18950Sstevel@tonic-gate 		nparts = roundup(nparts, V_NUMPAR);
18960Sstevel@tonic-gate 		goto gotit;
18970Sstevel@tonic-gate 	}
18980Sstevel@tonic-gate 
18990Sstevel@tonic-gate 	/* nothing worked */
19000Sstevel@tonic-gate 	dnp->type = MDT_UNKNOWN;
19010Sstevel@tonic-gate 	if (mdissyserror(ep, EACCES))
19020Sstevel@tonic-gate 		dnp->type = MDT_ACCES;
19030Sstevel@tonic-gate 
19040Sstevel@tonic-gate 	if (mdanysyserror(ep)) {
19050Sstevel@tonic-gate 		dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum;
19060Sstevel@tonic-gate 	} else {
19070Sstevel@tonic-gate 		dnp->errnum = ENOENT;
19080Sstevel@tonic-gate 	}
19090Sstevel@tonic-gate 
19100Sstevel@tonic-gate 	mdclrerror(ep);
19110Sstevel@tonic-gate 	nparts = V_NUMPAR;
1912*1623Stw21770 	if (uname2sliceno(rname, uname_type, &partno, ep) < 0) {
19130Sstevel@tonic-gate 		mdclrerror(ep);
19140Sstevel@tonic-gate 		partno = 0;
19150Sstevel@tonic-gate 	}
19160Sstevel@tonic-gate 
19170Sstevel@tonic-gate 	/* return success */
19180Sstevel@tonic-gate gotit:
19190Sstevel@tonic-gate 	assert(nparts > 0);
19200Sstevel@tonic-gate 
19210Sstevel@tonic-gate 	if (partno >= nparts)
19220Sstevel@tonic-gate 		return (mdsyserror(ep, ENOENT, rname));
19230Sstevel@tonic-gate 
19240Sstevel@tonic-gate 	*npartsp = nparts;
19250Sstevel@tonic-gate 	*partnop = partno;
19260Sstevel@tonic-gate 	return (0);
19270Sstevel@tonic-gate }
19280Sstevel@tonic-gate 
19290Sstevel@tonic-gate /*
19300Sstevel@tonic-gate  * get block name
19310Sstevel@tonic-gate  */
19320Sstevel@tonic-gate static int
19330Sstevel@tonic-gate getbname(
19340Sstevel@tonic-gate 	mdname_t	*np,
19350Sstevel@tonic-gate 	md_error_t	*ep
19360Sstevel@tonic-gate )
19370Sstevel@tonic-gate {
19380Sstevel@tonic-gate 	char		*rname = np->rname;
19390Sstevel@tonic-gate 	char		*bname;
19400Sstevel@tonic-gate 
19410Sstevel@tonic-gate 	/* fully qualified */
19420Sstevel@tonic-gate 	assert(rname != NULL);
19430Sstevel@tonic-gate 	if ((bname = blkname(rname)) != NULL) {
19440Sstevel@tonic-gate 		if (np->bname)
19450Sstevel@tonic-gate 			Free(np->bname);
19460Sstevel@tonic-gate 		np->bname = bname;
19470Sstevel@tonic-gate 		return (0);
19480Sstevel@tonic-gate 	}
19490Sstevel@tonic-gate 
19500Sstevel@tonic-gate 	/* out of luck */
19510Sstevel@tonic-gate 	return (mdsyserror(ep, ENOENT, rname));
19520Sstevel@tonic-gate }
19530Sstevel@tonic-gate 
19540Sstevel@tonic-gate static void
19550Sstevel@tonic-gate getcname(
19560Sstevel@tonic-gate 	mdsetname_t	*sp,
19570Sstevel@tonic-gate 	mdname_t	*np
19580Sstevel@tonic-gate )
19590Sstevel@tonic-gate {
19600Sstevel@tonic-gate 	char		*sname = sp->setname;
19610Sstevel@tonic-gate 	char		*bname = np->bname;
19620Sstevel@tonic-gate 	char		*p;
19630Sstevel@tonic-gate 	size_t		len;
19640Sstevel@tonic-gate 
19650Sstevel@tonic-gate 	assert(sname != NULL);
19660Sstevel@tonic-gate 	assert(bname != NULL);
19670Sstevel@tonic-gate 	assert(np->drivenamep->type != MDT_FAST_COMP &&
19680Sstevel@tonic-gate 	    np->drivenamep->type != MDT_FAST_META);
19690Sstevel@tonic-gate 
19700Sstevel@tonic-gate 	/* regular device */
19710Sstevel@tonic-gate 	if ((strncmp(bname, "/dev/dsk/", strlen("/dev/dsk/")) == 0) &&
19720Sstevel@tonic-gate 	    (strchr((p = bname + strlen("/dev/dsk/")), '/') == NULL)) {
19730Sstevel@tonic-gate 		if (np->cname)
19740Sstevel@tonic-gate 			Free(np->cname);
19750Sstevel@tonic-gate 		np->cname = Strdup(p);
19760Sstevel@tonic-gate 		return;
19770Sstevel@tonic-gate 	}
19780Sstevel@tonic-gate 
19790Sstevel@tonic-gate 	if ((strncmp(bname, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) &&
19800Sstevel@tonic-gate 	    (strchr((p = bname + strlen("/dev/ap/dsk/")), '/') == NULL)) {
19810Sstevel@tonic-gate 		if (np->cname)
19820Sstevel@tonic-gate 			Free(np->cname);
19830Sstevel@tonic-gate 		np->cname = Strdup(p);
19840Sstevel@tonic-gate 		return;
19850Sstevel@tonic-gate 	}
19860Sstevel@tonic-gate 
19870Sstevel@tonic-gate 	if ((strncmp(bname, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) &&
19880Sstevel@tonic-gate 	    (strchr((p = bname + strlen("/dev/did/dsk/")), '/') == NULL)) {
19890Sstevel@tonic-gate 		if (np->cname)
19900Sstevel@tonic-gate 			Free(np->cname);
19910Sstevel@tonic-gate 		np->cname = Strdup(p);
19920Sstevel@tonic-gate 		return;
19930Sstevel@tonic-gate 	}
19940Sstevel@tonic-gate 
19950Sstevel@tonic-gate 	/* anything else but metadevice */
19960Sstevel@tonic-gate 	if (np->drivenamep->type != MDT_META) {
19970Sstevel@tonic-gate 		if (np->cname)
19980Sstevel@tonic-gate 			Free(np->cname);
19990Sstevel@tonic-gate 		np->cname = Strdup(bname);
20000Sstevel@tonic-gate 		return;
20010Sstevel@tonic-gate 	}
20020Sstevel@tonic-gate 
20030Sstevel@tonic-gate 	/* metadevice */
20040Sstevel@tonic-gate 	p = strrchr(bname, '/');
20050Sstevel@tonic-gate 	assert(p != NULL);
20060Sstevel@tonic-gate 	++p;
20070Sstevel@tonic-gate 	if (metaislocalset(sp)) {
20080Sstevel@tonic-gate 		if (np->cname)
20090Sstevel@tonic-gate 			Free(np->cname);
20100Sstevel@tonic-gate 		np->cname = Strdup(p);
20110Sstevel@tonic-gate 	} else {
20120Sstevel@tonic-gate 		assert(sname[0] != '\0');
20130Sstevel@tonic-gate 		if (np->cname)
20140Sstevel@tonic-gate 			Free(np->cname);
20150Sstevel@tonic-gate 		len = strlen(sname) + 1 + strlen(p) + 1;
20160Sstevel@tonic-gate 		np->cname = Malloc(len);
20170Sstevel@tonic-gate 		(void) snprintf(np->cname, len, "%s/%s", sname, p);
20180Sstevel@tonic-gate 	}
20190Sstevel@tonic-gate }
20200Sstevel@tonic-gate 
20210Sstevel@tonic-gate /*
20220Sstevel@tonic-gate  * get dev
20230Sstevel@tonic-gate  */
20240Sstevel@tonic-gate int
20250Sstevel@tonic-gate meta_getdev(
20260Sstevel@tonic-gate 	mdsetname_t	*sp,
20270Sstevel@tonic-gate 	mdname_t	*np,
20280Sstevel@tonic-gate 	md_error_t	*ep
20290Sstevel@tonic-gate )
20300Sstevel@tonic-gate {
20310Sstevel@tonic-gate 	struct stat	statbuf;
20320Sstevel@tonic-gate 
20330Sstevel@tonic-gate 	/* get dev */
20340Sstevel@tonic-gate 	if (meta_stat(np->rname, &statbuf) != 0)
20350Sstevel@tonic-gate 		return (mdsyserror(ep, errno, np->rname));
20360Sstevel@tonic-gate 	else if (! S_ISCHR(statbuf.st_mode))
20370Sstevel@tonic-gate 		return (mddeverror(ep, MDE_NOT_DISK, NODEV64, np->rname));
20380Sstevel@tonic-gate 	np->dev = meta_expldev(statbuf.st_rdev);
20390Sstevel@tonic-gate 
20400Sstevel@tonic-gate 	assert(np->drivenamep->type != MDT_FAST_META &&
20410Sstevel@tonic-gate 	    np->drivenamep->type != MDT_FAST_COMP);
20420Sstevel@tonic-gate 
20430Sstevel@tonic-gate 	/* check set */
20440Sstevel@tonic-gate 	assert((np->drivenamep->type == MDT_META) ?
20450Sstevel@tonic-gate 	    (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1);
20460Sstevel@tonic-gate 
20470Sstevel@tonic-gate 	/* return sucess */
20480Sstevel@tonic-gate 	return (0);
20490Sstevel@tonic-gate }
20500Sstevel@tonic-gate 
20510Sstevel@tonic-gate /*
20520Sstevel@tonic-gate  * set up names for a slice
20530Sstevel@tonic-gate  */
20540Sstevel@tonic-gate static int
20550Sstevel@tonic-gate getnames(
20560Sstevel@tonic-gate 	mdsetname_t	*sp,
20570Sstevel@tonic-gate 	mdname_t	*np,
20580Sstevel@tonic-gate 	char		*rname,
20590Sstevel@tonic-gate 	md_error_t	*ep
20600Sstevel@tonic-gate )
20610Sstevel@tonic-gate {
20620Sstevel@tonic-gate 	/* get names */
20630Sstevel@tonic-gate 	if (np->rname)
20640Sstevel@tonic-gate 		Free(np->rname);
20650Sstevel@tonic-gate 	np->rname = Strdup(rname);
20660Sstevel@tonic-gate 	if (getbname(np, ep) != 0)
20670Sstevel@tonic-gate 		return (-1);
20680Sstevel@tonic-gate 	getcname(sp, np);
20690Sstevel@tonic-gate 	if (meta_getdev(sp, np, ep) != 0)
20700Sstevel@tonic-gate 		return (-1);
20710Sstevel@tonic-gate 
20720Sstevel@tonic-gate 	/* return success */
20730Sstevel@tonic-gate 	return (0);
20740Sstevel@tonic-gate }
20750Sstevel@tonic-gate 
20760Sstevel@tonic-gate /*
20770Sstevel@tonic-gate  * fake up names for a slice
20780Sstevel@tonic-gate  */
20790Sstevel@tonic-gate static void
20800Sstevel@tonic-gate getfakenames(
20810Sstevel@tonic-gate 	mdsetname_t	*sp,
20820Sstevel@tonic-gate 	mdname_t	*np,
20830Sstevel@tonic-gate 	char		*rname
20840Sstevel@tonic-gate )
20850Sstevel@tonic-gate {
20860Sstevel@tonic-gate 	char		*p;
20870Sstevel@tonic-gate 	char		onmb[BUFSIZ+1], snm[BUFSIZ+1];
20880Sstevel@tonic-gate 	uint_t		d = 0;
20890Sstevel@tonic-gate 	int		l = 0;
20900Sstevel@tonic-gate 
20910Sstevel@tonic-gate 	/* fake names */
20920Sstevel@tonic-gate 	if (np->rname != NULL)
20930Sstevel@tonic-gate 		Free(np->rname);
20940Sstevel@tonic-gate 	np->rname = Strdup(rname);
20950Sstevel@tonic-gate 
20960Sstevel@tonic-gate 	if (np->bname != NULL)
20970Sstevel@tonic-gate 		Free(np->bname);
20980Sstevel@tonic-gate 	np->bname = Strdup(rname);
20990Sstevel@tonic-gate 
21000Sstevel@tonic-gate 	/*
21010Sstevel@tonic-gate 	 * Fixup old style names
21020Sstevel@tonic-gate 	 */
21030Sstevel@tonic-gate 	if (sscanf(rname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
21040Sstevel@tonic-gate 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
21050Sstevel@tonic-gate 	    onmb, &d, snm, &l) == 3 && l == strlen(rname))
21060Sstevel@tonic-gate 		(void) snprintf(np->bname, l, "/dev/%s%u%s", onmb, d, snm);
21070Sstevel@tonic-gate 
21080Sstevel@tonic-gate 	/*
21090Sstevel@tonic-gate 	 * Fixup new style names
21100Sstevel@tonic-gate 	 */
21110Sstevel@tonic-gate 	if ((p = strstr(np->bname, "/rdsk/")) != NULL) {
21120Sstevel@tonic-gate 		for (++p; (*(p + 1) != '\0'); ++p)
21130Sstevel@tonic-gate 			*p = *(p + 1);
21140Sstevel@tonic-gate 		*p = '\0';
21150Sstevel@tonic-gate 	}
21160Sstevel@tonic-gate 
21170Sstevel@tonic-gate 	if (np->cname != NULL)
21180Sstevel@tonic-gate 		Free(np->cname);
21190Sstevel@tonic-gate 	getcname(sp, np);
21200Sstevel@tonic-gate }
21210Sstevel@tonic-gate 
21220Sstevel@tonic-gate static mdname_t *
21230Sstevel@tonic-gate setup_slice(
2124*1623Stw21770 	mdsetname_t		*sp,
2125*1623Stw21770 	meta_device_type_t	uname_type,
2126*1623Stw21770 	mddrivename_t		*dnp,
2127*1623Stw21770 	char			*uname,
2128*1623Stw21770 	char			*rname,
2129*1623Stw21770 	char			*dname,
2130*1623Stw21770 	uint_t			partno,
2131*1623Stw21770 	md_error_t		*ep
21320Sstevel@tonic-gate )
21330Sstevel@tonic-gate {
2134*1623Stw21770 	char			*srname = NULL;
2135*1623Stw21770 	mdname_t		*np;
21360Sstevel@tonic-gate 
21370Sstevel@tonic-gate 	/* must have a set */
21380Sstevel@tonic-gate 	assert(sp != NULL);
21390Sstevel@tonic-gate 	assert(partno < dnp->parts.parts_len);
21400Sstevel@tonic-gate 	assert(dname != NULL);
21410Sstevel@tonic-gate 
21420Sstevel@tonic-gate 	np = &dnp->parts.parts_val[partno];
21430Sstevel@tonic-gate 
21440Sstevel@tonic-gate 	if (rname)
21450Sstevel@tonic-gate 		srname = rname;
2146*1623Stw21770 	else if (uname_type == META_DEVICE)
21470Sstevel@tonic-gate 		srname = dname;
21480Sstevel@tonic-gate 	else {
21490Sstevel@tonic-gate 		char	onmb[BUFSIZ+1];
21500Sstevel@tonic-gate 		uint_t	d = 0;
21510Sstevel@tonic-gate 		int	l = 0, cl = strlen(dname);
21520Sstevel@tonic-gate 		size_t	len;
21530Sstevel@tonic-gate 
21540Sstevel@tonic-gate 		len = cl + 20 + 1;
21550Sstevel@tonic-gate 		srname = Malloc(len);
21560Sstevel@tonic-gate 
21570Sstevel@tonic-gate 		/*
21580Sstevel@tonic-gate 		 * Handle /dev/rXXNN.
21590Sstevel@tonic-gate 		 */
21600Sstevel@tonic-gate 		if (sscanf(dname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%n",
21610Sstevel@tonic-gate 		    onmb, &d, &l) == 2 && l == cl) {
21620Sstevel@tonic-gate 			(void) snprintf(srname, len, "/dev/r%s%u%c", onmb, d,
21630Sstevel@tonic-gate 			    'a' + partno);
21640Sstevel@tonic-gate 		} else if (sscanf(dname, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%n",
21650Sstevel@tonic-gate 		    onmb, &d, &l) == 2 && l == cl) {
21660Sstevel@tonic-gate 			    (void) snprintf(srname, len, "/dev/%s%u%c", onmb, d,
21670Sstevel@tonic-gate 				'a' + partno);
21680Sstevel@tonic-gate 		} else {
21690Sstevel@tonic-gate 			/* build the slice that is wanted */
21700Sstevel@tonic-gate 			(void) snprintf(srname, len, "%ss%u", dname, partno);
21710Sstevel@tonic-gate 		}
21720Sstevel@tonic-gate 	}
21730Sstevel@tonic-gate 
21740Sstevel@tonic-gate 	if (getnames(sp, np, srname, ep) != 0) {
21750Sstevel@tonic-gate 		if (dnp->type == MDT_UNKNOWN) {
21760Sstevel@tonic-gate 			mdclrerror(ep);
21770Sstevel@tonic-gate 			getfakenames(sp, np, srname);
21780Sstevel@tonic-gate 		} else if (dnp->type == MDT_COMP && mdissyserror(ep, ENOENT)) {
21790Sstevel@tonic-gate 			dnp->type = MDT_UNKNOWN;
21800Sstevel@tonic-gate 			if (mdanysyserror(ep)) {
21810Sstevel@tonic-gate 				dnp->errnum =
21820Sstevel@tonic-gate 				    ep->info.md_error_info_t_u.sys_error.errnum;
21830Sstevel@tonic-gate 			} else {
21840Sstevel@tonic-gate 				dnp->errnum = ENOENT;
21850Sstevel@tonic-gate 			}
21860Sstevel@tonic-gate 			mdclrerror(ep);
21870Sstevel@tonic-gate 			getfakenames(sp, np, srname);
21880Sstevel@tonic-gate 		} else {
21890Sstevel@tonic-gate 			mdclrerror(ep);
21900Sstevel@tonic-gate 			if (getnames(sp, np, dname, ep) != 0) {
21910Sstevel@tonic-gate 				np = NULL;
21920Sstevel@tonic-gate 				goto fixup;
21930Sstevel@tonic-gate 			}
21940Sstevel@tonic-gate 		}
21950Sstevel@tonic-gate 	}
21960Sstevel@tonic-gate 
21970Sstevel@tonic-gate out:
21980Sstevel@tonic-gate 	if ((srname != rname) && (srname != dname))
21990Sstevel@tonic-gate 		Free(srname);
22000Sstevel@tonic-gate 
22010Sstevel@tonic-gate 	/* return name */
22020Sstevel@tonic-gate 	return (np);
22030Sstevel@tonic-gate 
22040Sstevel@tonic-gate fixup:
22050Sstevel@tonic-gate 	if (mdanysyserror(ep)) {
22060Sstevel@tonic-gate 		char	*p;
22070Sstevel@tonic-gate 		int	errnum = ep->info.md_error_info_t_u.sys_error.errnum;
22080Sstevel@tonic-gate 
22090Sstevel@tonic-gate 		mdclrerror(ep);
22100Sstevel@tonic-gate 		if (uname && *uname) {
22110Sstevel@tonic-gate 			if ((p = strrchr(uname, '/')) != NULL)
22120Sstevel@tonic-gate 				(void) mdsyserror(ep, errnum, ++p);
22130Sstevel@tonic-gate 			else
22140Sstevel@tonic-gate 				(void) mdsyserror(ep, errnum, uname);
22150Sstevel@tonic-gate 		} else {
22160Sstevel@tonic-gate 			if ((p = strrchr(srname, '/')) != NULL)
22170Sstevel@tonic-gate 				(void) mdsyserror(ep, errnum, ++p);
22180Sstevel@tonic-gate 			else
22190Sstevel@tonic-gate 				(void) mdsyserror(ep, errnum, srname);
22200Sstevel@tonic-gate 		}
22210Sstevel@tonic-gate 	}
22220Sstevel@tonic-gate 	goto out;
22230Sstevel@tonic-gate }
22240Sstevel@tonic-gate 
22250Sstevel@tonic-gate /*
22260Sstevel@tonic-gate  * flush the fast name cache
22270Sstevel@tonic-gate  */
22280Sstevel@tonic-gate static void
22290Sstevel@tonic-gate metafreefastnm(mdname_t **np)
22300Sstevel@tonic-gate {
22310Sstevel@tonic-gate 	mddrivename_t	*dnp;
22320Sstevel@tonic-gate 
22330Sstevel@tonic-gate 	assert(np != NULL && *np != NULL);
22340Sstevel@tonic-gate 
22350Sstevel@tonic-gate 	if ((dnp = (*np)->drivenamep) != NULL) {
22360Sstevel@tonic-gate 		if (dnp->cname != NULL)
22370Sstevel@tonic-gate 			Free(dnp->cname);
22380Sstevel@tonic-gate 		if (dnp->rname != NULL)
22390Sstevel@tonic-gate 			Free(dnp->rname);
22400Sstevel@tonic-gate 		if (dnp->miscname != NULL)
22410Sstevel@tonic-gate 			Free(dnp->miscname);
22420Sstevel@tonic-gate 		meta_free_unit(dnp);
22430Sstevel@tonic-gate 		Free(dnp);
22440Sstevel@tonic-gate 	}
22450Sstevel@tonic-gate 	if ((*np)->cname != NULL)
22460Sstevel@tonic-gate 		Free((*np)->cname);
22470Sstevel@tonic-gate 	if ((*np)->bname != NULL)
22480Sstevel@tonic-gate 		Free((*np)->bname);
22490Sstevel@tonic-gate 	if ((*np)->rname != NULL)
22500Sstevel@tonic-gate 		Free((*np)->rname);
22510Sstevel@tonic-gate 	if ((*np)->devicesname != NULL)
22520Sstevel@tonic-gate 		Free((*np)->devicesname);
22530Sstevel@tonic-gate 	Free(*np);
22540Sstevel@tonic-gate 	*np = NULL;
22550Sstevel@tonic-gate }
22560Sstevel@tonic-gate 
22570Sstevel@tonic-gate /*
22580Sstevel@tonic-gate  * flush the fast name cache
22590Sstevel@tonic-gate  */
22600Sstevel@tonic-gate static void
22610Sstevel@tonic-gate metaflushfastnames()
22620Sstevel@tonic-gate {
22630Sstevel@tonic-gate 	mdnamelist_t	*p, *n;
22640Sstevel@tonic-gate 
22650Sstevel@tonic-gate 	for (p = fastnmlp, n = NULL; (p != NULL); p = n) {
22660Sstevel@tonic-gate 		n = p->next;
22670Sstevel@tonic-gate 		metafreefastnm(&p->namep);
22680Sstevel@tonic-gate 		Free(p);
22690Sstevel@tonic-gate 	}
22700Sstevel@tonic-gate 	fastnmlp = NULL;
22710Sstevel@tonic-gate }
22720Sstevel@tonic-gate static char *
2273*1623Stw21770 getrname_fast(char *unm, meta_device_type_t uname_type, md_error_t *ep)
22740Sstevel@tonic-gate {
22750Sstevel@tonic-gate 	uint_t			d = 0;
22760Sstevel@tonic-gate 	int			l = 0;
22770Sstevel@tonic-gate 	int			cl = strlen(unm);
22780Sstevel@tonic-gate 	char			onmb[BUFSIZ+1], snm[BUFSIZ+1], cnmb[BUFSIZ];
22790Sstevel@tonic-gate 	char			*rnm;
22800Sstevel@tonic-gate 	char			*p;
22810Sstevel@tonic-gate 	size_t			len;
22820Sstevel@tonic-gate 
2283*1623Stw21770 	if (uname_type == META_DEVICE) {
2284*1623Stw21770 		/* fully qualified  - local set */
2285*1623Stw21770 		if (((sscanf(unm, "/dev/md/dsk/%" VAL2STR(BUFSIZ) "s%n",
2286*1623Stw21770 				onmb, &len) == 1) && (cl == len)) ||
2287*1623Stw21770 		    ((sscanf(unm, "/dev/md/rdsk/%" VAL2STR(BUFSIZ) "s%n",
2288*1623Stw21770 				onmb, &len) == 1) && (cl == len))) {
2289*1623Stw21770 			len = strlen("/dev/md/rdsk/") +	strlen(onmb) + 1;
2290*1623Stw21770 			rnm = Zalloc(len);
2291*1623Stw21770 			(void) snprintf(rnm, len, "/dev/md/rdsk/%s", onmb);
2292*1623Stw21770 			return (rnm);
2293*1623Stw21770 		}
2294*1623Stw21770 
2295*1623Stw21770 		/* fully qualified - setname specified */
2296*1623Stw21770 		if (((sscanf(unm, "/dev/md/%[^/]/dsk/%"
2297*1623Stw21770 				VAL2STR(BUFSIZ) "s%n",
2298*1623Stw21770 				snm, onmb, &len) == 2) && (cl == len)) ||
2299*1623Stw21770 		    ((sscanf(unm, "/dev/md/%[^/]/rdsk/%"
2300*1623Stw21770 				VAL2STR(BUFSIZ) "s%n",
2301*1623Stw21770 				snm, onmb, &len) == 2) && (cl == len))) {
2302*1623Stw21770 
2303*1623Stw21770 			len = strlen("/dev/md//rdsk/") + strlen(snm) +
2304*1623Stw21770 				strlen(onmb) + 1;
2305*1623Stw21770 			rnm = Zalloc(len);
2306*1623Stw21770 			(void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s",
2307*1623Stw21770 			    snm, onmb);
23080Sstevel@tonic-gate 			return (rnm);
23090Sstevel@tonic-gate 		}
23100Sstevel@tonic-gate 
2311*1623Stw21770 		/* Fully qualified path - error */
2312*1623Stw21770 		if (unm[0] == '/') {
2313*1623Stw21770 			(void) mdsyserror(ep, EINVAL, unm);
2314*1623Stw21770 			return (NULL);
2315*1623Stw21770 		}
2316*1623Stw21770 
2317*1623Stw21770 		/* setname specified <setname>/<metadev> */
2318*1623Stw21770 		if (((sscanf(unm, "%[^/]/%" VAL2STR(BUFSIZ) "s%n",
2319*1623Stw21770 				snm, onmb, &len) == 2) && (cl == len))) {
2320*1623Stw21770 			/* Not <setname>/<metadev>  - error */
2321*1623Stw21770 			if (strchr(onmb, '/') != NULL) {
2322*1623Stw21770 				(void) mdsyserror(ep, EINVAL, unm);
2323*1623Stw21770 				return (NULL);
2324*1623Stw21770 			}
2325*1623Stw21770 
2326*1623Stw21770 			len = strlen("/dev/md//rdsk/") + strlen(snm) +
2327*1623Stw21770 				strlen(onmb) + 1;
2328*1623Stw21770 			rnm = Zalloc(len);
2329*1623Stw21770 			(void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s",
2330*1623Stw21770 			    snm, onmb);
23310Sstevel@tonic-gate 			return (rnm);
23320Sstevel@tonic-gate 		}
23330Sstevel@tonic-gate 
2334*1623Stw21770 		/* Must be simple metaname/hsp pool name */
2335*1623Stw21770 		len = strlen("/dev/md/rdsk/") + strlen(unm) + 1;
2336*1623Stw21770 		rnm = Zalloc(len);
2337*1623Stw21770 		(void) snprintf(rnm, len, "/dev/md/rdsk/%s", unm);
2338*1623Stw21770 		return (rnm);
23390Sstevel@tonic-gate 	}
23400Sstevel@tonic-gate 
23410Sstevel@tonic-gate 	/* NOT Fully qualified path, done */
23420Sstevel@tonic-gate 	if (unm[0] != '/') {
23430Sstevel@tonic-gate 		(void) mdsyserror(ep, EINVAL, unm);
23440Sstevel@tonic-gate 		return (NULL);
23450Sstevel@tonic-gate 	}
23460Sstevel@tonic-gate 
23470Sstevel@tonic-gate 	/*
23480Sstevel@tonic-gate 	 * Get slice information from old style names of the form
23490Sstevel@tonic-gate 	 * /dev/rXXNN[a-h] or /dev/XXNN[a-h], must be done before regular
23500Sstevel@tonic-gate 	 * devices, but after metadevices.
23510Sstevel@tonic-gate 	 */
23520Sstevel@tonic-gate 	if ((sscanf(unm, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
23530Sstevel@tonic-gate 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
23540Sstevel@tonic-gate 	    onmb, &d, snm, &l) == 3 ||
23550Sstevel@tonic-gate 	    sscanf(unm, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u"
23560Sstevel@tonic-gate 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
23570Sstevel@tonic-gate 	    onmb, &d, snm, &l) == 3) && l == cl) {
23580Sstevel@tonic-gate 		if ((p = strchr("abcdefgh", snm[0])) != NULL) {
23590Sstevel@tonic-gate 			(void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u%s",
23600Sstevel@tonic-gate 			    onmb, d, snm);
23610Sstevel@tonic-gate 			return (Strdup(cnmb));
23620Sstevel@tonic-gate 		}
23630Sstevel@tonic-gate 	}
23640Sstevel@tonic-gate 
23650Sstevel@tonic-gate 	if ((p = strstr(unm, "/dsk/")) != NULL) {	/* /.../dsk/... */
23660Sstevel@tonic-gate 		++p;
23670Sstevel@tonic-gate 		rnm = Zalloc(strlen(unm) + 1 + 1);
23680Sstevel@tonic-gate 		(void) strncpy(rnm, unm, (p - unm));
23690Sstevel@tonic-gate 		rnm[(p - unm)] = 'r';
23700Sstevel@tonic-gate 		(void) strcpy(&rnm[(p - unm) + 1], p);
23710Sstevel@tonic-gate 		return (rnm);
23720Sstevel@tonic-gate 	} else if (strstr(unm, "/rdsk/") != NULL) {	/* /.../rdsk/... */
23730Sstevel@tonic-gate 		return (Strdup(unm));
23740Sstevel@tonic-gate 	}
23750Sstevel@tonic-gate 
23760Sstevel@tonic-gate 	/*
23770Sstevel@tonic-gate 	 * Shouldn't get here but if we do then we have an unrecognized
23780Sstevel@tonic-gate 	 * fully qualified path - error
23790Sstevel@tonic-gate 	 */
23800Sstevel@tonic-gate 	(void) mdsyserror(ep, EINVAL, unm);
23810Sstevel@tonic-gate 	return (NULL);
23820Sstevel@tonic-gate }
23830Sstevel@tonic-gate 
23840Sstevel@tonic-gate static mdname_t *
23850Sstevel@tonic-gate metainitfastname(
2386*1623Stw21770 	mdsetname_t		*sp,
2387*1623Stw21770 	char			*uname,
2388*1623Stw21770 	meta_device_type_t	uname_type,
2389*1623Stw21770 	md_error_t		*ep
23900Sstevel@tonic-gate )
23910Sstevel@tonic-gate {
23920Sstevel@tonic-gate 	uint_t			c = 0, t = 0, d = 0, s = 0;
23930Sstevel@tonic-gate 	int			l = 0;
23940Sstevel@tonic-gate 	mddrivename_t		*dnp;
23950Sstevel@tonic-gate 	mdname_t		*np;
23960Sstevel@tonic-gate 	mdnamelist_t		**fnlpp;
2397*1623Stw21770 	char			*cname;
23980Sstevel@tonic-gate 
23990Sstevel@tonic-gate 	for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) {
24000Sstevel@tonic-gate 		np = (*fnlpp)->namep;
24010Sstevel@tonic-gate 
24020Sstevel@tonic-gate 		if (strcmp(np->bname, uname) == 0)
24030Sstevel@tonic-gate 			return (np);
24040Sstevel@tonic-gate 	}
24050Sstevel@tonic-gate 
24060Sstevel@tonic-gate 	*fnlpp = Zalloc(sizeof (**fnlpp));
24070Sstevel@tonic-gate 	np = (*fnlpp)->namep = Zalloc(sizeof (mdname_t));
24080Sstevel@tonic-gate 	metainitname(np);
24090Sstevel@tonic-gate 	dnp = np->drivenamep = Zalloc(sizeof (mddrivename_t));
24100Sstevel@tonic-gate 	metainitdrivename(dnp);
24110Sstevel@tonic-gate 
24120Sstevel@tonic-gate 
24130Sstevel@tonic-gate 	/* Metadevices */
2414*1623Stw21770 	if (uname_type == META_DEVICE &&
2415*1623Stw21770 	    (cname = meta_canonicalize(sp, uname)) != NULL) {
2416*1623Stw21770 
2417*1623Stw21770 		np->cname = cname;
24180Sstevel@tonic-gate 		dnp->type = MDT_FAST_META;
24190Sstevel@tonic-gate 		goto done;
24200Sstevel@tonic-gate 	}
24210Sstevel@tonic-gate 
24220Sstevel@tonic-gate 	/* Others */
24230Sstevel@tonic-gate 	dnp->type = MDT_FAST_COMP;
24240Sstevel@tonic-gate 
24250Sstevel@tonic-gate 	if (((sscanf(uname, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d,
24260Sstevel@tonic-gate 		&s, &l) == 4 ||
24270Sstevel@tonic-gate 	    sscanf(uname, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d,
24280Sstevel@tonic-gate 		&s, &l) == 4 ||
24290Sstevel@tonic-gate 	    sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c, &t, &d,
24300Sstevel@tonic-gate 		&s, &l) == 4 ||
24310Sstevel@tonic-gate 	    sscanf(uname, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c, &t, &d,
24320Sstevel@tonic-gate 		&s, &l) == 4 ||
24330Sstevel@tonic-gate 	    sscanf(uname, "/dev/did/rdsk/d%us%u%n", &t, &s, &l) == 2 ||
24340Sstevel@tonic-gate 	    sscanf(uname, "/dev/did/dsk/d%us%u%n", &t, &s, &l) == 2||
24350Sstevel@tonic-gate 	    sscanf(uname, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
24360Sstevel@tonic-gate 	    sscanf(uname, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
24370Sstevel@tonic-gate 	    sscanf(uname, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
24380Sstevel@tonic-gate 	    sscanf(uname, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
24390Sstevel@tonic-gate 	    sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
24400Sstevel@tonic-gate 	    sscanf(uname, "/dev/ap/dsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
24410Sstevel@tonic-gate 	    sscanf(uname, "/dev/did/rdsk/d%u%n", &t, &l) == 1 ||
24420Sstevel@tonic-gate 	    sscanf(uname, "/dev/did/dsk/d%u%n", &t, &l) == 1 ||
24430Sstevel@tonic-gate 	    sscanf(uname, "/dev/rdsk/c%ud%u%n", &c, &d, &l) == 2 ||
24440Sstevel@tonic-gate 	    sscanf(uname, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2) &&
24450Sstevel@tonic-gate 		l == strlen(uname))) {
24460Sstevel@tonic-gate 		if ((np->cname = strrchr(uname, '/')) == NULL)
24470Sstevel@tonic-gate 			np->cname = Strdup(uname);
24480Sstevel@tonic-gate 		else
24490Sstevel@tonic-gate 			np->cname = Strdup(++np->cname);
24500Sstevel@tonic-gate 	} else {
24510Sstevel@tonic-gate 		np->cname = Strdup(uname);
24520Sstevel@tonic-gate 	}
24530Sstevel@tonic-gate 
24540Sstevel@tonic-gate done:
24550Sstevel@tonic-gate 	/* Driver always gives us block names */
24560Sstevel@tonic-gate 	np->bname = Strdup(uname);
24570Sstevel@tonic-gate 
24580Sstevel@tonic-gate 	/* canonical disk name */
24590Sstevel@tonic-gate 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
24600Sstevel@tonic-gate 		dnp->cname = Strdup(np->cname);
24610Sstevel@tonic-gate 
2462*1623Stw21770 	if ((np->rname = getrname_fast(uname, uname_type, ep)) != NULL) {
24630Sstevel@tonic-gate 		if ((dnp->rname = metadiskname(np->rname)) == NULL)
24640Sstevel@tonic-gate 			dnp->rname = Strdup(np->rname);
24650Sstevel@tonic-gate 	} else {
24660Sstevel@tonic-gate 		metafreefastnm(&(*fnlpp)->namep);
24670Sstevel@tonic-gate 		Free(*fnlpp);
24680Sstevel@tonic-gate 		*fnlpp = NULL;
24690Sstevel@tonic-gate 		return (NULL);
24700Sstevel@tonic-gate 	}
24710Sstevel@tonic-gate 
24720Sstevel@tonic-gate 	/* cleanup, return success */
24730Sstevel@tonic-gate 	return (np);
24740Sstevel@tonic-gate }
24750Sstevel@tonic-gate 
24760Sstevel@tonic-gate /*
24770Sstevel@tonic-gate  * set up names for a device
24780Sstevel@tonic-gate  */
24790Sstevel@tonic-gate static mdname_t *
24800Sstevel@tonic-gate metaname_common(
24810Sstevel@tonic-gate 	mdsetname_t	**spp,
24820Sstevel@tonic-gate 	char		*uname,
24830Sstevel@tonic-gate 	int		fast,
2484*1623Stw21770 	meta_device_type_t	uname_type,
24850Sstevel@tonic-gate 	md_error_t	*ep
24860Sstevel@tonic-gate )
24870Sstevel@tonic-gate {
24880Sstevel@tonic-gate 	mddrivenamelist_t	**tail;
24890Sstevel@tonic-gate 	mddrivename_t		*dnp;
24900Sstevel@tonic-gate 	uint_t			slice;
24910Sstevel@tonic-gate 	mdname_t		*np;
24920Sstevel@tonic-gate 	char			*rname = NULL;
24930Sstevel@tonic-gate 	char			*dname = NULL;
24940Sstevel@tonic-gate 	char			*cname = NULL;
24950Sstevel@tonic-gate 	uint_t			nparts, partno;
24960Sstevel@tonic-gate 
24970Sstevel@tonic-gate 	assert(uname != NULL);
24980Sstevel@tonic-gate 
24990Sstevel@tonic-gate 	/* check setname */
2500*1623Stw21770 	if ((cname = meta_name_getname(spp, uname, uname_type, ep)) == NULL)
25010Sstevel@tonic-gate 		return (NULL);
25020Sstevel@tonic-gate 
25030Sstevel@tonic-gate 	assert(*spp != NULL);
25040Sstevel@tonic-gate 	Free(cname);
25050Sstevel@tonic-gate 
25060Sstevel@tonic-gate 	/* get raw name (rname) of the slice and drive (dname) we have */
2507*1623Stw21770 	if ((rname = getrawnames(spp, uname,
2508*1623Stw21770 				&dname, &uname_type, ep)) == NULL) {
25090Sstevel@tonic-gate 		return (NULL);
25100Sstevel@tonic-gate 	}
25110Sstevel@tonic-gate 
2512*1623Stw21770 	assert(uname_type != UNKNOWN);
2513*1623Stw21770 
25140Sstevel@tonic-gate 	/* look in cache first */
25150Sstevel@tonic-gate 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
25160Sstevel@tonic-gate 		dnp = (*tail)->drivenamep;
25170Sstevel@tonic-gate 
25180Sstevel@tonic-gate 		/* check to see if the drive name is already in the cache */
25190Sstevel@tonic-gate 		if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) {
25200Sstevel@tonic-gate 
25210Sstevel@tonic-gate 			Free(rname);
25220Sstevel@tonic-gate 			if (dname != NULL)
25230Sstevel@tonic-gate 				Free(dname);
25240Sstevel@tonic-gate 
2525*1623Stw21770 			if (uname2sliceno(uname, uname_type, &partno, ep) < 0)
25260Sstevel@tonic-gate 				return (NULL);
25270Sstevel@tonic-gate 
25280Sstevel@tonic-gate 			return (metaslicename(dnp, partno, ep));
25290Sstevel@tonic-gate 		}
25300Sstevel@tonic-gate 	}
25310Sstevel@tonic-gate 
25320Sstevel@tonic-gate 	/*
25330Sstevel@tonic-gate 	 * If a fast names is OK, then get one, and be done.
25340Sstevel@tonic-gate 	 */
25350Sstevel@tonic-gate 	if (fast) {
25360Sstevel@tonic-gate 		Free(rname);
25370Sstevel@tonic-gate 		if (dname != NULL)
25380Sstevel@tonic-gate 			Free(dname);
25390Sstevel@tonic-gate 
2540*1623Stw21770 		return (metainitfastname(*spp, uname, uname_type, ep));
25410Sstevel@tonic-gate 	}
25420Sstevel@tonic-gate 
25430Sstevel@tonic-gate 	/* allocate new list element and drive */
25440Sstevel@tonic-gate 	*tail = Zalloc(sizeof (**tail));
25450Sstevel@tonic-gate 	dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
25460Sstevel@tonic-gate 
25470Sstevel@tonic-gate 	metainitdrivename(dnp);
25480Sstevel@tonic-gate 
25490Sstevel@tonic-gate 	/* get parts info */
2550*1623Stw21770 	if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
25510Sstevel@tonic-gate 		goto out;
25520Sstevel@tonic-gate 
25530Sstevel@tonic-gate 	/*
25540Sstevel@tonic-gate 	 * libmeta needs at least V_NUMPAR partitions.
25550Sstevel@tonic-gate 	 * If we have an EFI partition with less than V_NUMPAR slices,
25560Sstevel@tonic-gate 	 * we nevertheless reserve space for V_NUMPAR
25570Sstevel@tonic-gate 	 */
25580Sstevel@tonic-gate 	if (nparts < V_NUMPAR) {
25590Sstevel@tonic-gate 		nparts = V_NUMPAR;
25600Sstevel@tonic-gate 	}
25610Sstevel@tonic-gate 
25620Sstevel@tonic-gate 	/* allocate and link in parts */
25630Sstevel@tonic-gate 	dnp->parts.parts_len = nparts;
25640Sstevel@tonic-gate 	dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) *
25650Sstevel@tonic-gate 	    dnp->parts.parts_len);
25660Sstevel@tonic-gate 	for (slice = 0; (slice < nparts); ++slice) {
25670Sstevel@tonic-gate 		np = &dnp->parts.parts_val[slice];
25680Sstevel@tonic-gate 		metainitname(np);
25690Sstevel@tonic-gate 		np->drivenamep = dnp;
25700Sstevel@tonic-gate 	}
25710Sstevel@tonic-gate 
25720Sstevel@tonic-gate 	/* setup name_t (or slice) wanted */
2573*1623Stw21770 	if ((np = setup_slice(*spp, uname_type, dnp, uname, rname,
2574*1623Stw21770 	    dname, partno, ep)) == NULL)
25750Sstevel@tonic-gate 		goto out;
25760Sstevel@tonic-gate 
25770Sstevel@tonic-gate 	/* canonical disk name */
25780Sstevel@tonic-gate 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
25790Sstevel@tonic-gate 		dnp->cname = Strdup(np->cname);
25800Sstevel@tonic-gate 	if ((dnp->rname = metadiskname(np->rname)) == NULL)
25810Sstevel@tonic-gate 		dnp->rname = Strdup(np->rname);
25820Sstevel@tonic-gate 
25830Sstevel@tonic-gate 	/* cleanup, return success */
25840Sstevel@tonic-gate 	if (dname != NULL)
25850Sstevel@tonic-gate 		Free(dname);
25860Sstevel@tonic-gate 	Free(rname);
25870Sstevel@tonic-gate 	return (np);
25880Sstevel@tonic-gate 
25890Sstevel@tonic-gate 	/* cleanup, return error */
25900Sstevel@tonic-gate out:
25910Sstevel@tonic-gate 	if (dname != NULL)
25920Sstevel@tonic-gate 		Free(dname);
25930Sstevel@tonic-gate 	if (rname != NULL)
25940Sstevel@tonic-gate 		Free(rname);
25950Sstevel@tonic-gate 
25960Sstevel@tonic-gate 	metafreedrivename(dnp);
25970Sstevel@tonic-gate 	Free(dnp);
25980Sstevel@tonic-gate 	Free(*tail);
25990Sstevel@tonic-gate 	*tail = NULL;
26000Sstevel@tonic-gate 	return (NULL);
26010Sstevel@tonic-gate }
26020Sstevel@tonic-gate 
26030Sstevel@tonic-gate mdname_t *
26040Sstevel@tonic-gate metaname(
26050Sstevel@tonic-gate 	mdsetname_t	**spp,
26060Sstevel@tonic-gate 	char		*uname,
2607*1623Stw21770 	meta_device_type_t	uname_type,
26080Sstevel@tonic-gate 	md_error_t	*ep
26090Sstevel@tonic-gate )
26100Sstevel@tonic-gate {
2611*1623Stw21770 	return (metaname_common(spp, uname, 0, uname_type, ep));
26120Sstevel@tonic-gate }
26130Sstevel@tonic-gate 
26140Sstevel@tonic-gate mdname_t *
26150Sstevel@tonic-gate metaname_fast(
26160Sstevel@tonic-gate 	mdsetname_t	**spp,
26170Sstevel@tonic-gate 	char		*uname,
2618*1623Stw21770 	meta_device_type_t	uname_type,
26190Sstevel@tonic-gate 	md_error_t	*ep
26200Sstevel@tonic-gate )
26210Sstevel@tonic-gate {
2622*1623Stw21770 	return (metaname_common(spp, uname, 1, uname_type, ep));
26230Sstevel@tonic-gate }
26240Sstevel@tonic-gate 
26250Sstevel@tonic-gate /*
26260Sstevel@tonic-gate  * set up names for a drive
26270Sstevel@tonic-gate  */
26280Sstevel@tonic-gate mddrivename_t *
26290Sstevel@tonic-gate metadrivename(
2630*1623Stw21770 	mdsetname_t		**spp,
2631*1623Stw21770 	char			*uname,
2632*1623Stw21770 	md_error_t		*ep
26330Sstevel@tonic-gate )
26340Sstevel@tonic-gate {
26350Sstevel@tonic-gate 	char		*slicename;
26360Sstevel@tonic-gate 	mdname_t	*np;
26370Sstevel@tonic-gate 
26380Sstevel@tonic-gate 	mddrivenamelist_t **tail;
26390Sstevel@tonic-gate 	mddrivename_t	*dnp;
26400Sstevel@tonic-gate 	char		*dname;
26410Sstevel@tonic-gate 	int		i;
26420Sstevel@tonic-gate 	int		mplen;
26430Sstevel@tonic-gate 	size_t		len;
26440Sstevel@tonic-gate 
26450Sstevel@tonic-gate 	assert(uname != NULL);
2646*1623Stw21770 
2647*1623Stw21770 	if ((dname = metadiskname(uname)) == NULL) {
26480Sstevel@tonic-gate 		(void) mdsyserror(ep, ENOENT, uname);
26490Sstevel@tonic-gate 		return (NULL);
26500Sstevel@tonic-gate 	}
26510Sstevel@tonic-gate 
26520Sstevel@tonic-gate 	/* look in cache first */
26530Sstevel@tonic-gate 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
26540Sstevel@tonic-gate 		dnp = (*tail)->drivenamep;
26550Sstevel@tonic-gate 		if ((dnp->cname != NULL &&
26560Sstevel@tonic-gate 		    (strcmp(dnp->cname, dname) == 0)) ||
26570Sstevel@tonic-gate 		    (dnp->rname != NULL &&
26580Sstevel@tonic-gate 		    (strcmp(dnp->rname, dname) == 0))) {
26590Sstevel@tonic-gate 			Free(dname);
26600Sstevel@tonic-gate 			return (dnp);
26610Sstevel@tonic-gate 		}
26620Sstevel@tonic-gate 	}
2663*1623Stw21770 	Free(dname);
26640Sstevel@tonic-gate 
26650Sstevel@tonic-gate 	/* Check each possible slice name based on MD_MAX_PARTS. */
26660Sstevel@tonic-gate 
26670Sstevel@tonic-gate 	/*
26680Sstevel@tonic-gate 	 * Figure out how much string space to reserve to fit
26690Sstevel@tonic-gate 	 * (MD_MAX_PARTS - 1) into the name string; the loop will
26700Sstevel@tonic-gate 	 * increment the mplen counter once for each decimal digit in
26710Sstevel@tonic-gate 	 * (MD_MAX_PARTS - 1).
26720Sstevel@tonic-gate 	 */
26730Sstevel@tonic-gate 	for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen);
26740Sstevel@tonic-gate 	len = strlen(uname) + mplen + 2;
26750Sstevel@tonic-gate 	slicename = Malloc(len);
26760Sstevel@tonic-gate 
26770Sstevel@tonic-gate 	/* Check for each slice in turn until we find one */
26780Sstevel@tonic-gate 	for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) {
26790Sstevel@tonic-gate 		(void) snprintf(slicename, len, "%ss%d", uname, i);
2680*1623Stw21770 		np = metaname(spp, slicename, LOGICAL_DEVICE, ep);
26810Sstevel@tonic-gate 	}
26820Sstevel@tonic-gate 	Free(slicename);
26830Sstevel@tonic-gate 
26840Sstevel@tonic-gate 	if (np == NULL) {
2685*1623Stw21770 		if ((mdiserror(ep, MDE_UNIT_NOT_FOUND)) &&
26860Sstevel@tonic-gate 		    ((dname = metadiskname(uname)) != NULL)) {
26870Sstevel@tonic-gate 			Free(dname);
26880Sstevel@tonic-gate 			(void) mderror(ep, MDE_NOT_DRIVENAME, uname);
26890Sstevel@tonic-gate 		}
26900Sstevel@tonic-gate 		return (NULL);
26910Sstevel@tonic-gate 	}
26920Sstevel@tonic-gate 	return (np->drivenamep);
26930Sstevel@tonic-gate }
26940Sstevel@tonic-gate 
26950Sstevel@tonic-gate /*
2696*1623Stw21770  * FUNCTION:	metaslicename_type()
2697*1623Stw21770  * INPUT:	dnp	- the drivename structure
2698*1623Stw21770  *		sliceno	- the slice on the drive to return
2699*1623Stw21770  *		type - LOGICAL_DEVICE or META_DEVICE
2700*1623Stw21770  * OUTPUT:	ep	- return error pointer
2701*1623Stw21770  * RETURNS:	mdname_t- pointer the the slice name structure
2702*1623Stw21770  * PURPOSE:	interface to the parts struct in the drive name struct
2703*1623Stw21770  *		Since there is no guarantee that the slice name
2704*1623Stw21770  *		structures are populated users should call this
2705*1623Stw21770  *		function rather than accessing the structure directly
2706*1623Stw21770  *		since it will populate the structure values if they
2707*1623Stw21770  *		haven't already been populated before returning.
2708*1623Stw21770  */
2709*1623Stw21770 mdname_t *
2710*1623Stw21770 metaslicename_type(
2711*1623Stw21770 	mddrivename_t		*dnp,
2712*1623Stw21770 	uint_t			sliceno,
2713*1623Stw21770 	meta_device_type_t	uname_type,
2714*1623Stw21770 	md_error_t		*ep
2715*1623Stw21770 )
2716*1623Stw21770 {
2717*1623Stw21770 	mdsetname_t	*sp = NULL;
2718*1623Stw21770 	char		*namep = NULL;
2719*1623Stw21770 	mdname_t	*np;
2720*1623Stw21770 
2721*1623Stw21770 	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
2722*1623Stw21770 
2723*1623Stw21770 	if (sliceno >= dnp->parts.parts_len) {
2724*1623Stw21770 		(void) mderror(ep, MDE_NOSLICE, dnp->cname);
2725*1623Stw21770 		return (NULL);
2726*1623Stw21770 	}
2727*1623Stw21770 
2728*1623Stw21770 	np = &dnp->parts.parts_val[sliceno];
2729*1623Stw21770 
2730*1623Stw21770 	/* check to see if the struct is already populated */
2731*1623Stw21770 	if (np->cname) {
2732*1623Stw21770 		return (np);
2733*1623Stw21770 	}
2734*1623Stw21770 
2735*1623Stw21770 	if ((namep = meta_name_getname(&sp, dnp->cname,
2736*1623Stw21770 					uname_type, ep)) == NULL)
2737*1623Stw21770 		return (NULL);
2738*1623Stw21770 
2739*1623Stw21770 	np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname,
2740*1623Stw21770 	    sliceno, ep);
2741*1623Stw21770 
2742*1623Stw21770 	Free(namep);
2743*1623Stw21770 
2744*1623Stw21770 	return (np);
2745*1623Stw21770 }
2746*1623Stw21770 
2747*1623Stw21770 /*
27480Sstevel@tonic-gate  * FUNCTION:	metaslicename()
27490Sstevel@tonic-gate  * INPUT:	dnp	- the drivename structure
27500Sstevel@tonic-gate  *		sliceno	- the slice on the drive to return
27510Sstevel@tonic-gate  * OUTPUT:	ep	- return error pointer
27520Sstevel@tonic-gate  * RETURNS:	mdname_t- pointer the the slice name structure
27530Sstevel@tonic-gate  * PURPOSE:	interface to the parts struct in the drive name struct
27540Sstevel@tonic-gate  *		Since there is no guarantee that the slice name
27550Sstevel@tonic-gate  *		structures are populated users should call this
27560Sstevel@tonic-gate  *		function rather than accessing the structure directly
27570Sstevel@tonic-gate  *		since it will populate the structure values if they
27580Sstevel@tonic-gate  *		haven't already been populated before returning.
27590Sstevel@tonic-gate  */
27600Sstevel@tonic-gate mdname_t *
27610Sstevel@tonic-gate metaslicename(
27620Sstevel@tonic-gate 	mddrivename_t	*dnp,
27630Sstevel@tonic-gate 	uint_t		sliceno,
27640Sstevel@tonic-gate 	md_error_t	*ep
27650Sstevel@tonic-gate )
27660Sstevel@tonic-gate {
2767*1623Stw21770 	return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep));
27680Sstevel@tonic-gate }
27690Sstevel@tonic-gate 
27700Sstevel@tonic-gate /*
27710Sstevel@tonic-gate  * set up metadevice name from id
27720Sstevel@tonic-gate  */
27730Sstevel@tonic-gate mdname_t *
27740Sstevel@tonic-gate metamnumname(
27750Sstevel@tonic-gate 	mdsetname_t	**spp,
27760Sstevel@tonic-gate 	minor_t		mnum,
27770Sstevel@tonic-gate 	int		fast,
27780Sstevel@tonic-gate 	md_error_t	*ep
27790Sstevel@tonic-gate )
27800Sstevel@tonic-gate {
27810Sstevel@tonic-gate 	set_t		setno = MD_MIN2SET(mnum);
27820Sstevel@tonic-gate 	mdsetname_t	*sp = NULL;
27830Sstevel@tonic-gate 	char		*uname;
27840Sstevel@tonic-gate 	mdname_t	*np;
2785*1623Stw21770 	md_dev64_t	dev;
2786*1623Stw21770 	mdkey_t		key;
27870Sstevel@tonic-gate 
27880Sstevel@tonic-gate 	/* check set first */
27890Sstevel@tonic-gate 	if (spp == NULL)
27900Sstevel@tonic-gate 		spp = &sp;
27910Sstevel@tonic-gate 	if (chksetno(spp, setno, ep) != 0)
27920Sstevel@tonic-gate 		return (NULL);
27930Sstevel@tonic-gate 	assert(*spp != NULL);
27940Sstevel@tonic-gate 	sp = *spp;
27950Sstevel@tonic-gate 
2796*1623Stw21770 	/* get corresponding device name */
2797*1623Stw21770 	dev = metamakedev(mnum);
2798*1623Stw21770 	if ((uname = meta_getnmentbydev(sp->setno, MD_SIDEWILD, dev,
2799*1623Stw21770 	    NULL, NULL, &key, ep)) == NULL)
2800*1623Stw21770 		return (NULL);
28010Sstevel@tonic-gate 
28020Sstevel@tonic-gate 	/* setup name */
28030Sstevel@tonic-gate 	if (fast) {
2804*1623Stw21770 		np = metaname_fast(spp, uname, META_DEVICE, ep);
2805*1623Stw21770 		if (np) {
2806*1623Stw21770 			np->dev = dev;
2807*1623Stw21770 			np->key = key;
2808*1623Stw21770 		}
28090Sstevel@tonic-gate 	} else
2810*1623Stw21770 		np = metaname(spp, uname, META_DEVICE, ep);
28110Sstevel@tonic-gate 
28120Sstevel@tonic-gate 	Free(uname);
28130Sstevel@tonic-gate 	return (np);
28140Sstevel@tonic-gate }
28150Sstevel@tonic-gate 
28160Sstevel@tonic-gate /*
28170Sstevel@tonic-gate  * return metadevice name
28180Sstevel@tonic-gate  */
28190Sstevel@tonic-gate char *
28200Sstevel@tonic-gate get_mdname(
2821*1623Stw21770 	mdsetname_t	*sp,
28220Sstevel@tonic-gate 	minor_t		mnum
28230Sstevel@tonic-gate )
28240Sstevel@tonic-gate {
28250Sstevel@tonic-gate 	mdname_t	*np;
28260Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
2827*1623Stw21770 	mdsetname_t	**spp = NULL;
2828*1623Stw21770 
2829*1623Stw21770 	if (sp != NULL)
2830*1623Stw21770 		spp = &sp;
28310Sstevel@tonic-gate 
28320Sstevel@tonic-gate 	/* get name */
2833*1623Stw21770 	if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) {
28340Sstevel@tonic-gate 		return (NULL);
28350Sstevel@tonic-gate 	}
28360Sstevel@tonic-gate 	assert(meta_getminor(np->dev) == mnum);
28370Sstevel@tonic-gate 
28380Sstevel@tonic-gate 	/* return name */
28390Sstevel@tonic-gate 	return (np->cname);
28400Sstevel@tonic-gate }
28410Sstevel@tonic-gate 
28420Sstevel@tonic-gate /*
28430Sstevel@tonic-gate  * check for device type
28440Sstevel@tonic-gate  */
28450Sstevel@tonic-gate int
28460Sstevel@tonic-gate metaismeta(
28470Sstevel@tonic-gate 	mdname_t	*np
28480Sstevel@tonic-gate )
28490Sstevel@tonic-gate {
28500Sstevel@tonic-gate 	return (np->drivenamep->type == MDT_META ||
28510Sstevel@tonic-gate 		np->drivenamep->type == MDT_FAST_META);
28520Sstevel@tonic-gate }
28530Sstevel@tonic-gate 
28540Sstevel@tonic-gate int
28550Sstevel@tonic-gate metachkmeta(
28560Sstevel@tonic-gate 	mdname_t	*np,
28570Sstevel@tonic-gate 	md_error_t	*ep
28580Sstevel@tonic-gate )
28590Sstevel@tonic-gate {
28600Sstevel@tonic-gate 	if (! metaismeta(np)) {
28610Sstevel@tonic-gate 		return (mddeverror(ep, MDE_NOT_META, np->dev,
28620Sstevel@tonic-gate 		    np->cname));
28630Sstevel@tonic-gate 	}
28640Sstevel@tonic-gate 	return (0);
28650Sstevel@tonic-gate }
28660Sstevel@tonic-gate 
28670Sstevel@tonic-gate int
28680Sstevel@tonic-gate metachkdisk(
28690Sstevel@tonic-gate 	mdname_t	*np,
28700Sstevel@tonic-gate 	md_error_t	*ep
28710Sstevel@tonic-gate )
28720Sstevel@tonic-gate {
28730Sstevel@tonic-gate 	mddrivename_t	*dnp = np->drivenamep;
28740Sstevel@tonic-gate 
28750Sstevel@tonic-gate 	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
28760Sstevel@tonic-gate 
28770Sstevel@tonic-gate 	if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) {
28780Sstevel@tonic-gate 		switch (dnp->type) {
28790Sstevel@tonic-gate 		    case MDT_ACCES:
28800Sstevel@tonic-gate 		    case MDT_UNKNOWN:
28810Sstevel@tonic-gate 			    return (mdsyserror(ep, dnp->errnum, np->bname));
28820Sstevel@tonic-gate 		    default:
28830Sstevel@tonic-gate 			    assert(0);
28840Sstevel@tonic-gate 			    return (mddeverror(ep, MDE_NOT_DISK, np->dev,
28850Sstevel@tonic-gate 				np->cname));
28860Sstevel@tonic-gate 		}
28870Sstevel@tonic-gate 	}
28880Sstevel@tonic-gate 	return (0);
28890Sstevel@tonic-gate }
28900Sstevel@tonic-gate 
28910Sstevel@tonic-gate int
28920Sstevel@tonic-gate metachkcomp(
28930Sstevel@tonic-gate 	mdname_t	*np,
28940Sstevel@tonic-gate 	md_error_t	*ep
28950Sstevel@tonic-gate )
28960Sstevel@tonic-gate {
28970Sstevel@tonic-gate 	if (metaismeta(np)) {
28980Sstevel@tonic-gate 		return (mddeverror(ep, MDE_IS_META, np->dev,
28990Sstevel@tonic-gate 		    np->cname));
29000Sstevel@tonic-gate 	}
29010Sstevel@tonic-gate 	return (metachkdisk(np, ep));
29020Sstevel@tonic-gate }
29030Sstevel@tonic-gate 
29040Sstevel@tonic-gate /*
29050Sstevel@tonic-gate  * free list of names
29060Sstevel@tonic-gate  */
29070Sstevel@tonic-gate void
29080Sstevel@tonic-gate metafreenamelist(
29090Sstevel@tonic-gate 	mdnamelist_t	*nlp
29100Sstevel@tonic-gate )
29110Sstevel@tonic-gate {
29120Sstevel@tonic-gate 	mdnamelist_t	*next = NULL;
29130Sstevel@tonic-gate 
29140Sstevel@tonic-gate 	for (/* void */; (nlp != NULL); nlp = next) {
29150Sstevel@tonic-gate 		next = nlp->next;
29160Sstevel@tonic-gate 		Free(nlp);
29170Sstevel@tonic-gate 	}
29180Sstevel@tonic-gate }
29190Sstevel@tonic-gate 
29200Sstevel@tonic-gate /*
29210Sstevel@tonic-gate  * build list of names
29220Sstevel@tonic-gate  */
29230Sstevel@tonic-gate int
29240Sstevel@tonic-gate metanamelist(
29250Sstevel@tonic-gate 	mdsetname_t	**spp,
29260Sstevel@tonic-gate 	mdnamelist_t	**nlpp,
29270Sstevel@tonic-gate 	int		argc,
29280Sstevel@tonic-gate 	char		*argv[],
2929*1623Stw21770 	meta_device_type_t	type,
29300Sstevel@tonic-gate 	md_error_t	*ep
29310Sstevel@tonic-gate )
29320Sstevel@tonic-gate {
29330Sstevel@tonic-gate 	mdnamelist_t	**tailpp = nlpp;
29340Sstevel@tonic-gate 	int		count = 0;
29350Sstevel@tonic-gate 
29360Sstevel@tonic-gate 	for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
29370Sstevel@tonic-gate 		mdnamelist_t	*nlp = Zalloc(sizeof (*nlp));
29380Sstevel@tonic-gate 
2939*1623Stw21770 		if ((nlp->namep = metaname(spp, argv[0],
2940*1623Stw21770 		    type, ep)) == NULL) {
29410Sstevel@tonic-gate 			metafreenamelist(*nlpp);
29420Sstevel@tonic-gate 			*nlpp = NULL;
29430Sstevel@tonic-gate 			return (-1);
29440Sstevel@tonic-gate 		}
29450Sstevel@tonic-gate 		*tailpp = nlp;
29460Sstevel@tonic-gate 		tailpp = &nlp->next;
29470Sstevel@tonic-gate 	}
29480Sstevel@tonic-gate 	return (count);
29490Sstevel@tonic-gate }
29500Sstevel@tonic-gate 
29510Sstevel@tonic-gate /*
29520Sstevel@tonic-gate  * append to end of name list
29530Sstevel@tonic-gate  */
29540Sstevel@tonic-gate mdname_t *
29550Sstevel@tonic-gate metanamelist_append(
29560Sstevel@tonic-gate 	mdnamelist_t	**nlpp,
29570Sstevel@tonic-gate 	mdname_t	*np
29580Sstevel@tonic-gate )
29590Sstevel@tonic-gate {
29600Sstevel@tonic-gate 	mdnamelist_t	*nlp;
29610Sstevel@tonic-gate 
29620Sstevel@tonic-gate 	/* run to end of list */
29630Sstevel@tonic-gate 	for (; (*nlpp != NULL); nlpp = &(*nlpp)->next)
29640Sstevel@tonic-gate 		;
29650Sstevel@tonic-gate 
29660Sstevel@tonic-gate 	/* allocate new list element */
29670Sstevel@tonic-gate 	nlp = *nlpp = Zalloc(sizeof (*nlp));
29680Sstevel@tonic-gate 
29690Sstevel@tonic-gate 	/* append name */
29700Sstevel@tonic-gate 	nlp->namep = np;
29710Sstevel@tonic-gate 	return (np);
29720Sstevel@tonic-gate }
29730Sstevel@tonic-gate 
29740Sstevel@tonic-gate /*
29750Sstevel@tonic-gate  * FUNCTION:	meta_namelist_append_wrapper()
29760Sstevel@tonic-gate  * INPUT:	tailpp	- pointer to the list tail pointer
29770Sstevel@tonic-gate  *		np	- name node to be appended to list
29780Sstevel@tonic-gate  * OUTPUT:	none
29790Sstevel@tonic-gate  * RETURNS:	mdnamelist_t * - new tail of the list.
29800Sstevel@tonic-gate  * PURPOSE:	wrapper to meta_namelist_append for performance.
29810Sstevel@tonic-gate  *		metanamelist_append finds the tail each time which slows
29820Sstevel@tonic-gate  *		down long lists.  By keeping track of the tail ourselves
29830Sstevel@tonic-gate  *		we can change metanamelist_append into a constant time
29840Sstevel@tonic-gate  *		operation.
29850Sstevel@tonic-gate  */
29860Sstevel@tonic-gate mdnamelist_t **
29870Sstevel@tonic-gate meta_namelist_append_wrapper(
29880Sstevel@tonic-gate 	mdnamelist_t	**tailpp,
29890Sstevel@tonic-gate 	mdname_t	*np
29900Sstevel@tonic-gate )
29910Sstevel@tonic-gate {
29920Sstevel@tonic-gate 	(void) metanamelist_append(tailpp, np);
29930Sstevel@tonic-gate 
29940Sstevel@tonic-gate 	/* If it's the first item in the list, return it instead of the next */
29950Sstevel@tonic-gate 	if ((*tailpp)->next == NULL)
29960Sstevel@tonic-gate 		return (tailpp);
29970Sstevel@tonic-gate 
29980Sstevel@tonic-gate 	return (&(*tailpp)->next);
29990Sstevel@tonic-gate }
30000Sstevel@tonic-gate 
30010Sstevel@tonic-gate 
30020Sstevel@tonic-gate /*
30030Sstevel@tonic-gate  *	mdhspname_t stuff
30040Sstevel@tonic-gate  */
30050Sstevel@tonic-gate 
30060Sstevel@tonic-gate /*
30070Sstevel@tonic-gate  * initialize hspname
30080Sstevel@tonic-gate  */
30090Sstevel@tonic-gate static void
30100Sstevel@tonic-gate metainithspname(
30110Sstevel@tonic-gate 	mdhspname_t	*hspnamep
30120Sstevel@tonic-gate )
30130Sstevel@tonic-gate {
30140Sstevel@tonic-gate 	(void) memset(hspnamep, '\0', sizeof (*hspnamep));
30150Sstevel@tonic-gate 	hspnamep->hsp = MD_HSP_NONE;
30160Sstevel@tonic-gate }
30170Sstevel@tonic-gate 
30180Sstevel@tonic-gate /*
30190Sstevel@tonic-gate  * free allocated hspname
30200Sstevel@tonic-gate  */
30210Sstevel@tonic-gate static void
30220Sstevel@tonic-gate metafreehspname(
30230Sstevel@tonic-gate 	mdhspname_t	*hspnamep
30240Sstevel@tonic-gate )
30250Sstevel@tonic-gate {
30260Sstevel@tonic-gate 	if (hspnamep->hspname != NULL)
30270Sstevel@tonic-gate 		Free(hspnamep->hspname);
30280Sstevel@tonic-gate 	if (hspnamep->unitp != NULL)
30290Sstevel@tonic-gate 		meta_invalidate_hsp(hspnamep);
30300Sstevel@tonic-gate 	metainithspname(hspnamep);
30310Sstevel@tonic-gate }
30320Sstevel@tonic-gate 
30330Sstevel@tonic-gate /*
30340Sstevel@tonic-gate  * clear the hspname cache
30350Sstevel@tonic-gate  */
30360Sstevel@tonic-gate static void
30370Sstevel@tonic-gate metaflushhspnames()
30380Sstevel@tonic-gate {
30390Sstevel@tonic-gate 	mdhspnamelist_t		*p, *n;
30400Sstevel@tonic-gate 
30410Sstevel@tonic-gate 	for (p = hsplistp, n = NULL; (p != NULL); p = n) {
30420Sstevel@tonic-gate 		n = p->next;
30430Sstevel@tonic-gate 		metafreehspname(p->hspnamep);
30440Sstevel@tonic-gate 		Free(p->hspnamep);
30450Sstevel@tonic-gate 		Free(p);
30460Sstevel@tonic-gate 	}
30470Sstevel@tonic-gate 	hsplistp = NULL;
30480Sstevel@tonic-gate }
30490Sstevel@tonic-gate 
30500Sstevel@tonic-gate /*
30510Sstevel@tonic-gate  * check set and get comparison name
30520Sstevel@tonic-gate  */
30530Sstevel@tonic-gate static char *
30540Sstevel@tonic-gate gethspname(
30550Sstevel@tonic-gate 	mdsetname_t	**spp,
30560Sstevel@tonic-gate 	char		*uname,
30570Sstevel@tonic-gate 	md_error_t	*ep
30580Sstevel@tonic-gate )
30590Sstevel@tonic-gate {
3060*1623Stw21770 	char		*cname = NULL;
3061*1623Stw21770 
3062*1623Stw21770 	cname = meta_canonicalize(*spp, uname);
3063*1623Stw21770 	/* if it is not a meta/hsp name then flag an error */
3064*1623Stw21770 	if (cname == NULL) {
3065*1623Stw21770 		(void) mdsyserror(ep, ENOENT, uname);
3066*1623Stw21770 		return (NULL);
3067*1623Stw21770 	}
3068*1623Stw21770 	return (cname);
3069*1623Stw21770 }
3070*1623Stw21770 
3071*1623Stw21770 /*
3072*1623Stw21770  * set up a hotspare pool name structure using both the name
3073*1623Stw21770  * and the self id
3074*1623Stw21770  */
3075*1623Stw21770 static mdhspname_t *
3076*1623Stw21770 metahspname_hsp(
3077*1623Stw21770 	mdsetname_t	**spp,
3078*1623Stw21770 	char		*uname,
3079*1623Stw21770 	hsp_t		hsp,
3080*1623Stw21770 	md_error_t	*ep
3081*1623Stw21770 )
3082*1623Stw21770 {
3083*1623Stw21770 	char		*cname;
3084*1623Stw21770 	mdhspnamelist_t	**tail;
3085*1623Stw21770 	mdhspname_t	*hspnp;
30860Sstevel@tonic-gate 
30870Sstevel@tonic-gate 	/* check setname */
30880Sstevel@tonic-gate 	assert(uname != NULL);
3089*1623Stw21770 	if ((cname = gethspname(spp, uname, ep)) == NULL)
30900Sstevel@tonic-gate 		return (NULL);
3091*1623Stw21770 	assert(*spp != NULL);
3092*1623Stw21770 
3093*1623Stw21770 	/* look in cache first */
3094*1623Stw21770 	for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) {
3095*1623Stw21770 		hspnp = (*tail)->hspnamep;
3096*1623Stw21770 		if (strcmp(hspnp->hspname, cname) == 0) {
3097*1623Stw21770 			Free(cname);
3098*1623Stw21770 			/* if the hsp value has not been set then set it now */
3099*1623Stw21770 			if (hspnp->hsp == MD_HSP_NONE)
3100*1623Stw21770 				hspnp->hsp = hsp;
3101*1623Stw21770 			return (hspnp);
3102*1623Stw21770 		}
31030Sstevel@tonic-gate 	}
3104*1623Stw21770 
3105*1623Stw21770 	/* if the hsp number isn't specified then attempt to get it */
3106*1623Stw21770 	if (hsp == MD_HSP_NONE && (hsp = meta_gethspnmentbyname((*spp)->setno,
3107*1623Stw21770 	    MD_SIDEWILD, cname, ep)) == MD_HSP_NONE) {
3108*1623Stw21770 		if (! mdisok(ep)) {
3109*1623Stw21770 			/*
3110*1623Stw21770 			 * If the error is ENOENT, then we will continue on,
3111*1623Stw21770 			 * because the device does not yet exist.
3112*1623Stw21770 			 * For other types of errors, however, we'll bail out.
3113*1623Stw21770 			 */
3114*1623Stw21770 			if (! mdissyserror(ep, ENOENT)) {
3115*1623Stw21770 				Free(cname);
3116*1623Stw21770 				return (NULL);
3117*1623Stw21770 			}
3118*1623Stw21770 			mdclrerror(ep);
3119*1623Stw21770 		}
31200Sstevel@tonic-gate 	}
3121*1623Stw21770 
3122*1623Stw21770 	/* allocate new list element and hspname */
3123*1623Stw21770 	*tail = Zalloc(sizeof (**tail));
3124*1623Stw21770 	hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp));
3125*1623Stw21770 	metainithspname(hspnp);
3126*1623Stw21770 
3127*1623Stw21770 	/* save hspname and number */
3128*1623Stw21770 	hspnp->hspname = cname;
3129*1623Stw21770 	hspnp->hsp = hsp;
3130*1623Stw21770 
3131*1623Stw21770 	/* success */
3132*1623Stw21770 	return (hspnp);
31330Sstevel@tonic-gate }
31340Sstevel@tonic-gate 
31350Sstevel@tonic-gate /*
31360Sstevel@tonic-gate  * set up names for a hotspare pool
31370Sstevel@tonic-gate  */
31380Sstevel@tonic-gate mdhspname_t *
31390Sstevel@tonic-gate metahspname(
31400Sstevel@tonic-gate 	mdsetname_t	**spp,
31410Sstevel@tonic-gate 	char		*uname,
31420Sstevel@tonic-gate 	md_error_t	*ep
31430Sstevel@tonic-gate )
31440Sstevel@tonic-gate {
3145*1623Stw21770 	return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep));
31460Sstevel@tonic-gate }
31470Sstevel@tonic-gate 
31480Sstevel@tonic-gate /*
3149*1623Stw21770  * set up hotspare pool name from key
31500Sstevel@tonic-gate  */
31510Sstevel@tonic-gate mdhspname_t *
31520Sstevel@tonic-gate metahsphspname(
31530Sstevel@tonic-gate 	mdsetname_t	**spp,
31540Sstevel@tonic-gate 	hsp_t		hsp,
31550Sstevel@tonic-gate 	md_error_t	*ep
31560Sstevel@tonic-gate )
31570Sstevel@tonic-gate {
31580Sstevel@tonic-gate 	set_t		setno = HSP_SET(hsp);
31590Sstevel@tonic-gate 	mdsetname_t	*sp = NULL;
31600Sstevel@tonic-gate 	char		*uname;
31610Sstevel@tonic-gate 	mdhspname_t	*hspnp;
31620Sstevel@tonic-gate 
31630Sstevel@tonic-gate 	/* check set first */
31640Sstevel@tonic-gate 	if (spp == NULL)
31650Sstevel@tonic-gate 		spp = &sp;
31660Sstevel@tonic-gate 	if (chksetno(spp, setno, ep) != 0)
31670Sstevel@tonic-gate 		return (NULL);
31680Sstevel@tonic-gate 	assert(*spp != NULL);
31690Sstevel@tonic-gate 	sp = *spp;
31700Sstevel@tonic-gate 
3171*1623Stw21770 	/* get corresponding hotspare pool name */
3172*1623Stw21770 	if ((uname = meta_gethspnmentbyid(sp->setno,
3173*1623Stw21770 			MD_SIDEWILD, hsp, ep)) == NULL)
3174*1623Stw21770 		return (NULL);
31750Sstevel@tonic-gate 
31760Sstevel@tonic-gate 	/* setup name */
3177*1623Stw21770 	hspnp = metahspname_hsp(spp, uname, hsp, ep);
31780Sstevel@tonic-gate 	Free(uname);
31790Sstevel@tonic-gate 	return (hspnp);
31800Sstevel@tonic-gate }
31810Sstevel@tonic-gate 
31820Sstevel@tonic-gate /*
31830Sstevel@tonic-gate  * return hotspare pool name
31840Sstevel@tonic-gate  */
31850Sstevel@tonic-gate char *
3186*1623Stw21770 get_hspname(mdsetname_t *sp, hsp_t hsp)
31870Sstevel@tonic-gate {
31880Sstevel@tonic-gate 	mdhspname_t	*hspnp;
31890Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
3190*1623Stw21770 	mdsetname_t	**spp = NULL;
3191*1623Stw21770 
3192*1623Stw21770 	if (sp != NULL)
3193*1623Stw21770 		spp = &sp;
31940Sstevel@tonic-gate 
31950Sstevel@tonic-gate 	/* get name */
3196*1623Stw21770 	if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) {
31970Sstevel@tonic-gate 		mdclrerror(&status);
31980Sstevel@tonic-gate 		return (NULL);
31990Sstevel@tonic-gate 	}
32000Sstevel@tonic-gate 
32010Sstevel@tonic-gate 	/* return name */
32020Sstevel@tonic-gate 	return (hspnp->hspname);
32030Sstevel@tonic-gate }
32040Sstevel@tonic-gate 
32050Sstevel@tonic-gate /*
32060Sstevel@tonic-gate  * free hotspare pool list
32070Sstevel@tonic-gate  */
32080Sstevel@tonic-gate void
32090Sstevel@tonic-gate metafreehspnamelist(mdhspnamelist_t *hspnlp)
32100Sstevel@tonic-gate {
32110Sstevel@tonic-gate 	mdhspnamelist_t	*next = NULL;
32120Sstevel@tonic-gate 
32130Sstevel@tonic-gate 	for (/* void */; (hspnlp != NULL); hspnlp = next) {
32140Sstevel@tonic-gate 		next = hspnlp->next;
32150Sstevel@tonic-gate 		Free(hspnlp);
32160Sstevel@tonic-gate 	}
32170Sstevel@tonic-gate }
32180Sstevel@tonic-gate 
32190Sstevel@tonic-gate /*
32200Sstevel@tonic-gate  * build list of hotspare pool names
32210Sstevel@tonic-gate  */
32220Sstevel@tonic-gate int
32230Sstevel@tonic-gate metahspnamelist(
32240Sstevel@tonic-gate 	mdsetname_t	**spp,
32250Sstevel@tonic-gate 	mdhspnamelist_t	**hspnlpp,
32260Sstevel@tonic-gate 	int		argc,
32270Sstevel@tonic-gate 	char		*argv[],
32280Sstevel@tonic-gate 	md_error_t	*ep
32290Sstevel@tonic-gate )
32300Sstevel@tonic-gate {
32310Sstevel@tonic-gate 	mdhspnamelist_t	**tailpp = hspnlpp;
32320Sstevel@tonic-gate 	int		count = 0;
32330Sstevel@tonic-gate 
32340Sstevel@tonic-gate 	for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
32350Sstevel@tonic-gate 		mdhspnamelist_t	*hspnlp = Zalloc(sizeof (*hspnlp));
32360Sstevel@tonic-gate 
32370Sstevel@tonic-gate 		if ((hspnlp->hspnamep = metahspname(spp, argv[0],
32380Sstevel@tonic-gate 		    ep)) == NULL) {
32390Sstevel@tonic-gate 			metafreehspnamelist(*hspnlpp);
32400Sstevel@tonic-gate 			*hspnlpp = NULL;
32410Sstevel@tonic-gate 			return (-1);
32420Sstevel@tonic-gate 		}
32430Sstevel@tonic-gate 		*tailpp = hspnlp;
32440Sstevel@tonic-gate 		tailpp = &hspnlp->next;
32450Sstevel@tonic-gate 	}
32460Sstevel@tonic-gate 	return (count);
32470Sstevel@tonic-gate }
32480Sstevel@tonic-gate 
32490Sstevel@tonic-gate /*
32500Sstevel@tonic-gate  * append to end of hotspare pool list
32510Sstevel@tonic-gate  */
32520Sstevel@tonic-gate mdhspname_t *
32530Sstevel@tonic-gate metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp)
32540Sstevel@tonic-gate {
32550Sstevel@tonic-gate 	mdhspnamelist_t	*hspnlp;
32560Sstevel@tonic-gate 
32570Sstevel@tonic-gate 	/* run to end of list */
32580Sstevel@tonic-gate 	for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next)
32590Sstevel@tonic-gate 		;
32600Sstevel@tonic-gate 
32610Sstevel@tonic-gate 	/* allocate new list element */
32620Sstevel@tonic-gate 	hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp));
32630Sstevel@tonic-gate 
32640Sstevel@tonic-gate 	/* append hotspare pool name */
32650Sstevel@tonic-gate 	hspnlp->hspnamep = hspnp;
32660Sstevel@tonic-gate 	return (hspnp);
32670Sstevel@tonic-gate }
32680Sstevel@tonic-gate 
32690Sstevel@tonic-gate /*
32700Sstevel@tonic-gate  * get name from dev
32710Sstevel@tonic-gate  */
32720Sstevel@tonic-gate mdname_t *
32730Sstevel@tonic-gate metadevname(
32740Sstevel@tonic-gate 	mdsetname_t **spp,
32750Sstevel@tonic-gate 	md_dev64_t dev,
32760Sstevel@tonic-gate 	md_error_t *ep)
32770Sstevel@tonic-gate {
32780Sstevel@tonic-gate 	char		*device_name;
32790Sstevel@tonic-gate 	mdname_t	*namep;
32800Sstevel@tonic-gate 	mdkey_t		key;
32810Sstevel@tonic-gate 
32820Sstevel@tonic-gate 	/* short circuit metadevices */
32830Sstevel@tonic-gate 	assert(dev != NODEV64);
32840Sstevel@tonic-gate 	if (meta_dev_ismeta(dev))
32850Sstevel@tonic-gate 		return (metamnumname(spp, meta_getminor(dev), 0, ep));
32860Sstevel@tonic-gate 
32870Sstevel@tonic-gate 	/* create local set, if necessary */
32880Sstevel@tonic-gate 	if (*spp == NULL) {
32890Sstevel@tonic-gate 		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
32900Sstevel@tonic-gate 			return (NULL);
32910Sstevel@tonic-gate 	}
32920Sstevel@tonic-gate 
32930Sstevel@tonic-gate 	/* get name from namespace */
32940Sstevel@tonic-gate 	if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD,
32950Sstevel@tonic-gate 	    dev, NULL, NULL, &key, ep)) == NULL) {
32960Sstevel@tonic-gate 		return (NULL);
32970Sstevel@tonic-gate 	}
3298*1623Stw21770 	namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep);
32990Sstevel@tonic-gate 	if (namep != NULL)
33000Sstevel@tonic-gate 		namep->key = key;
33010Sstevel@tonic-gate 
33020Sstevel@tonic-gate 	Free(device_name);
33030Sstevel@tonic-gate 	return (namep);
33040Sstevel@tonic-gate }
33050Sstevel@tonic-gate 
33060Sstevel@tonic-gate /*
33070Sstevel@tonic-gate  * return cached name from md_dev64_t
33080Sstevel@tonic-gate  */
33090Sstevel@tonic-gate static char *
33100Sstevel@tonic-gate metadevtocachename(md_dev64_t dev)
33110Sstevel@tonic-gate {
33120Sstevel@tonic-gate 	mddrivenamelist_t	*dnlp;
33130Sstevel@tonic-gate 
33140Sstevel@tonic-gate 	/* look in cache */
33150Sstevel@tonic-gate 	for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) {
33160Sstevel@tonic-gate 		mddrivename_t	*dnp = dnlp->drivenamep;
33170Sstevel@tonic-gate 		uint_t		i;
33180Sstevel@tonic-gate 
33190Sstevel@tonic-gate 		for (i = 0; (i < dnp->parts.parts_len); ++i) {
33200Sstevel@tonic-gate 			mdname_t	*np = &dnp->parts.parts_val[i];
33210Sstevel@tonic-gate 
33220Sstevel@tonic-gate 			if (np->dev == dev)
33230Sstevel@tonic-gate 				return (np->cname);
33240Sstevel@tonic-gate 		}
33250Sstevel@tonic-gate 	}
33260Sstevel@tonic-gate 
33270Sstevel@tonic-gate 	/* not found */
33280Sstevel@tonic-gate 	return (NULL);
33290Sstevel@tonic-gate }
33300Sstevel@tonic-gate 
33310Sstevel@tonic-gate /*
33320Sstevel@tonic-gate  * Ask the driver for the name, which has been stored in the
33330Sstevel@tonic-gate  * metadevice state database (on behalf of the utilities).
33340Sstevel@tonic-gate  * (by devno)
33350Sstevel@tonic-gate  */
33360Sstevel@tonic-gate char *
33370Sstevel@tonic-gate get_devname(
33380Sstevel@tonic-gate 	set_t setno,
33390Sstevel@tonic-gate 	md_dev64_t dev)
33400Sstevel@tonic-gate {
33410Sstevel@tonic-gate 	mdsetname_t	*sp;
33420Sstevel@tonic-gate 	mdname_t	*np;
33430Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
33440Sstevel@tonic-gate 
33450Sstevel@tonic-gate 	/* get name */
33460Sstevel@tonic-gate 	if ((setno == MD_SET_BAD) ||
33470Sstevel@tonic-gate 	    ((sp = metasetnosetname(setno, &status)) == NULL) ||
33480Sstevel@tonic-gate 	    ((np = metadevname(&sp, dev, &status)) == NULL)) {
33490Sstevel@tonic-gate 		mdclrerror(&status);
33500Sstevel@tonic-gate 		return (metadevtocachename(dev));
33510Sstevel@tonic-gate 	}
33520Sstevel@tonic-gate 
33530Sstevel@tonic-gate 	/* return name */
33540Sstevel@tonic-gate 	return (np->cname);
33550Sstevel@tonic-gate }
33560Sstevel@tonic-gate 
33570Sstevel@tonic-gate /*
33580Sstevel@tonic-gate  * get name from key
33590Sstevel@tonic-gate  */
33600Sstevel@tonic-gate mdname_t *
33610Sstevel@tonic-gate metakeyname(
33620Sstevel@tonic-gate 	mdsetname_t	**spp,
33630Sstevel@tonic-gate 	mdkey_t		key,
33640Sstevel@tonic-gate 	int		fast,
33650Sstevel@tonic-gate 	md_error_t	*ep
33660Sstevel@tonic-gate )
33670Sstevel@tonic-gate {
33680Sstevel@tonic-gate 	char		*device_name;
33690Sstevel@tonic-gate 	md_dev64_t	dev = NODEV64;
33700Sstevel@tonic-gate 	mdname_t	*namep;
33710Sstevel@tonic-gate 
33720Sstevel@tonic-gate 	/* create local set, if necessary */
33730Sstevel@tonic-gate 	if (*spp == NULL) {
33740Sstevel@tonic-gate 		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
33750Sstevel@tonic-gate 			return (NULL);
33760Sstevel@tonic-gate 	}
33770Sstevel@tonic-gate 
33780Sstevel@tonic-gate 	/* get name from namespace */
33790Sstevel@tonic-gate 	if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD,
33800Sstevel@tonic-gate 	    key, NULL, NULL, &dev, ep)) == NULL) {
33810Sstevel@tonic-gate 		return (NULL);
33820Sstevel@tonic-gate 	}
33830Sstevel@tonic-gate 	if (fast)
3384*1623Stw21770 		namep = metaname_fast(spp, device_name, UNKNOWN, ep);
33850Sstevel@tonic-gate 	else
3386*1623Stw21770 		namep = metaname(spp, device_name, UNKNOWN, ep);
33870Sstevel@tonic-gate 
33880Sstevel@tonic-gate 	assert(dev != NODEV64);
33890Sstevel@tonic-gate 	if (namep)
33900Sstevel@tonic-gate 		namep->dev = dev;
33910Sstevel@tonic-gate 	Free(device_name);
33920Sstevel@tonic-gate 	return (namep);
33930Sstevel@tonic-gate }
33940Sstevel@tonic-gate 
33950Sstevel@tonic-gate /*
3396*1623Stw21770  * completely flush metadev/hsp caches
3397*1623Stw21770  */
3398*1623Stw21770 void
3399*1623Stw21770 metaflushmetanames()
3400*1623Stw21770 {
3401*1623Stw21770 	metaflushhspnames();
3402*1623Stw21770 	metaflushdrivenames();
3403*1623Stw21770 	metaflushfastnames();
3404*1623Stw21770 	metaflushstatcache();
3405*1623Stw21770 }
3406*1623Stw21770 
3407*1623Stw21770 /*
34080Sstevel@tonic-gate  * completely flush the caches
34090Sstevel@tonic-gate  */
34100Sstevel@tonic-gate void
34110Sstevel@tonic-gate metaflushnames(int flush_sr_cache)
34120Sstevel@tonic-gate {
34130Sstevel@tonic-gate 	metaflushhspnames();
34140Sstevel@tonic-gate 	metaflushdrivenames();
34150Sstevel@tonic-gate 	metaflushsetnames();
34160Sstevel@tonic-gate 	metaflushctlrcache();
34170Sstevel@tonic-gate 	metaflushfastnames();
34180Sstevel@tonic-gate 	metaflushstatcache();
34190Sstevel@tonic-gate 	if (flush_sr_cache)
34200Sstevel@tonic-gate 		sr_cache_flush(0);
34210Sstevel@tonic-gate }
34220Sstevel@tonic-gate 
34230Sstevel@tonic-gate /*
34240Sstevel@tonic-gate  * meta_get_hotspare_names
34250Sstevel@tonic-gate  *  returns an mdnamelist_t of hot spare names
34260Sstevel@tonic-gate  */
34270Sstevel@tonic-gate 
34280Sstevel@tonic-gate int
34290Sstevel@tonic-gate meta_get_hotspare_names(
34300Sstevel@tonic-gate 	mdsetname_t	*sp,
34310Sstevel@tonic-gate 	mdnamelist_t	**nlpp,
34320Sstevel@tonic-gate 	int		options,
34330Sstevel@tonic-gate 	md_error_t	*ep
34340Sstevel@tonic-gate )
34350Sstevel@tonic-gate {
34360Sstevel@tonic-gate 	mdhspnamelist_t		*hspnlp	= NULL;
34370Sstevel@tonic-gate 	mdhspnamelist_t		*hspp;
34380Sstevel@tonic-gate 	int			cnt = 0;
34390Sstevel@tonic-gate 
34400Sstevel@tonic-gate 	assert(nlpp != NULL);
34410Sstevel@tonic-gate 
34420Sstevel@tonic-gate 	/* get hotspare names */
34430Sstevel@tonic-gate 	if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) {
34440Sstevel@tonic-gate 		cnt = -1;
34450Sstevel@tonic-gate 		goto out;
34460Sstevel@tonic-gate 	}
34470Sstevel@tonic-gate 
34480Sstevel@tonic-gate 	/* build name list */
34490Sstevel@tonic-gate 	for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) {
34500Sstevel@tonic-gate 		md_hsp_t	*hsp;
34510Sstevel@tonic-gate 		int		i;
34520Sstevel@tonic-gate 
34530Sstevel@tonic-gate 		if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) {
34540Sstevel@tonic-gate 			cnt = -1;
34550Sstevel@tonic-gate 			goto out;
34560Sstevel@tonic-gate 		}
34570Sstevel@tonic-gate 		for (i = 0; (i < hsp->hotspares.hotspares_len); i++) {
34580Sstevel@tonic-gate 			md_hs_t	*hs = &hsp->hotspares.hotspares_val[i];
34590Sstevel@tonic-gate 
34600Sstevel@tonic-gate 			(void) metanamelist_append(nlpp, hs->hsnamep);
34610Sstevel@tonic-gate 			++cnt;
34620Sstevel@tonic-gate 		}
34630Sstevel@tonic-gate 	}
34640Sstevel@tonic-gate 
34650Sstevel@tonic-gate 	/* cleanup and return count or error */
34660Sstevel@tonic-gate out:
34670Sstevel@tonic-gate 	metafreehspnamelist(hspnlp);
34680Sstevel@tonic-gate 	if ((cnt == -1) && mdisok(ep)) {
34690Sstevel@tonic-gate 		/*
34700Sstevel@tonic-gate 		 * At least try to give some sort of meaningful error
34710Sstevel@tonic-gate 		 */
34720Sstevel@tonic-gate 		(void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error");
34730Sstevel@tonic-gate 	}
34740Sstevel@tonic-gate 
34750Sstevel@tonic-gate 	return (cnt);
34760Sstevel@tonic-gate }
34770Sstevel@tonic-gate /*
34780Sstevel@tonic-gate  * meta_create_non_dup_list
34790Sstevel@tonic-gate  *    INPUT: mdnp mdname_t pointer to add to the list if a new name
34800Sstevel@tonic-gate  *           ldevidp list of non-duplicate names.
34810Sstevel@tonic-gate  *    OUTPUT: ldevidp list of non-duplicate names.
34820Sstevel@tonic-gate  * meta_create_non_dup_list will take a mdname_t pointer and if the device
34830Sstevel@tonic-gate  *    is not in the list (ldevidp) will add it to the list.
34840Sstevel@tonic-gate  *    User needs to free allocated memory.
34850Sstevel@tonic-gate  */
34860Sstevel@tonic-gate void
34870Sstevel@tonic-gate meta_create_non_dup_list(
34880Sstevel@tonic-gate 	mdname_t	*mdnp,
34890Sstevel@tonic-gate 	mddevid_t	**ldevidpp
34900Sstevel@tonic-gate )
34910Sstevel@tonic-gate {
34920Sstevel@tonic-gate 	char		*lcname;
34930Sstevel@tonic-gate 	mddevid_t	*tmp;
34940Sstevel@tonic-gate 	mddevid_t	*lastdevidp;
34950Sstevel@tonic-gate 	mddevid_t	*lldevidp;
34960Sstevel@tonic-gate 	char		*ctd, *slice;
34970Sstevel@tonic-gate 	mddevid_t	*ldevidp;
34980Sstevel@tonic-gate 
34990Sstevel@tonic-gate 	if (mdnp == NULL)
35000Sstevel@tonic-gate 		return;
35010Sstevel@tonic-gate 
35020Sstevel@tonic-gate 	ldevidp = *ldevidpp;
35030Sstevel@tonic-gate 	/*
35040Sstevel@tonic-gate 	 * Grab the name of the device and strip off slice information
35050Sstevel@tonic-gate 	 */
35060Sstevel@tonic-gate 	lcname = Strdup(mdnp->cname);
35070Sstevel@tonic-gate 	if (lcname == NULL) {
35080Sstevel@tonic-gate 		return;
35090Sstevel@tonic-gate 	}
35100Sstevel@tonic-gate 	ctd = strrchr(lcname, '/');
35110Sstevel@tonic-gate 	if (ctd != NULL)
35120Sstevel@tonic-gate 		slice = strrchr(ctd, 's');
35130Sstevel@tonic-gate 	else
35140Sstevel@tonic-gate 		slice = strrchr(lcname, 's');
35150Sstevel@tonic-gate 
35160Sstevel@tonic-gate 	if (slice != NULL)
35170Sstevel@tonic-gate 		*slice = '\0';
35180Sstevel@tonic-gate 
35190Sstevel@tonic-gate 	if (ldevidp == NULL) {
35200Sstevel@tonic-gate 		/* first item in list */
35210Sstevel@tonic-gate 		ldevidp = Zalloc(sizeof (mddevid_t));
35220Sstevel@tonic-gate 		ldevidp->ctdname = lcname;
35230Sstevel@tonic-gate 		ldevidp->key = mdnp->key;
35240Sstevel@tonic-gate 		*ldevidpp = ldevidp;
35250Sstevel@tonic-gate 	} else {
35260Sstevel@tonic-gate 		for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) {
35270Sstevel@tonic-gate 			if (strcmp(tmp->ctdname, lcname) == 0) {
35280Sstevel@tonic-gate 				/* already there so just return */
35290Sstevel@tonic-gate 				Free(lcname);
35300Sstevel@tonic-gate 				return;
35310Sstevel@tonic-gate 			}
35320Sstevel@tonic-gate 			lastdevidp = tmp;
35330Sstevel@tonic-gate 		}
35340Sstevel@tonic-gate 		lldevidp = Zalloc(sizeof (mddevid_t));
35350Sstevel@tonic-gate 		lldevidp->ctdname = lcname;
35360Sstevel@tonic-gate 		lldevidp->key = mdnp->key;
35370Sstevel@tonic-gate 		lastdevidp->next = lldevidp;
35380Sstevel@tonic-gate 	}
35390Sstevel@tonic-gate }
3540