xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_name.c (revision 871:f917b2ed7d21)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <meta.h>
300Sstevel@tonic-gate #include <metad.h>
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <ctype.h>
330Sstevel@tonic-gate #include <string.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 /*
640Sstevel@tonic-gate  * leak proof name conversion
650Sstevel@tonic-gate  */
660Sstevel@tonic-gate static char *
670Sstevel@tonic-gate rawname(
680Sstevel@tonic-gate 	char	*uname
690Sstevel@tonic-gate )
700Sstevel@tonic-gate {
710Sstevel@tonic-gate 	char	*p;
720Sstevel@tonic-gate 	struct stat	sbuf1, sbuf2;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	if ((p = getfullrawname(uname)) == NULL) {
750Sstevel@tonic-gate 		return (NULL);
760Sstevel@tonic-gate 	} else if (*p == '\0') {
770Sstevel@tonic-gate 		Free(p);
780Sstevel@tonic-gate 		return (NULL);
790Sstevel@tonic-gate 	} else {
800Sstevel@tonic-gate 		if (stat(uname, &sbuf1) != 0) {
810Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
820Sstevel@tonic-gate 			    "device to mount in /etc/vfstab is "
830Sstevel@tonic-gate 			    "invalid for device %s\n"), uname);
840Sstevel@tonic-gate 			exit(1);
850Sstevel@tonic-gate 		}
860Sstevel@tonic-gate 		if (stat(p, &sbuf2) != 0) {
870Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
880Sstevel@tonic-gate 			    "device to fsck in /etc/vfstab is "
890Sstevel@tonic-gate 			    "invalid for raw device %s\n"), p);
900Sstevel@tonic-gate 			exit(1);
910Sstevel@tonic-gate 		}
920Sstevel@tonic-gate 		if (sbuf1.st_rdev != sbuf2.st_rdev) {
930Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
940Sstevel@tonic-gate 			    "/etc/vfstab entries inconsistent on "
950Sstevel@tonic-gate 			    "line containing device %s\n"), uname);
960Sstevel@tonic-gate 			exit(1);
970Sstevel@tonic-gate 		}
98*871Scasper 		if (!S_ISBLK(sbuf1.st_mode)) {
990Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
1000Sstevel@tonic-gate 			    "/etc/vfstab device to mount is not a "
1010Sstevel@tonic-gate 			    "block device for device %s\n"), uname);
1020Sstevel@tonic-gate 			exit(1);
1030Sstevel@tonic-gate 		}
104*871Scasper 		if (!S_ISCHR(sbuf2.st_mode)) {
1050Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
1060Sstevel@tonic-gate 			    "/etc/vfstab device to fsck is not a "
1070Sstevel@tonic-gate 			    "raw device for device %s\n"), p);
1080Sstevel@tonic-gate 			exit(1);
1090Sstevel@tonic-gate 		}
1100Sstevel@tonic-gate 		return (p);
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate char *
1150Sstevel@tonic-gate blkname(
1160Sstevel@tonic-gate 	char	*uname
1170Sstevel@tonic-gate )
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate 	char	*p;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	if ((p = getfullblkname(uname)) == NULL) {
1220Sstevel@tonic-gate 		return (NULL);
1230Sstevel@tonic-gate 	} else if (*p == '\0') {
1240Sstevel@tonic-gate 		Free(p);
1250Sstevel@tonic-gate 		return (NULL);
1260Sstevel@tonic-gate 	} else {
1270Sstevel@tonic-gate 		return (p);
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate /*
1320Sstevel@tonic-gate  * parse up metadevice name
1330Sstevel@tonic-gate  */
1340Sstevel@tonic-gate static int
1350Sstevel@tonic-gate parse_metadevice(
1360Sstevel@tonic-gate 	char		*uname,
1370Sstevel@tonic-gate 	char		**snamep,
1380Sstevel@tonic-gate 	unit_t		*unitp
1390Sstevel@tonic-gate )
1400Sstevel@tonic-gate {
1410Sstevel@tonic-gate 	char		*sname = Malloc(strlen(uname) + 1);
1420Sstevel@tonic-gate 	char		*tname = Malloc(strlen(uname) + 1);
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	unit_t		unit;
1450Sstevel@tonic-gate 	int		len;
1460Sstevel@tonic-gate 	char *up;
1470Sstevel@tonic-gate 	char *tp;
1480Sstevel@tonic-gate 	int lcws;	/* last character was slash */
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	/* handle dont cares */
1510Sstevel@tonic-gate 	if (unitp == NULL)
1520Sstevel@tonic-gate 		unitp = &unit;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	/* Now copy uname to tname by throwing away any duplicate '/' */
1550Sstevel@tonic-gate 	for (lcws = 0, tp = tname, up = uname; *up; up++) {
1560Sstevel@tonic-gate 		if (lcws) {
1570Sstevel@tonic-gate 			if (*up == '/') {
1580Sstevel@tonic-gate 				continue;
1590Sstevel@tonic-gate 			} else {
1600Sstevel@tonic-gate 				lcws = 0;
1610Sstevel@tonic-gate 			}
1620Sstevel@tonic-gate 		}
1630Sstevel@tonic-gate 		if (*up == '/') {
1640Sstevel@tonic-gate 			lcws = 1;
1650Sstevel@tonic-gate 		}
1660Sstevel@tonic-gate 		*tp++ = *up; /* ++ is done by for loop */
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 	*tp = '\0';
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	/* without set */
1710Sstevel@tonic-gate 	if ((sscanf(tname, "d%lu%n", unitp, &len) == 1) &&
1720Sstevel@tonic-gate 	    (strlen(tname) == len) && ((long)*unitp >= 0)) {
1730Sstevel@tonic-gate 		if (snamep != NULL)
1740Sstevel@tonic-gate 			*snamep = NULL;
1750Sstevel@tonic-gate 		Free(sname);
1760Sstevel@tonic-gate 		Free(tname);
1770Sstevel@tonic-gate 		return (0);
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	/* fully-qualified without set */
1810Sstevel@tonic-gate 	if (((sscanf(tname, "/dev/md/dsk/d%lu%n", unitp, &len) == 1) &&
1820Sstevel@tonic-gate 	    (strlen(tname) == len) && ((long)*unitp >= 0)) ||
1830Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/rdsk/d%lu%n", unitp, &len) == 1) &&
1840Sstevel@tonic-gate 	    (strlen(tname) == len) && ((long)*unitp >= 0))) {
1850Sstevel@tonic-gate 		if (snamep != NULL)
1860Sstevel@tonic-gate 			*snamep = Strdup(MD_LOCAL_NAME);
1870Sstevel@tonic-gate 		Free(sname);
1880Sstevel@tonic-gate 		Free(tname);
1890Sstevel@tonic-gate 		return (0);
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	/* with set */
1930Sstevel@tonic-gate 	if (((sscanf(tname, "%[^/]/d%lu%n", sname, unitp, &len) == 2) &&
1940Sstevel@tonic-gate 	    (strlen(tname) == len) && ((long)*unitp >= 0)) ||
1950Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/%[^/]/dsk/d%lu%n", sname,
1960Sstevel@tonic-gate 	    unitp, &len) == 2) &&
1970Sstevel@tonic-gate 	    (strlen(tname) == len) && ((long)*unitp >= 0)) ||
1980Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/%[^/]/rdsk/d%lu%n", sname,
1990Sstevel@tonic-gate 	    unitp, &len) == 2) &&
2000Sstevel@tonic-gate 	    (strlen(tname) == len) && ((long)*unitp >= 0))) {
2010Sstevel@tonic-gate 		if (snamep != NULL) {
2020Sstevel@tonic-gate 			*snamep = sname;
2030Sstevel@tonic-gate 		} else {
2040Sstevel@tonic-gate 			Free(sname);
2050Sstevel@tonic-gate 		}
2060Sstevel@tonic-gate 		Free(tname);
2070Sstevel@tonic-gate 		return (0);
2080Sstevel@tonic-gate 	}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	/* no match */
2110Sstevel@tonic-gate 	if (snamep != NULL)
2120Sstevel@tonic-gate 		*snamep = NULL;
2130Sstevel@tonic-gate 	Free(sname);
2140Sstevel@tonic-gate 	Free(tname);
2150Sstevel@tonic-gate 	return (-1);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate /*
2190Sstevel@tonic-gate  * FUNCTION:	parse_device()
2200Sstevel@tonic-gate  * INPUT:	sp - pointer to setname struct
2210Sstevel@tonic-gate  *		uname - Name of either a hotspare pool or metadevice
2220Sstevel@tonic-gate  *			This can either be a fully qualified path or
2230Sstevel@tonic-gate  *			in the form [set name/]device
2240Sstevel@tonic-gate  * OUTPUT:	setnamep - name of the set that uname is in
2250Sstevel@tonic-gate  *		uname - name of the hotspare pools or metadevice
2260Sstevel@tonic-gate  *			only contains the name of the device with all
2270Sstevel@tonic-gate  *			other path information stripped off.
2280Sstevel@tonic-gate  * PURPOSE:	Parse uname and sp into the set name and device name strings.
2290Sstevel@tonic-gate  *		If the set name is specified as part of uname then use that
2300Sstevel@tonic-gate  *		otherwise attempt to get the set name from sp.
2310Sstevel@tonic-gate  */
2320Sstevel@tonic-gate static void
2330Sstevel@tonic-gate parse_device(
2340Sstevel@tonic-gate 	mdsetname_t	*sp,
2350Sstevel@tonic-gate 	char		*uname,
2360Sstevel@tonic-gate 	char		**setnamep /* dynamically alloced - caller must free */
2370Sstevel@tonic-gate )
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate 	char		setname[FILENAME_MAX+1];
2400Sstevel@tonic-gate 	char		*tname = Malloc(strlen(uname) + 1);
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	int		len;
2430Sstevel@tonic-gate 	char *up;
2440Sstevel@tonic-gate 	char *tp;
2450Sstevel@tonic-gate 	int lcws;	/* last character was slash */
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	/* Now copy uname to tname by throwing away any duplicate '/' */
2480Sstevel@tonic-gate 	for (lcws = 0, tp = tname, up = uname; *up; up++) {
2490Sstevel@tonic-gate 		if (lcws) {
2500Sstevel@tonic-gate 			if (*up == '/') {
2510Sstevel@tonic-gate 				continue;
2520Sstevel@tonic-gate 			} else {
2530Sstevel@tonic-gate 				lcws = 0;
2540Sstevel@tonic-gate 			}
2550Sstevel@tonic-gate 		}
2560Sstevel@tonic-gate 		if (*up == '/') {
2570Sstevel@tonic-gate 			lcws = 1;
2580Sstevel@tonic-gate 		}
2590Sstevel@tonic-gate 		*tp++ = *up; /* ++ is done by for loop */
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 	*tp = '\0';
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	/* fully-qualified  - local set */
2640Sstevel@tonic-gate 	if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
2650Sstevel@tonic-gate 			uname, &len) == 1) && (strlen(tname) == len)) ||
2660Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
2670Sstevel@tonic-gate 			uname, &len) == 1) && (strlen(tname) == len))) {
2680Sstevel@tonic-gate 		if (setnamep != NULL)
2690Sstevel@tonic-gate 			*setnamep = NULL;
2700Sstevel@tonic-gate 		Free(tname);
2710Sstevel@tonic-gate 		return;
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	/* with setname specified - either fully qualified and relative spec */
2750Sstevel@tonic-gate 	if (((sscanf(tname, "%" VAL2STR(FILENAME_MAX) "s/%"
2760Sstevel@tonic-gate 	    VAL2STR(FILENAME_MAX) "s%n", setname, uname, &len) == 2) &&
2770Sstevel@tonic-gate 			(strlen(tname) == len)) ||
2780Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
2790Sstevel@tonic-gate 		setname, uname, &len) == 2) && (strlen(tname) == len)) ||
2800Sstevel@tonic-gate 	    ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
2810Sstevel@tonic-gate 		setname, uname, &len) == 2) && (strlen(tname) == len))) {
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 		if (setnamep != NULL) {
2840Sstevel@tonic-gate 			*setnamep = Strdup(setname);
2850Sstevel@tonic-gate 		}
2860Sstevel@tonic-gate 		Free(tname);
2870Sstevel@tonic-gate 		return;
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	/* without setname specified */
2910Sstevel@tonic-gate 	(void) strcpy(uname, tname);
2920Sstevel@tonic-gate 	if (setnamep != NULL) {
2930Sstevel@tonic-gate 		if (sp != NULL && !metaislocalset(sp))
2940Sstevel@tonic-gate 			*setnamep = Strdup(sp->setname);
2950Sstevel@tonic-gate 		else
2960Sstevel@tonic-gate 			*setnamep = NULL;
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 	Free(tname);
2990Sstevel@tonic-gate }
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate /*
3020Sstevel@tonic-gate  * parse up hotspare pool name
3030Sstevel@tonic-gate  */
3040Sstevel@tonic-gate static int
3050Sstevel@tonic-gate parse_hsp(
3060Sstevel@tonic-gate 	char		*uname,
3070Sstevel@tonic-gate 	char		**snamep,
3080Sstevel@tonic-gate 	hsp_t		*hspp
3090Sstevel@tonic-gate )
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate 	char		*sname = Malloc(strlen(uname) + 1);
3120Sstevel@tonic-gate 	hsp_t		hsp;
3130Sstevel@tonic-gate 	int		len;
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	/* handle dont cares */
3160Sstevel@tonic-gate 	if (hspp == NULL)
3170Sstevel@tonic-gate 		hspp = &hsp;
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	/* without set */
3200Sstevel@tonic-gate 	if ((sscanf(uname, "hsp%03u%n", hspp, &len) == 1) &&
3210Sstevel@tonic-gate 	    (strlen(uname) == len) && ((long)*hspp >= 0)) {
3220Sstevel@tonic-gate 		if (snamep != NULL)
3230Sstevel@tonic-gate 			*snamep = NULL;
3240Sstevel@tonic-gate 		Free(sname);
3250Sstevel@tonic-gate 		return (0);
3260Sstevel@tonic-gate 	}
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	/* with set */
3290Sstevel@tonic-gate 	if ((sscanf(uname, "%[^/]/hsp%03u%n", sname,
3300Sstevel@tonic-gate 	    hspp, &len) == 2) &&
3310Sstevel@tonic-gate 	    (strlen(uname) == len) && ((long)*hspp >= 0)) {
3320Sstevel@tonic-gate 		if (snamep != NULL) {
3330Sstevel@tonic-gate 			*snamep = sname;
3340Sstevel@tonic-gate 		} else {
3350Sstevel@tonic-gate 			Free(sname);
3360Sstevel@tonic-gate 		}
3370Sstevel@tonic-gate 		return (0);
3380Sstevel@tonic-gate 	}
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	/* no match */
3410Sstevel@tonic-gate 	Free(sname);
3420Sstevel@tonic-gate 	return (-1);
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate /*
3460Sstevel@tonic-gate  * canonicalize metadevice name
3470Sstevel@tonic-gate  */
3480Sstevel@tonic-gate static char *
3490Sstevel@tonic-gate canon_metadevice(
3500Sstevel@tonic-gate 	char	*sname,
3510Sstevel@tonic-gate 	unit_t	unit
3520Sstevel@tonic-gate )
3530Sstevel@tonic-gate {
3540Sstevel@tonic-gate 	char	*cname;
3550Sstevel@tonic-gate 	size_t	len;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
3580Sstevel@tonic-gate 		len = strlen("d") + 20 + 1;
3590Sstevel@tonic-gate 		cname = Malloc(len);
3600Sstevel@tonic-gate 		(void) snprintf(cname, len, "d%lu", unit);
3610Sstevel@tonic-gate 	} else {
3620Sstevel@tonic-gate 		len = strlen(sname) + strlen("/d") + 20 + 1;
3630Sstevel@tonic-gate 		cname = Malloc(len);
3640Sstevel@tonic-gate 		(void) snprintf(cname, len, "%s/d%lu", sname, unit);
3650Sstevel@tonic-gate 	}
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	return (cname);
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate /*
3710Sstevel@tonic-gate  * canonicalize hotspare pool name
3720Sstevel@tonic-gate  */
3730Sstevel@tonic-gate static char *
3740Sstevel@tonic-gate canon_hsp(
3750Sstevel@tonic-gate 	char	*sname,
3760Sstevel@tonic-gate 	hsp_t	hsp
3770Sstevel@tonic-gate )
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate 	char	*cname;
3800Sstevel@tonic-gate 	size_t	len;
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
3830Sstevel@tonic-gate 		cname = Malloc(strlen("hsp000") + 1);
3840Sstevel@tonic-gate 		(void) sprintf(cname, "hsp%03u", hsp);
3850Sstevel@tonic-gate 	} else {
3860Sstevel@tonic-gate 		len = strlen(sname) + strlen("/hsp000") + 1;
3870Sstevel@tonic-gate 		cname = Malloc(len);
3880Sstevel@tonic-gate 		(void) snprintf(cname, len, "%s/hsp%03lu", sname, hsp);
3890Sstevel@tonic-gate 	}
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	return (cname);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate /*
3950Sstevel@tonic-gate  * canonicalize name, return type
3960Sstevel@tonic-gate  *
3970Sstevel@tonic-gate  * NOTE: this is really only for use by meta_tab*
3980Sstevel@tonic-gate  */
3990Sstevel@tonic-gate char *
4000Sstevel@tonic-gate meta_canonicalize(
4010Sstevel@tonic-gate 	mdsetname_t	*sp,
4020Sstevel@tonic-gate 	char		*uname
4030Sstevel@tonic-gate )
4040Sstevel@tonic-gate {
4050Sstevel@tonic-gate 	char	*sname = NULL;
4060Sstevel@tonic-gate 	char	*cname;
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	/* return the set name and dev name */
4090Sstevel@tonic-gate 	parse_device(sp, uname, &sname);
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	if (sname == NULL)
4120Sstevel@tonic-gate 		cname = Strdup(uname);
4130Sstevel@tonic-gate 	else {
4140Sstevel@tonic-gate 		size_t	cname_len;
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 		cname_len = strlen(uname) + strlen(sname) + 2;
4170Sstevel@tonic-gate 		cname = Malloc(cname_len);
4180Sstevel@tonic-gate 		(void) snprintf(
4190Sstevel@tonic-gate 		    cname, cname_len, "%s/%s", sname, uname);
4200Sstevel@tonic-gate 		Free(sname);
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate 	return (cname);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate /*
4260Sstevel@tonic-gate  * check that name is a metadevice
4270Sstevel@tonic-gate  */
4280Sstevel@tonic-gate int
4290Sstevel@tonic-gate is_metaname(
4300Sstevel@tonic-gate 	char	*uname
4310Sstevel@tonic-gate )
4320Sstevel@tonic-gate {
4330Sstevel@tonic-gate 	if (parse_metadevice(uname, NULL, NULL) == 0)
4340Sstevel@tonic-gate 		return (1);
4350Sstevel@tonic-gate 	else
4360Sstevel@tonic-gate 		return (0);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate /*
4400Sstevel@tonic-gate  * check that name is a hotspare pool
4410Sstevel@tonic-gate  */
4420Sstevel@tonic-gate int
4430Sstevel@tonic-gate is_hspname(
4440Sstevel@tonic-gate 	char	*uname
4450Sstevel@tonic-gate )
4460Sstevel@tonic-gate {
4470Sstevel@tonic-gate 	if (parse_hsp(uname, NULL, NULL) == 0)
4480Sstevel@tonic-gate 		return (1);
4490Sstevel@tonic-gate 	else
4500Sstevel@tonic-gate 		return (0);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate /*
4540Sstevel@tonic-gate  *	mdsetname_t stuff
4550Sstevel@tonic-gate  */
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate /*
4580Sstevel@tonic-gate  * initialize setname
4590Sstevel@tonic-gate  */
4600Sstevel@tonic-gate static void
4610Sstevel@tonic-gate metainitsetname(
4620Sstevel@tonic-gate 	mdsetname_t	*sp
4630Sstevel@tonic-gate )
4640Sstevel@tonic-gate {
4650Sstevel@tonic-gate 	(void) memset(sp, '\0', sizeof (*sp));
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate static void
4690Sstevel@tonic-gate metafreesetdesc(md_set_desc *sd)
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate 	md_mnnode_desc	*nd;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
4740Sstevel@tonic-gate 		nd = sd->sd_nodelist;
4750Sstevel@tonic-gate 		while (nd) {
4760Sstevel@tonic-gate 			sd->sd_nodelist = nd->nd_next;
4770Sstevel@tonic-gate 			Free(nd);
4780Sstevel@tonic-gate 			nd = sd->sd_nodelist;
4790Sstevel@tonic-gate 		}
4800Sstevel@tonic-gate 	}
4810Sstevel@tonic-gate 	metafreedrivedesc(&sd->sd_drvs);
4820Sstevel@tonic-gate 	Free(sd);
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate /*
4860Sstevel@tonic-gate  * free allocated setname
4870Sstevel@tonic-gate  */
4880Sstevel@tonic-gate static void
4890Sstevel@tonic-gate metafreesetname(
4900Sstevel@tonic-gate 	mdsetname_t	*sp
4910Sstevel@tonic-gate )
4920Sstevel@tonic-gate {
4930Sstevel@tonic-gate 	if (sp->setname != NULL)
4940Sstevel@tonic-gate 		Free(sp->setname);
4950Sstevel@tonic-gate 	if (sp->setdesc != NULL)
4960Sstevel@tonic-gate 		metafreesetdesc(sp->setdesc);
4970Sstevel@tonic-gate 	metainitsetname(sp);
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate /*
5010Sstevel@tonic-gate  * flush the setname cache
5020Sstevel@tonic-gate  */
5030Sstevel@tonic-gate static void
5040Sstevel@tonic-gate metaflushsetnames()
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate 	mdsetnamelist_t		*p, *n;
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	for (p = setlistp, n = NULL; (p != NULL); p = n) {
5090Sstevel@tonic-gate 		n = p->next;
5100Sstevel@tonic-gate 		metafreesetname(p->sp);
5110Sstevel@tonic-gate 		Free(p->sp);
5120Sstevel@tonic-gate 		Free(p);
5130Sstevel@tonic-gate 	}
5140Sstevel@tonic-gate 	setlistp = NULL;
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate /*
5180Sstevel@tonic-gate  * get set number
5190Sstevel@tonic-gate  */
5200Sstevel@tonic-gate static int
5210Sstevel@tonic-gate getsetno(
5220Sstevel@tonic-gate 	char		*sname,
5230Sstevel@tonic-gate 	set_t		*setnop,
5240Sstevel@tonic-gate 	md_error_t	*ep
5250Sstevel@tonic-gate )
5260Sstevel@tonic-gate {
5270Sstevel@tonic-gate 	md_set_record	*sr;
5280Sstevel@tonic-gate 	size_t		len;
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	/* local set */
5310Sstevel@tonic-gate 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
5320Sstevel@tonic-gate 		*setnop = 0;
5330Sstevel@tonic-gate 		return (0);
5340Sstevel@tonic-gate 	}
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	/* shared set */
5370Sstevel@tonic-gate 	if ((sr = getsetbyname(sname, ep)) == NULL) {
5380Sstevel@tonic-gate 		if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) {
5390Sstevel@tonic-gate 			char	*p;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 			len = strlen(sname) + 30;
5420Sstevel@tonic-gate 			p = Malloc(len);
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 			(void) snprintf(p, len, "setname \"%s\"", sname);
5450Sstevel@tonic-gate 			(void) mderror(ep, MDE_NO_SET, p);
5460Sstevel@tonic-gate 			Free(p);
5470Sstevel@tonic-gate 		}
5480Sstevel@tonic-gate 		return (-1);
5490Sstevel@tonic-gate 	}
5500Sstevel@tonic-gate 	*setnop = sr->sr_setno;
5510Sstevel@tonic-gate 	free_sr(sr);
5520Sstevel@tonic-gate 	return (0);
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate /*
5560Sstevel@tonic-gate  * find setname from name
5570Sstevel@tonic-gate  */
5580Sstevel@tonic-gate mdsetname_t *
5590Sstevel@tonic-gate metasetname(
5600Sstevel@tonic-gate 	char		*sname,
5610Sstevel@tonic-gate 	md_error_t	*ep
5620Sstevel@tonic-gate )
5630Sstevel@tonic-gate {
5640Sstevel@tonic-gate 	mdsetnamelist_t	**tail;
5650Sstevel@tonic-gate 	set_t		setno;
5660Sstevel@tonic-gate 	mdsetname_t	*sp;
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	/* look for cached value first */
5690Sstevel@tonic-gate 	assert(sname != NULL);
5700Sstevel@tonic-gate 	for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) {
5710Sstevel@tonic-gate 		sp = (*tail)->sp;
5720Sstevel@tonic-gate 		if (strcmp(sp->setname, sname) == 0) {
5730Sstevel@tonic-gate 			return (sp);
5740Sstevel@tonic-gate 		}
5750Sstevel@tonic-gate 	}
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	/* setup set */
5780Sstevel@tonic-gate 	if (getsetno(sname, &setno, ep) != 0)
5790Sstevel@tonic-gate 		return (NULL);
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	/* allocate new list element and setname */
5820Sstevel@tonic-gate 	*tail = Zalloc(sizeof (**tail));
5830Sstevel@tonic-gate 	sp = (*tail)->sp = Zalloc(sizeof (*sp));
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	sp->setname = Strdup(sname);
5860Sstevel@tonic-gate 	sp->setno = setno;
5870Sstevel@tonic-gate 	sp->lockfd = MD_NO_LOCK;
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	return (sp);
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate /*
5930Sstevel@tonic-gate  * find setname from setno
5940Sstevel@tonic-gate  */
5950Sstevel@tonic-gate mdsetname_t *
5960Sstevel@tonic-gate metasetnosetname(
5970Sstevel@tonic-gate 	set_t		setno,
5980Sstevel@tonic-gate 	md_error_t	*ep
5990Sstevel@tonic-gate )
6000Sstevel@tonic-gate {
6010Sstevel@tonic-gate 	mdsetnamelist_t	*slp;
6020Sstevel@tonic-gate 	mdsetname_t	*sp;
6030Sstevel@tonic-gate 	md_set_record	*sr;
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	/* look for cached value first */
6060Sstevel@tonic-gate 	for (slp = setlistp; (slp != NULL); slp = slp->next) {
6070Sstevel@tonic-gate 		sp = slp->sp;
6080Sstevel@tonic-gate 		if (sp->setno == setno)
6090Sstevel@tonic-gate 			return (sp);
6100Sstevel@tonic-gate 	}
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	/* local set */
6130Sstevel@tonic-gate 	if (setno == MD_LOCAL_SET)
6140Sstevel@tonic-gate 		return (metasetname(MD_LOCAL_NAME, ep));
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	/* shared set */
6170Sstevel@tonic-gate 	if ((sr = getsetbynum(setno, ep)) == NULL)
6180Sstevel@tonic-gate 		return (NULL);
6190Sstevel@tonic-gate 	sp = metasetname(sr->sr_setname, ep);
6200Sstevel@tonic-gate 	free_sr(sr);
6210Sstevel@tonic-gate 	return (sp);
6220Sstevel@tonic-gate }
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate mdsetname_t *
6250Sstevel@tonic-gate metafakesetname(
6260Sstevel@tonic-gate 	set_t		setno,
6270Sstevel@tonic-gate 	char		*sname
6280Sstevel@tonic-gate )
6290Sstevel@tonic-gate {
6300Sstevel@tonic-gate 	mdsetnamelist_t	**tail;
6310Sstevel@tonic-gate 	mdsetname_t	*sp;
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	/* look for cached value first */
6340Sstevel@tonic-gate 	for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) {
6350Sstevel@tonic-gate 		sp = (*tail)->sp;
6360Sstevel@tonic-gate 		if (sp->setno == setno) {
6370Sstevel@tonic-gate 			if ((sp->setname == NULL) && (sname != NULL))
6380Sstevel@tonic-gate 				sp->setname = Strdup(sname);
6390Sstevel@tonic-gate 			return (sp);
6400Sstevel@tonic-gate 		}
6410Sstevel@tonic-gate 	}
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 	/* allocate new list element and setname */
6440Sstevel@tonic-gate 	*tail = Zalloc(sizeof (**tail));
6450Sstevel@tonic-gate 	sp = (*tail)->sp = Zalloc(sizeof (*sp));
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	if (sname != NULL)
6480Sstevel@tonic-gate 		sp->setname = Strdup(sname);
6490Sstevel@tonic-gate 	sp->setno = setno;
6500Sstevel@tonic-gate 	sp->lockfd = MD_NO_LOCK;
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 	return (sp);
6530Sstevel@tonic-gate }
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate /*
6570Sstevel@tonic-gate  * setup set record (sr) and cache it in the mdsetname_t struct
6580Sstevel@tonic-gate  */
6590Sstevel@tonic-gate md_set_desc *
6600Sstevel@tonic-gate sr2setdesc(
6610Sstevel@tonic-gate 	md_set_record	*sr
6620Sstevel@tonic-gate )
6630Sstevel@tonic-gate {
6640Sstevel@tonic-gate 	md_set_desc	*sd;
6650Sstevel@tonic-gate 	int		i;
6660Sstevel@tonic-gate 	md_mnset_record	*mnsr;
6670Sstevel@tonic-gate 	md_mnnode_desc	*nd, *nd_prev = 0;
6680Sstevel@tonic-gate 	md_mnnode_record	*nr;
6690Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
6700Sstevel@tonic-gate 	md_error_t	*ep = &status;
6710Sstevel@tonic-gate 	int		nodecnt, nrcnt;
6720Sstevel@tonic-gate 	mndiskset_membershiplist_t *nl, *nl2;
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate 	sd = Zalloc(sizeof (*sd));
6750Sstevel@tonic-gate 	sd->sd_ctime = sr->sr_ctime;
6760Sstevel@tonic-gate 	sd->sd_genid = sr->sr_genid;
6770Sstevel@tonic-gate 	sd->sd_setno = sr->sr_setno;
6780Sstevel@tonic-gate 	sd->sd_flags = sr->sr_flags;
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
6810Sstevel@tonic-gate 		mnsr = (md_mnset_record *)sr;
6820Sstevel@tonic-gate 		(void) strlcpy(sd->sd_mn_master_nodenm,
6830Sstevel@tonic-gate 		    mnsr->sr_master_nodenm, sizeof (sd->sd_mn_master_nodenm));
6840Sstevel@tonic-gate 		sd->sd_mn_master_nodeid = mnsr->sr_master_nodeid;
6850Sstevel@tonic-gate 		if (strcmp(mnsr->sr_master_nodenm, mynode()) == 0) {
6860Sstevel@tonic-gate 			sd->sd_mn_am_i_master = 1;
6870Sstevel@tonic-gate 		}
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 		/*
6900Sstevel@tonic-gate 		 * Get membershiplist from API routine.  If there's
6910Sstevel@tonic-gate 		 * an error, just use a NULL nodelist.
6920Sstevel@tonic-gate 		 */
6930Sstevel@tonic-gate 		if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
6940Sstevel@tonic-gate 			nodecnt = 0;  /* no nodes are alive */
6950Sstevel@tonic-gate 			nl = NULL;
6960Sstevel@tonic-gate 		}
6970Sstevel@tonic-gate 		nr = mnsr->sr_nodechain;
6980Sstevel@tonic-gate 		nrcnt = 0;
6990Sstevel@tonic-gate 		/*
7000Sstevel@tonic-gate 		 * Node descriptor node list must be built in
7010Sstevel@tonic-gate 		 * ascending order of nodeid.  The nodechain
7020Sstevel@tonic-gate 		 * in the mnset record is in ascending order,
7030Sstevel@tonic-gate 		 * so just make them the same.
7040Sstevel@tonic-gate 		 */
7050Sstevel@tonic-gate 		while (nr) {
7060Sstevel@tonic-gate 			nd = Zalloc(sizeof (*nd));
7070Sstevel@tonic-gate 			if (nd_prev) {
7080Sstevel@tonic-gate 				nd_prev->nd_next = nd;
7090Sstevel@tonic-gate 			} else {
7100Sstevel@tonic-gate 				sd->sd_nodelist = nd;
7110Sstevel@tonic-gate 			}
7120Sstevel@tonic-gate 			nd->nd_ctime = nr->nr_ctime;
7130Sstevel@tonic-gate 			nd->nd_genid = nr->nr_genid;
7140Sstevel@tonic-gate 			nd->nd_flags = nr->nr_flags;
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 			(void) strlcpy(nd->nd_nodename, nr->nr_nodename,
7170Sstevel@tonic-gate 			    sizeof (nd->nd_nodename));
7180Sstevel@tonic-gate 			nd->nd_nodeid = nr->nr_nodeid;
7190Sstevel@tonic-gate 			if (strcmp(nd->nd_nodename, mynode()) == 0) {
7200Sstevel@tonic-gate 				sd->sd_mn_mynode = nd;
7210Sstevel@tonic-gate 			}
7220Sstevel@tonic-gate 			if (nd->nd_nodeid == sd->sd_mn_master_nodeid) {
7230Sstevel@tonic-gate 				sd->sd_mn_masternode = nd;
7240Sstevel@tonic-gate 			}
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 			/*
7270Sstevel@tonic-gate 			 * If node is marked ALIVE, then set priv_ic
7280Sstevel@tonic-gate 			 * from membership list.  During the early part
7290Sstevel@tonic-gate 			 * of a reconfig cycle, the membership list may
7300Sstevel@tonic-gate 			 * have been changed, (a node entering or leaving
7310Sstevel@tonic-gate 			 * the cluster), but rpc.metad hasn't flushed
7320Sstevel@tonic-gate 			 * its data yet.  So, if node is marked alive, but
7330Sstevel@tonic-gate 			 * is no longer in the membership list (node has
7340Sstevel@tonic-gate 			 * left the cluster) then just leave priv_ic to NULL.
7350Sstevel@tonic-gate 			 */
7360Sstevel@tonic-gate 			if (nd->nd_flags & MD_MN_NODE_ALIVE) {
7370Sstevel@tonic-gate 				nl2 = nl;
7380Sstevel@tonic-gate 				while (nl2) {
7390Sstevel@tonic-gate 					if (nl2->msl_node_id == nd->nd_nodeid) {
7400Sstevel@tonic-gate 						(void) strlcpy(nd->nd_priv_ic,
7410Sstevel@tonic-gate 						    nl2->msl_node_addr,
7420Sstevel@tonic-gate 						    sizeof (nd->nd_priv_ic));
7430Sstevel@tonic-gate 						break;
7440Sstevel@tonic-gate 					}
7450Sstevel@tonic-gate 					nl2 = nl2->next;
7460Sstevel@tonic-gate 				}
7470Sstevel@tonic-gate 			}
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 			nr = nr->nr_next;
7500Sstevel@tonic-gate 			nrcnt++;
7510Sstevel@tonic-gate 			nd_prev = nd;
7520Sstevel@tonic-gate 		}
7530Sstevel@tonic-gate 		sd->sd_mn_numnodes = nrcnt;
7540Sstevel@tonic-gate 		if (nodecnt)
7550Sstevel@tonic-gate 			meta_free_nodelist(nl);
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 		/* Just copying to keep consistent view between sr & sd */
7580Sstevel@tonic-gate 		(void) strlcpy(sd->sd_nodes[0], mnsr->sr_nodes_bw_compat[0],
7590Sstevel@tonic-gate 		    sizeof (sd->sd_nodes[0]));
7600Sstevel@tonic-gate 	} else {
7610Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++)
7620Sstevel@tonic-gate 			(void) strlcpy(sd->sd_nodes[i], sr->sr_nodes[i],
7630Sstevel@tonic-gate 			    sizeof (sd->sd_nodes[i]));
7640Sstevel@tonic-gate 	}
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 	sd->sd_med = sr->sr_med;		/* structure assignment */
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	return (sd);
7690Sstevel@tonic-gate }
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate md_set_desc *
7720Sstevel@tonic-gate metaget_setdesc(
7730Sstevel@tonic-gate 	mdsetname_t	*sp,
7740Sstevel@tonic-gate 	md_error_t	*ep
7750Sstevel@tonic-gate )
7760Sstevel@tonic-gate {
7770Sstevel@tonic-gate 	md_set_record	*sr;
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	if (sp->setdesc != NULL)
7800Sstevel@tonic-gate 		return (sp->setdesc);
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 	if (sp->setname != NULL) {
7830Sstevel@tonic-gate 		if ((sr = getsetbyname(sp->setname, ep)) != NULL) {
7840Sstevel@tonic-gate 			sp->setdesc = sr2setdesc(sr);
7850Sstevel@tonic-gate 			free_sr(sr);
7860Sstevel@tonic-gate 			return (sp->setdesc);
7870Sstevel@tonic-gate 		}
7880Sstevel@tonic-gate 	}
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	if (sp->setno > 0) {
7910Sstevel@tonic-gate 		if ((sr = getsetbynum(sp->setno, ep)) != NULL) {
7920Sstevel@tonic-gate 			sp->setdesc = sr2setdesc(sr);
7930Sstevel@tonic-gate 			free_sr(sr);
7940Sstevel@tonic-gate 			return (sp->setdesc);
7950Sstevel@tonic-gate 		}
7960Sstevel@tonic-gate 	}
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	return (NULL);
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate void
8020Sstevel@tonic-gate metaflushsetname(mdsetname_t *sp)
8030Sstevel@tonic-gate {
8040Sstevel@tonic-gate 	if (sp == NULL)
8050Sstevel@tonic-gate 		return;
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	if (sp->setdesc == NULL)
8080Sstevel@tonic-gate 		return;
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	metafreesetdesc(sp->setdesc);
8110Sstevel@tonic-gate 	sp->setdesc = NULL;
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate  * check for local set
8160Sstevel@tonic-gate  */
8170Sstevel@tonic-gate int
8180Sstevel@tonic-gate metaislocalset(
8190Sstevel@tonic-gate 	mdsetname_t	*sp
8200Sstevel@tonic-gate )
8210Sstevel@tonic-gate {
8220Sstevel@tonic-gate 	assert(sp->setname != NULL);
8230Sstevel@tonic-gate 	if (strcmp(sp->setname, MD_LOCAL_NAME) == 0) {
8240Sstevel@tonic-gate 		assert(sp->setno == MD_LOCAL_SET);
8250Sstevel@tonic-gate 		return (1);
8260Sstevel@tonic-gate 	} else {
8270Sstevel@tonic-gate 		assert(sp->setno != MD_LOCAL_SET);
8280Sstevel@tonic-gate 		return (0);
8290Sstevel@tonic-gate 	}
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate /*
8330Sstevel@tonic-gate  * check for same set
8340Sstevel@tonic-gate  */
8350Sstevel@tonic-gate int
8360Sstevel@tonic-gate metaissameset(
8370Sstevel@tonic-gate 	mdsetname_t	*sp1,
8380Sstevel@tonic-gate 	mdsetname_t	*sp2
8390Sstevel@tonic-gate )
8400Sstevel@tonic-gate {
8410Sstevel@tonic-gate 	if (strcmp(sp1->setname, sp2->setname) == 0) {
8420Sstevel@tonic-gate 		assert(sp1->setno == sp2->setno);
8430Sstevel@tonic-gate 		return (1);
8440Sstevel@tonic-gate 	} else {
8450Sstevel@tonic-gate 		assert(sp1->setno != sp2->setno);
8460Sstevel@tonic-gate 		return (0);
8470Sstevel@tonic-gate 	}
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate /*
8510Sstevel@tonic-gate  * check to see if set changed
8520Sstevel@tonic-gate  */
8530Sstevel@tonic-gate static int
8540Sstevel@tonic-gate chkset(
8550Sstevel@tonic-gate 	mdsetname_t	**spp,
8560Sstevel@tonic-gate 	char		*sname,
8570Sstevel@tonic-gate 	md_error_t	*ep
8580Sstevel@tonic-gate )
8590Sstevel@tonic-gate {
8600Sstevel@tonic-gate 	/* if we already have a set, make sure it's the same */
8610Sstevel@tonic-gate 	if (*spp != NULL) {
8620Sstevel@tonic-gate 		if ((*spp)->setname != sname &&
8630Sstevel@tonic-gate 				strcmp((*spp)->setname, sname) != 0) {
8640Sstevel@tonic-gate 			return (mderror(ep, MDE_SET_DIFF, sname));
8650Sstevel@tonic-gate 		}
8660Sstevel@tonic-gate 		return (0);
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate 	/* otherwise store new set name and number */
8700Sstevel@tonic-gate 	if ((*spp = metasetname(sname, ep)) == NULL) {
8710Sstevel@tonic-gate 		return (-1);
8720Sstevel@tonic-gate 	}
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	/* return success */
8750Sstevel@tonic-gate 	return (0);
8760Sstevel@tonic-gate }
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate /*
8790Sstevel@tonic-gate  * check to see if set changed from default
8800Sstevel@tonic-gate  */
8810Sstevel@tonic-gate static int
8820Sstevel@tonic-gate chksetname(
8830Sstevel@tonic-gate 	mdsetname_t	**spp,
8840Sstevel@tonic-gate 	char		*sname,
8850Sstevel@tonic-gate 	md_error_t	*ep
8860Sstevel@tonic-gate )
8870Sstevel@tonic-gate {
8880Sstevel@tonic-gate 	/* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */
8890Sstevel@tonic-gate 	if (sname == NULL) {
8900Sstevel@tonic-gate 		if (*spp) {
8910Sstevel@tonic-gate 			sname = (*spp)->setname;
8920Sstevel@tonic-gate 		} else {
8930Sstevel@tonic-gate 			sname = MD_LOCAL_NAME;
8940Sstevel@tonic-gate 		}
8950Sstevel@tonic-gate 	}
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	/* see if changed */
8980Sstevel@tonic-gate 	return (chkset(spp, sname, ep));
8990Sstevel@tonic-gate }
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate /*
9020Sstevel@tonic-gate  * check setname from setno
9030Sstevel@tonic-gate  */
9040Sstevel@tonic-gate static int
9050Sstevel@tonic-gate chksetno(
9060Sstevel@tonic-gate 	mdsetname_t	**spp,
9070Sstevel@tonic-gate 	set_t		setno,
9080Sstevel@tonic-gate 	md_error_t	*ep
9090Sstevel@tonic-gate )
9100Sstevel@tonic-gate {
9110Sstevel@tonic-gate 	md_set_record	*sr;
9120Sstevel@tonic-gate 	int		rval;
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate 	/* local set */
9150Sstevel@tonic-gate 	if (setno == 0)
9160Sstevel@tonic-gate 		return (chkset(spp, MD_LOCAL_NAME, ep));
9170Sstevel@tonic-gate 
9180Sstevel@tonic-gate 	/* shared set */
9190Sstevel@tonic-gate 	if ((sr = getsetbynum(setno, ep)) == NULL)
9200Sstevel@tonic-gate 		return (-1);
9210Sstevel@tonic-gate 	rval = chkset(spp, sr->sr_setname, ep);
9220Sstevel@tonic-gate 	free_sr(sr);
9230Sstevel@tonic-gate 	return (rval);
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate /*
9270Sstevel@tonic-gate  *	mddrivename_t stuff
9280Sstevel@tonic-gate  */
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate /*
9310Sstevel@tonic-gate  * initialize name
9320Sstevel@tonic-gate  */
9330Sstevel@tonic-gate static void
9340Sstevel@tonic-gate metainitname(
9350Sstevel@tonic-gate 	mdname_t	*np
9360Sstevel@tonic-gate )
9370Sstevel@tonic-gate {
9380Sstevel@tonic-gate 	(void) memset(np, 0, sizeof (*np));
9390Sstevel@tonic-gate 	np->dev = NODEV64;
9400Sstevel@tonic-gate 	np->key = MD_KEYBAD;
9410Sstevel@tonic-gate 	np->end_blk = -1;
9420Sstevel@tonic-gate 	np->start_blk = -1;
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate /*
9460Sstevel@tonic-gate  * free allocated name
9470Sstevel@tonic-gate  */
9480Sstevel@tonic-gate static void
9490Sstevel@tonic-gate metafreename(
9500Sstevel@tonic-gate 	mdname_t	*np
9510Sstevel@tonic-gate )
9520Sstevel@tonic-gate {
9530Sstevel@tonic-gate 	if (np->cname != NULL)
9540Sstevel@tonic-gate 		Free(np->cname);
9550Sstevel@tonic-gate 	if (np->bname != NULL)
9560Sstevel@tonic-gate 		Free(np->bname);
9570Sstevel@tonic-gate 	if (np->rname != NULL)
9580Sstevel@tonic-gate 		Free(np->rname);
9590Sstevel@tonic-gate 	if (np->devicesname != NULL)
9600Sstevel@tonic-gate 		Free(np->devicesname);
9610Sstevel@tonic-gate 	metainitname(np);
9620Sstevel@tonic-gate }
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate /*
9650Sstevel@tonic-gate  * initialize drive name
9660Sstevel@tonic-gate  */
9670Sstevel@tonic-gate static void
9680Sstevel@tonic-gate metainitdrivename(
9690Sstevel@tonic-gate 	mddrivename_t	*dnp
9700Sstevel@tonic-gate )
9710Sstevel@tonic-gate {
9720Sstevel@tonic-gate 	(void) memset(dnp, 0, sizeof (*dnp));
9730Sstevel@tonic-gate 	dnp->side_names_key = MD_KEYBAD;
9740Sstevel@tonic-gate }
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate /*
9770Sstevel@tonic-gate  * flush side names
9780Sstevel@tonic-gate  */
9790Sstevel@tonic-gate void
9800Sstevel@tonic-gate metaflushsidenames(
9810Sstevel@tonic-gate 	mddrivename_t	*dnp
9820Sstevel@tonic-gate )
9830Sstevel@tonic-gate {
9840Sstevel@tonic-gate 	mdsidenames_t	*p, *n;
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 	for (p = dnp->side_names, n = NULL; (p != NULL); p = n) {
9870Sstevel@tonic-gate 		n = p->next;
9880Sstevel@tonic-gate 		if (p->dname != NULL)
9890Sstevel@tonic-gate 			Free(p->dname);
9900Sstevel@tonic-gate 		if (p->cname != NULL)
9910Sstevel@tonic-gate 			Free(p->cname);
9920Sstevel@tonic-gate 		Free(p);
9930Sstevel@tonic-gate 	}
9940Sstevel@tonic-gate 	dnp->side_names = NULL;
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate /*
9980Sstevel@tonic-gate  * free drive name
9990Sstevel@tonic-gate  */
10000Sstevel@tonic-gate void
10010Sstevel@tonic-gate metafreedrivename(
10020Sstevel@tonic-gate 	mddrivename_t	*dnp
10030Sstevel@tonic-gate )
10040Sstevel@tonic-gate {
10050Sstevel@tonic-gate 	uint_t		slice;
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 	if (dnp->cname != NULL)
10080Sstevel@tonic-gate 		Free(dnp->cname);
10090Sstevel@tonic-gate 	if (dnp->rname != NULL)
10100Sstevel@tonic-gate 		Free(dnp->rname);
10110Sstevel@tonic-gate 	metafreevtoc(&dnp->vtoc);
10120Sstevel@tonic-gate 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice)
10130Sstevel@tonic-gate 		metafreename(&dnp->parts.parts_val[slice]);
10140Sstevel@tonic-gate 	if (dnp->parts.parts_val != NULL)
10150Sstevel@tonic-gate 		Free(dnp->parts.parts_val);
10160Sstevel@tonic-gate 	metaflushsidenames(dnp);
10170Sstevel@tonic-gate 	if (dnp->miscname != NULL)
10180Sstevel@tonic-gate 		Free(dnp->miscname);
10190Sstevel@tonic-gate 	meta_free_unit(dnp);
10200Sstevel@tonic-gate 	metainitdrivename(dnp);
10210Sstevel@tonic-gate }
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate /*
10240Sstevel@tonic-gate  * flush the drive name cache
10250Sstevel@tonic-gate  */
10260Sstevel@tonic-gate static void
10270Sstevel@tonic-gate metaflushdrivenames()
10280Sstevel@tonic-gate {
10290Sstevel@tonic-gate 	mddrivenamelist_t	*p, *n;
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate 	for (p = drivelistp, n = NULL; (p != NULL); p = n) {
10320Sstevel@tonic-gate 		n = p->next;
10330Sstevel@tonic-gate 		metafreedrivename(p->drivenamep);
10340Sstevel@tonic-gate 		Free(p->drivenamep);
10350Sstevel@tonic-gate 		Free(p);
10360Sstevel@tonic-gate 	}
10370Sstevel@tonic-gate 	drivelistp = NULL;
10380Sstevel@tonic-gate }
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate /*
10410Sstevel@tonic-gate  * peel off s%u from name
10420Sstevel@tonic-gate  */
10430Sstevel@tonic-gate char *
10440Sstevel@tonic-gate metadiskname(
10450Sstevel@tonic-gate 	char	*name
10460Sstevel@tonic-gate )
10470Sstevel@tonic-gate {
10480Sstevel@tonic-gate 	char	*p, *e;
10490Sstevel@tonic-gate 	char	onmb[BUFSIZ+1], cnmb[BUFSIZ];
10500Sstevel@tonic-gate 	uint_t	d = 0;
10510Sstevel@tonic-gate 	int	l = 0;
10520Sstevel@tonic-gate 	int	cl = strlen(name);
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 	if (is_metaname(name))
10550Sstevel@tonic-gate 	    return (Strdup(name));
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate 	/*
10580Sstevel@tonic-gate 	 * Handle old style names, which are of the form /dev/rXXNN[a-h].
10590Sstevel@tonic-gate 	 */
10600Sstevel@tonic-gate 	if (sscanf(name, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n",
10610Sstevel@tonic-gate 	    onmb, &d, &l) == 2 && l == cl) {
10620Sstevel@tonic-gate 		(void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u", onmb, d);
10630Sstevel@tonic-gate 		return (Strdup(cnmb));
10640Sstevel@tonic-gate 	}
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 	/*
10670Sstevel@tonic-gate 	 * Handle old style names, which are of the form /dev/XXNN[a-h].
10680Sstevel@tonic-gate 	 */
10690Sstevel@tonic-gate 	if (sscanf(name, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n",
10700Sstevel@tonic-gate 	    onmb, &d, &l) == 2 && l == cl) {
10710Sstevel@tonic-gate 		(void) snprintf(cnmb, sizeof (cnmb), "/dev/%s%u", onmb, d);
10720Sstevel@tonic-gate 		return (Strdup(cnmb));
10730Sstevel@tonic-gate 	}
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	/* gobble number and 's' */
10760Sstevel@tonic-gate 	p = e = name + strlen(name) - 1;
10770Sstevel@tonic-gate 	for (; (p > name); --p) {
10780Sstevel@tonic-gate 		if (!isdigit(*p))
10790Sstevel@tonic-gate 			break;
10800Sstevel@tonic-gate 	}
10810Sstevel@tonic-gate 	if ((p == e) || (p <= name))
10820Sstevel@tonic-gate 		return (Strdup(name));
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate 	if (*p != 's' && strchr("dt", *p) == NULL)
10850Sstevel@tonic-gate 		return (Strdup(name));
10860Sstevel@tonic-gate 	else if (strchr("dt", *p) != NULL)
10870Sstevel@tonic-gate 		return (Strdup(name));
10880Sstevel@tonic-gate 	p--;
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	if ((p <= name) || (!isdigit(*p)))
10910Sstevel@tonic-gate 		return (Strdup(name));
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	*(++p) = '\0';
10940Sstevel@tonic-gate 	e = Strdup(name);
10950Sstevel@tonic-gate 	*p = 's';
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate 	return (e);
10980Sstevel@tonic-gate }
10990Sstevel@tonic-gate 
11000Sstevel@tonic-gate /*
11010Sstevel@tonic-gate  * free list of drivenames
11020Sstevel@tonic-gate  */
11030Sstevel@tonic-gate void
11040Sstevel@tonic-gate metafreedrivenamelist(
11050Sstevel@tonic-gate 	mddrivenamelist_t	*dnlp
11060Sstevel@tonic-gate )
11070Sstevel@tonic-gate {
11080Sstevel@tonic-gate 	mddrivenamelist_t	*next = NULL;
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 	for (/* void */; (dnlp != NULL); dnlp = next) {
11110Sstevel@tonic-gate 		next = dnlp->next;
11120Sstevel@tonic-gate 		Free(dnlp);
11130Sstevel@tonic-gate 	}
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate /*
11170Sstevel@tonic-gate  * build list of drivenames
11180Sstevel@tonic-gate  */
11190Sstevel@tonic-gate int
11200Sstevel@tonic-gate metadrivenamelist(
11210Sstevel@tonic-gate 	mdsetname_t		**spp,
11220Sstevel@tonic-gate 	mddrivenamelist_t	**dnlpp,
11230Sstevel@tonic-gate 	int			argc,
11240Sstevel@tonic-gate 	char			*argv[],
11250Sstevel@tonic-gate 	md_error_t		*ep
11260Sstevel@tonic-gate )
11270Sstevel@tonic-gate {
11280Sstevel@tonic-gate 	mddrivenamelist_t	**tailpp = dnlpp;
11290Sstevel@tonic-gate 	int			count = 0;
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 	for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
11320Sstevel@tonic-gate 		mddrivenamelist_t	*dnlp = Zalloc(sizeof (*dnlp));
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 		if ((dnlp->drivenamep = metadrivename(spp, argv[0],
11350Sstevel@tonic-gate 		    ep)) == NULL) {
11360Sstevel@tonic-gate 			metafreedrivenamelist(*dnlpp);
11370Sstevel@tonic-gate 			*dnlpp = NULL;
11380Sstevel@tonic-gate 			return (-1);
11390Sstevel@tonic-gate 		}
11400Sstevel@tonic-gate 		*tailpp = dnlp;
11410Sstevel@tonic-gate 		tailpp = &dnlp->next;
11420Sstevel@tonic-gate 	}
11430Sstevel@tonic-gate 	return (count);
11440Sstevel@tonic-gate }
11450Sstevel@tonic-gate 
11460Sstevel@tonic-gate /*
11470Sstevel@tonic-gate  * append to end of drivename list
11480Sstevel@tonic-gate  */
11490Sstevel@tonic-gate mddrivename_t *
11500Sstevel@tonic-gate metadrivenamelist_append(
11510Sstevel@tonic-gate 	mddrivenamelist_t	**dnlpp,
11520Sstevel@tonic-gate 	mddrivename_t		*dnp
11530Sstevel@tonic-gate )
11540Sstevel@tonic-gate {
11550Sstevel@tonic-gate 	mddrivenamelist_t	*dnlp;
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 	/* run to end of list */
11580Sstevel@tonic-gate 	for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next)
11590Sstevel@tonic-gate 		;
11600Sstevel@tonic-gate 
11610Sstevel@tonic-gate 	/* allocate new list element */
11620Sstevel@tonic-gate 	dnlp = *dnlpp = Zalloc(sizeof (*dnlp));
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 	/* append drivename */
11650Sstevel@tonic-gate 	dnlp->drivenamep = dnp;
11660Sstevel@tonic-gate 	return (dnp);
11670Sstevel@tonic-gate }
11680Sstevel@tonic-gate 
11690Sstevel@tonic-gate /*
11700Sstevel@tonic-gate  * FUNCTION:	meta_drivenamelist_append_wrapper()
11710Sstevel@tonic-gate  * INPUT:	tailpp	- pointer to the list tail pointer
11720Sstevel@tonic-gate  *		dnp	- name node to be appended to list
11730Sstevel@tonic-gate  * OUTPUT:	none
11740Sstevel@tonic-gate  * RETURNS:	mddrivenamelist_t * - new tail of the list.
11750Sstevel@tonic-gate  * PURPOSE:	wrapper to meta_namelist_append for performance.
11760Sstevel@tonic-gate  *		metanamelist_append finds the tail each time which slows
11770Sstevel@tonic-gate  *		down long lists.  By keeping track of the tail ourselves
11780Sstevel@tonic-gate  *		we can change metadrivenamelist_append into a
11790Sstevel@tonic-gate  *		constant time operation.
11800Sstevel@tonic-gate  */
11810Sstevel@tonic-gate mddrivenamelist_t **
11820Sstevel@tonic-gate meta_drivenamelist_append_wrapper(
11830Sstevel@tonic-gate 	mddrivenamelist_t	**tailpp,
11840Sstevel@tonic-gate 	mddrivename_t	*dnp
11850Sstevel@tonic-gate )
11860Sstevel@tonic-gate {
11870Sstevel@tonic-gate 	(void) metadrivenamelist_append(tailpp, dnp);
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	/* If it's the first item in the list, return it instead of the next */
11900Sstevel@tonic-gate 	if ((*tailpp)->next == NULL)
11910Sstevel@tonic-gate 		return (tailpp);
11920Sstevel@tonic-gate 
11930Sstevel@tonic-gate 	return (&(*tailpp)->next);
11940Sstevel@tonic-gate }
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate 
11970Sstevel@tonic-gate /*
11980Sstevel@tonic-gate  *	mdname_t stuff
11990Sstevel@tonic-gate  */
12000Sstevel@tonic-gate 
12010Sstevel@tonic-gate /*
12020Sstevel@tonic-gate  * check set and get comparison name
12030Sstevel@tonic-gate  */
12040Sstevel@tonic-gate char *
12050Sstevel@tonic-gate meta_name_getname(
12060Sstevel@tonic-gate 	mdsetname_t	**spp,
12070Sstevel@tonic-gate 	char		*uname,
12080Sstevel@tonic-gate 	md_error_t	*ep
12090Sstevel@tonic-gate )
12100Sstevel@tonic-gate {
12110Sstevel@tonic-gate 	char		*sname = NULL;
12120Sstevel@tonic-gate 	int		ismeta = 0;
12130Sstevel@tonic-gate 	unit_t		unit;
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 	/* check set name */
12160Sstevel@tonic-gate 	if (parse_metadevice(uname, &sname, &unit) == 0)
12170Sstevel@tonic-gate 		ismeta = 1;
12180Sstevel@tonic-gate 	if (chksetname(spp, sname, ep) != 0) {
12190Sstevel@tonic-gate 		if (sname != NULL)
12200Sstevel@tonic-gate 			Free(sname);
12210Sstevel@tonic-gate 		return (NULL);
12220Sstevel@tonic-gate 	}
12230Sstevel@tonic-gate 	if (sname != NULL)
12240Sstevel@tonic-gate 		Free(sname);
12250Sstevel@tonic-gate 
12260Sstevel@tonic-gate 	/* return comparison name */
12270Sstevel@tonic-gate 	if (ismeta)
12280Sstevel@tonic-gate 		return (canon_metadevice((*spp)->setname, unit));
12290Sstevel@tonic-gate 	else
12300Sstevel@tonic-gate 		return (Strdup(uname));
12310Sstevel@tonic-gate }
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate /*
12340Sstevel@tonic-gate  * FUNCTION:	getrname()
12350Sstevel@tonic-gate  * INPUT:	spp	- the setname struct
12360Sstevel@tonic-gate  *		uname	- the possibly unqualified device name
12370Sstevel@tonic-gate  * OUTPUT:	ep	- return error pointer
12380Sstevel@tonic-gate  * RETURNS:	char*	- character string containing the fully
12390Sstevel@tonic-gate  *			qualified raw device name
12400Sstevel@tonic-gate  * PURPOSE:	Create the fully qualified raw name for the possibly
12410Sstevel@tonic-gate  *		unqualified device name.  If uname is an absolute
12420Sstevel@tonic-gate  *		path the raw name is derived from the input string.
12430Sstevel@tonic-gate  *		Otherwise, an attempt is made to get the rawname by
12440Sstevel@tonic-gate  *		catting "/dev/md/rdsk" and "/dev/rdsk".
12450Sstevel@tonic-gate  */
12460Sstevel@tonic-gate static char *
12470Sstevel@tonic-gate getrname(mdsetname_t **spp, char *uname, md_error_t *ep)
12480Sstevel@tonic-gate {
12490Sstevel@tonic-gate 	char	*rname,
12500Sstevel@tonic-gate 		*fname;
12510Sstevel@tonic-gate 	int	constructed = 0;
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 	assert(uname != NULL);
12540Sstevel@tonic-gate 	/* if it is an absolute name then just call rawname on the input */
12550Sstevel@tonic-gate 	if (uname[0] == '/') {
12560Sstevel@tonic-gate 	    if ((rname = rawname(uname)) != NULL)
12570Sstevel@tonic-gate 		return (rname);
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 	    /* out of luck */
12600Sstevel@tonic-gate 	    (void) mdsyserror(ep, ENOENT, uname);
12610Sstevel@tonic-gate 	    return (NULL);
12620Sstevel@tonic-gate 	}
12630Sstevel@tonic-gate 
12640Sstevel@tonic-gate 	/*
12650Sstevel@tonic-gate 	 * Check for metadevice before physical device.
12660Sstevel@tonic-gate 	 * With the introduction of softpartitions it is more
12670Sstevel@tonic-gate 	 * likely to be a metadevice.
12680Sstevel@tonic-gate 	 */
12690Sstevel@tonic-gate 
12700Sstevel@tonic-gate 	/* metadevice short form */
12710Sstevel@tonic-gate 	if (metaislocalset(*spp)) {
12720Sstevel@tonic-gate 		fname = Malloc(strlen(uname) + strlen("/dev/md/rdsk/") + 1);
12730Sstevel@tonic-gate 		(void) strcpy(fname, "/dev/md/rdsk/");
12740Sstevel@tonic-gate 		(void) strcat(fname, uname);
12750Sstevel@tonic-gate 		if (*uname == 'd')
12760Sstevel@tonic-gate 			constructed = 1;
12770Sstevel@tonic-gate 	} else {
12780Sstevel@tonic-gate 		char	*p;
12790Sstevel@tonic-gate 		size_t	len;
12800Sstevel@tonic-gate 
12810Sstevel@tonic-gate 		if ((p = strchr(uname, '/')) != NULL) {
12820Sstevel@tonic-gate 			++p;
12830Sstevel@tonic-gate 		} else {
12840Sstevel@tonic-gate 			p = uname;
12850Sstevel@tonic-gate 		}
12860Sstevel@tonic-gate 		len = strlen((*spp)->setname) + strlen(p) +
12870Sstevel@tonic-gate 		    strlen("/dev/md//rdsk/") + 1;
12880Sstevel@tonic-gate 		fname = Malloc(len);
12890Sstevel@tonic-gate 		(void) snprintf(fname, len, "/dev/md/%s/rdsk/%s",
12900Sstevel@tonic-gate 		    (*spp)->setname, p);
12910Sstevel@tonic-gate 		if (*p == 'd')
12920Sstevel@tonic-gate 			constructed = 1;
12930Sstevel@tonic-gate 	}
12940Sstevel@tonic-gate 	rname = rawname(fname);
12950Sstevel@tonic-gate 
12960Sstevel@tonic-gate 	/*
12970Sstevel@tonic-gate 	 * Handle the case where we have a new metadevice that does not yet
12980Sstevel@tonic-gate 	 * exist in the name-space. In this case we return the constructed
12990Sstevel@tonic-gate 	 * metadevice name as that will exist after the metainit call has
13000Sstevel@tonic-gate 	 * created it.
13010Sstevel@tonic-gate 	 */
13020Sstevel@tonic-gate 	if ((rname == NULL) && constructed) {
13030Sstevel@tonic-gate 		rname = Strdup(fname);
13040Sstevel@tonic-gate 	}
13050Sstevel@tonic-gate 	Free(fname);
13060Sstevel@tonic-gate 	if (rname != NULL)
13070Sstevel@tonic-gate 		return (rname);
13080Sstevel@tonic-gate 
13090Sstevel@tonic-gate 	fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1);
13100Sstevel@tonic-gate 	(void) strcpy(fname, "/dev/rdsk/");
13110Sstevel@tonic-gate 	(void) strcat(fname, uname);
13120Sstevel@tonic-gate 	rname = rawname(fname);
13130Sstevel@tonic-gate 	Free(fname);
13140Sstevel@tonic-gate 	if (rname != NULL)
13150Sstevel@tonic-gate 		return (rname);
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 	/*
13180Sstevel@tonic-gate 	 * If all else fails try the straight uname.
13190Sstevel@tonic-gate 	 * NOTE: This check was at the beginning of getrname instead
13200Sstevel@tonic-gate 	 * of here. It was moved to avoid a conflict with SC3.0. If
13210Sstevel@tonic-gate 	 * a diskset was mounted with the same name it would hang
13220Sstevel@tonic-gate 	 * the cluster in a loop. Example:
13230Sstevel@tonic-gate 	 *
13240Sstevel@tonic-gate 	 *	fubar/d10 -m fubar/d0 fubar/d1
13250Sstevel@tonic-gate 	 *	mount /dev/md/fubar/dsk/d10 /fubar
13260Sstevel@tonic-gate 	 *
13270Sstevel@tonic-gate 	 * When the system was booted DiskSuite would try to take ownership
13280Sstevel@tonic-gate 	 * of diskset fubar. This would cause rawname("fubar/d10") to be
13290Sstevel@tonic-gate 	 * called. rawname() stats the string which caused the cluster
13300Sstevel@tonic-gate 	 * reservation code to try and take ownership which it was already
13310Sstevel@tonic-gate 	 * doing and a deadlock would occur. By moving this final attempt
13320Sstevel@tonic-gate 	 * at resolving the rawname to the end we avoid this deadlock.
13330Sstevel@tonic-gate 	 */
13340Sstevel@tonic-gate 	if (rname = rawname(uname))
13350Sstevel@tonic-gate 		return (rname);
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate 	/* out of luck */
13380Sstevel@tonic-gate 	(void) mdsyserror(ep, ENOENT, uname);
13390Sstevel@tonic-gate 	return (NULL);
13400Sstevel@tonic-gate }
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate /*
13430Sstevel@tonic-gate  * get raw slice and drive names
13440Sstevel@tonic-gate  */
13450Sstevel@tonic-gate static char *
13460Sstevel@tonic-gate getrawnames(
13470Sstevel@tonic-gate 	mdsetname_t	**spp,
13480Sstevel@tonic-gate 	char		*uname,
13490Sstevel@tonic-gate 	char		**dnamep,
13500Sstevel@tonic-gate 	md_error_t	*ep
13510Sstevel@tonic-gate )
13520Sstevel@tonic-gate {
13530Sstevel@tonic-gate 	char		*rname;
13540Sstevel@tonic-gate 	size_t		len;
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate 	/* initialize */
13570Sstevel@tonic-gate 	*dnamep = NULL;
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 	/* get slice name */
13600Sstevel@tonic-gate 	if ((rname = getrname(spp, uname, ep)) != NULL) {
13610Sstevel@tonic-gate 		*dnamep = metadiskname(rname);
13620Sstevel@tonic-gate 		return (rname);
13630Sstevel@tonic-gate 	}
13640Sstevel@tonic-gate 
13650Sstevel@tonic-gate 	/*
13660Sstevel@tonic-gate 	 * If name cannot be found, if may be because is is not accessible.
13670Sstevel@tonic-gate 	 * If it is an absolute name, try all possible disk name formats and
13680Sstevel@tonic-gate 	 * if it is device name, assume it is /dev/rdsk/...
13690Sstevel@tonic-gate 	 */
13700Sstevel@tonic-gate 	if (mdissyserror(ep, ENOENT)) {
13710Sstevel@tonic-gate 		if (uname[0] == '/') {
13720Sstevel@tonic-gate 			/* Absolute name */
13730Sstevel@tonic-gate 			char			*p;
13740Sstevel@tonic-gate 			uint_t			d = 0;
13750Sstevel@tonic-gate 			int			l = 0;
13760Sstevel@tonic-gate 			char			onmb[BUFSIZ+1], snm[BUFSIZ+1];
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate 			/*
13790Sstevel@tonic-gate 			 * Handle old style raw names
13800Sstevel@tonic-gate 			 */
13810Sstevel@tonic-gate 			if (sscanf(uname,
13820Sstevel@tonic-gate 			    "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
13830Sstevel@tonic-gate 			    "%" VAL2STR(BUFSIZ) "[a-h]%n",
13840Sstevel@tonic-gate 			    onmb, &d, snm, &l) == 3 && l == strlen(uname)) {
13850Sstevel@tonic-gate 				mdclrerror(ep);
13860Sstevel@tonic-gate 				rname = Strdup(uname);
13870Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
13880Sstevel@tonic-gate 				return (rname);
13890Sstevel@tonic-gate 			}
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 			/*
13920Sstevel@tonic-gate 			 * Handle old style block names
13930Sstevel@tonic-gate 			 */
13940Sstevel@tonic-gate 			if (sscanf(uname,
13950Sstevel@tonic-gate 			    "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u"
13960Sstevel@tonic-gate 			    "%" VAL2STR(BUFSIZ) "[a-h]%n",
13970Sstevel@tonic-gate 			    onmb, &d, snm, &l) == 3 && l == strlen(uname)) {
13980Sstevel@tonic-gate 				len = strlen(uname) + 1 + 1;
13990Sstevel@tonic-gate 				rname = Malloc(len);
14000Sstevel@tonic-gate 				(void) snprintf(rname, len, "/dev/r%s%u%s",
14010Sstevel@tonic-gate 				    onmb, d, snm);
14020Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
14030Sstevel@tonic-gate 				return (rname);
14040Sstevel@tonic-gate 			}
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 			/* /.../dsk/... */
14070Sstevel@tonic-gate 			if ((p = strstr(uname, "/dsk/")) != NULL) {
14080Sstevel@tonic-gate 				mdclrerror(ep);
14090Sstevel@tonic-gate 				++p;
14100Sstevel@tonic-gate 				rname = Malloc(strlen(uname) + 1 + 1);
14110Sstevel@tonic-gate 				(void) strncpy(rname, uname, (p - uname));
14120Sstevel@tonic-gate 				rname[(p - uname)] = 'r';
14130Sstevel@tonic-gate 				(void) strcpy(&rname[(p - uname) + 1], p);
14140Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
14150Sstevel@tonic-gate 				return (rname);
14160Sstevel@tonic-gate 			}
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate 			/* /.../rdsk/... */
14190Sstevel@tonic-gate 			else if (strstr(uname, "/rdsk/") != NULL) {
14200Sstevel@tonic-gate 				mdclrerror(ep);
14210Sstevel@tonic-gate 				rname = Strdup(uname);
14220Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
14230Sstevel@tonic-gate 				return (rname);
14240Sstevel@tonic-gate 			}
14250Sstevel@tonic-gate 		} else {
14260Sstevel@tonic-gate 			/*
14270Sstevel@tonic-gate 			 * If it's not an absolute name but is a valid ctd name,
14280Sstevel@tonic-gate 			 * guess at /dev/rdsk/...
14290Sstevel@tonic-gate 			 */
14300Sstevel@tonic-gate 			uint_t	s;
14310Sstevel@tonic-gate 			if (parse_ctd(uname, &s) == 0) {
14320Sstevel@tonic-gate 				len = strlen(uname) + strlen("/dev/rdsk/") + 1;
14330Sstevel@tonic-gate 				rname = Malloc(len);
14340Sstevel@tonic-gate 				(void) snprintf(rname, len, "/dev/rdsk/%s",
14350Sstevel@tonic-gate 				    uname);
14360Sstevel@tonic-gate 				*dnamep = metadiskname(rname);
14370Sstevel@tonic-gate 				return (rname);
14380Sstevel@tonic-gate 			}
14390Sstevel@tonic-gate 		}
14400Sstevel@tonic-gate 	}
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 	/* out of luck */
14430Sstevel@tonic-gate 	return (NULL);
14440Sstevel@tonic-gate }
14450Sstevel@tonic-gate 
14460Sstevel@tonic-gate /*
14470Sstevel@tonic-gate  * get number of slices for name
14480Sstevel@tonic-gate  */
14490Sstevel@tonic-gate static int
14500Sstevel@tonic-gate getnslice(
14510Sstevel@tonic-gate 	char		*rname,
14520Sstevel@tonic-gate 	char		*dname,
14530Sstevel@tonic-gate 	uint_t		*slicep
14540Sstevel@tonic-gate )
14550Sstevel@tonic-gate {
14560Sstevel@tonic-gate 	char		*srname;
14570Sstevel@tonic-gate 	uint_t		nslice;
14580Sstevel@tonic-gate 	size_t		dl = strlen(dname);
14590Sstevel@tonic-gate 	size_t		rl = strlen(rname);
14600Sstevel@tonic-gate 	size_t		l = 0;
14610Sstevel@tonic-gate 	size_t		len;
14620Sstevel@tonic-gate 
14630Sstevel@tonic-gate 	/*
14640Sstevel@tonic-gate 	 * get our slice number - works only with names that end in s%u -
14650Sstevel@tonic-gate 	 * all others return -1.
14660Sstevel@tonic-gate 	 */
14670Sstevel@tonic-gate 	if (dl >= rl ||
14680Sstevel@tonic-gate 	    sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl ||
14690Sstevel@tonic-gate 	    (int)*slicep < 0) {
14700Sstevel@tonic-gate 		return (-1);
14710Sstevel@tonic-gate 	}
14720Sstevel@tonic-gate 
14730Sstevel@tonic-gate 	/*
14740Sstevel@tonic-gate 	 * go find how many slices there really are
14750Sstevel@tonic-gate 	 */
14760Sstevel@tonic-gate 	len = strlen(dname) + 20 + 1;
14770Sstevel@tonic-gate 	srname = Malloc(len);
14780Sstevel@tonic-gate 	for (nslice = 0; /* void */; ++nslice) {
14790Sstevel@tonic-gate 		struct stat	statbuf;
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 		/* build slice name */
14820Sstevel@tonic-gate 		(void) snprintf(srname, len, "%ss%u", dname, nslice);
14830Sstevel@tonic-gate 
14840Sstevel@tonic-gate 		/* see if it's there */
14850Sstevel@tonic-gate 		if ((meta_stat(srname, &statbuf) != 0) ||
14860Sstevel@tonic-gate 		    (! S_ISCHR(statbuf.st_mode))) {
14870Sstevel@tonic-gate 			break;
14880Sstevel@tonic-gate 		}
14890Sstevel@tonic-gate 	}
14900Sstevel@tonic-gate 	Free(srname);
14910Sstevel@tonic-gate 
14920Sstevel@tonic-gate 	/* Need to make sure that we at least have V_NUMPAR */
14930Sstevel@tonic-gate 	nslice = max(nslice, V_NUMPAR);
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 	/* make sure we have at least our slice */
14960Sstevel@tonic-gate 	if (nslice < *slicep)
14970Sstevel@tonic-gate 		return (-1);
14980Sstevel@tonic-gate 
14990Sstevel@tonic-gate 	/* return number of slices */
15000Sstevel@tonic-gate 	return (nslice);
15010Sstevel@tonic-gate }
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate /*
15040Sstevel@tonic-gate  * Attempt to parse the input string as a c[t]ds specifier
15050Sstevel@tonic-gate  * The target can either be a SCSI target id or if the device
15060Sstevel@tonic-gate  * is in a fabric configuration in a fibre channel setup then
15070Sstevel@tonic-gate  * the target is a standard WWN (world wide name).
15080Sstevel@tonic-gate  *
15090Sstevel@tonic-gate  * if successful	return 0
15100Sstevel@tonic-gate  * if c[t]dp name	return 1
15110Sstevel@tonic-gate  * otherwise		return -1
15120Sstevel@tonic-gate  */
15130Sstevel@tonic-gate int
15140Sstevel@tonic-gate parse_ctd(
15150Sstevel@tonic-gate 	char	*uname,
15160Sstevel@tonic-gate 	uint_t	*slice)
15170Sstevel@tonic-gate {
15180Sstevel@tonic-gate 	uint_t	channel;
15190Sstevel@tonic-gate 	uint_t	target;
15200Sstevel@tonic-gate 	uint_t	device;
15210Sstevel@tonic-gate 	int	has_target = 1;
15220Sstevel@tonic-gate 	uint_t	cl;
15230Sstevel@tonic-gate 	uint_t	target_str_len;
15240Sstevel@tonic-gate 	char	*partial_ctd_str;
15250Sstevel@tonic-gate 	char	*target_str;
15260Sstevel@tonic-gate 	char	*device_start_pos;
15270Sstevel@tonic-gate 	int	l = -1;
15280Sstevel@tonic-gate 
15290Sstevel@tonic-gate 	/* pull off the channel spec and the 't' for the target */
15300Sstevel@tonic-gate 	if (sscanf(uname, "c%ut%n", &channel, &l) != 1 || l == -1) {
15310Sstevel@tonic-gate 		/* check for cds style name */
15320Sstevel@tonic-gate 		if (sscanf(uname, "c%ud%n", &channel, &l) != 1 || l == -1) {
15330Sstevel@tonic-gate 			return (-1);
15340Sstevel@tonic-gate 		} else {
15350Sstevel@tonic-gate 			l--;	/* we want to be on the 'd' */
15360Sstevel@tonic-gate 			has_target = 0;
15370Sstevel@tonic-gate 		}
15380Sstevel@tonic-gate 	}
15390Sstevel@tonic-gate 	partial_ctd_str = uname + l;
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate 	/* find the beginning of the device specifier */
15420Sstevel@tonic-gate 	device_start_pos = strrchr(partial_ctd_str, 'd');
15430Sstevel@tonic-gate 	if (device_start_pos == NULL) {
15440Sstevel@tonic-gate 		return (-1);
15450Sstevel@tonic-gate 	}
15460Sstevel@tonic-gate 
15470Sstevel@tonic-gate 	/* check to see if it is a ctd with a WWN or SCSI target */
15480Sstevel@tonic-gate 	if (has_target) {
15490Sstevel@tonic-gate 		/* pull off the target and see if it is a WWN */
15500Sstevel@tonic-gate 		target_str_len = device_start_pos - partial_ctd_str + 2;
15510Sstevel@tonic-gate 		target_str = (char *)Malloc(target_str_len+1);
15520Sstevel@tonic-gate 		(void) strcpy(target_str, "0X");
15530Sstevel@tonic-gate 		(void) strncpy(target_str+2, partial_ctd_str,
15540Sstevel@tonic-gate 		    target_str_len - 2);
15550Sstevel@tonic-gate 		target_str[target_str_len] = '\0';
15560Sstevel@tonic-gate 		if (sscanf(target_str, "%x%n", &target, &l) != 1 ||
15570Sstevel@tonic-gate 		    l != target_str_len) {
15580Sstevel@tonic-gate 			Free(target_str);
15590Sstevel@tonic-gate 			return (-1);
15600Sstevel@tonic-gate 		}
15610Sstevel@tonic-gate 		Free(target_str);
15620Sstevel@tonic-gate 	}
15630Sstevel@tonic-gate 
15640Sstevel@tonic-gate 	/* check the device and slice */
15650Sstevel@tonic-gate 	cl = strlen(device_start_pos);
15660Sstevel@tonic-gate 	if (sscanf(device_start_pos, "d%us%u%n", &device, slice, &l) != 2 ||
15670Sstevel@tonic-gate 			l != cl) {
15680Sstevel@tonic-gate 		/* check the device and partition */
15690Sstevel@tonic-gate 		if (sscanf(device_start_pos, "d%up%u%n", &device, slice, &l)
15700Sstevel@tonic-gate 		    == 2 && l == cl) {
15710Sstevel@tonic-gate 			return (1);
15720Sstevel@tonic-gate 		}
15730Sstevel@tonic-gate 		return (-1);
15740Sstevel@tonic-gate 	}
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate 	return (0);
15770Sstevel@tonic-gate }
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 
15800Sstevel@tonic-gate /*
15810Sstevel@tonic-gate  * get number of slices for name
15820Sstevel@tonic-gate  */
15830Sstevel@tonic-gate static int
15840Sstevel@tonic-gate uname2sliceno(
15850Sstevel@tonic-gate 	char		*uname,
15860Sstevel@tonic-gate 	uint_t		*slicep,
15870Sstevel@tonic-gate 	md_error_t	*ep
15880Sstevel@tonic-gate )
15890Sstevel@tonic-gate {
15900Sstevel@tonic-gate 	uint_t			c = 0, t = 0, d = 0;
15910Sstevel@tonic-gate 	int			l = 0, cl = 0;
15920Sstevel@tonic-gate 	int			fd;
15930Sstevel@tonic-gate 	struct dk_cinfo		cinfo;
15940Sstevel@tonic-gate 	char			*p;
15950Sstevel@tonic-gate 	char			*rname = NULL;
15960Sstevel@tonic-gate 
15970Sstevel@tonic-gate 	if (is_metaname(uname))
15980Sstevel@tonic-gate 		return (*slicep = 0);
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate 	if ((p = strrchr(uname, '/')) != NULL)
16010Sstevel@tonic-gate 		p++;
16020Sstevel@tonic-gate 	else
16030Sstevel@tonic-gate 		p = uname;
16040Sstevel@tonic-gate 
16050Sstevel@tonic-gate 	cl = strlen(p);
16060Sstevel@tonic-gate 
16070Sstevel@tonic-gate 	if (parse_ctd(p, slicep) == 0)
16080Sstevel@tonic-gate 		return (*slicep);
16090Sstevel@tonic-gate 	else if (sscanf(p, "mc%ut%ud%us%u%n", &c, &t, &d, slicep, &l) == 4 &&
16100Sstevel@tonic-gate 	    l == cl)
16110Sstevel@tonic-gate 		return (*slicep);
16120Sstevel@tonic-gate 	else if (sscanf(p, "d%us%u%n", &d, slicep, &l) == 2 && l == cl)
16130Sstevel@tonic-gate 		return (*slicep);
16140Sstevel@tonic-gate 
16150Sstevel@tonic-gate 	/*
16160Sstevel@tonic-gate 	 * If we can't get the slice from the name, then we have to do it the
16170Sstevel@tonic-gate 	 * hard and expensive way.
16180Sstevel@tonic-gate 	 */
16190Sstevel@tonic-gate 	if ((rname = rawname(uname)) == NULL)
16200Sstevel@tonic-gate 		return (-1);
16210Sstevel@tonic-gate 
16220Sstevel@tonic-gate 	/* get controller info */
16230Sstevel@tonic-gate 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
16240Sstevel@tonic-gate 		Free(rname);
16250Sstevel@tonic-gate 		return (-1);
16260Sstevel@tonic-gate 	}
16270Sstevel@tonic-gate 
16280Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &cinfo) != 0) {
16290Sstevel@tonic-gate 		int	save = errno;
16300Sstevel@tonic-gate 
16310Sstevel@tonic-gate 		if (save == ENOTTY)
16320Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname);
16330Sstevel@tonic-gate 		else
16340Sstevel@tonic-gate 			(void) mdsyserror(ep, save, rname);
16350Sstevel@tonic-gate 
16360Sstevel@tonic-gate 		Free(rname);
16370Sstevel@tonic-gate 		(void) close(fd);
16380Sstevel@tonic-gate 		return (-1);
16390Sstevel@tonic-gate 	}
16400Sstevel@tonic-gate 	(void) close(fd);	/* sd/ssd bug */
16410Sstevel@tonic-gate 
16420Sstevel@tonic-gate 	if (cinfo.dki_partition < V_NUMPAR) {
16430Sstevel@tonic-gate 		Free(rname);
16440Sstevel@tonic-gate 		return (*slicep = cinfo.dki_partition);
16450Sstevel@tonic-gate 	}
16460Sstevel@tonic-gate 
16470Sstevel@tonic-gate 	return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname));
16480Sstevel@tonic-gate }
16490Sstevel@tonic-gate 
16500Sstevel@tonic-gate /*
16510Sstevel@tonic-gate  * get partition info
16520Sstevel@tonic-gate  */
16530Sstevel@tonic-gate static int
16540Sstevel@tonic-gate getparts(
16550Sstevel@tonic-gate 	mddrivename_t	*dnp,
16560Sstevel@tonic-gate 	char		*rname,
16570Sstevel@tonic-gate 	char		*dname,
16580Sstevel@tonic-gate 	uint_t		*npartsp,
16590Sstevel@tonic-gate 	uint_t		*partnop,
16600Sstevel@tonic-gate 	md_error_t	*ep
16610Sstevel@tonic-gate )
16620Sstevel@tonic-gate {
16630Sstevel@tonic-gate 	int		nparts;
16640Sstevel@tonic-gate 	uint_t		partno;
16650Sstevel@tonic-gate 	mdname_t	name;
16660Sstevel@tonic-gate 	mdvtoc_t	*vtocp;
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate 	/* metadevice */
16690Sstevel@tonic-gate 	if (is_metaname(rname)) {
16700Sstevel@tonic-gate 		dnp->type = MDT_META;
16710Sstevel@tonic-gate 		nparts = 1;
16720Sstevel@tonic-gate 		partno = 0;
16730Sstevel@tonic-gate 		goto gotit;
16740Sstevel@tonic-gate 	}
16750Sstevel@tonic-gate 
16760Sstevel@tonic-gate 	/* see how many partitions in drive, this is really tricky */
16770Sstevel@tonic-gate 	metainitname(&name);
16780Sstevel@tonic-gate 	name.rname = rname;
16790Sstevel@tonic-gate 	name.drivenamep = dnp;
16800Sstevel@tonic-gate 	if ((vtocp = metagetvtoc(&name, TRUE, &partno, ep)) != NULL) {
16810Sstevel@tonic-gate 		dnp->type = MDT_COMP;
16820Sstevel@tonic-gate 		nparts = vtocp->nparts;
16830Sstevel@tonic-gate 		/* partno already setup */
16840Sstevel@tonic-gate 		/* dname already setup */
16850Sstevel@tonic-gate 		goto gotit;
16860Sstevel@tonic-gate 	}
16870Sstevel@tonic-gate 
16880Sstevel@tonic-gate 	if ((ep->info.errclass == MDEC_DEV) &&
16890Sstevel@tonic-gate 	    (ep->info.md_error_info_t_u.dev_error.errnum == MDE_TOO_MANY_PARTS))
16900Sstevel@tonic-gate 		return (-1);
16910Sstevel@tonic-gate 
16920Sstevel@tonic-gate 	/* fallback and try and guess (used to check for just EACCES here) */
16930Sstevel@tonic-gate 	if ((dname != NULL) &&
16940Sstevel@tonic-gate 	    ((nparts = getnslice(rname, dname, &partno)) > 0)) {
16950Sstevel@tonic-gate 		dnp->type = MDT_ACCES;
16960Sstevel@tonic-gate 		if (mdanysyserror(ep)) {
16970Sstevel@tonic-gate 			dnp->errnum =
16980Sstevel@tonic-gate 			    ep->info.md_error_info_t_u.sys_error.errnum;
16990Sstevel@tonic-gate 		} else {
17000Sstevel@tonic-gate 			dnp->errnum = ENOENT;
17010Sstevel@tonic-gate 		}
17020Sstevel@tonic-gate 		mdclrerror(ep);
17030Sstevel@tonic-gate 		/* nparts already setup */
17040Sstevel@tonic-gate 		/* partno already setup */
17050Sstevel@tonic-gate 		/* dname already setup */
17060Sstevel@tonic-gate 		nparts = roundup(nparts, V_NUMPAR);
17070Sstevel@tonic-gate 		goto gotit;
17080Sstevel@tonic-gate 	}
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 	/* nothing worked */
17110Sstevel@tonic-gate 	dnp->type = MDT_UNKNOWN;
17120Sstevel@tonic-gate 	if (mdissyserror(ep, EACCES))
17130Sstevel@tonic-gate 		dnp->type = MDT_ACCES;
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate 	if (mdanysyserror(ep)) {
17160Sstevel@tonic-gate 		dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum;
17170Sstevel@tonic-gate 	} else {
17180Sstevel@tonic-gate 		dnp->errnum = ENOENT;
17190Sstevel@tonic-gate 	}
17200Sstevel@tonic-gate 
17210Sstevel@tonic-gate 	mdclrerror(ep);
17220Sstevel@tonic-gate 	nparts = V_NUMPAR;
17230Sstevel@tonic-gate 	if (uname2sliceno(rname, &partno, ep) < 0) {
17240Sstevel@tonic-gate 		mdclrerror(ep);
17250Sstevel@tonic-gate 		partno = 0;
17260Sstevel@tonic-gate 	}
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 	/* return success */
17290Sstevel@tonic-gate gotit:
17300Sstevel@tonic-gate 	assert(nparts > 0);
17310Sstevel@tonic-gate 
17320Sstevel@tonic-gate 	if (partno >= nparts)
17330Sstevel@tonic-gate 		return (mdsyserror(ep, ENOENT, rname));
17340Sstevel@tonic-gate 
17350Sstevel@tonic-gate 	*npartsp = nparts;
17360Sstevel@tonic-gate 	*partnop = partno;
17370Sstevel@tonic-gate 	return (0);
17380Sstevel@tonic-gate }
17390Sstevel@tonic-gate 
17400Sstevel@tonic-gate /*
17410Sstevel@tonic-gate  * get block name
17420Sstevel@tonic-gate  */
17430Sstevel@tonic-gate static int
17440Sstevel@tonic-gate getbname(
17450Sstevel@tonic-gate 	mdname_t	*np,
17460Sstevel@tonic-gate 	md_error_t	*ep
17470Sstevel@tonic-gate )
17480Sstevel@tonic-gate {
17490Sstevel@tonic-gate 	char		*rname = np->rname;
17500Sstevel@tonic-gate 	char		*bname;
17510Sstevel@tonic-gate 
17520Sstevel@tonic-gate 	/* fully qualified */
17530Sstevel@tonic-gate 	assert(rname != NULL);
17540Sstevel@tonic-gate 	if ((bname = blkname(rname)) != NULL) {
17550Sstevel@tonic-gate 		if (np->bname)
17560Sstevel@tonic-gate 			Free(np->bname);
17570Sstevel@tonic-gate 		np->bname = bname;
17580Sstevel@tonic-gate 		return (0);
17590Sstevel@tonic-gate 	}
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate 	/* out of luck */
17620Sstevel@tonic-gate 	return (mdsyserror(ep, ENOENT, rname));
17630Sstevel@tonic-gate }
17640Sstevel@tonic-gate 
17650Sstevel@tonic-gate static void
17660Sstevel@tonic-gate getcname(
17670Sstevel@tonic-gate 	mdsetname_t	*sp,
17680Sstevel@tonic-gate 	mdname_t	*np
17690Sstevel@tonic-gate )
17700Sstevel@tonic-gate {
17710Sstevel@tonic-gate 	char		*sname = sp->setname;
17720Sstevel@tonic-gate 	char		*bname = np->bname;
17730Sstevel@tonic-gate 	char		*p;
17740Sstevel@tonic-gate 	size_t		len;
17750Sstevel@tonic-gate 
17760Sstevel@tonic-gate 	assert(sname != NULL);
17770Sstevel@tonic-gate 	assert(bname != NULL);
17780Sstevel@tonic-gate 	assert(np->drivenamep->type != MDT_FAST_COMP &&
17790Sstevel@tonic-gate 	    np->drivenamep->type != MDT_FAST_META);
17800Sstevel@tonic-gate 
17810Sstevel@tonic-gate 	/* regular device */
17820Sstevel@tonic-gate 	if ((strncmp(bname, "/dev/dsk/", strlen("/dev/dsk/")) == 0) &&
17830Sstevel@tonic-gate 	    (strchr((p = bname + strlen("/dev/dsk/")), '/') == NULL)) {
17840Sstevel@tonic-gate 		if (np->cname)
17850Sstevel@tonic-gate 			Free(np->cname);
17860Sstevel@tonic-gate 		np->cname = Strdup(p);
17870Sstevel@tonic-gate 		return;
17880Sstevel@tonic-gate 	}
17890Sstevel@tonic-gate 
17900Sstevel@tonic-gate 	if ((strncmp(bname, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) &&
17910Sstevel@tonic-gate 	    (strchr((p = bname + strlen("/dev/ap/dsk/")), '/') == NULL)) {
17920Sstevel@tonic-gate 		if (np->cname)
17930Sstevel@tonic-gate 			Free(np->cname);
17940Sstevel@tonic-gate 		np->cname = Strdup(p);
17950Sstevel@tonic-gate 		return;
17960Sstevel@tonic-gate 	}
17970Sstevel@tonic-gate 
17980Sstevel@tonic-gate 	if ((strncmp(bname, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) &&
17990Sstevel@tonic-gate 	    (strchr((p = bname + strlen("/dev/did/dsk/")), '/') == NULL)) {
18000Sstevel@tonic-gate 		if (np->cname)
18010Sstevel@tonic-gate 			Free(np->cname);
18020Sstevel@tonic-gate 		np->cname = Strdup(p);
18030Sstevel@tonic-gate 		return;
18040Sstevel@tonic-gate 	}
18050Sstevel@tonic-gate 
18060Sstevel@tonic-gate 	/* anything else but metadevice */
18070Sstevel@tonic-gate 	if (np->drivenamep->type != MDT_META) {
18080Sstevel@tonic-gate 		if (np->cname)
18090Sstevel@tonic-gate 			Free(np->cname);
18100Sstevel@tonic-gate 		np->cname = Strdup(bname);
18110Sstevel@tonic-gate 		return;
18120Sstevel@tonic-gate 	}
18130Sstevel@tonic-gate 
18140Sstevel@tonic-gate 	/* metadevice */
18150Sstevel@tonic-gate 	p = strrchr(bname, '/');
18160Sstevel@tonic-gate 	assert(p != NULL);
18170Sstevel@tonic-gate 	++p;
18180Sstevel@tonic-gate 	if (metaislocalset(sp)) {
18190Sstevel@tonic-gate 		if (np->cname)
18200Sstevel@tonic-gate 			Free(np->cname);
18210Sstevel@tonic-gate 		np->cname = Strdup(p);
18220Sstevel@tonic-gate 	} else {
18230Sstevel@tonic-gate 		assert(sname[0] != '\0');
18240Sstevel@tonic-gate 		if (np->cname)
18250Sstevel@tonic-gate 			Free(np->cname);
18260Sstevel@tonic-gate 		len = strlen(sname) + 1 + strlen(p) + 1;
18270Sstevel@tonic-gate 		np->cname = Malloc(len);
18280Sstevel@tonic-gate 		(void) snprintf(np->cname, len, "%s/%s", sname, p);
18290Sstevel@tonic-gate 	}
18300Sstevel@tonic-gate }
18310Sstevel@tonic-gate 
18320Sstevel@tonic-gate /*
18330Sstevel@tonic-gate  * get dev
18340Sstevel@tonic-gate  */
18350Sstevel@tonic-gate int
18360Sstevel@tonic-gate meta_getdev(
18370Sstevel@tonic-gate 	mdsetname_t	*sp,
18380Sstevel@tonic-gate 	mdname_t	*np,
18390Sstevel@tonic-gate 	md_error_t	*ep
18400Sstevel@tonic-gate )
18410Sstevel@tonic-gate {
18420Sstevel@tonic-gate 	struct stat	statbuf;
18430Sstevel@tonic-gate 
18440Sstevel@tonic-gate 	/* get dev */
18450Sstevel@tonic-gate 	if (meta_stat(np->rname, &statbuf) != 0)
18460Sstevel@tonic-gate 		return (mdsyserror(ep, errno, np->rname));
18470Sstevel@tonic-gate 	else if (! S_ISCHR(statbuf.st_mode))
18480Sstevel@tonic-gate 		return (mddeverror(ep, MDE_NOT_DISK, NODEV64, np->rname));
18490Sstevel@tonic-gate 	np->dev = meta_expldev(statbuf.st_rdev);
18500Sstevel@tonic-gate 
18510Sstevel@tonic-gate 	assert(np->drivenamep->type != MDT_FAST_META &&
18520Sstevel@tonic-gate 	    np->drivenamep->type != MDT_FAST_COMP);
18530Sstevel@tonic-gate 
18540Sstevel@tonic-gate 	/* check set */
18550Sstevel@tonic-gate 	assert((np->drivenamep->type == MDT_META) ?
18560Sstevel@tonic-gate 	    (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1);
18570Sstevel@tonic-gate 
18580Sstevel@tonic-gate 	/* return sucess */
18590Sstevel@tonic-gate 	return (0);
18600Sstevel@tonic-gate }
18610Sstevel@tonic-gate 
18620Sstevel@tonic-gate /*
18630Sstevel@tonic-gate  * set up names for a slice
18640Sstevel@tonic-gate  */
18650Sstevel@tonic-gate static int
18660Sstevel@tonic-gate getnames(
18670Sstevel@tonic-gate 	mdsetname_t	*sp,
18680Sstevel@tonic-gate 	mdname_t	*np,
18690Sstevel@tonic-gate 	char		*rname,
18700Sstevel@tonic-gate 	md_error_t	*ep
18710Sstevel@tonic-gate )
18720Sstevel@tonic-gate {
18730Sstevel@tonic-gate 	/* get names */
18740Sstevel@tonic-gate 	if (np->rname)
18750Sstevel@tonic-gate 		Free(np->rname);
18760Sstevel@tonic-gate 	np->rname = Strdup(rname);
18770Sstevel@tonic-gate 	if (getbname(np, ep) != 0)
18780Sstevel@tonic-gate 		return (-1);
18790Sstevel@tonic-gate 	getcname(sp, np);
18800Sstevel@tonic-gate 	if (meta_getdev(sp, np, ep) != 0)
18810Sstevel@tonic-gate 		return (-1);
18820Sstevel@tonic-gate 
18830Sstevel@tonic-gate 	/* return success */
18840Sstevel@tonic-gate 	return (0);
18850Sstevel@tonic-gate }
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate /*
18880Sstevel@tonic-gate  * fake up names for a slice
18890Sstevel@tonic-gate  */
18900Sstevel@tonic-gate static void
18910Sstevel@tonic-gate getfakenames(
18920Sstevel@tonic-gate 	mdsetname_t	*sp,
18930Sstevel@tonic-gate 	mdname_t	*np,
18940Sstevel@tonic-gate 	char		*rname
18950Sstevel@tonic-gate )
18960Sstevel@tonic-gate {
18970Sstevel@tonic-gate 	char		*p;
18980Sstevel@tonic-gate 	char		onmb[BUFSIZ+1], snm[BUFSIZ+1];
18990Sstevel@tonic-gate 	uint_t		d = 0;
19000Sstevel@tonic-gate 	int		l = 0;
19010Sstevel@tonic-gate 
19020Sstevel@tonic-gate 	/* fake names */
19030Sstevel@tonic-gate 	if (np->rname != NULL)
19040Sstevel@tonic-gate 		Free(np->rname);
19050Sstevel@tonic-gate 	np->rname = Strdup(rname);
19060Sstevel@tonic-gate 
19070Sstevel@tonic-gate 	if (np->bname != NULL)
19080Sstevel@tonic-gate 		Free(np->bname);
19090Sstevel@tonic-gate 	np->bname = Strdup(rname);
19100Sstevel@tonic-gate 
19110Sstevel@tonic-gate 	/*
19120Sstevel@tonic-gate 	 * Fixup old style names
19130Sstevel@tonic-gate 	 */
19140Sstevel@tonic-gate 	if (sscanf(rname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
19150Sstevel@tonic-gate 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
19160Sstevel@tonic-gate 	    onmb, &d, snm, &l) == 3 && l == strlen(rname))
19170Sstevel@tonic-gate 		(void) snprintf(np->bname, l, "/dev/%s%u%s", onmb, d, snm);
19180Sstevel@tonic-gate 
19190Sstevel@tonic-gate 	/*
19200Sstevel@tonic-gate 	 * Fixup new style names
19210Sstevel@tonic-gate 	 */
19220Sstevel@tonic-gate 	if ((p = strstr(np->bname, "/rdsk/")) != NULL) {
19230Sstevel@tonic-gate 		for (++p; (*(p + 1) != '\0'); ++p)
19240Sstevel@tonic-gate 			*p = *(p + 1);
19250Sstevel@tonic-gate 		*p = '\0';
19260Sstevel@tonic-gate 	}
19270Sstevel@tonic-gate 
19280Sstevel@tonic-gate 	if (np->cname != NULL)
19290Sstevel@tonic-gate 		Free(np->cname);
19300Sstevel@tonic-gate 	getcname(sp, np);
19310Sstevel@tonic-gate }
19320Sstevel@tonic-gate 
19330Sstevel@tonic-gate static mdname_t *
19340Sstevel@tonic-gate setup_slice(
19350Sstevel@tonic-gate 	mdsetname_t	*sp,
19360Sstevel@tonic-gate 	mddrivename_t	*dnp,
19370Sstevel@tonic-gate 	char		*uname,
19380Sstevel@tonic-gate 	char		*rname,
19390Sstevel@tonic-gate 	char		*dname,
19400Sstevel@tonic-gate 	uint_t		partno,
19410Sstevel@tonic-gate 	md_error_t	*ep
19420Sstevel@tonic-gate )
19430Sstevel@tonic-gate {
19440Sstevel@tonic-gate 	char		*srname = NULL;
19450Sstevel@tonic-gate 	mdname_t	*np;
19460Sstevel@tonic-gate 
19470Sstevel@tonic-gate 	/* must have a set */
19480Sstevel@tonic-gate 	assert(sp != NULL);
19490Sstevel@tonic-gate 	assert(partno < dnp->parts.parts_len);
19500Sstevel@tonic-gate 	assert(dname != NULL);
19510Sstevel@tonic-gate 
19520Sstevel@tonic-gate 	np = &dnp->parts.parts_val[partno];
19530Sstevel@tonic-gate 
19540Sstevel@tonic-gate 	if (rname)
19550Sstevel@tonic-gate 		srname = rname;
19560Sstevel@tonic-gate 	else if (is_metaname(dname))
19570Sstevel@tonic-gate 		srname = dname;
19580Sstevel@tonic-gate 	else {
19590Sstevel@tonic-gate 		char	onmb[BUFSIZ+1];
19600Sstevel@tonic-gate 		uint_t	d = 0;
19610Sstevel@tonic-gate 		int	l = 0, cl = strlen(dname);
19620Sstevel@tonic-gate 		size_t	len;
19630Sstevel@tonic-gate 
19640Sstevel@tonic-gate 		len = cl + 20 + 1;
19650Sstevel@tonic-gate 		srname = Malloc(len);
19660Sstevel@tonic-gate 
19670Sstevel@tonic-gate 		/*
19680Sstevel@tonic-gate 		 * Handle /dev/rXXNN.
19690Sstevel@tonic-gate 		 */
19700Sstevel@tonic-gate 		if (sscanf(dname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%n",
19710Sstevel@tonic-gate 		    onmb, &d, &l) == 2 && l == cl) {
19720Sstevel@tonic-gate 			(void) snprintf(srname, len, "/dev/r%s%u%c", onmb, d,
19730Sstevel@tonic-gate 			    'a' + partno);
19740Sstevel@tonic-gate 		} else if (sscanf(dname, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%n",
19750Sstevel@tonic-gate 		    onmb, &d, &l) == 2 && l == cl) {
19760Sstevel@tonic-gate 			    (void) snprintf(srname, len, "/dev/%s%u%c", onmb, d,
19770Sstevel@tonic-gate 				'a' + partno);
19780Sstevel@tonic-gate 		} else {
19790Sstevel@tonic-gate 			/* build the slice that is wanted */
19800Sstevel@tonic-gate 			(void) snprintf(srname, len, "%ss%u", dname, partno);
19810Sstevel@tonic-gate 		}
19820Sstevel@tonic-gate 	}
19830Sstevel@tonic-gate 
19840Sstevel@tonic-gate 	if (getnames(sp, np, srname, ep) != 0) {
19850Sstevel@tonic-gate 		if (dnp->type == MDT_UNKNOWN) {
19860Sstevel@tonic-gate 			mdclrerror(ep);
19870Sstevel@tonic-gate 			getfakenames(sp, np, srname);
19880Sstevel@tonic-gate 		} else if (dnp->type == MDT_COMP && mdissyserror(ep, ENOENT)) {
19890Sstevel@tonic-gate 			dnp->type = MDT_UNKNOWN;
19900Sstevel@tonic-gate 			if (mdanysyserror(ep)) {
19910Sstevel@tonic-gate 				dnp->errnum =
19920Sstevel@tonic-gate 				    ep->info.md_error_info_t_u.sys_error.errnum;
19930Sstevel@tonic-gate 			} else {
19940Sstevel@tonic-gate 				dnp->errnum = ENOENT;
19950Sstevel@tonic-gate 			}
19960Sstevel@tonic-gate 			mdclrerror(ep);
19970Sstevel@tonic-gate 			getfakenames(sp, np, srname);
19980Sstevel@tonic-gate 		} else {
19990Sstevel@tonic-gate 			mdclrerror(ep);
20000Sstevel@tonic-gate 			if (getnames(sp, np, dname, ep) != 0) {
20010Sstevel@tonic-gate 				np = NULL;
20020Sstevel@tonic-gate 				goto fixup;
20030Sstevel@tonic-gate 			}
20040Sstevel@tonic-gate 		}
20050Sstevel@tonic-gate 	}
20060Sstevel@tonic-gate 
20070Sstevel@tonic-gate out:
20080Sstevel@tonic-gate 	if ((srname != rname) && (srname != dname))
20090Sstevel@tonic-gate 		Free(srname);
20100Sstevel@tonic-gate 
20110Sstevel@tonic-gate 	/* return name */
20120Sstevel@tonic-gate 	return (np);
20130Sstevel@tonic-gate 
20140Sstevel@tonic-gate fixup:
20150Sstevel@tonic-gate 	if (mdanysyserror(ep)) {
20160Sstevel@tonic-gate 		char	*p;
20170Sstevel@tonic-gate 		int	errnum = ep->info.md_error_info_t_u.sys_error.errnum;
20180Sstevel@tonic-gate 
20190Sstevel@tonic-gate 		mdclrerror(ep);
20200Sstevel@tonic-gate 		if (uname && *uname) {
20210Sstevel@tonic-gate 			if ((p = strrchr(uname, '/')) != NULL)
20220Sstevel@tonic-gate 				(void) mdsyserror(ep, errnum, ++p);
20230Sstevel@tonic-gate 			else
20240Sstevel@tonic-gate 				(void) mdsyserror(ep, errnum, uname);
20250Sstevel@tonic-gate 		} else {
20260Sstevel@tonic-gate 			if ((p = strrchr(srname, '/')) != NULL)
20270Sstevel@tonic-gate 				(void) mdsyserror(ep, errnum, ++p);
20280Sstevel@tonic-gate 			else
20290Sstevel@tonic-gate 				(void) mdsyserror(ep, errnum, srname);
20300Sstevel@tonic-gate 		}
20310Sstevel@tonic-gate 	}
20320Sstevel@tonic-gate 	goto out;
20330Sstevel@tonic-gate }
20340Sstevel@tonic-gate 
20350Sstevel@tonic-gate /*
20360Sstevel@tonic-gate  * flush the fast name cache
20370Sstevel@tonic-gate  */
20380Sstevel@tonic-gate static void
20390Sstevel@tonic-gate metafreefastnm(mdname_t **np)
20400Sstevel@tonic-gate {
20410Sstevel@tonic-gate 	mddrivename_t	*dnp;
20420Sstevel@tonic-gate 
20430Sstevel@tonic-gate 	assert(np != NULL && *np != NULL);
20440Sstevel@tonic-gate 
20450Sstevel@tonic-gate 	if ((dnp = (*np)->drivenamep) != NULL) {
20460Sstevel@tonic-gate 		if (dnp->cname != NULL)
20470Sstevel@tonic-gate 			Free(dnp->cname);
20480Sstevel@tonic-gate 		if (dnp->rname != NULL)
20490Sstevel@tonic-gate 			Free(dnp->rname);
20500Sstevel@tonic-gate 		if (dnp->miscname != NULL)
20510Sstevel@tonic-gate 			Free(dnp->miscname);
20520Sstevel@tonic-gate 		meta_free_unit(dnp);
20530Sstevel@tonic-gate 		Free(dnp);
20540Sstevel@tonic-gate 	}
20550Sstevel@tonic-gate 	if ((*np)->cname != NULL)
20560Sstevel@tonic-gate 		Free((*np)->cname);
20570Sstevel@tonic-gate 	if ((*np)->bname != NULL)
20580Sstevel@tonic-gate 		Free((*np)->bname);
20590Sstevel@tonic-gate 	if ((*np)->rname != NULL)
20600Sstevel@tonic-gate 		Free((*np)->rname);
20610Sstevel@tonic-gate 	if ((*np)->devicesname != NULL)
20620Sstevel@tonic-gate 		Free((*np)->devicesname);
20630Sstevel@tonic-gate 	Free(*np);
20640Sstevel@tonic-gate 	*np = NULL;
20650Sstevel@tonic-gate }
20660Sstevel@tonic-gate 
20670Sstevel@tonic-gate /*
20680Sstevel@tonic-gate  * flush the fast name cache
20690Sstevel@tonic-gate  */
20700Sstevel@tonic-gate static void
20710Sstevel@tonic-gate metaflushfastnames()
20720Sstevel@tonic-gate {
20730Sstevel@tonic-gate 	mdnamelist_t	*p, *n;
20740Sstevel@tonic-gate 
20750Sstevel@tonic-gate 	for (p = fastnmlp, n = NULL; (p != NULL); p = n) {
20760Sstevel@tonic-gate 		n = p->next;
20770Sstevel@tonic-gate 		metafreefastnm(&p->namep);
20780Sstevel@tonic-gate 		Free(p);
20790Sstevel@tonic-gate 	}
20800Sstevel@tonic-gate 	fastnmlp = NULL;
20810Sstevel@tonic-gate }
20820Sstevel@tonic-gate 
20830Sstevel@tonic-gate static char *
20840Sstevel@tonic-gate getrname_fast(char *unm, md_error_t *ep)
20850Sstevel@tonic-gate {
20860Sstevel@tonic-gate 	uint_t			d = 0;
20870Sstevel@tonic-gate 	int			l = 0;
20880Sstevel@tonic-gate 	int			cl = strlen(unm);
20890Sstevel@tonic-gate 	char			onmb[BUFSIZ+1], snm[BUFSIZ+1], cnmb[BUFSIZ];
20900Sstevel@tonic-gate 	char			*rnm;
20910Sstevel@tonic-gate 	char			*p;
20920Sstevel@tonic-gate 	size_t			len;
20930Sstevel@tonic-gate 
20940Sstevel@tonic-gate 	if (is_metaname(unm)) {
20950Sstevel@tonic-gate 		/* without set */
20960Sstevel@tonic-gate 		if (sscanf(unm, "d%u%n", &d, &l) == 1 && cl == l) {
20970Sstevel@tonic-gate 			rnm = Zalloc(14 + cl + 1);
20980Sstevel@tonic-gate 			(void) sprintf(rnm, "/dev/md/rdsk/d%u", d);
20990Sstevel@tonic-gate 			return (rnm);
21000Sstevel@tonic-gate 		}
21010Sstevel@tonic-gate 
21020Sstevel@tonic-gate 		/* fully-qualified without set */
21030Sstevel@tonic-gate 		if ((sscanf(unm, "/dev/md/dsk/d%u%n", &d, &l) == 1 ||
21040Sstevel@tonic-gate 		    sscanf(unm, "/dev/md/rdsk/d%u%n", &d, &l) == 1) &&
21050Sstevel@tonic-gate 		    cl == l) {
21060Sstevel@tonic-gate 			rnm = Zalloc(14 + cl + 1);
21070Sstevel@tonic-gate 			(void) sprintf(rnm, "/dev/md/rdsk/d%u", d);
21080Sstevel@tonic-gate 			return (rnm);
21090Sstevel@tonic-gate 		}
21100Sstevel@tonic-gate 
21110Sstevel@tonic-gate 		/* with set */
21120Sstevel@tonic-gate 		if ((sscanf(unm,
21130Sstevel@tonic-gate 		    "%" VAL2STR(BUFSIZ) "[^/]/d%u%n", snm, &d, &l) == 2 ||
21140Sstevel@tonic-gate 		    sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/d%u%n",
21150Sstevel@tonic-gate 		    snm, &d, &l) == 2 ||
21160Sstevel@tonic-gate 		    sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/rdsk/d%u%n",
21170Sstevel@tonic-gate 		    snm, &d, &l) == 2) && cl == l) {
21180Sstevel@tonic-gate 			len = 14 + cl + strlen(snm) + 1;
21190Sstevel@tonic-gate 			rnm = Zalloc(len);
21200Sstevel@tonic-gate 			(void) snprintf(rnm, len, "/dev/md/%s/rdsk/d%u",
21210Sstevel@tonic-gate 			    snm, d);
21220Sstevel@tonic-gate 			return (rnm);
21230Sstevel@tonic-gate 		}
21240Sstevel@tonic-gate 	}
21250Sstevel@tonic-gate 
21260Sstevel@tonic-gate 	/* NOT Fully qualified path, done */
21270Sstevel@tonic-gate 	if (unm[0] != '/') {
21280Sstevel@tonic-gate 		(void) mdsyserror(ep, EINVAL, unm);
21290Sstevel@tonic-gate 		return (NULL);
21300Sstevel@tonic-gate 	}
21310Sstevel@tonic-gate 
21320Sstevel@tonic-gate 	/*
21330Sstevel@tonic-gate 	 * Get slice information from old style names of the form
21340Sstevel@tonic-gate 	 * /dev/rXXNN[a-h] or /dev/XXNN[a-h], must be done before regular
21350Sstevel@tonic-gate 	 * devices, but after metadevices.
21360Sstevel@tonic-gate 	 */
21370Sstevel@tonic-gate 	if ((sscanf(unm, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
21380Sstevel@tonic-gate 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
21390Sstevel@tonic-gate 	    onmb, &d, snm, &l) == 3 ||
21400Sstevel@tonic-gate 	    sscanf(unm, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u"
21410Sstevel@tonic-gate 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
21420Sstevel@tonic-gate 	    onmb, &d, snm, &l) == 3) && l == cl) {
21430Sstevel@tonic-gate 		if ((p = strchr("abcdefgh", snm[0])) != NULL) {
21440Sstevel@tonic-gate 			(void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u%s",
21450Sstevel@tonic-gate 			    onmb, d, snm);
21460Sstevel@tonic-gate 			return (Strdup(cnmb));
21470Sstevel@tonic-gate 		}
21480Sstevel@tonic-gate 	}
21490Sstevel@tonic-gate 
21500Sstevel@tonic-gate 	if ((p = strstr(unm, "/dsk/")) != NULL) {	/* /.../dsk/... */
21510Sstevel@tonic-gate 		++p;
21520Sstevel@tonic-gate 		rnm = Zalloc(strlen(unm) + 1 + 1);
21530Sstevel@tonic-gate 		(void) strncpy(rnm, unm, (p - unm));
21540Sstevel@tonic-gate 		rnm[(p - unm)] = 'r';
21550Sstevel@tonic-gate 		(void) strcpy(&rnm[(p - unm) + 1], p);
21560Sstevel@tonic-gate 		return (rnm);
21570Sstevel@tonic-gate 	} else if (strstr(unm, "/rdsk/") != NULL) {	/* /.../rdsk/... */
21580Sstevel@tonic-gate 		return (Strdup(unm));
21590Sstevel@tonic-gate 	}
21600Sstevel@tonic-gate 
21610Sstevel@tonic-gate 	/*
21620Sstevel@tonic-gate 	 * Shouldn't get here but if we do then we have an unrecognized
21630Sstevel@tonic-gate 	 * fully qualified path - error
21640Sstevel@tonic-gate 	 */
21650Sstevel@tonic-gate 	(void) mdsyserror(ep, EINVAL, unm);
21660Sstevel@tonic-gate 	return (NULL);
21670Sstevel@tonic-gate }
21680Sstevel@tonic-gate 
21690Sstevel@tonic-gate static mdname_t *
21700Sstevel@tonic-gate metainitfastname(
21710Sstevel@tonic-gate 	mdsetname_t	*sp,
21720Sstevel@tonic-gate 	char		*uname,
21730Sstevel@tonic-gate 	md_error_t	*ep
21740Sstevel@tonic-gate )
21750Sstevel@tonic-gate {
21760Sstevel@tonic-gate 	uint_t			c = 0, t = 0, d = 0, s = 0;
21770Sstevel@tonic-gate 	int			l = 0;
21780Sstevel@tonic-gate 	mddrivename_t		*dnp;
21790Sstevel@tonic-gate 	mdname_t		*np;
21800Sstevel@tonic-gate 	mdnamelist_t		**fnlpp;
21810Sstevel@tonic-gate 
21820Sstevel@tonic-gate 	for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) {
21830Sstevel@tonic-gate 		np = (*fnlpp)->namep;
21840Sstevel@tonic-gate 
21850Sstevel@tonic-gate 		if (strcmp(np->bname, uname) == 0)
21860Sstevel@tonic-gate 			return (np);
21870Sstevel@tonic-gate 	}
21880Sstevel@tonic-gate 
21890Sstevel@tonic-gate 	*fnlpp = Zalloc(sizeof (**fnlpp));
21900Sstevel@tonic-gate 	np = (*fnlpp)->namep = Zalloc(sizeof (mdname_t));
21910Sstevel@tonic-gate 	metainitname(np);
21920Sstevel@tonic-gate 	dnp = np->drivenamep = Zalloc(sizeof (mddrivename_t));
21930Sstevel@tonic-gate 	metainitdrivename(dnp);
21940Sstevel@tonic-gate 
21950Sstevel@tonic-gate 
21960Sstevel@tonic-gate 	/* Metadevices */
21970Sstevel@tonic-gate 	if (is_metaname(uname)) {
21980Sstevel@tonic-gate 		char *p;
21990Sstevel@tonic-gate 		size_t len;
22000Sstevel@tonic-gate 
22010Sstevel@tonic-gate 		if ((p = strrchr(uname, '/')) != NULL)
22020Sstevel@tonic-gate 			++p;
22030Sstevel@tonic-gate 		else
22040Sstevel@tonic-gate 			p = uname;
22050Sstevel@tonic-gate 
22060Sstevel@tonic-gate 		if (metaislocalset(sp)) {
22070Sstevel@tonic-gate 			if (np->cname)
22080Sstevel@tonic-gate 				Free(np->cname);
22090Sstevel@tonic-gate 			np->cname = Strdup(p);
22100Sstevel@tonic-gate 		} else {
22110Sstevel@tonic-gate 			if (np->cname)
22120Sstevel@tonic-gate 				Free(np->cname);
22130Sstevel@tonic-gate 			len = strlen(sp->setname) + 1 + strlen(p) + 1;
22140Sstevel@tonic-gate 			np->cname = Zalloc(len);
22150Sstevel@tonic-gate 			(void) snprintf(np->cname, len, "%s/%s",
22160Sstevel@tonic-gate 			    sp->setname, p);
22170Sstevel@tonic-gate 		}
22180Sstevel@tonic-gate 		dnp->type = MDT_FAST_META;
22190Sstevel@tonic-gate 		goto done;
22200Sstevel@tonic-gate 	}
22210Sstevel@tonic-gate 
22220Sstevel@tonic-gate 	/* Others */
22230Sstevel@tonic-gate 	dnp->type = MDT_FAST_COMP;
22240Sstevel@tonic-gate 
22250Sstevel@tonic-gate 	if (((sscanf(uname, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d,
22260Sstevel@tonic-gate 		&s, &l) == 4 ||
22270Sstevel@tonic-gate 	    sscanf(uname, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d,
22280Sstevel@tonic-gate 		&s, &l) == 4 ||
22290Sstevel@tonic-gate 	    sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c, &t, &d,
22300Sstevel@tonic-gate 		&s, &l) == 4 ||
22310Sstevel@tonic-gate 	    sscanf(uname, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c, &t, &d,
22320Sstevel@tonic-gate 		&s, &l) == 4 ||
22330Sstevel@tonic-gate 	    sscanf(uname, "/dev/did/rdsk/d%us%u%n", &t, &s, &l) == 2 ||
22340Sstevel@tonic-gate 	    sscanf(uname, "/dev/did/dsk/d%us%u%n", &t, &s, &l) == 2||
22350Sstevel@tonic-gate 	    sscanf(uname, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
22360Sstevel@tonic-gate 	    sscanf(uname, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
22370Sstevel@tonic-gate 	    sscanf(uname, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
22380Sstevel@tonic-gate 	    sscanf(uname, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
22390Sstevel@tonic-gate 	    sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
22400Sstevel@tonic-gate 	    sscanf(uname, "/dev/ap/dsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
22410Sstevel@tonic-gate 	    sscanf(uname, "/dev/did/rdsk/d%u%n", &t, &l) == 1 ||
22420Sstevel@tonic-gate 	    sscanf(uname, "/dev/did/dsk/d%u%n", &t, &l) == 1 ||
22430Sstevel@tonic-gate 	    sscanf(uname, "/dev/rdsk/c%ud%u%n", &c, &d, &l) == 2 ||
22440Sstevel@tonic-gate 	    sscanf(uname, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2) &&
22450Sstevel@tonic-gate 		l == strlen(uname))) {
22460Sstevel@tonic-gate 		if ((np->cname = strrchr(uname, '/')) == NULL)
22470Sstevel@tonic-gate 			np->cname = Strdup(uname);
22480Sstevel@tonic-gate 		else
22490Sstevel@tonic-gate 			np->cname = Strdup(++np->cname);
22500Sstevel@tonic-gate 	} else {
22510Sstevel@tonic-gate 		np->cname = Strdup(uname);
22520Sstevel@tonic-gate 	}
22530Sstevel@tonic-gate 
22540Sstevel@tonic-gate done:
22550Sstevel@tonic-gate 	/* Driver always gives us block names */
22560Sstevel@tonic-gate 	np->bname = Strdup(uname);
22570Sstevel@tonic-gate 
22580Sstevel@tonic-gate 	/* canonical disk name */
22590Sstevel@tonic-gate 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
22600Sstevel@tonic-gate 		dnp->cname = Strdup(np->cname);
22610Sstevel@tonic-gate 
22620Sstevel@tonic-gate 	if ((np->rname = getrname_fast(uname, ep)) != NULL) {
22630Sstevel@tonic-gate 		if ((dnp->rname = metadiskname(np->rname)) == NULL)
22640Sstevel@tonic-gate 			dnp->rname = Strdup(np->rname);
22650Sstevel@tonic-gate 	} else {
22660Sstevel@tonic-gate 		metafreefastnm(&(*fnlpp)->namep);
22670Sstevel@tonic-gate 		Free(*fnlpp);
22680Sstevel@tonic-gate 		*fnlpp = NULL;
22690Sstevel@tonic-gate 		return (NULL);
22700Sstevel@tonic-gate 	}
22710Sstevel@tonic-gate 
22720Sstevel@tonic-gate 	/* cleanup, return success */
22730Sstevel@tonic-gate 	return (np);
22740Sstevel@tonic-gate }
22750Sstevel@tonic-gate 
22760Sstevel@tonic-gate /*
22770Sstevel@tonic-gate  * set up names for a device
22780Sstevel@tonic-gate  */
22790Sstevel@tonic-gate static mdname_t *
22800Sstevel@tonic-gate metaname_common(
22810Sstevel@tonic-gate 	mdsetname_t	**spp,
22820Sstevel@tonic-gate 	char		*uname,
22830Sstevel@tonic-gate 	int		fast,
22840Sstevel@tonic-gate 	md_error_t	*ep
22850Sstevel@tonic-gate )
22860Sstevel@tonic-gate {
22870Sstevel@tonic-gate 	mddrivenamelist_t	**tail;
22880Sstevel@tonic-gate 	mddrivename_t		*dnp;
22890Sstevel@tonic-gate 	uint_t			slice;
22900Sstevel@tonic-gate 	mdname_t		*np;
22910Sstevel@tonic-gate 	char			*rname = NULL;
22920Sstevel@tonic-gate 	char			*dname = NULL;
22930Sstevel@tonic-gate 	char			*cname = NULL;
22940Sstevel@tonic-gate 	uint_t			nparts, partno;
22950Sstevel@tonic-gate 
22960Sstevel@tonic-gate 	assert(uname != NULL);
22970Sstevel@tonic-gate 
22980Sstevel@tonic-gate 	/* check setname */
22990Sstevel@tonic-gate 	if ((cname = meta_name_getname(spp, uname, ep)) == NULL)
23000Sstevel@tonic-gate 		return (NULL);
23010Sstevel@tonic-gate 
23020Sstevel@tonic-gate 	assert(*spp != NULL);
23030Sstevel@tonic-gate 	Free(cname);
23040Sstevel@tonic-gate 
23050Sstevel@tonic-gate 	/* get raw name (rname) of the slice and drive (dname) we have */
23060Sstevel@tonic-gate 	if ((rname = getrawnames(spp, uname, &dname, ep)) == NULL) {
23070Sstevel@tonic-gate 		return (NULL);
23080Sstevel@tonic-gate 	}
23090Sstevel@tonic-gate 
23100Sstevel@tonic-gate 	/* look in cache first */
23110Sstevel@tonic-gate 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
23120Sstevel@tonic-gate 		dnp = (*tail)->drivenamep;
23130Sstevel@tonic-gate 
23140Sstevel@tonic-gate 		/* check to see if the drive name is already in the cache */
23150Sstevel@tonic-gate 		if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) {
23160Sstevel@tonic-gate 
23170Sstevel@tonic-gate 			Free(rname);
23180Sstevel@tonic-gate 			if (dname != NULL)
23190Sstevel@tonic-gate 				Free(dname);
23200Sstevel@tonic-gate 
23210Sstevel@tonic-gate 			if (uname2sliceno(uname, &partno, ep) < 0)
23220Sstevel@tonic-gate 				return (NULL);
23230Sstevel@tonic-gate 
23240Sstevel@tonic-gate 			return (metaslicename(dnp, partno, ep));
23250Sstevel@tonic-gate 		}
23260Sstevel@tonic-gate 	}
23270Sstevel@tonic-gate 
23280Sstevel@tonic-gate 	/*
23290Sstevel@tonic-gate 	 * If a fast names is OK, then get one, and be done.
23300Sstevel@tonic-gate 	 */
23310Sstevel@tonic-gate 	if (fast) {
23320Sstevel@tonic-gate 		Free(rname);
23330Sstevel@tonic-gate 		if (dname != NULL)
23340Sstevel@tonic-gate 			Free(dname);
23350Sstevel@tonic-gate 
23360Sstevel@tonic-gate 		return (metainitfastname(*spp, uname, ep));
23370Sstevel@tonic-gate 	}
23380Sstevel@tonic-gate 
23390Sstevel@tonic-gate 	/* allocate new list element and drive */
23400Sstevel@tonic-gate 	*tail = Zalloc(sizeof (**tail));
23410Sstevel@tonic-gate 	dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
23420Sstevel@tonic-gate 
23430Sstevel@tonic-gate 	metainitdrivename(dnp);
23440Sstevel@tonic-gate 
23450Sstevel@tonic-gate 	/* get parts info */
23460Sstevel@tonic-gate 	if (getparts(dnp, rname, dname, &nparts, &partno, ep) != 0)
23470Sstevel@tonic-gate 		goto out;
23480Sstevel@tonic-gate 
23490Sstevel@tonic-gate 	/*
23500Sstevel@tonic-gate 	 * libmeta needs at least V_NUMPAR partitions.
23510Sstevel@tonic-gate 	 * If we have an EFI partition with less than V_NUMPAR slices,
23520Sstevel@tonic-gate 	 * we nevertheless reserve space for V_NUMPAR
23530Sstevel@tonic-gate 	 */
23540Sstevel@tonic-gate 	if (nparts < V_NUMPAR) {
23550Sstevel@tonic-gate 		nparts = V_NUMPAR;
23560Sstevel@tonic-gate 	}
23570Sstevel@tonic-gate 
23580Sstevel@tonic-gate 	/* allocate and link in parts */
23590Sstevel@tonic-gate 	dnp->parts.parts_len = nparts;
23600Sstevel@tonic-gate 	dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) *
23610Sstevel@tonic-gate 	    dnp->parts.parts_len);
23620Sstevel@tonic-gate 	for (slice = 0; (slice < nparts); ++slice) {
23630Sstevel@tonic-gate 		np = &dnp->parts.parts_val[slice];
23640Sstevel@tonic-gate 		metainitname(np);
23650Sstevel@tonic-gate 		np->drivenamep = dnp;
23660Sstevel@tonic-gate 	}
23670Sstevel@tonic-gate 
23680Sstevel@tonic-gate 	/* setup name_t (or slice) wanted */
23690Sstevel@tonic-gate 	if ((np = setup_slice(*spp, dnp, uname, rname, dname, partno, ep))
23700Sstevel@tonic-gate 	    == NULL)
23710Sstevel@tonic-gate 		goto out;
23720Sstevel@tonic-gate 
23730Sstevel@tonic-gate 	/* canonical disk name */
23740Sstevel@tonic-gate 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
23750Sstevel@tonic-gate 		dnp->cname = Strdup(np->cname);
23760Sstevel@tonic-gate 	if ((dnp->rname = metadiskname(np->rname)) == NULL)
23770Sstevel@tonic-gate 		dnp->rname = Strdup(np->rname);
23780Sstevel@tonic-gate 
23790Sstevel@tonic-gate 	/* cleanup, return success */
23800Sstevel@tonic-gate 	if (dname != NULL)
23810Sstevel@tonic-gate 		Free(dname);
23820Sstevel@tonic-gate 	Free(rname);
23830Sstevel@tonic-gate 	return (np);
23840Sstevel@tonic-gate 
23850Sstevel@tonic-gate 	/* cleanup, return error */
23860Sstevel@tonic-gate out:
23870Sstevel@tonic-gate 	if (dname != NULL)
23880Sstevel@tonic-gate 		Free(dname);
23890Sstevel@tonic-gate 	if (rname != NULL)
23900Sstevel@tonic-gate 		Free(rname);
23910Sstevel@tonic-gate 
23920Sstevel@tonic-gate 	metafreedrivename(dnp);
23930Sstevel@tonic-gate 	Free(dnp);
23940Sstevel@tonic-gate 	Free(*tail);
23950Sstevel@tonic-gate 	*tail = NULL;
23960Sstevel@tonic-gate 	return (NULL);
23970Sstevel@tonic-gate }
23980Sstevel@tonic-gate 
23990Sstevel@tonic-gate mdname_t *
24000Sstevel@tonic-gate metaname(
24010Sstevel@tonic-gate 	mdsetname_t	**spp,
24020Sstevel@tonic-gate 	char		*uname,
24030Sstevel@tonic-gate 	md_error_t	*ep
24040Sstevel@tonic-gate )
24050Sstevel@tonic-gate {
24060Sstevel@tonic-gate 	return (metaname_common(spp, uname, 0, ep));
24070Sstevel@tonic-gate }
24080Sstevel@tonic-gate 
24090Sstevel@tonic-gate mdname_t *
24100Sstevel@tonic-gate metaname_fast(
24110Sstevel@tonic-gate 	mdsetname_t	**spp,
24120Sstevel@tonic-gate 	char		*uname,
24130Sstevel@tonic-gate 	md_error_t	*ep
24140Sstevel@tonic-gate )
24150Sstevel@tonic-gate {
24160Sstevel@tonic-gate 	return (metaname_common(spp, uname, 1, ep));
24170Sstevel@tonic-gate }
24180Sstevel@tonic-gate 
24190Sstevel@tonic-gate /*
24200Sstevel@tonic-gate  * set up names for a drive
24210Sstevel@tonic-gate  */
24220Sstevel@tonic-gate mddrivename_t *
24230Sstevel@tonic-gate metadrivename(
24240Sstevel@tonic-gate 	mdsetname_t	**spp,
24250Sstevel@tonic-gate 	char		*uname,
24260Sstevel@tonic-gate 	md_error_t	*ep
24270Sstevel@tonic-gate )
24280Sstevel@tonic-gate {
24290Sstevel@tonic-gate 	char		*slicename;
24300Sstevel@tonic-gate 	mdname_t	*np;
24310Sstevel@tonic-gate 
24320Sstevel@tonic-gate 	char		*cname;
24330Sstevel@tonic-gate 	mddrivenamelist_t **tail;
24340Sstevel@tonic-gate 	mddrivename_t	*dnp;
24350Sstevel@tonic-gate 	char		*dname;
24360Sstevel@tonic-gate 	int		i;
24370Sstevel@tonic-gate 	int		mplen;
24380Sstevel@tonic-gate 	size_t		len;
24390Sstevel@tonic-gate 
24400Sstevel@tonic-gate 	/* check setname, get comparison name */
24410Sstevel@tonic-gate 	assert(uname != NULL);
24420Sstevel@tonic-gate 	if ((cname = meta_name_getname(spp, uname, ep)) == NULL) {
24430Sstevel@tonic-gate 		(void) mdsyserror(ep, ENOENT, uname);
24440Sstevel@tonic-gate 		return (NULL);
24450Sstevel@tonic-gate 	}
24460Sstevel@tonic-gate 
24470Sstevel@tonic-gate 	assert(*spp != NULL);
24480Sstevel@tonic-gate 
24490Sstevel@tonic-gate 	if ((dname = metadiskname(cname)) == NULL) {
24500Sstevel@tonic-gate 		(void) mdsyserror(ep, ENOENT, cname);
24510Sstevel@tonic-gate 		Free(cname);
24520Sstevel@tonic-gate 		return (NULL);
24530Sstevel@tonic-gate 	}
24540Sstevel@tonic-gate 
24550Sstevel@tonic-gate 	/* look in cache first */
24560Sstevel@tonic-gate 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
24570Sstevel@tonic-gate 		dnp = (*tail)->drivenamep;
24580Sstevel@tonic-gate 		if ((dnp->cname != NULL &&
24590Sstevel@tonic-gate 		    (strcmp(dnp->cname, dname) == 0)) ||
24600Sstevel@tonic-gate 		    (dnp->rname != NULL &&
24610Sstevel@tonic-gate 		    (strcmp(dnp->rname, dname) == 0))) {
24620Sstevel@tonic-gate 			Free(cname);
24630Sstevel@tonic-gate 			Free(dname);
24640Sstevel@tonic-gate 			return (dnp);
24650Sstevel@tonic-gate 		}
24660Sstevel@tonic-gate 	}
24670Sstevel@tonic-gate 
24680Sstevel@tonic-gate 	/* Check each possible slice name based on MD_MAX_PARTS. */
24690Sstevel@tonic-gate 
24700Sstevel@tonic-gate 	/*
24710Sstevel@tonic-gate 	 * Figure out how much string space to reserve to fit
24720Sstevel@tonic-gate 	 * (MD_MAX_PARTS - 1) into the name string; the loop will
24730Sstevel@tonic-gate 	 * increment the mplen counter once for each decimal digit in
24740Sstevel@tonic-gate 	 * (MD_MAX_PARTS - 1).
24750Sstevel@tonic-gate 	 */
24760Sstevel@tonic-gate 	for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen);
24770Sstevel@tonic-gate 	len = strlen(uname) + mplen + 2;
24780Sstevel@tonic-gate 	slicename = Malloc(len);
24790Sstevel@tonic-gate 
24800Sstevel@tonic-gate 	/* Check for each slice in turn until we find one */
24810Sstevel@tonic-gate 	for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) {
24820Sstevel@tonic-gate 		(void) snprintf(slicename, len, "%ss%d", uname, i);
24830Sstevel@tonic-gate 		np = metaname(spp, slicename, ep);
24840Sstevel@tonic-gate 	}
24850Sstevel@tonic-gate 	Free(slicename);
24860Sstevel@tonic-gate 
24870Sstevel@tonic-gate 	if (np == NULL) {
24880Sstevel@tonic-gate 		char	*dname;
24890Sstevel@tonic-gate 
24900Sstevel@tonic-gate 		if ((mdissyserror(ep, ENOENT)) &&
24910Sstevel@tonic-gate 		    ((dname = metadiskname(uname)) != NULL)) {
24920Sstevel@tonic-gate 			Free(dname);
24930Sstevel@tonic-gate 			(void) mderror(ep, MDE_NOT_DRIVENAME, uname);
24940Sstevel@tonic-gate 		}
24950Sstevel@tonic-gate 		return (NULL);
24960Sstevel@tonic-gate 	}
24970Sstevel@tonic-gate 	return (np->drivenamep);
24980Sstevel@tonic-gate }
24990Sstevel@tonic-gate 
25000Sstevel@tonic-gate /*
25010Sstevel@tonic-gate  * FUNCTION:	metaslicename()
25020Sstevel@tonic-gate  * INPUT:	dnp	- the drivename structure
25030Sstevel@tonic-gate  *		sliceno	- the slice on the drive to return
25040Sstevel@tonic-gate  * OUTPUT:	ep	- return error pointer
25050Sstevel@tonic-gate  * RETURNS:	mdname_t- pointer the the slice name structure
25060Sstevel@tonic-gate  * PURPOSE:	interface to the parts struct in the drive name struct
25070Sstevel@tonic-gate  *		Since there is no guarantee that the slice name
25080Sstevel@tonic-gate  *		structures are populated users should call this
25090Sstevel@tonic-gate  *		function rather than accessing the structure directly
25100Sstevel@tonic-gate  *		since it will populate the structure values if they
25110Sstevel@tonic-gate  *		haven't already been populated before returning.
25120Sstevel@tonic-gate  */
25130Sstevel@tonic-gate mdname_t *
25140Sstevel@tonic-gate metaslicename(
25150Sstevel@tonic-gate 	mddrivename_t	*dnp,
25160Sstevel@tonic-gate 	uint_t		sliceno,
25170Sstevel@tonic-gate 	md_error_t	*ep
25180Sstevel@tonic-gate )
25190Sstevel@tonic-gate {
25200Sstevel@tonic-gate 	mdsetname_t	*sp = NULL;
25210Sstevel@tonic-gate 	char		*namep = NULL;
25220Sstevel@tonic-gate 	mdname_t	*np;
25230Sstevel@tonic-gate 
25240Sstevel@tonic-gate 	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
25250Sstevel@tonic-gate 
25260Sstevel@tonic-gate 	if (sliceno >= dnp->parts.parts_len) {
25270Sstevel@tonic-gate 		(void) mderror(ep, MDE_NOSLICE, dnp->cname);
25280Sstevel@tonic-gate 		return (NULL);
25290Sstevel@tonic-gate 	}
25300Sstevel@tonic-gate 
25310Sstevel@tonic-gate 	np = &dnp->parts.parts_val[sliceno];
25320Sstevel@tonic-gate 
25330Sstevel@tonic-gate 	/* check to see if the struct is already populated */
25340Sstevel@tonic-gate 	if (np->cname) {
25350Sstevel@tonic-gate 		return (np);
25360Sstevel@tonic-gate 	}
25370Sstevel@tonic-gate 
25380Sstevel@tonic-gate 	if ((namep = meta_name_getname(&sp, dnp->cname, ep)) == NULL)
25390Sstevel@tonic-gate 		return (NULL);
25400Sstevel@tonic-gate 
25410Sstevel@tonic-gate 	np = setup_slice(sp, dnp, NULL, NULL, dnp->rname, sliceno, ep);
25420Sstevel@tonic-gate 
25430Sstevel@tonic-gate 	Free(namep);
25440Sstevel@tonic-gate 
25450Sstevel@tonic-gate 	return (np);
25460Sstevel@tonic-gate }
25470Sstevel@tonic-gate 
25480Sstevel@tonic-gate /*
25490Sstevel@tonic-gate  * set up metadevice name from id
25500Sstevel@tonic-gate  */
25510Sstevel@tonic-gate mdname_t *
25520Sstevel@tonic-gate metamnumname(
25530Sstevel@tonic-gate 	mdsetname_t	**spp,
25540Sstevel@tonic-gate 	minor_t		mnum,
25550Sstevel@tonic-gate 	int		fast,
25560Sstevel@tonic-gate 	md_error_t	*ep
25570Sstevel@tonic-gate )
25580Sstevel@tonic-gate {
25590Sstevel@tonic-gate 	set_t		setno = MD_MIN2SET(mnum);
25600Sstevel@tonic-gate 	mdsetname_t	*sp = NULL;
25610Sstevel@tonic-gate 	char		*uname;
25620Sstevel@tonic-gate 	mdname_t	*np;
25630Sstevel@tonic-gate 	size_t		len;
25640Sstevel@tonic-gate 
25650Sstevel@tonic-gate 	/* check set first */
25660Sstevel@tonic-gate 	if (spp == NULL)
25670Sstevel@tonic-gate 		spp = &sp;
25680Sstevel@tonic-gate 	if (chksetno(spp, setno, ep) != 0)
25690Sstevel@tonic-gate 		return (NULL);
25700Sstevel@tonic-gate 	assert(*spp != NULL);
25710Sstevel@tonic-gate 	sp = *spp;
25720Sstevel@tonic-gate 
25730Sstevel@tonic-gate 	/* build corresponding device name */
25740Sstevel@tonic-gate 	if (metaislocalset(sp)) {
25750Sstevel@tonic-gate 		uname = Malloc(20);
25760Sstevel@tonic-gate 		(void) sprintf(uname, "d%lu", MD_MIN2UNIT(mnum));
25770Sstevel@tonic-gate 	} else {
25780Sstevel@tonic-gate 		len = strlen(sp->setname) + 1 + 20;
25790Sstevel@tonic-gate 		uname = Malloc(len);
25800Sstevel@tonic-gate 		(void) snprintf(uname, len, "%s/d%lu", sp->setname,
25810Sstevel@tonic-gate 		    MD_MIN2UNIT(mnum));
25820Sstevel@tonic-gate 	}
25830Sstevel@tonic-gate 
25840Sstevel@tonic-gate 	/* setup name */
25850Sstevel@tonic-gate 	if (fast) {
25860Sstevel@tonic-gate 		np = metaname_fast(spp, uname, ep);
25870Sstevel@tonic-gate 		np->dev = metamakedev(mnum);
25880Sstevel@tonic-gate 	} else
25890Sstevel@tonic-gate 		np = metaname(spp, uname, ep);
25900Sstevel@tonic-gate 
25910Sstevel@tonic-gate 	Free(uname);
25920Sstevel@tonic-gate 	return (np);
25930Sstevel@tonic-gate }
25940Sstevel@tonic-gate 
25950Sstevel@tonic-gate /*
25960Sstevel@tonic-gate  * return metadevice name
25970Sstevel@tonic-gate  */
25980Sstevel@tonic-gate char *
25990Sstevel@tonic-gate get_mdname(
26000Sstevel@tonic-gate 	minor_t		mnum
26010Sstevel@tonic-gate )
26020Sstevel@tonic-gate {
26030Sstevel@tonic-gate 	mdname_t	*np;
26040Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
26050Sstevel@tonic-gate 
26060Sstevel@tonic-gate 	/* get name */
26070Sstevel@tonic-gate 	if ((np = metamnumname(NULL, mnum, 0, &status)) == NULL) {
26080Sstevel@tonic-gate 		mdclrerror(&status);
26090Sstevel@tonic-gate 		return (NULL);
26100Sstevel@tonic-gate 	}
26110Sstevel@tonic-gate 	assert(meta_getminor(np->dev) == mnum);
26120Sstevel@tonic-gate 
26130Sstevel@tonic-gate 	/* return name */
26140Sstevel@tonic-gate 	return (np->cname);
26150Sstevel@tonic-gate }
26160Sstevel@tonic-gate 
26170Sstevel@tonic-gate /*
26180Sstevel@tonic-gate  * check for device type
26190Sstevel@tonic-gate  */
26200Sstevel@tonic-gate int
26210Sstevel@tonic-gate metaismeta(
26220Sstevel@tonic-gate 	mdname_t	*np
26230Sstevel@tonic-gate )
26240Sstevel@tonic-gate {
26250Sstevel@tonic-gate 	return (np->drivenamep->type == MDT_META ||
26260Sstevel@tonic-gate 		np->drivenamep->type == MDT_FAST_META);
26270Sstevel@tonic-gate }
26280Sstevel@tonic-gate 
26290Sstevel@tonic-gate int
26300Sstevel@tonic-gate metachkmeta(
26310Sstevel@tonic-gate 	mdname_t	*np,
26320Sstevel@tonic-gate 	md_error_t	*ep
26330Sstevel@tonic-gate )
26340Sstevel@tonic-gate {
26350Sstevel@tonic-gate 	if (! metaismeta(np)) {
26360Sstevel@tonic-gate 		return (mddeverror(ep, MDE_NOT_META, np->dev,
26370Sstevel@tonic-gate 		    np->cname));
26380Sstevel@tonic-gate 	}
26390Sstevel@tonic-gate 	return (0);
26400Sstevel@tonic-gate }
26410Sstevel@tonic-gate 
26420Sstevel@tonic-gate int
26430Sstevel@tonic-gate metachkdisk(
26440Sstevel@tonic-gate 	mdname_t	*np,
26450Sstevel@tonic-gate 	md_error_t	*ep
26460Sstevel@tonic-gate )
26470Sstevel@tonic-gate {
26480Sstevel@tonic-gate 	mddrivename_t	*dnp = np->drivenamep;
26490Sstevel@tonic-gate 
26500Sstevel@tonic-gate 	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
26510Sstevel@tonic-gate 
26520Sstevel@tonic-gate 	if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) {
26530Sstevel@tonic-gate 		switch (dnp->type) {
26540Sstevel@tonic-gate 		    case MDT_ACCES:
26550Sstevel@tonic-gate 		    case MDT_UNKNOWN:
26560Sstevel@tonic-gate 			    return (mdsyserror(ep, dnp->errnum, np->bname));
26570Sstevel@tonic-gate 		    default:
26580Sstevel@tonic-gate 			    assert(0);
26590Sstevel@tonic-gate 			    return (mddeverror(ep, MDE_NOT_DISK, np->dev,
26600Sstevel@tonic-gate 				np->cname));
26610Sstevel@tonic-gate 		}
26620Sstevel@tonic-gate 	}
26630Sstevel@tonic-gate 	return (0);
26640Sstevel@tonic-gate }
26650Sstevel@tonic-gate 
26660Sstevel@tonic-gate int
26670Sstevel@tonic-gate metachkcomp(
26680Sstevel@tonic-gate 	mdname_t	*np,
26690Sstevel@tonic-gate 	md_error_t	*ep
26700Sstevel@tonic-gate )
26710Sstevel@tonic-gate {
26720Sstevel@tonic-gate 	if (metaismeta(np)) {
26730Sstevel@tonic-gate 		return (mddeverror(ep, MDE_IS_META, np->dev,
26740Sstevel@tonic-gate 		    np->cname));
26750Sstevel@tonic-gate 	}
26760Sstevel@tonic-gate 	return (metachkdisk(np, ep));
26770Sstevel@tonic-gate }
26780Sstevel@tonic-gate 
26790Sstevel@tonic-gate /*
26800Sstevel@tonic-gate  * free list of names
26810Sstevel@tonic-gate  */
26820Sstevel@tonic-gate void
26830Sstevel@tonic-gate metafreenamelist(
26840Sstevel@tonic-gate 	mdnamelist_t	*nlp
26850Sstevel@tonic-gate )
26860Sstevel@tonic-gate {
26870Sstevel@tonic-gate 	mdnamelist_t	*next = NULL;
26880Sstevel@tonic-gate 
26890Sstevel@tonic-gate 	for (/* void */; (nlp != NULL); nlp = next) {
26900Sstevel@tonic-gate 		next = nlp->next;
26910Sstevel@tonic-gate 		Free(nlp);
26920Sstevel@tonic-gate 	}
26930Sstevel@tonic-gate }
26940Sstevel@tonic-gate 
26950Sstevel@tonic-gate /*
26960Sstevel@tonic-gate  * build list of names
26970Sstevel@tonic-gate  */
26980Sstevel@tonic-gate int
26990Sstevel@tonic-gate metanamelist(
27000Sstevel@tonic-gate 	mdsetname_t	**spp,
27010Sstevel@tonic-gate 	mdnamelist_t	**nlpp,
27020Sstevel@tonic-gate 	int		argc,
27030Sstevel@tonic-gate 	char		*argv[],
27040Sstevel@tonic-gate 	md_error_t	*ep
27050Sstevel@tonic-gate )
27060Sstevel@tonic-gate {
27070Sstevel@tonic-gate 	mdnamelist_t	**tailpp = nlpp;
27080Sstevel@tonic-gate 	int		count = 0;
27090Sstevel@tonic-gate 
27100Sstevel@tonic-gate 	for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
27110Sstevel@tonic-gate 		mdnamelist_t	*nlp = Zalloc(sizeof (*nlp));
27120Sstevel@tonic-gate 
27130Sstevel@tonic-gate 		if ((nlp->namep = metaname(spp, argv[0], ep)) == NULL) {
27140Sstevel@tonic-gate 			metafreenamelist(*nlpp);
27150Sstevel@tonic-gate 			*nlpp = NULL;
27160Sstevel@tonic-gate 			return (-1);
27170Sstevel@tonic-gate 		}
27180Sstevel@tonic-gate 		*tailpp = nlp;
27190Sstevel@tonic-gate 		tailpp = &nlp->next;
27200Sstevel@tonic-gate 	}
27210Sstevel@tonic-gate 	return (count);
27220Sstevel@tonic-gate }
27230Sstevel@tonic-gate 
27240Sstevel@tonic-gate /*
27250Sstevel@tonic-gate  * append to end of name list
27260Sstevel@tonic-gate  */
27270Sstevel@tonic-gate mdname_t *
27280Sstevel@tonic-gate metanamelist_append(
27290Sstevel@tonic-gate 	mdnamelist_t	**nlpp,
27300Sstevel@tonic-gate 	mdname_t	*np
27310Sstevel@tonic-gate )
27320Sstevel@tonic-gate {
27330Sstevel@tonic-gate 	mdnamelist_t	*nlp;
27340Sstevel@tonic-gate 
27350Sstevel@tonic-gate 	/* run to end of list */
27360Sstevel@tonic-gate 	for (; (*nlpp != NULL); nlpp = &(*nlpp)->next)
27370Sstevel@tonic-gate 		;
27380Sstevel@tonic-gate 
27390Sstevel@tonic-gate 	/* allocate new list element */
27400Sstevel@tonic-gate 	nlp = *nlpp = Zalloc(sizeof (*nlp));
27410Sstevel@tonic-gate 
27420Sstevel@tonic-gate 	/* append name */
27430Sstevel@tonic-gate 	nlp->namep = np;
27440Sstevel@tonic-gate 	return (np);
27450Sstevel@tonic-gate }
27460Sstevel@tonic-gate 
27470Sstevel@tonic-gate /*
27480Sstevel@tonic-gate  * FUNCTION:	meta_namelist_append_wrapper()
27490Sstevel@tonic-gate  * INPUT:	tailpp	- pointer to the list tail pointer
27500Sstevel@tonic-gate  *		np	- name node to be appended to list
27510Sstevel@tonic-gate  * OUTPUT:	none
27520Sstevel@tonic-gate  * RETURNS:	mdnamelist_t * - new tail of the list.
27530Sstevel@tonic-gate  * PURPOSE:	wrapper to meta_namelist_append for performance.
27540Sstevel@tonic-gate  *		metanamelist_append finds the tail each time which slows
27550Sstevel@tonic-gate  *		down long lists.  By keeping track of the tail ourselves
27560Sstevel@tonic-gate  *		we can change metanamelist_append into a constant time
27570Sstevel@tonic-gate  *		operation.
27580Sstevel@tonic-gate  */
27590Sstevel@tonic-gate mdnamelist_t **
27600Sstevel@tonic-gate meta_namelist_append_wrapper(
27610Sstevel@tonic-gate 	mdnamelist_t	**tailpp,
27620Sstevel@tonic-gate 	mdname_t	*np
27630Sstevel@tonic-gate )
27640Sstevel@tonic-gate {
27650Sstevel@tonic-gate 	(void) metanamelist_append(tailpp, np);
27660Sstevel@tonic-gate 
27670Sstevel@tonic-gate 	/* If it's the first item in the list, return it instead of the next */
27680Sstevel@tonic-gate 	if ((*tailpp)->next == NULL)
27690Sstevel@tonic-gate 		return (tailpp);
27700Sstevel@tonic-gate 
27710Sstevel@tonic-gate 	return (&(*tailpp)->next);
27720Sstevel@tonic-gate }
27730Sstevel@tonic-gate 
27740Sstevel@tonic-gate 
27750Sstevel@tonic-gate /*
27760Sstevel@tonic-gate  *	mdhspname_t stuff
27770Sstevel@tonic-gate  */
27780Sstevel@tonic-gate 
27790Sstevel@tonic-gate /*
27800Sstevel@tonic-gate  * initialize hspname
27810Sstevel@tonic-gate  */
27820Sstevel@tonic-gate static void
27830Sstevel@tonic-gate metainithspname(
27840Sstevel@tonic-gate 	mdhspname_t	*hspnamep
27850Sstevel@tonic-gate )
27860Sstevel@tonic-gate {
27870Sstevel@tonic-gate 	(void) memset(hspnamep, '\0', sizeof (*hspnamep));
27880Sstevel@tonic-gate 	hspnamep->hsp = MD_HSP_NONE;
27890Sstevel@tonic-gate }
27900Sstevel@tonic-gate 
27910Sstevel@tonic-gate /*
27920Sstevel@tonic-gate  * free allocated hspname
27930Sstevel@tonic-gate  */
27940Sstevel@tonic-gate static void
27950Sstevel@tonic-gate metafreehspname(
27960Sstevel@tonic-gate 	mdhspname_t	*hspnamep
27970Sstevel@tonic-gate )
27980Sstevel@tonic-gate {
27990Sstevel@tonic-gate 	if (hspnamep->hspname != NULL)
28000Sstevel@tonic-gate 		Free(hspnamep->hspname);
28010Sstevel@tonic-gate 	if (hspnamep->unitp != NULL)
28020Sstevel@tonic-gate 		meta_invalidate_hsp(hspnamep);
28030Sstevel@tonic-gate 	metainithspname(hspnamep);
28040Sstevel@tonic-gate }
28050Sstevel@tonic-gate 
28060Sstevel@tonic-gate /*
28070Sstevel@tonic-gate  * clear the hspname cache
28080Sstevel@tonic-gate  */
28090Sstevel@tonic-gate static void
28100Sstevel@tonic-gate metaflushhspnames()
28110Sstevel@tonic-gate {
28120Sstevel@tonic-gate 	mdhspnamelist_t		*p, *n;
28130Sstevel@tonic-gate 
28140Sstevel@tonic-gate 	for (p = hsplistp, n = NULL; (p != NULL); p = n) {
28150Sstevel@tonic-gate 		n = p->next;
28160Sstevel@tonic-gate 		metafreehspname(p->hspnamep);
28170Sstevel@tonic-gate 		Free(p->hspnamep);
28180Sstevel@tonic-gate 		Free(p);
28190Sstevel@tonic-gate 	}
28200Sstevel@tonic-gate 	hsplistp = NULL;
28210Sstevel@tonic-gate }
28220Sstevel@tonic-gate 
28230Sstevel@tonic-gate /*
28240Sstevel@tonic-gate  * check set and get comparison name
28250Sstevel@tonic-gate  */
28260Sstevel@tonic-gate static char *
28270Sstevel@tonic-gate gethspname(
28280Sstevel@tonic-gate 	mdsetname_t	**spp,
28290Sstevel@tonic-gate 	char		*uname,
28300Sstevel@tonic-gate 	hsp_t		*hspp,
28310Sstevel@tonic-gate 	md_error_t	*ep
28320Sstevel@tonic-gate )
28330Sstevel@tonic-gate {
28340Sstevel@tonic-gate 	char		*sname = NULL;
28350Sstevel@tonic-gate 
28360Sstevel@tonic-gate 	/* check setname */
28370Sstevel@tonic-gate 	assert(uname != NULL);
28380Sstevel@tonic-gate 	if (parse_hsp(uname, &sname, hspp) != 0) {
28390Sstevel@tonic-gate 		(void) mdsyserror(ep, ENOENT, uname);
28400Sstevel@tonic-gate 		return (NULL);
28410Sstevel@tonic-gate 	}
28420Sstevel@tonic-gate 	if (chksetname(spp, sname, ep) != 0) {
28430Sstevel@tonic-gate 		if (sname != NULL)
28440Sstevel@tonic-gate 			Free(sname);
28450Sstevel@tonic-gate 		return (NULL);
28460Sstevel@tonic-gate 	}
28470Sstevel@tonic-gate 	if (sname != NULL)
28480Sstevel@tonic-gate 		Free(sname);
28490Sstevel@tonic-gate 
28500Sstevel@tonic-gate 	/* return comparison name */
28510Sstevel@tonic-gate 	return (canon_hsp((*spp)->setname, *hspp));
28520Sstevel@tonic-gate }
28530Sstevel@tonic-gate 
28540Sstevel@tonic-gate /*
28550Sstevel@tonic-gate  * set up names for a hotspare pool
28560Sstevel@tonic-gate  */
28570Sstevel@tonic-gate mdhspname_t *
28580Sstevel@tonic-gate metahspname(
28590Sstevel@tonic-gate 	mdsetname_t	**spp,
28600Sstevel@tonic-gate 	char		*uname,
28610Sstevel@tonic-gate 	md_error_t	*ep
28620Sstevel@tonic-gate )
28630Sstevel@tonic-gate {
28640Sstevel@tonic-gate 	char		*cname;
28650Sstevel@tonic-gate 	hsp_t		hsp;
28660Sstevel@tonic-gate 	mdhspnamelist_t	**tail;
28670Sstevel@tonic-gate 	mdhspname_t	*hspnp;
28680Sstevel@tonic-gate 
28690Sstevel@tonic-gate 	/* check setname */
28700Sstevel@tonic-gate 	assert(uname != NULL);
28710Sstevel@tonic-gate 	if ((cname = gethspname(spp, uname, &hsp, ep)) == NULL)
28720Sstevel@tonic-gate 		return (NULL);
28730Sstevel@tonic-gate 	assert(*spp != NULL);
28740Sstevel@tonic-gate 
28750Sstevel@tonic-gate 	/* look in cache first */
28760Sstevel@tonic-gate 	for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) {
28770Sstevel@tonic-gate 		hspnp = (*tail)->hspnamep;
28780Sstevel@tonic-gate 		if (strcmp(hspnp->hspname, cname) == 0) {
28790Sstevel@tonic-gate 			Free(cname);
28800Sstevel@tonic-gate 			return (hspnp);
28810Sstevel@tonic-gate 		}
28820Sstevel@tonic-gate 	}
28830Sstevel@tonic-gate 
28840Sstevel@tonic-gate 	/* allocate new list element and hspname */
28850Sstevel@tonic-gate 	*tail = Zalloc(sizeof (**tail));
28860Sstevel@tonic-gate 	hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp));
28870Sstevel@tonic-gate 	metainithspname(hspnp);
28880Sstevel@tonic-gate 
28890Sstevel@tonic-gate 	/* save hspname and number */
28900Sstevel@tonic-gate 	hspnp->hspname = cname;
28910Sstevel@tonic-gate 	hspnp->hsp = MAKE_HSP_ID((*spp)->setno, hsp);
28920Sstevel@tonic-gate 
28930Sstevel@tonic-gate 	/* success */
28940Sstevel@tonic-gate 	return (hspnp);
28950Sstevel@tonic-gate 
28960Sstevel@tonic-gate 	/* cleanup, return error */
28970Sstevel@tonic-gate out:
28980Sstevel@tonic-gate 	metafreehspname(hspnp);
28990Sstevel@tonic-gate 	Free(hspnp);
29000Sstevel@tonic-gate 	Free(*tail);
29010Sstevel@tonic-gate 	*tail = NULL;
29020Sstevel@tonic-gate 	return (NULL);
29030Sstevel@tonic-gate 
29040Sstevel@tonic-gate 
29050Sstevel@tonic-gate }
29060Sstevel@tonic-gate 
29070Sstevel@tonic-gate /*
29080Sstevel@tonic-gate  * set up hotspare pool name from id
29090Sstevel@tonic-gate  */
29100Sstevel@tonic-gate mdhspname_t *
29110Sstevel@tonic-gate metahsphspname(
29120Sstevel@tonic-gate 	mdsetname_t	**spp,
29130Sstevel@tonic-gate 	hsp_t		hsp,
29140Sstevel@tonic-gate 	md_error_t	*ep
29150Sstevel@tonic-gate )
29160Sstevel@tonic-gate {
29170Sstevel@tonic-gate 	set_t		setno = HSP_SET(hsp);
29180Sstevel@tonic-gate 	mdsetname_t	*sp = NULL;
29190Sstevel@tonic-gate 	char		*uname;
29200Sstevel@tonic-gate 	mdhspname_t	*hspnp;
29210Sstevel@tonic-gate 	size_t		len;
29220Sstevel@tonic-gate 
29230Sstevel@tonic-gate 	/* check set first */
29240Sstevel@tonic-gate 	if (spp == NULL)
29250Sstevel@tonic-gate 		spp = &sp;
29260Sstevel@tonic-gate 	if (chksetno(spp, setno, ep) != 0)
29270Sstevel@tonic-gate 		return (NULL);
29280Sstevel@tonic-gate 	assert(*spp != NULL);
29290Sstevel@tonic-gate 	sp = *spp;
29300Sstevel@tonic-gate 
29310Sstevel@tonic-gate 	/* build corresponding hotspare pool name */
29320Sstevel@tonic-gate 	if (metaislocalset(sp)) {
29330Sstevel@tonic-gate 		uname = Malloc(20);
29340Sstevel@tonic-gate 		(void) sprintf(uname, "hsp%03u", HSP_ID(hsp));
29350Sstevel@tonic-gate 	} else {
29360Sstevel@tonic-gate 		len = strlen(sp->setname) + 1 + 20;
29370Sstevel@tonic-gate 		uname = Malloc(len);
29380Sstevel@tonic-gate 		(void) snprintf(uname, len, "%s/hsp%03lu", sp->setname,
29390Sstevel@tonic-gate 		    HSP_ID(hsp));
29400Sstevel@tonic-gate 	}
29410Sstevel@tonic-gate 
29420Sstevel@tonic-gate 	/* setup name */
29430Sstevel@tonic-gate 	hspnp = metahspname(spp, uname, ep);
29440Sstevel@tonic-gate 	Free(uname);
29450Sstevel@tonic-gate 	return (hspnp);
29460Sstevel@tonic-gate }
29470Sstevel@tonic-gate 
29480Sstevel@tonic-gate /*
29490Sstevel@tonic-gate  * return hotspare pool name
29500Sstevel@tonic-gate  */
29510Sstevel@tonic-gate char *
29520Sstevel@tonic-gate get_hspname(hsp_t hsp)
29530Sstevel@tonic-gate {
29540Sstevel@tonic-gate 	mdhspname_t	*hspnp;
29550Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
29560Sstevel@tonic-gate 
29570Sstevel@tonic-gate 	/* get name */
29580Sstevel@tonic-gate 	if ((hspnp = metahsphspname(NULL, hsp, &status)) == NULL) {
29590Sstevel@tonic-gate 		mdclrerror(&status);
29600Sstevel@tonic-gate 		return (NULL);
29610Sstevel@tonic-gate 	}
29620Sstevel@tonic-gate 
29630Sstevel@tonic-gate 	/* return name */
29640Sstevel@tonic-gate 	return (hspnp->hspname);
29650Sstevel@tonic-gate }
29660Sstevel@tonic-gate 
29670Sstevel@tonic-gate /*
29680Sstevel@tonic-gate  * free hotspare pool list
29690Sstevel@tonic-gate  */
29700Sstevel@tonic-gate void
29710Sstevel@tonic-gate metafreehspnamelist(mdhspnamelist_t *hspnlp)
29720Sstevel@tonic-gate {
29730Sstevel@tonic-gate 	mdhspnamelist_t	*next = NULL;
29740Sstevel@tonic-gate 
29750Sstevel@tonic-gate 	for (/* void */; (hspnlp != NULL); hspnlp = next) {
29760Sstevel@tonic-gate 		next = hspnlp->next;
29770Sstevel@tonic-gate 		Free(hspnlp);
29780Sstevel@tonic-gate 	}
29790Sstevel@tonic-gate }
29800Sstevel@tonic-gate 
29810Sstevel@tonic-gate /*
29820Sstevel@tonic-gate  * build list of hotspare pool names
29830Sstevel@tonic-gate  */
29840Sstevel@tonic-gate int
29850Sstevel@tonic-gate metahspnamelist(
29860Sstevel@tonic-gate 	mdsetname_t	**spp,
29870Sstevel@tonic-gate 	mdhspnamelist_t	**hspnlpp,
29880Sstevel@tonic-gate 	int		argc,
29890Sstevel@tonic-gate 	char		*argv[],
29900Sstevel@tonic-gate 	md_error_t	*ep
29910Sstevel@tonic-gate )
29920Sstevel@tonic-gate {
29930Sstevel@tonic-gate 	mdhspnamelist_t	**tailpp = hspnlpp;
29940Sstevel@tonic-gate 	int		count = 0;
29950Sstevel@tonic-gate 
29960Sstevel@tonic-gate 	for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
29970Sstevel@tonic-gate 		mdhspnamelist_t	*hspnlp = Zalloc(sizeof (*hspnlp));
29980Sstevel@tonic-gate 
29990Sstevel@tonic-gate 		if ((hspnlp->hspnamep = metahspname(spp, argv[0],
30000Sstevel@tonic-gate 		    ep)) == NULL) {
30010Sstevel@tonic-gate 			metafreehspnamelist(*hspnlpp);
30020Sstevel@tonic-gate 			*hspnlpp = NULL;
30030Sstevel@tonic-gate 			return (-1);
30040Sstevel@tonic-gate 		}
30050Sstevel@tonic-gate 		*tailpp = hspnlp;
30060Sstevel@tonic-gate 		tailpp = &hspnlp->next;
30070Sstevel@tonic-gate 	}
30080Sstevel@tonic-gate 	return (count);
30090Sstevel@tonic-gate }
30100Sstevel@tonic-gate 
30110Sstevel@tonic-gate /*
30120Sstevel@tonic-gate  * append to end of hotspare pool list
30130Sstevel@tonic-gate  */
30140Sstevel@tonic-gate mdhspname_t *
30150Sstevel@tonic-gate metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp)
30160Sstevel@tonic-gate {
30170Sstevel@tonic-gate 	mdhspnamelist_t	*hspnlp;
30180Sstevel@tonic-gate 
30190Sstevel@tonic-gate 	/* run to end of list */
30200Sstevel@tonic-gate 	for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next)
30210Sstevel@tonic-gate 		;
30220Sstevel@tonic-gate 
30230Sstevel@tonic-gate 	/* allocate new list element */
30240Sstevel@tonic-gate 	hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp));
30250Sstevel@tonic-gate 
30260Sstevel@tonic-gate 	/* append hotspare pool name */
30270Sstevel@tonic-gate 	hspnlp->hspnamep = hspnp;
30280Sstevel@tonic-gate 	return (hspnp);
30290Sstevel@tonic-gate }
30300Sstevel@tonic-gate 
30310Sstevel@tonic-gate /*
30320Sstevel@tonic-gate  * get name from dev
30330Sstevel@tonic-gate  */
30340Sstevel@tonic-gate mdname_t *
30350Sstevel@tonic-gate metadevname(
30360Sstevel@tonic-gate 	mdsetname_t **spp,
30370Sstevel@tonic-gate 	md_dev64_t dev,
30380Sstevel@tonic-gate 	md_error_t *ep)
30390Sstevel@tonic-gate {
30400Sstevel@tonic-gate 	char		*device_name;
30410Sstevel@tonic-gate 	mdname_t	*namep;
30420Sstevel@tonic-gate 	mdkey_t		key;
30430Sstevel@tonic-gate 
30440Sstevel@tonic-gate 	/* short circuit metadevices */
30450Sstevel@tonic-gate 	assert(dev != NODEV64);
30460Sstevel@tonic-gate 	if (meta_dev_ismeta(dev))
30470Sstevel@tonic-gate 		return (metamnumname(spp, meta_getminor(dev), 0, ep));
30480Sstevel@tonic-gate 
30490Sstevel@tonic-gate 	/* create local set, if necessary */
30500Sstevel@tonic-gate 	if (*spp == NULL) {
30510Sstevel@tonic-gate 		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
30520Sstevel@tonic-gate 			return (NULL);
30530Sstevel@tonic-gate 	}
30540Sstevel@tonic-gate 
30550Sstevel@tonic-gate 	/* get name from namespace */
30560Sstevel@tonic-gate 	if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD,
30570Sstevel@tonic-gate 	    dev, NULL, NULL, &key, ep)) == NULL) {
30580Sstevel@tonic-gate 		return (NULL);
30590Sstevel@tonic-gate 	}
30600Sstevel@tonic-gate 	namep = metaname_fast(spp, device_name, ep);
30610Sstevel@tonic-gate 	if (namep != NULL)
30620Sstevel@tonic-gate 		namep->key = key;
30630Sstevel@tonic-gate 
30640Sstevel@tonic-gate 	Free(device_name);
30650Sstevel@tonic-gate 	return (namep);
30660Sstevel@tonic-gate }
30670Sstevel@tonic-gate 
30680Sstevel@tonic-gate /*
30690Sstevel@tonic-gate  * return cached name from md_dev64_t
30700Sstevel@tonic-gate  */
30710Sstevel@tonic-gate static char *
30720Sstevel@tonic-gate metadevtocachename(md_dev64_t dev)
30730Sstevel@tonic-gate {
30740Sstevel@tonic-gate 	mddrivenamelist_t	*dnlp;
30750Sstevel@tonic-gate 
30760Sstevel@tonic-gate 	/* look in cache */
30770Sstevel@tonic-gate 	for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) {
30780Sstevel@tonic-gate 		mddrivename_t	*dnp = dnlp->drivenamep;
30790Sstevel@tonic-gate 		uint_t		i;
30800Sstevel@tonic-gate 
30810Sstevel@tonic-gate 		for (i = 0; (i < dnp->parts.parts_len); ++i) {
30820Sstevel@tonic-gate 			mdname_t	*np = &dnp->parts.parts_val[i];
30830Sstevel@tonic-gate 
30840Sstevel@tonic-gate 			if (np->dev == dev)
30850Sstevel@tonic-gate 				return (np->cname);
30860Sstevel@tonic-gate 		}
30870Sstevel@tonic-gate 	}
30880Sstevel@tonic-gate 
30890Sstevel@tonic-gate 	/* not found */
30900Sstevel@tonic-gate 	return (NULL);
30910Sstevel@tonic-gate }
30920Sstevel@tonic-gate 
30930Sstevel@tonic-gate /*
30940Sstevel@tonic-gate  * Ask the driver for the name, which has been stored in the
30950Sstevel@tonic-gate  * metadevice state database (on behalf of the utilities).
30960Sstevel@tonic-gate  * (by devno)
30970Sstevel@tonic-gate  */
30980Sstevel@tonic-gate char *
30990Sstevel@tonic-gate get_devname(
31000Sstevel@tonic-gate 	set_t setno,
31010Sstevel@tonic-gate 	md_dev64_t dev)
31020Sstevel@tonic-gate {
31030Sstevel@tonic-gate 	mdsetname_t	*sp;
31040Sstevel@tonic-gate 	mdname_t	*np;
31050Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
31060Sstevel@tonic-gate 
31070Sstevel@tonic-gate 	/* get name */
31080Sstevel@tonic-gate 	if ((setno == MD_SET_BAD) ||
31090Sstevel@tonic-gate 	    ((sp = metasetnosetname(setno, &status)) == NULL) ||
31100Sstevel@tonic-gate 	    ((np = metadevname(&sp, dev, &status)) == NULL)) {
31110Sstevel@tonic-gate 		mdclrerror(&status);
31120Sstevel@tonic-gate 		return (metadevtocachename(dev));
31130Sstevel@tonic-gate 	}
31140Sstevel@tonic-gate 
31150Sstevel@tonic-gate 	/* return name */
31160Sstevel@tonic-gate 	return (np->cname);
31170Sstevel@tonic-gate }
31180Sstevel@tonic-gate 
31190Sstevel@tonic-gate /*
31200Sstevel@tonic-gate  * get name from key
31210Sstevel@tonic-gate  */
31220Sstevel@tonic-gate mdname_t *
31230Sstevel@tonic-gate metakeyname(
31240Sstevel@tonic-gate 	mdsetname_t	**spp,
31250Sstevel@tonic-gate 	mdkey_t		key,
31260Sstevel@tonic-gate 	int		fast,
31270Sstevel@tonic-gate 	md_error_t	*ep
31280Sstevel@tonic-gate )
31290Sstevel@tonic-gate {
31300Sstevel@tonic-gate 	char		*device_name;
31310Sstevel@tonic-gate 	md_dev64_t	dev = NODEV64;
31320Sstevel@tonic-gate 	mdname_t	*namep;
31330Sstevel@tonic-gate 
31340Sstevel@tonic-gate 	/* create local set, if necessary */
31350Sstevel@tonic-gate 	if (*spp == NULL) {
31360Sstevel@tonic-gate 		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
31370Sstevel@tonic-gate 			return (NULL);
31380Sstevel@tonic-gate 	}
31390Sstevel@tonic-gate 
31400Sstevel@tonic-gate 	/* get name from namespace */
31410Sstevel@tonic-gate 	if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD,
31420Sstevel@tonic-gate 	    key, NULL, NULL, &dev, ep)) == NULL) {
31430Sstevel@tonic-gate 		return (NULL);
31440Sstevel@tonic-gate 	}
31450Sstevel@tonic-gate 	if (fast)
31460Sstevel@tonic-gate 		namep = metaname_fast(spp, device_name, ep);
31470Sstevel@tonic-gate 	else
31480Sstevel@tonic-gate 		namep = metaname(spp, device_name, ep);
31490Sstevel@tonic-gate 
31500Sstevel@tonic-gate 	assert(dev != NODEV64);
31510Sstevel@tonic-gate 	if (namep)
31520Sstevel@tonic-gate 		namep->dev = dev;
31530Sstevel@tonic-gate 	Free(device_name);
31540Sstevel@tonic-gate 	return (namep);
31550Sstevel@tonic-gate }
31560Sstevel@tonic-gate 
31570Sstevel@tonic-gate /*
31580Sstevel@tonic-gate  * completely flush the caches
31590Sstevel@tonic-gate  */
31600Sstevel@tonic-gate void
31610Sstevel@tonic-gate metaflushnames(int flush_sr_cache)
31620Sstevel@tonic-gate {
31630Sstevel@tonic-gate 	metaflushhspnames();
31640Sstevel@tonic-gate 	metaflushdrivenames();
31650Sstevel@tonic-gate 	metaflushsetnames();
31660Sstevel@tonic-gate 	metaflushctlrcache();
31670Sstevel@tonic-gate 	metaflushfastnames();
31680Sstevel@tonic-gate 	metaflushstatcache();
31690Sstevel@tonic-gate 	if (flush_sr_cache)
31700Sstevel@tonic-gate 		sr_cache_flush(0);
31710Sstevel@tonic-gate }
31720Sstevel@tonic-gate 
31730Sstevel@tonic-gate /*
31740Sstevel@tonic-gate  * meta_get_hotspare_names
31750Sstevel@tonic-gate  *  returns an mdnamelist_t of hot spare names
31760Sstevel@tonic-gate  */
31770Sstevel@tonic-gate 
31780Sstevel@tonic-gate int
31790Sstevel@tonic-gate meta_get_hotspare_names(
31800Sstevel@tonic-gate 	mdsetname_t	*sp,
31810Sstevel@tonic-gate 	mdnamelist_t	**nlpp,
31820Sstevel@tonic-gate 	int		options,
31830Sstevel@tonic-gate 	md_error_t	*ep
31840Sstevel@tonic-gate )
31850Sstevel@tonic-gate {
31860Sstevel@tonic-gate 	mdhspnamelist_t		*hspnlp	= NULL;
31870Sstevel@tonic-gate 	mdhspnamelist_t		*hspp;
31880Sstevel@tonic-gate 	int			cnt = 0;
31890Sstevel@tonic-gate 
31900Sstevel@tonic-gate 	assert(nlpp != NULL);
31910Sstevel@tonic-gate 
31920Sstevel@tonic-gate 	/* get hotspare names */
31930Sstevel@tonic-gate 	if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) {
31940Sstevel@tonic-gate 		cnt = -1;
31950Sstevel@tonic-gate 		goto out;
31960Sstevel@tonic-gate 	}
31970Sstevel@tonic-gate 
31980Sstevel@tonic-gate 	/* build name list */
31990Sstevel@tonic-gate 	for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) {
32000Sstevel@tonic-gate 		md_hsp_t	*hsp;
32010Sstevel@tonic-gate 		int		i;
32020Sstevel@tonic-gate 
32030Sstevel@tonic-gate 		if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) {
32040Sstevel@tonic-gate 			cnt = -1;
32050Sstevel@tonic-gate 			goto out;
32060Sstevel@tonic-gate 		}
32070Sstevel@tonic-gate 		for (i = 0; (i < hsp->hotspares.hotspares_len); i++) {
32080Sstevel@tonic-gate 			md_hs_t	*hs = &hsp->hotspares.hotspares_val[i];
32090Sstevel@tonic-gate 
32100Sstevel@tonic-gate 			(void) metanamelist_append(nlpp, hs->hsnamep);
32110Sstevel@tonic-gate 			++cnt;
32120Sstevel@tonic-gate 		}
32130Sstevel@tonic-gate 	}
32140Sstevel@tonic-gate 
32150Sstevel@tonic-gate 	/* cleanup and return count or error */
32160Sstevel@tonic-gate out:
32170Sstevel@tonic-gate 	metafreehspnamelist(hspnlp);
32180Sstevel@tonic-gate 	if ((cnt == -1) && mdisok(ep)) {
32190Sstevel@tonic-gate 		/*
32200Sstevel@tonic-gate 		 * At least try to give some sort of meaningful error
32210Sstevel@tonic-gate 		 */
32220Sstevel@tonic-gate 		(void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error");
32230Sstevel@tonic-gate 	}
32240Sstevel@tonic-gate 
32250Sstevel@tonic-gate 	return (cnt);
32260Sstevel@tonic-gate }
32270Sstevel@tonic-gate /*
32280Sstevel@tonic-gate  * meta_create_non_dup_list
32290Sstevel@tonic-gate  *    INPUT: mdnp mdname_t pointer to add to the list if a new name
32300Sstevel@tonic-gate  *           ldevidp list of non-duplicate names.
32310Sstevel@tonic-gate  *    OUTPUT: ldevidp list of non-duplicate names.
32320Sstevel@tonic-gate  * meta_create_non_dup_list will take a mdname_t pointer and if the device
32330Sstevel@tonic-gate  *    is not in the list (ldevidp) will add it to the list.
32340Sstevel@tonic-gate  *    User needs to free allocated memory.
32350Sstevel@tonic-gate  */
32360Sstevel@tonic-gate void
32370Sstevel@tonic-gate meta_create_non_dup_list(
32380Sstevel@tonic-gate 	mdname_t	*mdnp,
32390Sstevel@tonic-gate 	mddevid_t	**ldevidpp
32400Sstevel@tonic-gate )
32410Sstevel@tonic-gate {
32420Sstevel@tonic-gate 	char		*lcname;
32430Sstevel@tonic-gate 	mddevid_t	*tmp;
32440Sstevel@tonic-gate 	mddevid_t	*lastdevidp;
32450Sstevel@tonic-gate 	mddevid_t	*lldevidp;
32460Sstevel@tonic-gate 	char		*ctd, *slice;
32470Sstevel@tonic-gate 	mddevid_t	*ldevidp;
32480Sstevel@tonic-gate 
32490Sstevel@tonic-gate 	if (mdnp == NULL)
32500Sstevel@tonic-gate 		return;
32510Sstevel@tonic-gate 
32520Sstevel@tonic-gate 	ldevidp = *ldevidpp;
32530Sstevel@tonic-gate 	/*
32540Sstevel@tonic-gate 	 * Grab the name of the device and strip off slice information
32550Sstevel@tonic-gate 	 */
32560Sstevel@tonic-gate 	lcname = Strdup(mdnp->cname);
32570Sstevel@tonic-gate 	if (lcname == NULL) {
32580Sstevel@tonic-gate 		return;
32590Sstevel@tonic-gate 	}
32600Sstevel@tonic-gate 	ctd = strrchr(lcname, '/');
32610Sstevel@tonic-gate 	if (ctd != NULL)
32620Sstevel@tonic-gate 		slice = strrchr(ctd, 's');
32630Sstevel@tonic-gate 	else
32640Sstevel@tonic-gate 		slice = strrchr(lcname, 's');
32650Sstevel@tonic-gate 
32660Sstevel@tonic-gate 	if (slice != NULL)
32670Sstevel@tonic-gate 		*slice = '\0';
32680Sstevel@tonic-gate 
32690Sstevel@tonic-gate 	if (ldevidp == NULL) {
32700Sstevel@tonic-gate 		/* first item in list */
32710Sstevel@tonic-gate 		ldevidp = Zalloc(sizeof (mddevid_t));
32720Sstevel@tonic-gate 		ldevidp->ctdname = lcname;
32730Sstevel@tonic-gate 		ldevidp->key = mdnp->key;
32740Sstevel@tonic-gate 		*ldevidpp = ldevidp;
32750Sstevel@tonic-gate 	} else {
32760Sstevel@tonic-gate 		for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) {
32770Sstevel@tonic-gate 			if (strcmp(tmp->ctdname, lcname) == 0) {
32780Sstevel@tonic-gate 				/* already there so just return */
32790Sstevel@tonic-gate 				Free(lcname);
32800Sstevel@tonic-gate 				return;
32810Sstevel@tonic-gate 			}
32820Sstevel@tonic-gate 			lastdevidp = tmp;
32830Sstevel@tonic-gate 		}
32840Sstevel@tonic-gate 		lldevidp = Zalloc(sizeof (mddevid_t));
32850Sstevel@tonic-gate 		lldevidp->ctdname = lcname;
32860Sstevel@tonic-gate 		lldevidp->key = mdnp->key;
32870Sstevel@tonic-gate 		lastdevidp->next = lldevidp;
32880Sstevel@tonic-gate 	}
32890Sstevel@tonic-gate }
3290