Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <meta.h>
     28 #include <metad.h>
     29 
     30 #include <ctype.h>
     31 #include <string.h>
     32 #include <sys/fs/ufs_fsdir.h>
     33 
     34 /*
     35  * Just in case we're not in a build environment, make sure that
     36  * TEXT_DOMAIN gets set to something.
     37  */
     38 #if !defined(TEXT_DOMAIN)
     39 #define	TEXT_DOMAIN "SYS_TEST"
     40 #endif
     41 
     42 /*
     43  *	Macros to produce a quoted string containing the value of a
     44  *	preprocessor macro. For example, if SIZE is defined to be 256,
     45  *	VAL2STR(SIZE) is "256". This is used to construct format
     46  *	strings for scanf-family functions below.
     47  */
     48 #define	QUOTE(x)	#x
     49 #define	VAL2STR(x)	QUOTE(x)
     50 
     51 extern	char	*getfullblkname();
     52 
     53 /*
     54  * caches
     55  */
     56 static	mdsetnamelist_t		*setlistp = NULL;
     57 static	mddrivenamelist_t	*drivelistp = NULL;
     58 static	mdnamelist_t		*fastnmlp = NULL;
     59 static	mdhspnamelist_t		*hsplistp = NULL;
     60 
     61 /*
     62  * Static definitions
     63  */
     64 static int chksetname(mdsetname_t **spp, char *sname, md_error_t *ep);
     65 
     66 /*
     67  * FUNCTION:	meta_dsk_to_rdsk()
     68  * INPUT:	str - Fully qualified pathname of a block or character device
     69  * RETURNS:	char * - The pathname of the raw device
     70  * PURPOSE:	Allocation of a new string representing the character device
     71  *		associated with the input string.  Note that no checking is
     72  *		done to verify the existence of this device file.
     73  */
     74 static char *
     75 meta_dsk_to_rdsk(char *str)
     76 {
     77 	char	*dp = NULL;
     78 	char	*rdskp = NULL;
     79 
     80 	assert(*str == '/');
     81 
     82 	if ((dp = strstr(str, "/rdsk/")) != NULL)
     83 		return (Strdup(str));
     84 
     85 	/*
     86 	 * If this is a malformed string, (i.e. containing neither
     87 	 * "/rdsk/" nor "/dsk/") then check to see if the caller
     88 	 * is passing old school device names like "/dev/[r]sd" or
     89 	 * exotic hardware presenting "/dev/[r]dc" names.
     90 	 */
     91 	if ((dp = strstr(str, "/dsk/")) == NULL) {
     92 		if (strncmp(str, "/dev/r", 6) == 0) {
     93 			return (Strdup(str));
     94 		} else if (strncmp(str, "/dev/", 5) == 0) {
     95 			dp = str + 4;
     96 		} else {
     97 			return (NULL);
     98 		}
     99 	}
    100 
    101 	dp++;
    102 	if (*dp == '\0')
    103 		return (NULL);
    104 
    105 	rdskp = Zalloc(strlen(str) + 2);
    106 	(void) strncpy(rdskp, str, dp - str);
    107 	rdskp[dp - str] = 'r';
    108 	(void) strcpy(rdskp + (dp - str) + 1, dp);
    109 
    110 	return (rdskp);
    111 }
    112 
    113 /*
    114  * FUNCTION:	rawname()
    115  * INPUT:	uname - Fully qualified pathname of a block or character device
    116  * RETURNS:	char * - The fully qualified character device pathname
    117  * PURPOSE:	Return the fully qualified pathname of the character device
    118  *		corresponding to the block or character device passed in.
    119  */
    120 static char *
    121 rawname(char *uname)
    122 {
    123 	char		*new_path = NULL;
    124 	int		ret = -1;
    125 	struct stat	statbuf;
    126 
    127 	if (*uname != '/')
    128 		return (NULL);
    129 
    130 	if ((new_path = meta_dsk_to_rdsk(uname)) == NULL)
    131 		return (NULL);
    132 
    133 	if (strncmp("/dev/", new_path, 5) == 0) {
    134 		ret = stat(new_path, &statbuf);
    135 		if (ret != 0 || (! S_ISCHR(statbuf.st_mode))) {
    136 			Free(new_path);
    137 			return (NULL);
    138 		}
    139 	}
    140 
    141 	return (new_path);
    142 }
    143 
    144 char *
    145 blkname(
    146 	char	*uname
    147 )
    148 {
    149 	char	*p;
    150 
    151 	if ((p = getfullblkname(uname)) == NULL) {
    152 		return (NULL);
    153 	} else if (*p == '\0') {
    154 		Free(p);
    155 		return (NULL);
    156 	} else {
    157 		return (p);
    158 	}
    159 }
    160 
    161 /*
    162  * FUNCTION:	parse_device()
    163  * INPUT:	sp - pointer to setname struct
    164  *		uname - Name of either a hotspare pool or metadevice
    165  *			This can either be a fully qualified path or
    166  *			in the form [set name/]device
    167  * OUTPUT:	snamep - name of the set that uname is in
    168  *		fnamep - metadevice or hsp with path and set name info stripped
    169  *		    This parameter is dynamically allocated and must be
    170  *		    freed by the calling function.
    171  * PURPOSE:	Parse uname and sp into the set name and device name strings.
    172  *		If the set name is specified as part of uname then use that
    173  *		otherwise attempt to get the set name from sp.
    174  */
    175 void
    176 parse_device(
    177 	mdsetname_t	*sp,
    178 	char		*uname,
    179 	char		**fnamep, /* dynamically alloced - caller must free */
    180 	char		**snamep  /* dynamically alloced - caller must free */
    181 )
    182 {
    183 	char		setname[FILENAME_MAX+1];
    184 	char		devname[FILENAME_MAX+1];
    185 	char		*tname = Malloc(strlen(uname) + 1);
    186 
    187 	int		len;
    188 	char *up;
    189 	char *tp;
    190 	int lcws;	/* last character was slash */
    191 
    192 	/* Now copy uname to tname by throwing away any duplicate '/' */
    193 	for (lcws = 0, tp = tname, up = uname; *up; up++) {
    194 		if (lcws) {
    195 			if (*up == '/') {
    196 				continue;
    197 			} else {
    198 				lcws = 0;
    199 			}
    200 		}
    201 		if (*up == '/') {
    202 			lcws = 1;
    203 		}
    204 		*tp++ = *up; /* ++ is done by for loop */
    205 	}
    206 	*tp = '\0';
    207 
    208 	/* fully-qualified  - local set */
    209 	if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
    210 	    devname, &len) == 1) && (strlen(tname) == len)) ||
    211 	    ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
    212 	    devname, &len) == 1) && (strlen(tname) == len))) {
    213 		*snamep = Strdup(MD_LOCAL_NAME);
    214 		*fnamep = Strdup(devname);
    215 		Free(tname);
    216 		return;
    217 	}
    218 
    219 	/* with setname specified - either fully qualified and relative spec */
    220 	if (((sscanf(tname, "%[^/]/%" VAL2STR(FILENAME_MAX) "s%n",
    221 	    setname, devname, &len) == 2) && (strlen(tname) == len)) ||
    222 	    ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
    223 	    setname, devname, &len) == 2) && (strlen(tname) == len)) ||
    224 	    ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
    225 	    setname, devname, &len) == 2) && (strlen(tname) == len))) {
    226 
    227 		*snamep = Strdup(setname);
    228 		*fnamep = Strdup(devname);
    229 		Free(tname);
    230 		return;
    231 	}
    232 
    233 	/* without setname specified */
    234 	*fnamep = tname;
    235 	if (sp != NULL && !metaislocalset(sp))
    236 		*snamep = Strdup(sp->setname);
    237 	else
    238 		*snamep = NULL;
    239 }
    240 
    241 /*
    242  * check for "all"
    243  */
    244 int
    245 meta_is_all(char *s)
    246 {
    247 	if ((strcoll(s, gettext("all")) == 0) ||
    248 	    (strcoll(s, gettext("ALL")) == 0))
    249 		return (1);
    250 	return (0);
    251 }
    252 
    253 /*
    254  * check for "none"
    255  */
    256 int
    257 meta_is_none(char *s)
    258 {
    259 	if ((strcoll(s, gettext("none")) == 0) ||
    260 	    (strcoll(s, gettext("NONE")) == 0))
    261 		return (1);
    262 	return (0);
    263 }
    264 
    265 static int
    266 valid_name_syntax(char *uname)
    267 {
    268 	int	i;
    269 	int	uname_len;
    270 
    271 	if (uname == NULL || !isalpha(uname[0]))
    272 		return (0);
    273 
    274 	uname_len = strlen(uname);
    275 	if (uname_len > MAXNAMLEN)
    276 		return (0);
    277 
    278 	/* 'all' and 'none' are reserved */
    279 	if (meta_is_all(uname) || meta_is_none(uname))
    280 		return (0);
    281 
    282 	for (i = 1; i < uname_len; i++) {
    283 		if ((isalnum(uname[i]) || uname[i] == '-' ||
    284 		    uname[i] == '_' || uname[i] == '.'))
    285 			continue;
    286 		break;
    287 	}
    288 
    289 	if (i < uname_len)
    290 		return (0);
    291 
    292 	return (1);
    293 
    294 }
    295 
    296 /*
    297  * canonicalize name
    298  */
    299 char *
    300 meta_canonicalize(
    301 	mdsetname_t	*sp,
    302 	char		*uname
    303 )
    304 {
    305 	char	*sname = NULL;
    306 	char	*tname = NULL;
    307 	char	*cname;
    308 
    309 	/* return the dev name and set name */
    310 	parse_device(sp, uname, &tname, &sname);
    311 
    312 	if (!valid_name_syntax(tname)) {
    313 		Free(tname);
    314 		if (sname != NULL)
    315 			Free(sname);
    316 		return (NULL);
    317 	}
    318 
    319 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
    320 		cname = tname;
    321 	else {
    322 		size_t	cname_len;
    323 
    324 		cname_len = strlen(tname) + strlen(sname) + 2;
    325 		cname = Malloc(cname_len);
    326 		(void) snprintf(
    327 		    cname, cname_len, "%s/%s", sname, tname);
    328 		Free(tname);
    329 	}
    330 
    331 	if (sname != NULL)
    332 		Free(sname);
    333 
    334 	return (cname);
    335 }
    336 
    337 /*
    338  * canonicalize name and check the set
    339  */
    340 char *
    341 meta_canonicalize_check_set(
    342 	mdsetname_t	**spp,
    343 	char		*uname,
    344 	md_error_t	*ep
    345 )
    346 {
    347 	char		*sname = NULL;
    348 	char		*tname = NULL;
    349 	char		*cname;
    350 
    351 	/* return the dev name and set name */
    352 	parse_device(*spp, uname, &tname, &sname);
    353 
    354 	if (!valid_name_syntax(tname)) {
    355 		(void) mderror(ep, MDE_NAME_ILLEGAL, tname);
    356 		if (sname != NULL)
    357 			Free(sname);
    358 		Free(tname);
    359 		return (NULL);
    360 	}
    361 
    362 	/* check the set name returned from the name for validity */
    363 	if (chksetname(spp, sname, ep) != 0) {
    364 		Free(tname);
    365 		if (sname != NULL)
    366 			Free(sname);
    367 		return (NULL);
    368 	}
    369 
    370 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
    371 		cname = tname;
    372 	else {
    373 		size_t	cname_len;
    374 
    375 		cname_len = strlen(tname) + strlen(sname) + 2;
    376 		cname = Malloc(cname_len);
    377 		(void) snprintf(
    378 		    cname, cname_len, "%s/%s", sname, tname);
    379 		Free(tname);
    380 	}
    381 
    382 	if (sname != NULL)
    383 		Free(sname);
    384 
    385 	return (cname);
    386 }
    387 
    388 /*
    389  * Verify that the name is a valid hsp/metadevice name
    390  */
    391 static int
    392 parse_meta_hsp_name(char *uname)
    393 {
    394 	char	*sname = NULL;
    395 	char	*tname = NULL;
    396 	int	ret;
    397 
    398 	/* return the dev name and set name */
    399 	parse_device(NULL, uname, &tname, &sname);
    400 
    401 	ret = valid_name_syntax(tname);
    402 	if (sname != NULL)
    403 		Free(sname);
    404 	Free(tname);
    405 	return (ret);
    406 }
    407 
    408 /*
    409  * check that name is a metadevice
    410  */
    411 int
    412 is_metaname(
    413 	char	*uname
    414 )
    415 {
    416 	return (parse_meta_hsp_name(uname));
    417 }
    418 
    419 /*
    420  * check that name is a hotspare pool
    421  */
    422 int
    423 is_hspname(
    424 	char	*uname
    425 )
    426 {
    427 	return (parse_meta_hsp_name(uname));
    428 }
    429 
    430 /*
    431  * check to verify that name is an existing metadevice
    432  */
    433 int
    434 is_existing_metadevice(
    435 	mdsetname_t	*sp,
    436 	char		*uname
    437 )
    438 {
    439 	char		*raw_name;
    440 	char		*set_name;
    441 	char		*full_path;
    442 	char		*fname = NULL;
    443 	int		pathlen;
    444 	int		retval = 0;
    445 
    446 	assert(uname != NULL);
    447 	/*
    448 	 * If it is an absolute name of a metadevice, then just call rawname
    449 	 * on the input
    450 	 */
    451 	if (uname[0] == '/') {
    452 		if (strncmp("/dev/md", uname, strlen("/dev/md")) == 0 &&
    453 		    (raw_name = rawname(uname)) != NULL) {
    454 			Free(raw_name);
    455 			return (1);
    456 		}
    457 		return (0);
    458 	}
    459 
    460 	/* create a fully specified path from the parsed string */
    461 	parse_device(sp, uname, &fname, &set_name);
    462 
    463 	if ((set_name == NULL) || (strcmp(set_name, MD_LOCAL_NAME) == 0)) {
    464 		pathlen = strlen("/dev/md/rdsk/") + strlen(fname) + 1;
    465 		full_path = Zalloc(pathlen);
    466 		(void) snprintf(full_path, pathlen, "/dev/md/rdsk/%s", fname);
    467 	} else {
    468 		pathlen = strlen("/dev/md//rdsk/") + strlen(fname) +
    469 		    strlen(set_name) + 1;
    470 		full_path = Zalloc(pathlen);
    471 		(void) snprintf(full_path, pathlen, "/dev/md/%s/rdsk/%s",
    472 		    set_name, fname);
    473 	}
    474 
    475 	if ((raw_name = rawname(full_path)) != NULL) {
    476 		Free(raw_name);
    477 		retval = 1;
    478 	}
    479 
    480 	if (set_name != NULL)
    481 		Free(set_name);
    482 
    483 	Free(fname);
    484 	Free(full_path);
    485 	return (retval);
    486 }
    487 
    488 /*
    489  * check to verify that name is an existing hsp
    490  */
    491 int
    492 is_existing_hsp(
    493 	mdsetname_t	*sp,
    494 	char		*uname
    495 )
    496 {
    497 	md_error_t	status = mdnullerror;
    498 	hsp_t		hsp;
    499 	set_t		cur_set;
    500 
    501 	if (sp != NULL)
    502 		cur_set = sp->setno;
    503 	else
    504 		cur_set = 0;
    505 
    506 	hsp = meta_gethspnmentbyname(cur_set, MD_SIDEWILD, uname, &status);
    507 
    508 	if (hsp == MD_HSP_NONE) {
    509 		mdclrerror(&status);
    510 		return (0);
    511 	}
    512 	return (1);
    513 }
    514 
    515 /*
    516  * check to verify that name is an existing metadevice or hotspare pool
    517  */
    518 int
    519 is_existing_meta_hsp(
    520 	mdsetname_t	*sp,
    521 	char		*uname
    522 )
    523 {
    524 	if (is_existing_metadevice(sp, uname) ||
    525 	    is_existing_hsp(sp, uname))
    526 		return (1);
    527 
    528 	return (0);
    529 }
    530 
    531 /*
    532  *	mdsetname_t stuff
    533  */
    534 
    535 /*
    536  * initialize setname
    537  */
    538 static void
    539 metainitsetname(
    540 	mdsetname_t	*sp
    541 )
    542 {
    543 	(void) memset(sp, '\0', sizeof (*sp));
    544 }
    545 
    546 static void
    547 metafreesetdesc(md_set_desc *sd)
    548 {
    549 	md_mnnode_desc	*nd;
    550 
    551 	if (MD_MNSET_DESC(sd)) {
    552 		nd = sd->sd_nodelist;
    553 		while (nd) {
    554 			sd->sd_nodelist = nd->nd_next;
    555 			Free(nd);
    556 			nd = sd->sd_nodelist;
    557 		}
    558 	}
    559 	metafreedrivedesc(&sd->sd_drvs);
    560 	Free(sd);
    561 }
    562 
    563 /*
    564  * free allocated setname
    565  */
    566 static void
    567 metafreesetname(
    568 	mdsetname_t	*sp
    569 )
    570 {
    571 	if (sp->setname != NULL)
    572 		Free(sp->setname);
    573 	if (sp->setdesc != NULL)
    574 		metafreesetdesc(sp->setdesc);
    575 	metainitsetname(sp);
    576 }
    577 
    578 /*
    579  * flush the setname cache
    580  */
    581 static void
    582 metaflushsetnames()
    583 {
    584 	mdsetnamelist_t		*p, *n;
    585 
    586 	for (p = setlistp, n = NULL; (p != NULL); p = n) {
    587 		n = p->next;
    588 		metafreesetname(p->sp);
    589 		Free(p->sp);
    590 		Free(p);
    591 	}
    592 	setlistp = NULL;
    593 }
    594 
    595 /*
    596  * get set number
    597  */
    598 static int
    599 getsetno(
    600 	char		*sname,
    601 	set_t		*setnop,
    602 	md_error_t	*ep
    603 )
    604 {
    605 	md_set_record	*sr;
    606 	size_t		len;
    607 
    608 	/* local set */
    609 	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
    610 		*setnop = 0;
    611 		return (0);
    612 	}
    613 
    614 	/* shared set */
    615 	if ((sr = getsetbyname(sname, ep)) == NULL) {
    616 		if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) {
    617 			char	*p;
    618 
    619 			len = strlen(sname) + 30;
    620 			p = Malloc(len);
    621 
    622 			(void) snprintf(p, len, "setname \"%s\"", sname);
    623 			(void) mderror(ep, MDE_NO_SET, p);
    624 			Free(p);
    625 		}
    626 		return (-1);
    627 	}
    628 	*setnop = sr->sr_setno;
    629 	free_sr(sr);
    630 	return (0);
    631 }
    632 
    633 /*
    634  * find setname from name
    635  */
    636 mdsetname_t *
    637 metasetname(
    638 	char		*sname,
    639 	md_error_t	*ep
    640 )
    641 {
    642 	mdsetnamelist_t	**tail;
    643 	set_t		setno;
    644 	mdsetname_t	*sp;
    645 
    646 	/* look for cached value first */
    647 	assert(sname != NULL);
    648 	for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) {
    649 		sp = (*tail)->sp;
    650 		if (strcmp(sp->setname, sname) == 0) {
    651 			return (sp);
    652 		}
    653 	}
    654 
    655 	/* setup set */
    656 	if (getsetno(sname, &setno, ep) != 0)
    657 		return (NULL);
    658 
    659 	/* allocate new list element and setname */
    660 	*tail = Zalloc(sizeof (**tail));
    661 	sp = (*tail)->sp = Zalloc(sizeof (*sp));
    662 
    663 	sp->setname = Strdup(sname);
    664 	sp->setno = setno;
    665 	sp->lockfd = MD_NO_LOCK;
    666 
    667 	return (sp);
    668 }
    669 
    670 /*
    671  * find setname from setno
    672  */
    673 mdsetname_t *
    674 metasetnosetname(
    675 	set_t		setno,
    676 	md_error_t	*ep
    677 )
    678 {
    679 	mdsetnamelist_t	*slp;
    680 	mdsetname_t	*sp;
    681 	md_set_record	*sr;
    682 
    683 	/* look for cached value first */
    684 	for (slp = setlistp; (slp != NULL); slp = slp->next) {
    685 		sp = slp->sp;
    686 		if (sp->setno == setno)
    687 			return (sp);
    688 	}
    689 
    690 	/* local set */
    691 	if (setno == MD_LOCAL_SET)
    692 		return (metasetname(MD_LOCAL_NAME, ep));
    693 
    694 	/* shared set */
    695 	if ((sr = getsetbynum(setno, ep)) == NULL)
    696 		return (NULL);
    697 	sp = metasetname(sr->sr_setname, ep);
    698 	free_sr(sr);
    699 	return (sp);
    700 }
    701 
    702 mdsetname_t *
    703 metafakesetname(
    704 	set_t		setno,
    705 	char		*sname
    706 )
    707 {
    708 	mdsetnamelist_t	**tail;
    709 	mdsetname_t	*sp;
    710 
    711 	/* look for cached value first */
    712 	for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) {
    713 		sp = (*tail)->sp;
    714 		if (sp->setno == setno) {
    715 			if ((sp->setname == NULL) && (sname != NULL))
    716 				sp->setname = Strdup(sname);
    717 			return (sp);
    718 		}
    719 	}
    720 
    721 	/* allocate new list element and setname */
    722 	*tail = Zalloc(sizeof (**tail));
    723 	sp = (*tail)->sp = Zalloc(sizeof (*sp));
    724 
    725 	if (sname != NULL)
    726 		sp->setname = Strdup(sname);
    727 	sp->setno = setno;
    728 	sp->lockfd = MD_NO_LOCK;
    729 
    730 	return (sp);
    731 }
    732 
    733 
    734 /*
    735  * setup set record (sr) and cache it in the mdsetname_t struct
    736  */
    737 md_set_desc *
    738 sr2setdesc(
    739 	md_set_record	*sr
    740 )
    741 {
    742 	md_set_desc	*sd;
    743 	int		i;
    744 	md_mnset_record	*mnsr;
    745 	md_mnnode_desc	*nd, *nd_prev = 0;
    746 	md_mnnode_record	*nr;
    747 	md_error_t	status = mdnullerror;
    748 	md_error_t	*ep = &status;
    749 	int		nodecnt, nrcnt;
    750 	mndiskset_membershiplist_t *nl, *nl2;
    751 
    752 	sd = Zalloc(sizeof (*sd));
    753 	sd->sd_ctime = sr->sr_ctime;
    754 	sd->sd_genid = sr->sr_genid;
    755 	sd->sd_setno = sr->sr_setno;
    756 	sd->sd_flags = sr->sr_flags;
    757 
    758 	if (MD_MNSET_DESC(sd)) {
    759 		mnsr = (md_mnset_record *)sr;
    760 		(void) strlcpy(sd->sd_mn_master_nodenm,
    761 		    mnsr->sr_master_nodenm, sizeof (sd->sd_mn_master_nodenm));
    762 		sd->sd_mn_master_nodeid = mnsr->sr_master_nodeid;
    763 		if (strcmp(mnsr->sr_master_nodenm, mynode()) == 0) {
    764 			sd->sd_mn_am_i_master = 1;
    765 		}
    766 
    767 		/*
    768 		 * Get membershiplist from API routine.  If there's
    769 		 * an error, just use a NULL nodelist.
    770 		 */
    771 		if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
    772 			nodecnt = 0;  /* no nodes are alive */
    773 			nl = NULL;
    774 		}
    775 		nr = mnsr->sr_nodechain;
    776 		nrcnt = 0;
    777 		/*
    778 		 * Node descriptor node list must be built in
    779 		 * ascending order of nodeid.  The nodechain
    780 		 * in the mnset record is in ascending order,
    781 		 * so just make them the same.
    782 		 */
    783 		while (nr) {
    784 			nd = Zalloc(sizeof (*nd));
    785 			if (nd_prev) {
    786 				nd_prev->nd_next = nd;
    787 			} else {
    788 				sd->sd_nodelist = nd;
    789 			}
    790 			nd->nd_ctime = nr->nr_ctime;
    791 			nd->nd_genid = nr->nr_genid;
    792 			nd->nd_flags = nr->nr_flags;
    793 
    794 			(void) strlcpy(nd->nd_nodename, nr->nr_nodename,
    795 			    sizeof (nd->nd_nodename));
    796 			nd->nd_nodeid = nr->nr_nodeid;
    797 			if (strcmp(nd->nd_nodename, mynode()) == 0) {
    798 				sd->sd_mn_mynode = nd;
    799 			}
    800 			if (nd->nd_nodeid == sd->sd_mn_master_nodeid) {
    801 				sd->sd_mn_masternode = nd;
    802 			}
    803 
    804 			/*
    805 			 * If node is marked ALIVE, then set priv_ic
    806 			 * from membership list.  During the early part
    807 			 * of a reconfig cycle, the membership list may
    808 			 * have been changed, (a node entering or leaving
    809 			 * the cluster), but rpc.metad hasn't flushed
    810 			 * its data yet.  So, if node is marked alive, but
    811 			 * is no longer in the membership list (node has
    812 			 * left the cluster) then just leave priv_ic to NULL.
    813 			 */
    814 			if (nd->nd_flags & MD_MN_NODE_ALIVE) {
    815 				nl2 = nl;
    816 				while (nl2) {
    817 					if (nl2->msl_node_id == nd->nd_nodeid) {
    818 						(void) strlcpy(nd->nd_priv_ic,
    819 						    nl2->msl_node_addr,
    820 						    sizeof (nd->nd_priv_ic));
    821 						break;
    822 					}
    823 					nl2 = nl2->next;
    824 				}
    825 			}
    826 
    827 			nr = nr->nr_next;
    828 			nrcnt++;
    829 			nd_prev = nd;
    830 		}
    831 		sd->sd_mn_numnodes = nrcnt;
    832 		if (nodecnt)
    833 			meta_free_nodelist(nl);
    834 
    835 		/* Just copying to keep consistent view between sr & sd */
    836 		(void) strlcpy(sd->sd_nodes[0], mnsr->sr_nodes_bw_compat[0],
    837 		    sizeof (sd->sd_nodes[0]));
    838 	} else {
    839 		for (i = 0; i < MD_MAXSIDES; i++)
    840 			(void) strlcpy(sd->sd_nodes[i], sr->sr_nodes[i],
    841 			    sizeof (sd->sd_nodes[i]));
    842 	}
    843 
    844 	sd->sd_med = sr->sr_med;		/* structure assignment */
    845 
    846 	return (sd);
    847 }
    848 
    849 md_set_desc *
    850 metaget_setdesc(
    851 	mdsetname_t	*sp,
    852 	md_error_t	*ep
    853 )
    854 {
    855 	md_set_record	*sr;
    856 
    857 	if (sp->setdesc != NULL)
    858 		return (sp->setdesc);
    859 
    860 	if (sp->setname != NULL) {
    861 		if ((sr = getsetbyname(sp->setname, ep)) != NULL) {
    862 			sp->setdesc = sr2setdesc(sr);
    863 			free_sr(sr);
    864 			return (sp->setdesc);
    865 		}
    866 	}
    867 
    868 	if (sp->setno > 0) {
    869 		if ((sr = getsetbynum(sp->setno, ep)) != NULL) {
    870 			sp->setdesc = sr2setdesc(sr);
    871 			free_sr(sr);
    872 			return (sp->setdesc);
    873 		}
    874 	}
    875 
    876 	return (NULL);
    877 }
    878 
    879 void
    880 metaflushsetname(mdsetname_t *sp)
    881 {
    882 	if (sp == NULL)
    883 		return;
    884 
    885 	if (sp->setdesc == NULL)
    886 		return;
    887 
    888 	metafreesetdesc(sp->setdesc);
    889 	sp->setdesc = NULL;
    890 }
    891 
    892 /*
    893  * check for local set
    894  */
    895 int
    896 metaislocalset(
    897 	mdsetname_t	*sp
    898 )
    899 {
    900 	assert(sp->setname != NULL);
    901 	if (strcmp(sp->setname, MD_LOCAL_NAME) == 0) {
    902 		assert(sp->setno == MD_LOCAL_SET);
    903 		return (1);
    904 	} else {
    905 		assert(sp->setno != MD_LOCAL_SET);
    906 		return (0);
    907 	}
    908 }
    909 
    910 /*
    911  * check for same set
    912  */
    913 int
    914 metaissameset(
    915 	mdsetname_t	*sp1,
    916 	mdsetname_t	*sp2
    917 )
    918 {
    919 	if (strcmp(sp1->setname, sp2->setname) == 0) {
    920 		assert(sp1->setno == sp2->setno);
    921 		return (1);
    922 	} else {
    923 		assert(sp1->setno != sp2->setno);
    924 		return (0);
    925 	}
    926 }
    927 
    928 /*
    929  * check to see if set changed
    930  */
    931 static int
    932 chkset(
    933 	mdsetname_t	**spp,
    934 	char		*sname,
    935 	md_error_t	*ep
    936 )
    937 {
    938 	/* if we already have a set, make sure it's the same */
    939 	if (*spp != NULL && !metaislocalset(*spp)) {
    940 		if ((*spp)->setname != sname &&
    941 		    strcmp((*spp)->setname, sname) != 0) {
    942 			return (mderror(ep, MDE_SET_DIFF, sname));
    943 		}
    944 		return (0);
    945 	}
    946 
    947 	/* otherwise store new set name and number */
    948 	if ((*spp = metasetname(sname, ep)) == NULL) {
    949 		return (-1);
    950 	}
    951 
    952 	/* return success */
    953 	return (0);
    954 }
    955 
    956 /*
    957  * check to see if set changed from default
    958  */
    959 static int
    960 chksetname(
    961 	mdsetname_t	**spp,
    962 	char		*sname,
    963 	md_error_t	*ep
    964 )
    965 {
    966 	/* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */
    967 	if (sname == NULL) {
    968 		if (*spp) {
    969 			return (0);
    970 		} else {
    971 			sname = MD_LOCAL_NAME;
    972 		}
    973 	}
    974 
    975 	/* see if changed */
    976 	return (chkset(spp, sname, ep));
    977 }
    978 
    979 /*
    980  * check setname from setno
    981  */
    982 static int
    983 chksetno(
    984 	mdsetname_t	**spp,
    985 	set_t		setno,
    986 	md_error_t	*ep
    987 )
    988 {
    989 	md_set_record	*sr;
    990 	int		rval;
    991 
    992 	/* local set */
    993 	if (setno == 0)
    994 		return (chkset(spp, MD_LOCAL_NAME, ep));
    995 
    996 	/* shared set */
    997 	if ((sr = getsetbynum(setno, ep)) == NULL)
    998 		return (-1);
    999 	rval = chkset(spp, sr->sr_setname, ep);
   1000 	free_sr(sr);
   1001 	return (rval);
   1002 }
   1003 
   1004 /*
   1005  *	mddrivename_t stuff
   1006  */
   1007 
   1008 /*
   1009  * initialize name
   1010  */
   1011 static void
   1012 metainitname(
   1013 	mdname_t	*np
   1014 )
   1015 {
   1016 	(void) memset(np, 0, sizeof (*np));
   1017 	np->dev = NODEV64;
   1018 	np->key = MD_KEYBAD;
   1019 	np->end_blk = -1;
   1020 	np->start_blk = -1;
   1021 }
   1022 
   1023 /*
   1024  * free allocated name
   1025  */
   1026 static void
   1027 metafreename(
   1028 	mdname_t	*np
   1029 )
   1030 {
   1031 	if (np->cname != NULL)
   1032 		Free(np->cname);
   1033 	if (np->bname != NULL)
   1034 		Free(np->bname);
   1035 	if (np->rname != NULL)
   1036 		Free(np->rname);
   1037 	if (np->devicesname != NULL)
   1038 		Free(np->devicesname);
   1039 	metainitname(np);
   1040 }
   1041 
   1042 /*
   1043  * initialize drive name
   1044  */
   1045 static void
   1046 metainitdrivename(
   1047 	mddrivename_t	*dnp
   1048 )
   1049 {
   1050 	(void) memset(dnp, 0, sizeof (*dnp));
   1051 	dnp->side_names_key = MD_KEYBAD;
   1052 }
   1053 
   1054 /*
   1055  * flush side names
   1056  */
   1057 void
   1058 metaflushsidenames(
   1059 	mddrivename_t	*dnp
   1060 )
   1061 {
   1062 	mdsidenames_t	*p, *n;
   1063 
   1064 	for (p = dnp->side_names, n = NULL; (p != NULL); p = n) {
   1065 		n = p->next;
   1066 		if (p->dname != NULL)
   1067 			Free(p->dname);
   1068 		if (p->cname != NULL)
   1069 			Free(p->cname);
   1070 		Free(p);
   1071 	}
   1072 	dnp->side_names = NULL;
   1073 }
   1074 
   1075 /*
   1076  * free drive name
   1077  */
   1078 void
   1079 metafreedrivename(
   1080 	mddrivename_t	*dnp
   1081 )
   1082 {
   1083 	uint_t		slice;
   1084 
   1085 	if (dnp->cname != NULL)
   1086 		Free(dnp->cname);
   1087 	if (dnp->rname != NULL)
   1088 		Free(dnp->rname);
   1089 	metafreevtoc(&dnp->vtoc);
   1090 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice)
   1091 		metafreename(&dnp->parts.parts_val[slice]);
   1092 	if (dnp->parts.parts_val != NULL)
   1093 		Free(dnp->parts.parts_val);
   1094 	metaflushsidenames(dnp);
   1095 	if (dnp->miscname != NULL)
   1096 		Free(dnp->miscname);
   1097 	meta_free_unit(dnp);
   1098 	metainitdrivename(dnp);
   1099 }
   1100 
   1101 /*
   1102  * flush the drive name cache
   1103  */
   1104 void
   1105 metaflushdrivenames()
   1106 {
   1107 	mddrivenamelist_t	*p, *n;
   1108 
   1109 	for (p = drivelistp, n = NULL; (p != NULL); p = n) {
   1110 		n = p->next;
   1111 		metafreedrivename(p->drivenamep);
   1112 		Free(p->drivenamep);
   1113 		Free(p);
   1114 	}
   1115 	drivelistp = NULL;
   1116 }
   1117 
   1118 /*
   1119  * peel off s%u from name
   1120  */
   1121 char *
   1122 metadiskname(
   1123 	char	*name
   1124 )
   1125 {
   1126 	char	*p, *e;
   1127 	char	onmb[BUFSIZ+1], cnmb[BUFSIZ];
   1128 	uint_t	d = 0;
   1129 	int	l = 0;
   1130 	int	cl = strlen(name);
   1131 
   1132 	/*
   1133 	 * Handle old style names, which are of the form /dev/rXXNN[a-h].
   1134 	 */
   1135 	if (sscanf(name, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n",
   1136 	    onmb, &d, &l) == 2 && l == cl) {
   1137 		(void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u", onmb, d);
   1138 		return (Strdup(cnmb));
   1139 	}
   1140 
   1141 	/*
   1142 	 * Handle old style names, which are of the form /dev/XXNN[a-h].
   1143 	 */
   1144 	if (sscanf(name, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n",
   1145 	    onmb, &d, &l) == 2 && l == cl) {
   1146 		(void) snprintf(cnmb, sizeof (cnmb), "/dev/%s%u", onmb, d);
   1147 		return (Strdup(cnmb));
   1148 	}
   1149 
   1150 	/* gobble number and 's' */
   1151 	p = e = name + strlen(name) - 1;
   1152 	for (; (p > name); --p) {
   1153 		if (!isdigit(*p))
   1154 			break;
   1155 	}
   1156 	if ((p == e) || (p <= name))
   1157 		return (Strdup(name));
   1158 
   1159 	if (*p != 's' && strchr("dt", *p) == NULL)
   1160 		return (Strdup(name));
   1161 	else if (strchr("dt", *p) != NULL)
   1162 		return (Strdup(name));
   1163 	p--;
   1164 
   1165 	if ((p <= name) || (!isdigit(*p)))
   1166 		return (Strdup(name));
   1167 
   1168 	*(++p) = '\0';
   1169 	e = Strdup(name);
   1170 	*p = 's';
   1171 
   1172 	return (e);
   1173 }
   1174 
   1175 /*
   1176  * free list of drivenames
   1177  */
   1178 void
   1179 metafreedrivenamelist(
   1180 	mddrivenamelist_t	*dnlp
   1181 )
   1182 {
   1183 	mddrivenamelist_t	*next = NULL;
   1184 
   1185 	for (/* void */; (dnlp != NULL); dnlp = next) {
   1186 		next = dnlp->next;
   1187 		Free(dnlp);
   1188 	}
   1189 }
   1190 
   1191 /*
   1192  * build list of drivenames
   1193  */
   1194 int
   1195 metadrivenamelist(
   1196 	mdsetname_t		**spp,
   1197 	mddrivenamelist_t	**dnlpp,
   1198 	int			argc,
   1199 	char			*argv[],
   1200 	md_error_t		*ep
   1201 )
   1202 {
   1203 	mddrivenamelist_t	**tailpp = dnlpp;
   1204 	int			count = 0;
   1205 
   1206 	for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
   1207 		mddrivenamelist_t	*dnlp = Zalloc(sizeof (*dnlp));
   1208 
   1209 		if ((dnlp->drivenamep = metadrivename(spp, argv[0],
   1210 		    ep)) == NULL) {
   1211 			metafreedrivenamelist(*dnlpp);
   1212 			*dnlpp = NULL;
   1213 			return (-1);
   1214 		}
   1215 		*tailpp = dnlp;
   1216 		tailpp = &dnlp->next;
   1217 	}
   1218 	return (count);
   1219 }
   1220 
   1221 /*
   1222  * append to end of drivename list
   1223  */
   1224 mddrivename_t *
   1225 metadrivenamelist_append(
   1226 	mddrivenamelist_t	**dnlpp,
   1227 	mddrivename_t		*dnp
   1228 )
   1229 {
   1230 	mddrivenamelist_t	*dnlp;
   1231 
   1232 	/* run to end of list */
   1233 	for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next)
   1234 		;
   1235 
   1236 	/* allocate new list element */
   1237 	dnlp = *dnlpp = Zalloc(sizeof (*dnlp));
   1238 
   1239 	/* append drivename */
   1240 	dnlp->drivenamep = dnp;
   1241 	return (dnp);
   1242 }
   1243 
   1244 /*
   1245  * FUNCTION:	meta_drivenamelist_append_wrapper()
   1246  * INPUT:	tailpp	- pointer to the list tail pointer
   1247  *		dnp	- name node to be appended to list
   1248  * OUTPUT:	none
   1249  * RETURNS:	mddrivenamelist_t * - new tail of the list.
   1250  * PURPOSE:	wrapper to meta_namelist_append for performance.
   1251  *		metanamelist_append finds the tail each time which slows
   1252  *		down long lists.  By keeping track of the tail ourselves
   1253  *		we can change metadrivenamelist_append into a
   1254  *		constant time operation.
   1255  */
   1256 mddrivenamelist_t **
   1257 meta_drivenamelist_append_wrapper(
   1258 	mddrivenamelist_t	**tailpp,
   1259 	mddrivename_t	*dnp
   1260 )
   1261 {
   1262 	(void) metadrivenamelist_append(tailpp, dnp);
   1263 
   1264 	/* If it's the first item in the list, return it instead of the next */
   1265 	if ((*tailpp)->next == NULL)
   1266 		return (tailpp);
   1267 
   1268 	return (&(*tailpp)->next);
   1269 }
   1270 
   1271 
   1272 /*
   1273  *	mdname_t stuff
   1274  */
   1275 
   1276 /*
   1277  * check set and get comparison name
   1278  *
   1279  * NOTE: This function has a side effect of setting *spp if the setname
   1280  * has been specified and *spp is not already set.
   1281  */
   1282 char *
   1283 meta_name_getname(
   1284 	mdsetname_t		**spp,
   1285 	char			*uname,
   1286 	meta_device_type_t	uname_type,
   1287 	md_error_t		*ep
   1288 )
   1289 {
   1290 	if (uname_type == META_DEVICE || uname_type == HSP_DEVICE ||
   1291 	    (uname_type == UNKNOWN && is_existing_metadevice(*spp, uname))) {
   1292 
   1293 		/*
   1294 		 * if the setname is specified in uname, *spp is set,
   1295 		 * and the set names don't agree then canonical name will be
   1296 		 * returned as NULL
   1297 		 */
   1298 		return (meta_canonicalize_check_set(spp, uname, ep));
   1299 	}
   1300 
   1301 	/* if it is not a meta/hsp and *spp is not set then set it to local */
   1302 	if (chksetname(spp, NULL, ep) != 0)
   1303 		return (NULL);
   1304 
   1305 	/* if it is not a meta/hsp name then just return uname */
   1306 	return (Strdup(uname));
   1307 }
   1308 
   1309 /*
   1310  * FUNCTION:	getrname()
   1311  * INPUT:	spp	- the setname struct
   1312  *		uname	- the possibly unqualified device name
   1313  *		type 	- ptr to the device type of uname
   1314  * OUTPUT:	ep	- return error pointer
   1315  * RETURNS:	char*	- character string containing the fully
   1316  *			qualified raw device name
   1317  * PURPOSE:	Create the fully qualified raw name for the possibly
   1318  *		unqualified device name.  If uname is an absolute
   1319  *		path the raw name is derived from the input string.
   1320  *		Otherwise, an attempt is made to get the rawname by
   1321  *		catting "/dev/md/rdsk" and "/dev/rdsk". If the input
   1322  *		value of type is UNKNOWN and it can be successfully
   1323  *		determined then update type to the correct value.
   1324  */
   1325 static	char *
   1326 getrname(mdsetname_t **spp, char *uname,
   1327     meta_device_type_t *type, md_error_t *ep)
   1328 {
   1329 	char			*rname;
   1330 	char			*fname;
   1331 	int			i;
   1332 	int 			rname_cnt = 0;
   1333 	char			*rname_list[3];
   1334 	meta_device_type_t	tmp_type;
   1335 
   1336 	assert(uname != NULL);
   1337 	/* if it is an absolute name then just call rawname on the input */
   1338 	if (uname[0] == '/') {
   1339 		if ((rname = rawname(uname)) != NULL) {
   1340 			/*
   1341 			 * If the returned rname does not match with
   1342 			 * the specified uname type, we'll return null.
   1343 			 */
   1344 			if (strncmp(rname, "/dev/md", strlen("/dev/md")) == 0) {
   1345 				if (*type == LOGICAL_DEVICE) {
   1346 					(void) mdsyserror(ep, ENOENT, uname);
   1347 					return (NULL);
   1348 				}
   1349 				*type = META_DEVICE;
   1350 			} else {
   1351 				if (*type == META_DEVICE) {
   1352 					(void) mdsyserror(ep, ENOENT, uname);
   1353 					return (NULL);
   1354 				}
   1355 				*type = LOGICAL_DEVICE;
   1356 			}
   1357 			return (rname);
   1358 		}
   1359 
   1360 		/* out of luck */
   1361 		(void) mdsyserror(ep, ENOENT, uname);
   1362 		return (NULL);
   1363 	}
   1364 
   1365 	/*
   1366 	 * Get device that matches the requested type. If
   1367 	 * a match is found, return immediately. If type is
   1368 	 * UNKNOWN, save all the found devices in rname_list
   1369 	 * so we can determine later whether the input uname
   1370 	 * is ambiguous.
   1371 	 *
   1372 	 * Check for metadevice before physical device.
   1373 	 * With the introduction of softpartitions it is more
   1374 	 * likely to be a metadevice.
   1375 	 */
   1376 
   1377 	/* metadevice short form */
   1378 	if (*type == META_DEVICE || *type == UNKNOWN) {
   1379 		if (metaislocalset(*spp)) {
   1380 			fname = Malloc(strlen(uname) +
   1381 			    strlen("/dev/md/rdsk/") + 1);
   1382 			(void) strcpy(fname, "/dev/md/rdsk/");
   1383 			(void) strcat(fname, uname);
   1384 		} else {
   1385 			char	*p;
   1386 			size_t	len;
   1387 
   1388 			if ((p = strchr(uname, '/')) != NULL) {
   1389 				++p;
   1390 			} else {
   1391 				p = uname;
   1392 			}
   1393 			len = strlen((*spp)->setname) + strlen(p) +
   1394 			    strlen("/dev/md//rdsk/") + 1;
   1395 			fname = Malloc(len);
   1396 			(void) snprintf(fname, len, "/dev/md/%s/rdsk/%s",
   1397 			    (*spp)->setname, p);
   1398 		}
   1399 		rname = rawname(fname);
   1400 
   1401 		if (*type == META_DEVICE) {
   1402 			/*
   1403 			 * Handle the case where we have a new metadevice
   1404 			 * that does not yet exist in the name-space(e.g
   1405 			 * metarecover in MN sets where /dev/md entry is
   1406 			 * not yet created in the non-master nodes). In
   1407 			 * this case we return the constructed metadevice
   1408 			 * name as that will exist after the metainit call
   1409 			 * has created it.
   1410 			 */
   1411 			if (rname == NULL) {
   1412 				rname = Strdup(fname);
   1413 			}
   1414 
   1415 			Free(fname);
   1416 			return (rname);
   1417 		}
   1418 
   1419 		Free(fname);
   1420 		if ((rname != NULL) && (*type == UNKNOWN)) {
   1421 			/* Save this result */
   1422 			rname_list[rname_cnt] = rname;
   1423 			rname_cnt ++;
   1424 		}
   1425 	}
   1426 
   1427 	if (*type == LOGICAL_DEVICE || *type == UNKNOWN) {
   1428 		fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1);
   1429 		(void) strcpy(fname, "/dev/rdsk/");
   1430 		(void) strcat(fname, uname);
   1431 		rname = rawname(fname);
   1432 
   1433 		Free(fname);
   1434 		if (rname != NULL) {
   1435 			/* Simply return if a logical device was requested */
   1436 			if (*type == LOGICAL_DEVICE) {
   1437 				return (rname);
   1438 			} else {
   1439 				rname_list[rname_cnt] = rname;
   1440 				rname_cnt ++;
   1441 			}
   1442 		}
   1443 	}
   1444 
   1445 	/*
   1446 	 * At this point, we've searched /dev/md/rdsk, /dev/rdsk and
   1447 	 * ./ for the specified device. rname_list contains all
   1448 	 * the matches we've found and rname_cnt is the number of
   1449 	 * matches.
   1450 	 *
   1451 	 * We know that either we don't have a match if a specific
   1452 	 * type was given, in which case we simply return NULL or
   1453 	 * we have an UNKNOWN device with 1-3 entries in rname_list.
   1454 	 *
   1455 	 * If we get 3 entries, rname_cnt == 3, it's ambiguous.
   1456 	 * If we only get 1 entry, rname_cnt == 1, return rname_list[0].
   1457 	 * If we get 2 entries that are not the same, it's ambigous.
   1458 	 */
   1459 	rname = NULL;
   1460 	if (rname_cnt == 0 || *type != UNKNOWN) {
   1461 		/* out of luck */
   1462 		(void) mdsyserror(ep, ENOENT, uname);
   1463 		return (NULL);
   1464 	} else {
   1465 		if (rname_cnt == 3) {
   1466 			(void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
   1467 			(void) printf(dgettext(TEXT_DOMAIN,
   1468 			    "Error: ambiguous device name.\n%s %s %s\n\n"),
   1469 			    rname_list[0], rname_list[1], rname_list[2]);
   1470 			rname = NULL;
   1471 		}
   1472 
   1473 		/* grab the type in case it is not ambiguous */
   1474 		if (strncmp(rname_list[0], "/dev/md", strlen("/dev/md")) == 0)
   1475 			tmp_type =  META_DEVICE;
   1476 		else
   1477 			tmp_type =  LOGICAL_DEVICE;
   1478 
   1479 		if (rname_cnt == 1) {
   1480 			rname = Strdup(rname_list[0]);
   1481 			*type = tmp_type;
   1482 		} else {
   1483 			/*
   1484 			 * Prevent the case where the command is run in
   1485 			 * either /dev/md/rdsk or /dev/rdsk so the both
   1486 			 * rname_list[0] and rname_list[1] are the same.
   1487 			 */
   1488 			if (strcmp(rname_list[0], rname_list[1]) != 0) {
   1489 				(void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
   1490 				if (rname_cnt != 3) {
   1491 					/*
   1492 					 * For the rname_cnt == 3 case, the
   1493 					 * error was printed above.
   1494 					 */
   1495 					(void) printf(dgettext(TEXT_DOMAIN,
   1496 					    "Error: ambiguous device "
   1497 					    "name.\n%s %s\n\n"),
   1498 					    rname_list[0], rname_list[1]);
   1499 				}
   1500 				rname = NULL;
   1501 			} else {
   1502 				rname = Strdup(rname_list[0]);
   1503 				*type = tmp_type;
   1504 			}
   1505 		}
   1506 		for (i = 0; i < rname_cnt; i++)
   1507 			Free(rname_list[i]);
   1508 		return (rname);
   1509 	}
   1510 }
   1511 
   1512 /*
   1513  * get raw slice and drive names
   1514  */
   1515 static char *
   1516 getrawnames(
   1517 	mdsetname_t		**spp,
   1518 	char			*uname,
   1519 	char			**dnamep,
   1520 	meta_device_type_t	*uname_type,
   1521 	md_error_t		*ep
   1522 )
   1523 {
   1524 	char		*rname = NULL;
   1525 	size_t		len;
   1526 
   1527 	/*
   1528 	 * Incorrect code path if type is HSP_DEVICE
   1529 	 */
   1530 	assert(*uname_type != HSP_DEVICE);
   1531 
   1532 	/* initialize */
   1533 	*dnamep = NULL;
   1534 
   1535 	/* get slice name */
   1536 	if ((rname = getrname(spp, uname, uname_type, ep)) != NULL) {
   1537 		*dnamep = metadiskname(rname);
   1538 		return (rname);
   1539 	}
   1540 
   1541 	/*
   1542 	 * If name cannot be found, if may be because is is not accessible.
   1543 	 * If it is an absolute name, try all possible disk name formats and
   1544 	 * if it is device name, assume it is /dev/rdsk/..
   1545 	 * Since the code below assumes logical devices, if the given
   1546 	 * uname_type is META_DEVICE, there's nothing to do.
   1547 	 */
   1548 	if (mdissyserror(ep, ENOENT) && *uname_type != META_DEVICE) {
   1549 		if (uname[0] == '/') {
   1550 			/* Absolute name */
   1551 			uint_t			d = 0;
   1552 			int			l = 0;
   1553 			char			onmb[BUFSIZ+1], snm[BUFSIZ+1];
   1554 
   1555 			/*
   1556 			 * Handle old style raw names
   1557 			 */
   1558 			if (sscanf(uname,
   1559 			    "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
   1560 			    "%" VAL2STR(BUFSIZ) "[a-h]%n",
   1561 			    onmb, &d, snm, &l) == 3 && l == strlen(uname)) {
   1562 				mdclrerror(ep);
   1563 				rname = Strdup(uname);
   1564 				*dnamep = metadiskname(rname);
   1565 				*uname_type = LOGICAL_DEVICE;
   1566 				return (rname);
   1567 			}
   1568 
   1569 			/*
   1570 			 * Handle old style block names
   1571 			 */
   1572 			if (sscanf(uname,
   1573 			    "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u"
   1574 			    "%" VAL2STR(BUFSIZ) "[a-h]%n",
   1575 			    onmb, &d, snm, &l) == 3 && l == strlen(uname)) {
   1576 				len = strlen(uname) + 1 + 1;
   1577 				rname = Malloc(len);
   1578 				(void) snprintf(rname, len, "/dev/r%s%u%s",
   1579 				    onmb, d, snm);
   1580 				*dnamep = metadiskname(rname);
   1581 				*uname_type = LOGICAL_DEVICE;
   1582 				return (rname);
   1583 			}
   1584 
   1585 			/* /.../dsk/... or /.../rdsk/... */
   1586 			if ((rname = meta_dsk_to_rdsk(uname)) != NULL) {
   1587 				mdclrerror(ep);
   1588 				*dnamep = metadiskname(rname);
   1589 				*uname_type = LOGICAL_DEVICE;
   1590 				return (rname);
   1591 			}
   1592 		} else {
   1593 			/*
   1594 			 * If it's not an absolute name but is a valid ctd name,
   1595 			 * guess at /dev/rdsk/...
   1596 			 */
   1597 			uint_t	s;
   1598 			if (parse_ctd(uname, &s) == 0) {
   1599 				len = strlen(uname) + strlen("/dev/rdsk/") + 1;
   1600 				rname = Malloc(len);
   1601 				(void) snprintf(rname, len, "/dev/rdsk/%s",
   1602 				    uname);
   1603 				*dnamep = metadiskname(rname);
   1604 				*uname_type = LOGICAL_DEVICE;
   1605 				return (rname);
   1606 			}
   1607 		}
   1608 	}
   1609 
   1610 	/* out of luck */
   1611 	if (!mdiserror(ep, MDE_AMBIGUOUS_DEV))
   1612 		(void) mderror(ep, MDE_UNIT_NOT_FOUND, uname);
   1613 	return (NULL);
   1614 }
   1615 
   1616 /*
   1617  * get number of slices for name
   1618  */
   1619 static int
   1620 getnslice(
   1621 	char		*rname,
   1622 	char		*dname,
   1623 	uint_t		*slicep
   1624 )
   1625 {
   1626 	char		*srname;
   1627 	uint_t		nslice;
   1628 	size_t		dl = strlen(dname);
   1629 	size_t		rl = strlen(rname);
   1630 	size_t		l = 0;
   1631 	size_t		len;
   1632 
   1633 	/*
   1634 	 * get our slice number - works only with names that end in s%u -
   1635 	 * all others return -1.
   1636 	 */
   1637 	if (dl >= rl ||
   1638 	    sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl ||
   1639 	    (int)*slicep < 0) {
   1640 		return (-1);
   1641 	}
   1642 
   1643 	/*
   1644 	 * go find how many slices there really are
   1645 	 */
   1646 	len = strlen(dname) + 20 + 1;
   1647 	srname = Malloc(len);
   1648 	for (nslice = 0; /* void */; ++nslice) {
   1649 		struct stat	statbuf;
   1650 
   1651 		/* build slice name */
   1652 		(void) snprintf(srname, len, "%ss%u", dname, nslice);
   1653 
   1654 		/* see if it's there */
   1655 		if ((meta_stat(srname, &statbuf) != 0) ||
   1656 		    (! S_ISCHR(statbuf.st_mode))) {
   1657 			break;
   1658 		}
   1659 	}
   1660 	Free(srname);
   1661 
   1662 	/* Need to make sure that we at least have V_NUMPAR */
   1663 	nslice = max(nslice, V_NUMPAR);
   1664 
   1665 	/* make sure we have at least our slice */
   1666 	if (nslice < *slicep)
   1667 		return (-1);
   1668 
   1669 	/* return number of slices */
   1670 	return (nslice);
   1671 }
   1672 
   1673 /*
   1674  * Attempt to parse the input string as a c[t]ds specifier
   1675  * The target can either be a SCSI target id or if the device
   1676  * is in a fabric configuration in a fibre channel setup then
   1677  * the target is a standard WWN (world wide name).
   1678  *
   1679  * if successful	return 0
   1680  * if c[t]dp name	return 1
   1681  * otherwise		return -1
   1682  */
   1683 int
   1684 parse_ctd(
   1685 	char	*uname,
   1686 	uint_t	*slice)
   1687 {
   1688 	uint_t	channel;
   1689 	uint_t	target;
   1690 	uint_t	device;
   1691 	int	has_target = 1;
   1692 	uint_t	cl;
   1693 	uint_t	target_str_len;
   1694 	char	*partial_ctd_str;
   1695 	char	*target_str;
   1696 	char	*device_start_pos;
   1697 	int	l = -1;
   1698 
   1699 	/* pull off the channel spec and the 't' for the target */
   1700 	if (sscanf(uname, "c%ut%n", &channel, &l) != 1 || l == -1) {
   1701 		/* check for cds style name */
   1702 		if (sscanf(uname, "c%ud%n", &channel, &l) != 1 || l == -1) {
   1703 			return (-1);
   1704 		} else {
   1705 			l--;	/* we want to be on the 'd' */
   1706 			has_target = 0;
   1707 		}
   1708 	}
   1709 	partial_ctd_str = uname + l;
   1710 
   1711 	/* find the beginning of the device specifier */
   1712 	device_start_pos = strrchr(partial_ctd_str, 'd');
   1713 	if (device_start_pos == NULL) {
   1714 		return (-1);
   1715 	}
   1716 
   1717 	/* check to see if it is a ctd with a WWN or SCSI target */
   1718 	if (has_target) {
   1719 		/* pull off the target and see if it is a WWN */
   1720 		target_str_len = device_start_pos - partial_ctd_str + 2;
   1721 		target_str = (char *)Malloc(target_str_len+1);
   1722 		(void) strcpy(target_str, "0X");
   1723 		(void) strncpy(target_str+2, partial_ctd_str,
   1724 		    target_str_len - 2);
   1725 		target_str[target_str_len] = '\0';
   1726 		if (sscanf(target_str, "%x%n", &target, &l) != 1 ||
   1727 		    l != target_str_len) {
   1728 			Free(target_str);
   1729 			return (-1);
   1730 		}
   1731 		Free(target_str);
   1732 	}
   1733 
   1734 	/* check the device and slice */
   1735 	cl = strlen(device_start_pos);
   1736 	if (sscanf(device_start_pos, "d%us%u%n", &device, slice, &l) != 2 ||
   1737 	    l != cl) {
   1738 		/* check the device and partition */
   1739 		if (sscanf(device_start_pos, "d%up%u%n", &device, slice, &l)
   1740 		    == 2 && l == cl) {
   1741 			return (1);
   1742 		}
   1743 		return (-1);
   1744 	}
   1745 
   1746 	return (0);
   1747 }
   1748 
   1749 
   1750 /*
   1751  * get number of slices for name
   1752  */
   1753 static int
   1754 uname2sliceno(
   1755 	char			*uname,
   1756 	meta_device_type_t	uname_type,
   1757 	uint_t			*slicep,
   1758 	md_error_t		*ep
   1759 )
   1760 {
   1761 	uint_t			c = 0, t = 0, d = 0;
   1762 	int			l = 0, cl = 0;
   1763 	int			fd;
   1764 	struct dk_cinfo		cinfo;
   1765 	char			*p;
   1766 	char			*rname = NULL;
   1767 
   1768 
   1769 	if (uname_type == META_DEVICE)
   1770 		return (*slicep = 0);
   1771 
   1772 	if ((p = strrchr(uname, '/')) != NULL)
   1773 		p++;
   1774 	else
   1775 		p = uname;
   1776 
   1777 	cl = strlen(p);
   1778 
   1779 	if (parse_ctd(p, slicep) == 0)
   1780 		return (*slicep);
   1781 	else if (sscanf(p, "mc%ut%ud%us%u%n", &c, &t, &d, slicep, &l) == 4 &&
   1782 	    l == cl)
   1783 		return (*slicep);
   1784 	else if (sscanf(p, "d%us%u%n", &d, slicep, &l) == 2 && l == cl)
   1785 		return (*slicep);
   1786 
   1787 	/*
   1788 	 * If we can't get the slice from the name, then we have to do it the
   1789 	 * hard and expensive way.
   1790 	 */
   1791 	if ((rname = rawname(uname)) == NULL)
   1792 		return (-1);
   1793 
   1794 	/* get controller info */
   1795 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
   1796 		Free(rname);
   1797 		return (-1);
   1798 	}
   1799 
   1800 	if (ioctl(fd, DKIOCINFO, &cinfo) != 0) {
   1801 		int	save = errno;
   1802 
   1803 		if (save == ENOTTY)
   1804 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname);
   1805 		else
   1806 			(void) mdsyserror(ep, save, rname);
   1807 
   1808 		Free(rname);
   1809 		(void) close(fd);
   1810 		return (-1);
   1811 	}
   1812 	(void) close(fd);	/* sd/ssd bug */
   1813 
   1814 	if (cinfo.dki_partition < V_NUMPAR) {
   1815 		Free(rname);
   1816 		return (*slicep = cinfo.dki_partition);
   1817 	}
   1818 
   1819 	return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname));
   1820 }
   1821 
   1822 /*
   1823  * get partition info
   1824  */
   1825 static int
   1826 getparts(
   1827 	mddrivename_t		*dnp,
   1828 	char			*rname,
   1829 	char			*dname,
   1830 	meta_device_type_t	uname_type,
   1831 	uint_t			*npartsp,
   1832 	uint_t			*partnop,
   1833 	md_error_t		*ep
   1834 )
   1835 {
   1836 	int		nparts;
   1837 	uint_t		partno;
   1838 	mdname_t	name;
   1839 	mdvtoc_t	*vtocp;
   1840 
   1841 	/* metadevice */
   1842 	if (uname_type == META_DEVICE) {
   1843 		dnp->type = MDT_META;
   1844 		nparts = 1;
   1845 		partno = 0;
   1846 		goto gotit;
   1847 	}
   1848 
   1849 	/* see how many partitions in drive, this is really tricky */
   1850 	metainitname(&name);
   1851 	name.rname = rname;
   1852 	name.drivenamep = dnp;
   1853 	if ((vtocp = metagetvtoc(&name, TRUE, &partno, ep)) != NULL) {
   1854 		dnp->type = MDT_COMP;
   1855 		nparts = vtocp->nparts;
   1856 		/* partno already setup */
   1857 		/* dname already setup */
   1858 		goto gotit;
   1859 	}
   1860 
   1861 	if ((ep->info.errclass == MDEC_DEV) &&
   1862 	    (ep->info.md_error_info_t_u.dev_error.errnum == MDE_TOO_MANY_PARTS))
   1863 		return (-1);
   1864 
   1865 	/* fallback and try and guess (used to check for just EACCES here) */
   1866 	if ((dname != NULL) &&
   1867 	    ((nparts = getnslice(rname, dname, &partno)) > 0)) {
   1868 		dnp->type = MDT_ACCES;
   1869 		if (mdanysyserror(ep)) {
   1870 			dnp->errnum =
   1871 			    ep->info.md_error_info_t_u.sys_error.errnum;
   1872 		} else {
   1873 			dnp->errnum = ENOENT;
   1874 		}
   1875 		mdclrerror(ep);
   1876 		/* nparts already setup */
   1877 		/* partno already setup */
   1878 		/* dname already setup */
   1879 		nparts = roundup(nparts, V_NUMPAR);
   1880 		goto gotit;
   1881 	}
   1882 
   1883 	/* nothing worked */
   1884 	dnp->type = MDT_UNKNOWN;
   1885 	if (mdissyserror(ep, EACCES))
   1886 		dnp->type = MDT_ACCES;
   1887 
   1888 	if (mdanysyserror(ep)) {
   1889 		dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum;
   1890 	} else {
   1891 		dnp->errnum = ENOENT;
   1892 	}
   1893 
   1894 	mdclrerror(ep);
   1895 	nparts = V_NUMPAR;
   1896 	if (uname2sliceno(rname, uname_type, &partno, ep) < 0) {
   1897 		mdclrerror(ep);
   1898 		partno = 0;
   1899 	}
   1900 
   1901 	/* return success */
   1902 gotit:
   1903 	assert(nparts > 0);
   1904 
   1905 	if (partno >= nparts)
   1906 		return (mdsyserror(ep, ENOENT, rname));
   1907 
   1908 	*npartsp = nparts;
   1909 	*partnop = partno;
   1910 	return (0);
   1911 }
   1912 
   1913 /*
   1914  * get block name
   1915  */
   1916 static int
   1917 getbname(
   1918 	mdname_t	*np,
   1919 	md_error_t	*ep
   1920 )
   1921 {
   1922 	char		*rname = np->rname;
   1923 	char		*bname;
   1924 
   1925 	/* fully qualified */
   1926 	assert(rname != NULL);
   1927 	if ((bname = blkname(rname)) != NULL) {
   1928 		if (np->bname)
   1929 			Free(np->bname);
   1930 		np->bname = bname;
   1931 		return (0);
   1932 	}
   1933 
   1934 	/* out of luck */
   1935 	return (mdsyserror(ep, ENOENT, rname));
   1936 }
   1937 
   1938 static void
   1939 getcname(
   1940 	mdsetname_t	*sp,
   1941 	mdname_t	*np
   1942 )
   1943 {
   1944 	char		*sname = sp->setname;
   1945 	char		*bname = np->bname;
   1946 	char		*p;
   1947 	size_t		len;
   1948 
   1949 	assert(sname != NULL);
   1950 	assert(bname != NULL);
   1951 	assert(np->drivenamep->type != MDT_FAST_COMP &&
   1952 	    np->drivenamep->type != MDT_FAST_META);
   1953 
   1954 	/* regular device */
   1955 	if ((strncmp(bname, "/dev/dsk/", strlen("/dev/dsk/")) == 0) &&
   1956 	    (strchr((p = bname + strlen("/dev/dsk/")), '/') == NULL)) {
   1957 		if (np->cname)
   1958 			Free(np->cname);
   1959 		np->cname = Strdup(p);
   1960 		return;
   1961 	}
   1962 
   1963 	if ((strncmp(bname, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) &&
   1964 	    (strchr((p = bname + strlen("/dev/ap/dsk/")), '/') == NULL)) {
   1965 		if (np->cname)
   1966 			Free(np->cname);
   1967 		np->cname = Strdup(p);
   1968 		return;
   1969 	}
   1970 
   1971 	if ((strncmp(bname, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) &&
   1972 	    (strchr((p = bname + strlen("/dev/did/dsk/")), '/') == NULL)) {
   1973 		if (np->cname)
   1974 			Free(np->cname);
   1975 		np->cname = Strdup(p);
   1976 		return;
   1977 	}
   1978 
   1979 	/* anything else but metadevice */
   1980 	if (np->drivenamep->type != MDT_META) {
   1981 		if (np->cname)
   1982 			Free(np->cname);
   1983 		np->cname = Strdup(bname);
   1984 		return;
   1985 	}
   1986 
   1987 	/* metadevice */
   1988 	p = strrchr(bname, '/');
   1989 	assert(p != NULL);
   1990 	++p;
   1991 	if (metaislocalset(sp)) {
   1992 		if (np->cname)
   1993 			Free(np->cname);
   1994 		np->cname = Strdup(p);
   1995 	} else {
   1996 		assert(sname[0] != '\0');
   1997 		if (np->cname)
   1998 			Free(np->cname);
   1999 		len = strlen(sname) + 1 + strlen(p) + 1;
   2000 		np->cname = Malloc(len);
   2001 		(void) snprintf(np->cname, len, "%s/%s", sname, p);
   2002 	}
   2003 }
   2004 
   2005 /*
   2006  * get dev
   2007  */
   2008 int
   2009 meta_getdev(
   2010 	mdsetname_t	*sp,
   2011 	mdname_t	*np,
   2012 	md_error_t	*ep
   2013 )
   2014 {
   2015 	struct stat	statbuf;
   2016 
   2017 	/* get dev */
   2018 	if (meta_stat(np->rname, &statbuf) != 0)
   2019 		return (mdsyserror(ep, errno, np->rname));
   2020 	else if (! S_ISCHR(statbuf.st_mode))
   2021 		return (mddeverror(ep, MDE_NOT_DISK, NODEV64, np->rname));
   2022 	np->dev = meta_expldev(statbuf.st_rdev);
   2023 
   2024 	assert(np->drivenamep->type != MDT_FAST_META &&
   2025 	    np->drivenamep->type != MDT_FAST_COMP);
   2026 
   2027 	/* check set */
   2028 	assert((np->drivenamep->type == MDT_META) ?
   2029 	    (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1);
   2030 
   2031 	/* return sucess */
   2032 	return (0);
   2033 }
   2034 
   2035 /*
   2036  * set up names for a slice
   2037  */
   2038 static int
   2039 getnames(
   2040 	mdsetname_t	*sp,
   2041 	mdname_t	*np,
   2042 	char		*rname,
   2043 	md_error_t	*ep
   2044 )
   2045 {
   2046 	/* get names */
   2047 	if (np->rname)
   2048 		Free(np->rname);
   2049 	np->rname = Strdup(rname);
   2050 	if (getbname(np, ep) != 0)
   2051 		return (-1);
   2052 	getcname(sp, np);
   2053 	if (meta_getdev(sp, np, ep) != 0)
   2054 		return (-1);
   2055 
   2056 	/* return success */
   2057 	return (0);
   2058 }
   2059 
   2060 /*
   2061  * fake up names for a slice
   2062  */
   2063 static void
   2064 getfakenames(
   2065 	mdsetname_t	*sp,
   2066 	mdname_t	*np,
   2067 	char		*rname
   2068 )
   2069 {
   2070 	char		*p;
   2071 	char		onmb[BUFSIZ+1], snm[BUFSIZ+1];
   2072 	uint_t		d = 0;
   2073 	int		l = 0;
   2074 
   2075 	/* fake names */
   2076 	if (np->rname != NULL)
   2077 		Free(np->rname);
   2078 	np->rname = Strdup(rname);
   2079 
   2080 	if (np->bname != NULL)
   2081 		Free(np->bname);
   2082 	np->bname = Strdup(rname);
   2083 
   2084 	/*
   2085 	 * Fixup old style names
   2086 	 */
   2087 	if (sscanf(rname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
   2088 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
   2089 	    onmb, &d, snm, &l) == 3 && l == strlen(rname))
   2090 		(void) snprintf(np->bname, l, "/dev/%s%u%s", onmb, d, snm);
   2091 
   2092 	/*
   2093 	 * Fixup new style names
   2094 	 */
   2095 	if ((p = strstr(np->bname, "/rdsk/")) != NULL) {
   2096 		for (++p; (*(p + 1) != '\0'); ++p)
   2097 			*p = *(p + 1);
   2098 		*p = '\0';
   2099 	}
   2100 
   2101 	if (np->cname != NULL)
   2102 		Free(np->cname);
   2103 	getcname(sp, np);
   2104 }
   2105 
   2106 static mdname_t *
   2107 setup_slice(
   2108 	mdsetname_t		*sp,
   2109 	meta_device_type_t	uname_type,
   2110 	mddrivename_t		*dnp,
   2111 	char			*uname,
   2112 	char			*rname,
   2113 	char			*dname,
   2114 	uint_t			partno,
   2115 	md_error_t		*ep
   2116 )
   2117 {
   2118 	char			*srname = NULL;
   2119 	mdname_t		*np;
   2120 
   2121 	/* must have a set */
   2122 	assert(sp != NULL);
   2123 	assert(partno < dnp->parts.parts_len);
   2124 	assert(dname != NULL);
   2125 
   2126 	np = &dnp->parts.parts_val[partno];
   2127 
   2128 	if (rname)
   2129 		srname = rname;
   2130 	else if (uname_type == META_DEVICE)
   2131 		srname = dname;
   2132 	else {
   2133 		char	onmb[BUFSIZ+1];
   2134 		uint_t	d = 0;
   2135 		int	l = 0, cl = strlen(dname);
   2136 		size_t	len;
   2137 
   2138 		len = cl + 20 + 1;
   2139 		srname = Malloc(len);
   2140 
   2141 		/*
   2142 		 * Handle /dev/rXXNN.
   2143 		 */
   2144 		if (sscanf(dname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%n",
   2145 		    onmb, &d, &l) == 2 && l == cl) {
   2146 			(void) snprintf(srname, len, "/dev/r%s%u%c", onmb, d,
   2147 			    'a' + partno);
   2148 		} else if (sscanf(dname, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%n",
   2149 		    onmb, &d, &l) == 2 && l == cl) {
   2150 			(void) snprintf(srname, len, "/dev/%s%u%c", onmb, d,
   2151 			    'a' + partno);
   2152 		} else {
   2153 			/* build the slice that is wanted */
   2154 			(void) snprintf(srname, len, "%ss%u", dname, partno);
   2155 		}
   2156 	}
   2157 
   2158 	if (getnames(sp, np, srname, ep) != 0) {
   2159 		if (dnp->type == MDT_UNKNOWN) {
   2160 			mdclrerror(ep);
   2161 			getfakenames(sp, np, srname);
   2162 		} else if (dnp->type == MDT_COMP && mdissyserror(ep, ENOENT)) {
   2163 			dnp->type = MDT_UNKNOWN;
   2164 			if (mdanysyserror(ep)) {
   2165 				dnp->errnum =
   2166 				    ep->info.md_error_info_t_u.sys_error.errnum;
   2167 			} else {
   2168 				dnp->errnum = ENOENT;
   2169 			}
   2170 			mdclrerror(ep);
   2171 			getfakenames(sp, np, srname);
   2172 		} else {
   2173 			mdclrerror(ep);
   2174 			if (getnames(sp, np, dname, ep) != 0) {
   2175 				np = NULL;
   2176 				goto fixup;
   2177 			}
   2178 		}
   2179 	}
   2180 
   2181 out:
   2182 	if ((srname != rname) && (srname != dname))
   2183 		Free(srname);
   2184 
   2185 	/* return name */
   2186 	return (np);
   2187 
   2188 fixup:
   2189 	if (mdanysyserror(ep)) {
   2190 		char	*p;
   2191 		int	errnum = ep->info.md_error_info_t_u.sys_error.errnum;
   2192 
   2193 		mdclrerror(ep);
   2194 		if (uname && *uname) {
   2195 			if ((p = strrchr(uname, '/')) != NULL)
   2196 				(void) mdsyserror(ep, errnum, ++p);
   2197 			else
   2198 				(void) mdsyserror(ep, errnum, uname);
   2199 		} else {
   2200 			if ((p = strrchr(srname, '/')) != NULL)
   2201 				(void) mdsyserror(ep, errnum, ++p);
   2202 			else
   2203 				(void) mdsyserror(ep, errnum, srname);
   2204 		}
   2205 	}
   2206 	goto out;
   2207 }
   2208 
   2209 /*
   2210  * flush the fast name cache
   2211  */
   2212 static void
   2213 metafreefastnm(mdname_t **np)
   2214 {
   2215 	mddrivename_t	*dnp;
   2216 
   2217 	assert(np != NULL && *np != NULL);
   2218 
   2219 	if ((dnp = (*np)->drivenamep) != NULL) {
   2220 		if (dnp->cname != NULL)
   2221 			Free(dnp->cname);
   2222 		if (dnp->rname != NULL)
   2223 			Free(dnp->rname);
   2224 		if (dnp->miscname != NULL)
   2225 			Free(dnp->miscname);
   2226 		meta_free_unit(dnp);
   2227 		Free(dnp);
   2228 	}
   2229 	if ((*np)->cname != NULL)
   2230 		Free((*np)->cname);
   2231 	if ((*np)->bname != NULL)
   2232 		Free((*np)->bname);
   2233 	if ((*np)->rname != NULL)
   2234 		Free((*np)->rname);
   2235 	if ((*np)->devicesname != NULL)
   2236 		Free((*np)->devicesname);
   2237 	Free(*np);
   2238 	*np = NULL;
   2239 }
   2240 
   2241 /*
   2242  * flush the fast name cache
   2243  */
   2244 static void
   2245 metaflushfastnames()
   2246 {
   2247 	mdnamelist_t	*p, *n;
   2248 
   2249 	for (p = fastnmlp, n = NULL; (p != NULL); p = n) {
   2250 		n = p->next;
   2251 		metafreefastnm(&p->namep);
   2252 		Free(p);
   2253 	}
   2254 	fastnmlp = NULL;
   2255 }
   2256 
   2257 static char *
   2258 getrname_fast(char *unm, meta_device_type_t uname_type, md_error_t *ep)
   2259 {
   2260 	uint_t			d = 0;
   2261 	int			l = 0;
   2262 	int			cl = strlen(unm);
   2263 	char			onmb[BUFSIZ+1], snm[BUFSIZ+1], cnmb[BUFSIZ];
   2264 	char			*rnm;
   2265 	size_t			len;
   2266 
   2267 	if (uname_type == META_DEVICE) {
   2268 		/* fully qualified  - local set */
   2269 		if (((sscanf(unm, "/dev/md/dsk/%" VAL2STR(BUFSIZ) "s%n",
   2270 		    onmb, &len) == 1) && (cl == len)) || ((sscanf(unm,
   2271 		    "/dev/md/rdsk/%" VAL2STR(BUFSIZ) "s%n",
   2272 		    onmb, &len) == 1) && (cl == len))) {
   2273 			len = strlen("/dev/md/rdsk/") +	strlen(onmb) + 1;
   2274 			rnm = Zalloc(len);
   2275 			(void) snprintf(rnm, len, "/dev/md/rdsk/%s", onmb);
   2276 			return (rnm);
   2277 		}
   2278 
   2279 		/* fully qualified - setname specified */
   2280 		if (((sscanf(unm, "/dev/md/%[^/]/dsk/%"
   2281 		    VAL2STR(BUFSIZ) "s%n", snm, onmb, &len) == 2) &&
   2282 		    (cl == len)) || ((sscanf(unm, "/dev/md/%[^/]/rdsk/%"
   2283 		    VAL2STR(BUFSIZ) "s%n", snm, onmb, &len) == 2) &&
   2284 		    (cl == len))) {
   2285 
   2286 			len = strlen("/dev/md//rdsk/") + strlen(snm) +
   2287 			    strlen(onmb) + 1;
   2288 			rnm = Zalloc(len);
   2289 			(void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s",
   2290 			    snm, onmb);
   2291 			return (rnm);
   2292 		}
   2293 
   2294 		/* Fully qualified path - error */
   2295 		if (unm[0] == '/') {
   2296 			(void) mdsyserror(ep, EINVAL, unm);
   2297 			return (NULL);
   2298 		}
   2299 
   2300 		/* setname specified <setname>/<metadev> */
   2301 		if (((sscanf(unm, "%[^/]/%" VAL2STR(BUFSIZ) "s%n",
   2302 		    snm, onmb, &len) == 2) && (cl == len))) {
   2303 			/* Not <setname>/<metadev>  - error */
   2304 			if (strchr(onmb, '/') != NULL) {
   2305 				(void) mdsyserror(ep, EINVAL, unm);
   2306 				return (NULL);
   2307 			}
   2308 
   2309 			len = strlen("/dev/md//rdsk/") + strlen(snm) +
   2310 			    strlen(onmb) + 1;
   2311 			rnm = Zalloc(len);
   2312 			(void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s",
   2313 			    snm, onmb);
   2314 			return (rnm);
   2315 		}
   2316 
   2317 		/* Must be simple metaname/hsp pool name */
   2318 		len = strlen("/dev/md/rdsk/") + strlen(unm) + 1;
   2319 		rnm = Zalloc(len);
   2320 		(void) snprintf(rnm, len, "/dev/md/rdsk/%s", unm);
   2321 		return (rnm);
   2322 	}
   2323 
   2324 	/* NOT Fully qualified path, done */
   2325 	if (unm[0] != '/') {
   2326 		(void) mdsyserror(ep, EINVAL, unm);
   2327 		return (NULL);
   2328 	}
   2329 
   2330 	/*
   2331 	 * Get slice information from old style names of the form
   2332 	 * /dev/rXXNN[a-h] or /dev/XXNN[a-h], must be done before regular
   2333 	 * devices, but after metadevices.
   2334 	 */
   2335 	if ((sscanf(unm, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
   2336 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
   2337 	    onmb, &d, snm, &l) == 3 ||
   2338 	    sscanf(unm, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u"
   2339 	    "%" VAL2STR(BUFSIZ) "[a-h]%n",
   2340 	    onmb, &d, snm, &l) == 3) && l == cl) {
   2341 		if (strchr("abcdefgh", snm[0]) != NULL) {
   2342 			(void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u%s",
   2343 			    onmb, d, snm);
   2344 			return (Strdup(cnmb));
   2345 		}
   2346 	}
   2347 
   2348 	/* /.../dsk/... or /.../rdsk/... */
   2349 	if ((rnm = meta_dsk_to_rdsk(unm)) != NULL)
   2350 		return (rnm);
   2351 
   2352 	/*
   2353 	 * Shouldn't get here but if we do then we have an unrecognized
   2354 	 * fully qualified path - error
   2355 	 */
   2356 	(void) mdsyserror(ep, EINVAL, unm);
   2357 	return (NULL);
   2358 }
   2359 
   2360 static mdname_t *
   2361 metainitfastname(
   2362 	mdsetname_t		*sp,
   2363 	char			*uname,
   2364 	meta_device_type_t	uname_type,
   2365 	md_error_t		*ep
   2366 )
   2367 {
   2368 	uint_t			c = 0, t = 0, d = 0, s = 0;
   2369 	int			l = 0;
   2370 	mddrivename_t		*dnp;
   2371 	mdname_t		*np;
   2372 	mdnamelist_t		**fnlpp;
   2373 	char			*cname;
   2374 
   2375 	for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) {
   2376 		np = (*fnlpp)->namep;
   2377 
   2378 		if (strcmp(np->bname, uname) == 0)
   2379 			return (np);
   2380 	}
   2381 
   2382 	*fnlpp = Zalloc(sizeof (**fnlpp));
   2383 	np = (*fnlpp)->namep = Zalloc(sizeof (mdname_t));
   2384 	metainitname(np);
   2385 	dnp = np->drivenamep = Zalloc(sizeof (mddrivename_t));
   2386 	metainitdrivename(dnp);
   2387 
   2388 
   2389 	/* Metadevices */
   2390 	if (uname_type == META_DEVICE &&
   2391 	    (cname = meta_canonicalize(sp, uname)) != NULL) {
   2392 
   2393 		np->cname = cname;
   2394 		dnp->type = MDT_FAST_META;
   2395 		goto done;
   2396 	}
   2397 
   2398 	/* Others */
   2399 	dnp->type = MDT_FAST_COMP;
   2400 
   2401 	if (((sscanf(uname, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d,
   2402 	    &s, &l) == 4 ||
   2403 	    sscanf(uname, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d,
   2404 	    &s, &l) == 4 ||
   2405 	    sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c, &t, &d,
   2406 	    &s, &l) == 4 ||
   2407 	    sscanf(uname, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c, &t, &d,
   2408 	    &s, &l) == 4 ||
   2409 	    sscanf(uname, "/dev/did/rdsk/d%us%u%n", &t, &s, &l) == 2 ||
   2410 	    sscanf(uname, "/dev/did/dsk/d%us%u%n", &t, &s, &l) == 2||
   2411 	    sscanf(uname, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
   2412 	    sscanf(uname, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
   2413 	    sscanf(uname, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
   2414 	    sscanf(uname, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
   2415 	    sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
   2416 	    sscanf(uname, "/dev/ap/dsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
   2417 	    sscanf(uname, "/dev/did/rdsk/d%u%n", &t, &l) == 1 ||
   2418 	    sscanf(uname, "/dev/did/dsk/d%u%n", &t, &l) == 1 ||
   2419 	    sscanf(uname, "/dev/rdsk/c%ud%u%n", &c, &d, &l) == 2 ||
   2420 	    sscanf(uname, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2) &&
   2421 	    l == strlen(uname))) {
   2422 		if ((np->cname = strrchr(uname, '/')) == NULL)
   2423 			np->cname = Strdup(uname);
   2424 		else
   2425 			np->cname = Strdup(++np->cname);
   2426 	} else {
   2427 		np->cname = Strdup(uname);
   2428 	}
   2429 
   2430 done:
   2431 	/* Driver always gives us block names */
   2432 	np->bname = Strdup(uname);
   2433 
   2434 	/* canonical disk name */
   2435 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
   2436 		dnp->cname = Strdup(np->cname);
   2437 
   2438 	if ((np->rname = getrname_fast(uname, uname_type, ep)) != NULL) {
   2439 		if ((dnp->rname = metadiskname(np->rname)) == NULL)
   2440 			dnp->rname = Strdup(np->rname);
   2441 	} else {
   2442 		metafreefastnm(&(*fnlpp)->namep);
   2443 		Free(*fnlpp);
   2444 		*fnlpp = NULL;
   2445 		return (NULL);
   2446 	}
   2447 
   2448 	/* cleanup, return success */
   2449 	return (np);
   2450 }
   2451 
   2452 /*
   2453  * set up names for a device
   2454  */
   2455 static mdname_t *
   2456 metaname_common(
   2457 	mdsetname_t	**spp,
   2458 	char		*uname,
   2459 	int		fast,
   2460 	meta_device_type_t	uname_type,
   2461 	md_error_t	*ep
   2462 )
   2463 {
   2464 	mddrivenamelist_t	**tail;
   2465 	mddrivename_t		*dnp;
   2466 	uint_t			slice;
   2467 	mdname_t		*np;
   2468 	char			*rname = NULL;
   2469 	char			*dname = NULL;
   2470 	char			*cname = NULL;
   2471 	uint_t			nparts, partno;
   2472 
   2473 	assert(uname != NULL);
   2474 
   2475 	/* check setname */
   2476 	if ((cname = meta_name_getname(spp, uname, uname_type, ep)) == NULL)
   2477 		return (NULL);
   2478 
   2479 	assert(*spp != NULL);
   2480 	Free(cname);
   2481 
   2482 	/* get raw name (rname) of the slice and drive (dname) we have */
   2483 	if ((rname = getrawnames(spp, uname,
   2484 	    &dname, &uname_type, ep)) == NULL) {
   2485 		return (NULL);
   2486 	}
   2487 
   2488 	assert(uname_type != UNKNOWN);
   2489 
   2490 	/* look in cache first */
   2491 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
   2492 		dnp = (*tail)->drivenamep;
   2493 
   2494 		/* check to see if the drive name is already in the cache */
   2495 		if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) {
   2496 
   2497 			Free(rname);
   2498 			if (dname != NULL)
   2499 				Free(dname);
   2500 
   2501 			if (uname2sliceno(uname, uname_type, &partno, ep) < 0)
   2502 				return (NULL);
   2503 
   2504 			return (metaslicename(dnp, partno, ep));
   2505 		}
   2506 	}
   2507 
   2508 	/*
   2509 	 * If a fast names is OK, then get one, and be done.
   2510 	 */
   2511 	if (fast) {
   2512 		Free(rname);
   2513 		if (dname != NULL)
   2514 			Free(dname);
   2515 
   2516 		return (metainitfastname(*spp, uname, uname_type, ep));
   2517 	}
   2518 
   2519 	/* allocate new list element and drive */
   2520 	*tail = Zalloc(sizeof (**tail));
   2521 	dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
   2522 
   2523 	metainitdrivename(dnp);
   2524 
   2525 	/* get parts info */
   2526 	if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
   2527 		goto out;
   2528 
   2529 	/*
   2530 	 * libmeta needs at least V_NUMPAR partitions.
   2531 	 * If we have an EFI partition with less than V_NUMPAR slices,
   2532 	 * we nevertheless reserve space for V_NUMPAR
   2533 	 */
   2534 	if (nparts < V_NUMPAR) {
   2535 		nparts = V_NUMPAR;
   2536 	}
   2537 
   2538 	/* allocate and link in parts */
   2539 	dnp->parts.parts_len = nparts;
   2540 	dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) *
   2541 	    dnp->parts.parts_len);
   2542 	for (slice = 0; (slice < nparts); ++slice) {
   2543 		np = &dnp->parts.parts_val[slice];
   2544 		metainitname(np);
   2545 		np->drivenamep = dnp;
   2546 	}
   2547 
   2548 	/* setup name_t (or slice) wanted */
   2549 	if ((np = setup_slice(*spp, uname_type, dnp, uname, rname,
   2550 	    dname, partno, ep)) == NULL)
   2551 		goto out;
   2552 
   2553 	/* canonical disk name */
   2554 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
   2555 		dnp->cname = Strdup(np->cname);
   2556 	if ((dnp->rname = metadiskname(np->rname)) == NULL)
   2557 		dnp->rname = Strdup(np->rname);
   2558 
   2559 	/* cleanup, return success */
   2560 	if (dname != NULL)
   2561 		Free(dname);
   2562 	Free(rname);
   2563 	return (np);
   2564 
   2565 	/* cleanup, return error */
   2566 out:
   2567 	if (dname != NULL)
   2568 		Free(dname);
   2569 	if (rname != NULL)
   2570 		Free(rname);
   2571 
   2572 	metafreedrivename(dnp);
   2573 	Free(dnp);
   2574 	Free(*tail);
   2575 	*tail = NULL;
   2576 	return (NULL);
   2577 }
   2578 
   2579 /*
   2580  * metaname()
   2581  *
   2582  * Wrapper function for metaname_common()
   2583  * If the second arg is a metadevice name then it is important that this should
   2584  * be a canonical name (eg d30 rather than /dev/md/dsk/d30). If this is not the
   2585  * case then a bad entry may be placed into the drivelistp cache.
   2586  */
   2587 mdname_t *
   2588 metaname(
   2589 	mdsetname_t	**spp,
   2590 	char		*uname,
   2591 	meta_device_type_t	uname_type,
   2592 	md_error_t	*ep
   2593 )
   2594 {
   2595 	return (metaname_common(spp, uname, 0, uname_type, ep));
   2596 }
   2597 
   2598 mdname_t *
   2599 metaname_fast(
   2600 	mdsetname_t	**spp,
   2601 	char		*uname,
   2602 	meta_device_type_t	uname_type,
   2603 	md_error_t	*ep
   2604 )
   2605 {
   2606 	return (metaname_common(spp, uname, 1, uname_type, ep));
   2607 }
   2608 /*
   2609  * Get the dnp using the device id.
   2610  *
   2611  * We have the potential to have more than 1 dnp with the same disk name but
   2612  * have different device ids. This would happen in the case of a partial
   2613  * diskset. The unavailable disk name is relative to the prior host and could
   2614  * possibly be the same as a disk on this system. The only way to tell which
   2615  * dnp belongs with this disk is by searching by device id. We have the
   2616  * potential to have the case where 1) the disk who's device id we pass in is
   2617  * in the system. In this case the name and the device id are both valid for
   2618  * the disk. 2) The disk whose device id we've been passed is not in the
   2619  * system and no disk with the same name has a dnp on the list. And 3) The
   2620  * disk whose device id we've been passed is not on the system but there is
   2621  * a disk with the same name (different devid) that is on the system. Here's
   2622  * what we return for each of those cases:
   2623  * 1) If disk is in system:
   2624  * 	disk is found on drivelistp or we create a new drivename and it's
   2625  * 	fully populated as expected.
   2626  * 2) If disk not in system, no collision
   2627  *	Disk with the same devid is not found on drivelistp, we create a new
   2628  *	drivename structure and the dnp->devid is filled in not from getparts
   2629  *	but from the devidp passed in. No other disk in the system has the
   2630  *	same "name" or devid.
   2631  *	This situation would be caused by the import of a partial diskset.
   2632  * 3) If disk not in system, collision
   2633  *	Disk with the same devid is not found on the drivelistp, we create a
   2634  *	new drivename struct but getparts will use the information from the
   2635  *	name which is actually in reference to another disk of the same name
   2636  *	in the system. getparts will fill in the dnp->devid with the value
   2637  *	from the other disk and	we overwrite this with the value of this disk.
   2638  *	To get into this situation one of the disks is actually unavailable
   2639  *	as in the case of a partial import.
   2640  */
   2641 mddrivename_t *
   2642 meta_getdnp_bydevid(
   2643 	mdsetname_t	*sp,
   2644 	side_t		sideno,
   2645 	ddi_devid_t	devidp,
   2646 	mdkey_t		key,
   2647 	md_error_t	*ep
   2648 )
   2649 {
   2650 	ddi_devid_t		dnp_devidp;
   2651 	char			*nm;
   2652 	mddrivenamelist_t	**tail;
   2653 	mddrivename_t		*dnp;
   2654 	uint_t			slice;
   2655 	mdname_t		*np;
   2656 	char			*rname = NULL;
   2657 	char			*dname = NULL;
   2658 	uint_t			nparts, partno;
   2659 	int			ret;
   2660 	md_set_desc		*sd = NULL;
   2661 	meta_device_type_t	uname_type = LOGICAL_DEVICE;
   2662 
   2663 	/* look in the cache first */
   2664 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
   2665 		dnp = (*tail)->drivenamep;
   2666 		if (dnp->type != MDT_COMP)
   2667 			continue;
   2668 		ret = devid_str_decode(dnp->devid, &dnp_devidp, NULL);
   2669 		if (ret != 0) {
   2670 			/* unable to decode the devid */
   2671 			return (NULL);
   2672 		}
   2673 		/* compare with the devid passed in. */
   2674 		if (devid_compare(devidp, dnp_devidp) == 0) {
   2675 			/* match! We have the same disk */
   2676 			devid_free(dnp_devidp);
   2677 			return (dnp);
   2678 		}
   2679 		devid_free(dnp_devidp);
   2680 	}
   2681 
   2682 	/* drive not in the cache */
   2683 
   2684 	if ((sd = metaget_setdesc(sp, ep)) == NULL) {
   2685 		return (NULL);
   2686 	}
   2687 	/* get namespace info */
   2688 	if (MD_MNSET_DESC(sd)) {
   2689 		if ((nm = meta_getnmbykey(MD_LOCAL_SET, sideno,
   2690 		    key, ep)) == NULL)
   2691 			return (NULL);
   2692 	} else {
   2693 		if ((nm = meta_getnmbykey(MD_LOCAL_SET,
   2694 		    sideno+SKEW, key, ep)) == NULL)
   2695 			return (NULL);
   2696 	}
   2697 
   2698 	/* get raw name (rname) of the slice and drive name (dname) */
   2699 	if ((rname = getrawnames(&sp, nm, &dname, &uname_type, ep)) == NULL) {
   2700 		return (NULL);
   2701 	}
   2702 
   2703 	/* allocate new list element and drive */
   2704 	*tail = Zalloc(sizeof (**tail));
   2705 	dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
   2706 	metainitdrivename(dnp);
   2707 
   2708 	/* get parts info */
   2709 	/*
   2710 	 * Note that if the disk is unavailable this name will point to
   2711 	 * either a nonexistent disk and thus the part info and devid will
   2712 	 * be empty or the name will point to the wrong disk and this
   2713 	 * information will be invalid. Because of this, we overwrite the
   2714 	 * dnp->devid with the correct one after getparts returns.
   2715 	 */
   2716 	if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
   2717 		goto out;
   2718 
   2719 	dnp->devid = devid_str_encode(devidp, NULL);
   2720 
   2721 	/*
   2722 	 * libmeta needs at least V_NUMPAR partitions.
   2723 	 * If we have an EFI partition with less than V_NUMPAR slices,
   2724 	 * we nevertheless reserve space for V_NUMPAR
   2725 	 */
   2726 	if (nparts < V_NUMPAR) {
   2727 		nparts = V_NUMPAR;
   2728 	}
   2729 
   2730 	/* allocate and link in parts */
   2731 	dnp->parts.parts_len = nparts;
   2732 	dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) *
   2733 	    dnp->parts.parts_len);
   2734 
   2735 	for (slice = 0; (slice < nparts); ++slice) {
   2736 		np = &dnp->parts.parts_val[slice];
   2737 		metainitname(np);
   2738 		np->drivenamep = dnp;
   2739 	}
   2740 
   2741 	/* setup name_t (or slice) wanted */
   2742 	if ((np = setup_slice(sp, uname_type, dnp, nm, rname,
   2743 	    dname, partno, ep)) == NULL)
   2744 		goto out;
   2745 
   2746 	/* canonical disk name */
   2747 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
   2748 		dnp->cname = Strdup(np->cname);
   2749 	if ((dnp->rname = metadiskname(np->rname)) == NULL)
   2750 		dnp->rname = Strdup(np->rname);
   2751 
   2752 	if (dname != NULL)
   2753 		Free(dname);
   2754 	Free(rname);
   2755 	return (dnp);
   2756 
   2757 out:
   2758 	if (dname != NULL)
   2759 		Free(dname);
   2760 
   2761 	if (rname != NULL)
   2762 		Free(rname);
   2763 
   2764 	metafreedrivename(dnp);
   2765 	Free(dnp);
   2766 	Free(*tail);
   2767 	*tail = NULL;
   2768 	return (NULL);
   2769 }
   2770 
   2771 /*
   2772  * Search the drivename list by devid instead of name. If you don't find
   2773  * an entry with the same device id, create one for the uname passed in.
   2774  */
   2775 mddrivename_t *
   2776 metadrivenamebydevid(
   2777 	mdsetname_t		**spp,
   2778 	char			*devid,
   2779 	char			*uname,
   2780 	md_error_t		*ep
   2781 )
   2782 {
   2783 	ddi_devid_t		dnp_devidp, in_devidp;
   2784 	mdname_t		*np;
   2785 	mddrivenamelist_t	**tail;
   2786 	char			*rname = NULL;
   2787 	mddrivename_t		*dnp;
   2788 	char			*dname;
   2789 	int			ret;
   2790 	uint_t			nparts, partno;
   2791 	uint_t			slice;
   2792 	meta_device_type_t	uname_type = LOGICAL_DEVICE;
   2793 
   2794 	/* look in the cache first */
   2795 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
   2796 		dnp = (*tail)->drivenamep;
   2797 		if (dnp->type != MDT_COMP)
   2798 			continue;
   2799 
   2800 		/* decode the dnp devid */
   2801 		ret = devid_str_decode(dnp->devid, &dnp_devidp, NULL);
   2802 		if (ret != 0) {
   2803 			/* unable to decode the devid */
   2804 			return (NULL);
   2805 		}
   2806 		/* decode the passed in devid */
   2807 		ret = devid_str_decode(devid, &in_devidp, NULL);
   2808 		if (ret != 0) {
   2809 			/* unable to decode the devid */
   2810 			devid_free(dnp_devidp);
   2811 			return (NULL);
   2812 		}
   2813 		/* compare with the devids */
   2814 		if (devid_compare(in_devidp, dnp_devidp) == 0) {
   2815 			/* match! We have the same disk */
   2816 			devid_free(dnp_devidp);
   2817 			devid_free(in_devidp);
   2818 			return (dnp);
   2819 		}
   2820 	}
   2821 	devid_free(dnp_devidp);
   2822 	devid_free(in_devidp);
   2823 
   2824 	/* not in the cache */
   2825 
   2826 	/* get raw name (rname) of the slice and drive (dname) we have */
   2827 	if ((rname = getrawnames(spp, uname, &dname, &uname_type,
   2828 	    ep)) == NULL) {
   2829 		return (NULL);
   2830 	}
   2831 
   2832 	/* allocate new list element and drive */
   2833 	*tail = Zalloc(sizeof (**tail));
   2834 	dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
   2835 
   2836 	metainitdrivename(dnp);
   2837 
   2838 	/* get parts info */
   2839 	if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
   2840 		goto out;
   2841 
   2842 	/*
   2843 	 * libmeta needs at least V_NUMPAR partitions.
   2844 	 * If we have an EFI partition with less than V_NUMPAR slices,
   2845 	 * we nevertheless reserve space for V_NUMPAR
   2846 	 */
   2847 	if (nparts < V_NUMPAR) {
   2848 		nparts = V_NUMPAR;
   2849 	}
   2850 
   2851 	/* allocate and link in parts */
   2852 	dnp->parts.parts_len = nparts;
   2853 	dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) *
   2854 	    dnp->parts.parts_len);
   2855 	for (slice = 0; (slice < nparts); ++slice) {
   2856 		np = &dnp->parts.parts_val[slice];
   2857 		metainitname(np);
   2858 		np->drivenamep = dnp;
   2859 	}
   2860 
   2861 	/* setup name_t (or slice) wanted */
   2862 	if ((np = setup_slice(*spp, uname_type, dnp, uname, rname,
   2863 	    dname, partno, ep)) == NULL)
   2864 		goto out;
   2865 
   2866 	/* canonical disk name */
   2867 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
   2868 		dnp->cname = Strdup(np->cname);
   2869 	if ((dnp->rname = metadiskname(np->rname)) == NULL)
   2870 		dnp->rname = Strdup(np->rname);
   2871 
   2872 	/* cleanup, return success */
   2873 	if (dname != NULL)
   2874 		Free(dname);
   2875 	Free(rname);
   2876 	return (dnp);
   2877 
   2878 	/* cleanup, return error */
   2879 out:
   2880 	if (dname != NULL)
   2881 		Free(dname);
   2882 	if (rname != NULL)
   2883 		Free(rname);
   2884 
   2885 	metafreedrivename(dnp);
   2886 	Free(dnp);
   2887 	Free(*tail);
   2888 	*tail = NULL;
   2889 	return (NULL);
   2890 }
   2891 /*
   2892  * set up names for a drive
   2893  */
   2894 mddrivename_t *
   2895 metadrivename(
   2896 	mdsetname_t		**spp,
   2897 	char			*uname,
   2898 	md_error_t		*ep
   2899 )
   2900 {
   2901 	char		*slicename;
   2902 	mdname_t	*np;
   2903 
   2904 	mddrivenamelist_t **tail;
   2905 	mddrivename_t	*dnp;
   2906 	char		*dname;
   2907 	int		i;
   2908 	int		mplen;
   2909 	size_t		len;
   2910 
   2911 	assert(uname != NULL);
   2912 
   2913 	if ((dname = metadiskname(uname)) == NULL) {
   2914 		(void) mdsyserror(ep, ENOENT, uname);
   2915 		return (NULL);
   2916 	}
   2917 
   2918 	/* look in cache first */
   2919 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
   2920 		dnp = (*tail)->drivenamep;
   2921 		if ((dnp->cname != NULL &&
   2922 		    (strcmp(dnp->cname, dname) == 0)) ||
   2923 		    (dnp->rname != NULL &&
   2924 		    (strcmp(dnp->rname, dname) == 0))) {
   2925 			Free(dname);
   2926 			return (dnp);
   2927 		}
   2928 	}
   2929 	Free(dname);
   2930 
   2931 	/* Check each possible slice name based on MD_MAX_PARTS. */
   2932 
   2933 	/*
   2934 	 * Figure out how much string space to reserve to fit
   2935 	 * (MD_MAX_PARTS - 1) into the name string; the loop will
   2936 	 * increment the mplen counter once for each decimal digit in
   2937 	 * (MD_MAX_PARTS - 1).
   2938 	 */
   2939 	for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen)
   2940 		;
   2941 	len = strlen(uname) + mplen + 2;
   2942 	slicename = Malloc(len);
   2943 
   2944 	/* Check for each slice in turn until we find one */
   2945 	for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) {
   2946 		(void) snprintf(slicename, len, "%ss%d", uname, i);
   2947 		np = metaname(spp, slicename, LOGICAL_DEVICE, ep);
   2948 	}
   2949 	Free(slicename);
   2950 
   2951 	if (np == NULL) {
   2952 		if ((mdiserror(ep, MDE_UNIT_NOT_FOUND)) &&
   2953 		    ((dname = metadiskname(uname)) != NULL)) {
   2954 			Free(dname);
   2955 			(void) mderror(ep, MDE_NOT_DRIVENAME, uname);
   2956 		}
   2957 		return (NULL);
   2958 	}
   2959 	return (np->drivenamep);
   2960 }
   2961 
   2962 /*
   2963  * FUNCTION:	metaslicename_type()
   2964  * INPUT:	dnp	- the drivename structure
   2965  *		sliceno	- the slice on the drive to return
   2966  *		type - LOGICAL_DEVICE or META_DEVICE
   2967  * OUTPUT:	ep	- return error pointer
   2968  * RETURNS:	mdname_t- pointer the the slice name structure
   2969  * PURPOSE:	interface to the parts struct in the drive name struct
   2970  *		Since there is no guarantee that the slice name
   2971  *		structures are populated users should call this
   2972  *		function rather than accessing the structure directly
   2973  *		since it will populate the structure values if they
   2974  *		haven't already been populated before returning.
   2975  */
   2976 mdname_t *
   2977 metaslicename_type(
   2978 	mddrivename_t		*dnp,
   2979 	uint_t			sliceno,
   2980 	meta_device_type_t	uname_type,
   2981 	md_error_t		*ep
   2982 )
   2983 {
   2984 	mdsetname_t	*sp = NULL;
   2985 	char		*namep = NULL;
   2986 	mdname_t	*np;
   2987 
   2988 	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
   2989 
   2990 	if (sliceno >= dnp->parts.parts_len) {
   2991 		(void) mderror(ep, MDE_NOSLICE, dnp->cname);
   2992 		return (NULL);
   2993 	}
   2994 
   2995 	np = &dnp->parts.parts_val[sliceno];
   2996 
   2997 	/* check to see if the struct is already populated */
   2998 	if (np->cname) {
   2999 		return (np);
   3000 	}
   3001 
   3002 	if ((namep = meta_name_getname(&sp, dnp->cname,
   3003 	    uname_type, ep)) == NULL)
   3004 		return (NULL);
   3005 
   3006 	np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname,
   3007 	    sliceno, ep);
   3008 
   3009 	Free(namep);
   3010 
   3011 	return (np);
   3012 }
   3013 
   3014 /*
   3015  * FUNCTION:	metaslicename()
   3016  * INPUT:	dnp	- the drivename structure
   3017  *		sliceno	- the slice on the drive to return
   3018  * OUTPUT:	ep	- return error pointer
   3019  * RETURNS:	mdname_t- pointer the the slice name structure
   3020  * PURPOSE:	interface to the parts struct in the drive name struct
   3021  *		Since there is no guarantee that the slice name
   3022  *		structures are populated users should call this
   3023  *		function rather than accessing the structure directly
   3024  *		since it will populate the structure values if they
   3025  *		haven't already been populated before returning.
   3026  */
   3027 mdname_t *
   3028 metaslicename(
   3029 	mddrivename_t	*dnp,
   3030 	uint_t		sliceno,
   3031 	md_error_t	*ep
   3032 )
   3033 {
   3034 	return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep));
   3035 }
   3036 
   3037 /*
   3038  * set up metadevice name from id
   3039  */
   3040 mdname_t *
   3041 metamnumname(
   3042 	mdsetname_t	**spp,
   3043 	minor_t		mnum,
   3044 	int		fast,
   3045 	md_error_t	*ep
   3046 )
   3047 {
   3048 	set_t		setno = MD_MIN2SET(mnum);
   3049 	mdsetname_t	*sp = NULL;
   3050 	char		*uname;
   3051 	mdname_t	*np;
   3052 	md_dev64_t	dev;
   3053 	mdkey_t		key;
   3054 
   3055 	/* check set first */
   3056 	if (spp == NULL)
   3057 		spp = &sp;
   3058 	if (chksetno(spp, setno, ep) != 0)
   3059 		return (NULL);
   3060 	assert(*spp != NULL);
   3061 	sp = *spp;
   3062 
   3063 	/* get corresponding device name */
   3064 	dev = metamakedev(mnum);
   3065 	if ((uname = meta_getnmentbydev(sp->setno, MD_SIDEWILD, dev,
   3066 	    NULL, NULL, &key, ep)) == NULL)
   3067 		return (NULL);
   3068 
   3069 	/* setup name */
   3070 	if (fast) {
   3071 		np = metaname_fast(spp, uname, META_DEVICE, ep);
   3072 		if (np) {
   3073 			np->dev = dev;
   3074 			np->key = key;
   3075 		}
   3076 	} else
   3077 		np = metaname(spp, uname, META_DEVICE, ep);
   3078 
   3079 	Free(uname);
   3080 	return (np);
   3081 }
   3082 
   3083 /*
   3084  * return metadevice name
   3085  */
   3086 char *
   3087 get_mdname(
   3088 	mdsetname_t	*sp,
   3089 	minor_t		mnum
   3090 )
   3091 {
   3092 	mdname_t	*np;
   3093 	md_error_t	status = mdnullerror;
   3094 	mdsetname_t	**spp = NULL;
   3095 
   3096 	if (sp != NULL)
   3097 		spp = &sp;
   3098 
   3099 	/* get name */
   3100 	if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) {
   3101 		return (NULL);
   3102 	}
   3103 	assert(meta_getminor(np->dev) == mnum);
   3104 
   3105 	/* return name */
   3106 	return (np->cname);
   3107 }
   3108 
   3109 /*
   3110  * check for device type
   3111  */
   3112 int
   3113 metaismeta(
   3114 	mdname_t	*np
   3115 )
   3116 {
   3117 	return (np->drivenamep->type == MDT_META ||
   3118 	    np->drivenamep->type == MDT_FAST_META);
   3119 }
   3120 
   3121 int
   3122 metachkmeta(
   3123 	mdname_t	*np,
   3124 	md_error_t	*ep
   3125 )
   3126 {
   3127 	if (! metaismeta(np)) {
   3128 		return (mddeverror(ep, MDE_NOT_META, np->dev,
   3129 		    np->cname));
   3130 	}
   3131 	return (0);
   3132 }
   3133 
   3134 int
   3135 metachkdisk(
   3136 	mdname_t	*np,
   3137 	md_error_t	*ep
   3138 )
   3139 {
   3140 	mddrivename_t	*dnp = np->drivenamep;
   3141 
   3142 	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
   3143 
   3144 	if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) {
   3145 		switch (dnp->type) {
   3146 			case MDT_ACCES:
   3147 			case MDT_UNKNOWN:
   3148 				return (mdsyserror(ep, dnp->errnum, np->bname));
   3149 			default:
   3150 				assert(0);
   3151 				return (mddeverror(ep, MDE_NOT_DISK, np->dev,
   3152 				    np->cname));
   3153 		}
   3154 	}
   3155 	return (0);
   3156 }
   3157 
   3158 int
   3159 metachkcomp(
   3160 	mdname_t	*np,
   3161 	md_error_t	*ep
   3162 )
   3163 {
   3164 	if (metaismeta(np)) {
   3165 		return (mddeverror(ep, MDE_IS_META, np->dev,
   3166 		    np->cname));
   3167 	}
   3168 	return (metachkdisk(np, ep));
   3169 }
   3170 
   3171 /*
   3172  * free list of names
   3173  */
   3174 void
   3175 metafreenamelist(
   3176 	mdnamelist_t	*nlp
   3177 )
   3178 {
   3179 	mdnamelist_t	*next = NULL;
   3180 
   3181 	for (/* void */; (nlp != NULL); nlp = next) {
   3182 		next = nlp->next;
   3183 		Free(nlp);
   3184 	}
   3185 }
   3186 
   3187 /*
   3188  * build list of names
   3189  */
   3190 int
   3191 metanamelist(
   3192 	mdsetname_t	**spp,
   3193 	mdnamelist_t	**nlpp,
   3194 	int		argc,
   3195 	char		*argv[],
   3196 	meta_device_type_t	type,
   3197 	md_error_t	*ep
   3198 )
   3199 {
   3200 	mdnamelist_t	**tailpp = nlpp;
   3201 	int		count = 0;
   3202 
   3203 	for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
   3204 		mdnamelist_t	*nlp = Zalloc(sizeof (*nlp));
   3205 
   3206 		if ((nlp->namep = metaname(spp, argv[0],
   3207 		    type, ep)) == NULL) {
   3208 			metafreenamelist(*nlpp);
   3209 			*nlpp = NULL;
   3210 			return (-1);
   3211 		}
   3212 		*tailpp = nlp;
   3213 		tailpp = &nlp->next;
   3214 	}
   3215 	return (count);
   3216 }
   3217 
   3218 /*
   3219  * append to end of name list
   3220  */
   3221 mdname_t *
   3222 metanamelist_append(
   3223 	mdnamelist_t	**nlpp,
   3224 	mdname_t	*np
   3225 )
   3226 {
   3227 	mdnamelist_t	*nlp;
   3228 
   3229 	/* run to end of list */
   3230 	for (; (*nlpp != NULL); nlpp = &(*nlpp)->next)
   3231 		;
   3232 
   3233 	/* allocate new list element */
   3234 	nlp = *nlpp = Zalloc(sizeof (*nlp));
   3235 
   3236 	/* append name */
   3237 	nlp->namep = np;
   3238 	return (np);
   3239 }
   3240 
   3241 /*
   3242  * FUNCTION:	meta_namelist_append_wrapper()
   3243  * INPUT:	tailpp	- pointer to the list tail pointer
   3244  *		np	- name node to be appended to list
   3245  * OUTPUT:	none
   3246  * RETURNS:	mdnamelist_t * - new tail of the list.
   3247  * PURPOSE:	wrapper to meta_namelist_append for performance.
   3248  *		metanamelist_append finds the tail each time which slows
   3249  *		down long lists.  By keeping track of the tail ourselves
   3250  *		we can change metanamelist_append into a constant time
   3251  *		operation.
   3252  */
   3253 mdnamelist_t **
   3254 meta_namelist_append_wrapper(
   3255 	mdnamelist_t	**tailpp,
   3256 	mdname_t	*np
   3257 )
   3258 {
   3259 	(void) metanamelist_append(tailpp, np);
   3260 
   3261 	/* If it's the first item in the list, return it instead of the next */
   3262 	if ((*tailpp)->next == NULL)
   3263 		return (tailpp);
   3264 
   3265 	return (&(*tailpp)->next);
   3266 }
   3267 
   3268 
   3269 /*
   3270  *	mdhspname_t stuff
   3271  */
   3272 
   3273 /*
   3274  * initialize hspname
   3275  */
   3276 static void
   3277 metainithspname(
   3278 	mdhspname_t	*hspnamep
   3279 )
   3280 {
   3281 	(void) memset(hspnamep, '\0', sizeof (*hspnamep));
   3282 	hspnamep->hsp = MD_HSP_NONE;
   3283 }
   3284 
   3285 /*
   3286  * free allocated hspname
   3287  */
   3288 static void
   3289 metafreehspname(
   3290 	mdhspname_t	*hspnamep
   3291 )
   3292 {
   3293 	if (hspnamep->hspname != NULL)
   3294 		Free(hspnamep->hspname);
   3295 	if (hspnamep->unitp != NULL)
   3296 		meta_invalidate_hsp(hspnamep);
   3297 	metainithspname(hspnamep);
   3298 }
   3299 
   3300 /*
   3301  * clear the hspname cache
   3302  */
   3303 static void
   3304 metaflushhspnames()
   3305 {
   3306 	mdhspnamelist_t		*p, *n;
   3307 
   3308 	for (p = hsplistp, n = NULL; (p != NULL); p = n) {
   3309 		n = p->next;
   3310 		metafreehspname(p->hspnamep);
   3311 		Free(p->hspnamep);
   3312 		Free(p);
   3313 	}
   3314 	hsplistp = NULL;
   3315 }
   3316 
   3317 /*
   3318  * check set and get comparison name
   3319  */
   3320 static char *
   3321 gethspname(
   3322 	mdsetname_t	**spp,
   3323 	char		*uname,
   3324 	md_error_t	*ep
   3325 )
   3326 {
   3327 	char		*cname = NULL;
   3328 
   3329 	cname = meta_canonicalize(*spp, uname);
   3330 	/* if it is not a meta/hsp name then flag an error */
   3331 	if (cname == NULL) {
   3332 		(void) mdsyserror(ep, ENOENT, uname);
   3333 		return (NULL);
   3334 	}
   3335 	return (cname);
   3336 }
   3337 
   3338 /*
   3339  * set up a hotspare pool name structure using both the name
   3340  * and the self id
   3341  */
   3342 static mdhspname_t *
   3343 metahspname_hsp(
   3344 	mdsetname_t	**spp,
   3345 	char		*uname,
   3346 	hsp_t		hsp,
   3347 	md_error_t	*ep
   3348 )
   3349 {
   3350 	char		*cname;
   3351 	mdhspnamelist_t	**tail;
   3352 	mdhspname_t	*hspnp;
   3353 
   3354 	/* check setname */
   3355 	assert(uname != NULL);
   3356 	if ((cname = gethspname(spp, uname, ep)) == NULL)
   3357 		return (NULL);
   3358 	assert(*spp != NULL);
   3359 
   3360 	/* look in cache first */
   3361 	for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) {
   3362 		hspnp = (*tail)->hspnamep;
   3363 		if (strcmp(hspnp->hspname, cname) == 0) {
   3364 			Free(cname);
   3365 			/* if the hsp value has not been set then set it now */
   3366 			if (hspnp->hsp == MD_HSP_NONE)
   3367 				hspnp->hsp = hsp;
   3368 			return (hspnp);
   3369 		}
   3370 	}
   3371 
   3372 	/* if the hsp number isn't specified then attempt to get it */
   3373 	if (hsp == MD_HSP_NONE && (hsp = meta_gethspnmentbyname((*spp)->setno,
   3374 	    MD_SIDEWILD, cname, ep)) == MD_HSP_NONE) {
   3375 		if (! mdisok(ep)) {
   3376 			/*
   3377 			 * If the error is ENOENT, then we will continue on,
   3378 			 * because the device does not yet exist.
   3379 			 * For other types of errors, however, we'll bail out.
   3380 			 */
   3381 			if (! mdissyserror(ep, ENOENT)) {
   3382 				Free(cname);
   3383 				return (NULL);
   3384 			}
   3385 			mdclrerror(ep);
   3386 		}
   3387 	}
   3388 
   3389 	/* allocate new list element and hspname */
   3390 	*tail = Zalloc(sizeof (**tail));
   3391 	hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp));
   3392 	metainithspname(hspnp);
   3393 
   3394 	/* save hspname and number */
   3395 	hspnp->hspname = cname;
   3396 	hspnp->hsp = hsp;
   3397 
   3398 	/* success */
   3399 	return (hspnp);
   3400 }
   3401 
   3402 /*
   3403  * set up names for a hotspare pool
   3404  */
   3405 mdhspname_t *
   3406 metahspname(
   3407 	mdsetname_t	**spp,
   3408 	char		*uname,
   3409 	md_error_t	*ep
   3410 )
   3411 {
   3412 	return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep));
   3413 }
   3414 
   3415 /*
   3416  * set up hotspare pool name from key
   3417  */
   3418 mdhspname_t *
   3419 metahsphspname(
   3420 	mdsetname_t	**spp,
   3421 	hsp_t		hsp,
   3422 	md_error_t	*ep
   3423 )
   3424 {
   3425 	set_t		setno = HSP_SET(hsp);
   3426 	mdsetname_t	*sp = NULL;
   3427 	char		*uname;
   3428 	mdhspname_t	*hspnp;
   3429 
   3430 	/* check set first */
   3431 	if (spp == NULL)
   3432 		spp = &sp;
   3433 	if (chksetno(spp, setno, ep) != 0)
   3434 		return (NULL);
   3435 	assert(*spp != NULL);
   3436 	sp = *spp;
   3437 
   3438 	/* get corresponding hotspare pool name */
   3439 	if ((uname = meta_gethspnmentbyid(sp->setno,
   3440 	    MD_SIDEWILD, hsp, ep)) == NULL)
   3441 		return (NULL);
   3442 
   3443 	/* setup name */
   3444 	hspnp = metahspname_hsp(spp, uname, hsp, ep);
   3445 	Free(uname);
   3446 	return (hspnp);
   3447 }
   3448 
   3449 /*
   3450  * return hotspare pool name
   3451  */
   3452 char *
   3453 get_hspname(mdsetname_t *sp, hsp_t hsp)
   3454 {
   3455 	mdhspname_t	*hspnp;
   3456 	md_error_t	status = mdnullerror;
   3457 	mdsetname_t	**spp = NULL;
   3458 
   3459 	if (sp != NULL)
   3460 		spp = &sp;
   3461 
   3462 	/* get name */
   3463 	if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) {
   3464 		mdclrerror(&status);
   3465 		return (NULL);
   3466 	}
   3467 
   3468 	/* return name */
   3469 	return (hspnp->hspname);
   3470 }
   3471 
   3472 /*
   3473  * free hotspare pool list
   3474  */
   3475 void
   3476 metafreehspnamelist(mdhspnamelist_t *hspnlp)
   3477 {
   3478 	mdhspnamelist_t	*next = NULL;
   3479 
   3480 	for (/* void */; (hspnlp != NULL); hspnlp = next) {
   3481 		next = hspnlp->next;
   3482 		Free(hspnlp);
   3483 	}
   3484 }
   3485 
   3486 /*
   3487  * build list of hotspare pool names
   3488  */
   3489 int
   3490 metahspnamelist(
   3491 	mdsetname_t	**spp,
   3492 	mdhspnamelist_t	**hspnlpp,
   3493 	int		argc,
   3494 	char		*argv[],
   3495 	md_error_t	*ep
   3496 )
   3497 {
   3498 	mdhspnamelist_t	**tailpp = hspnlpp;
   3499 	int		count = 0;
   3500 
   3501 	for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
   3502 		mdhspnamelist_t	*hspnlp = Zalloc(sizeof (*hspnlp));
   3503 
   3504 		if ((hspnlp->hspnamep = metahspname(spp, argv[0],
   3505 		    ep)) == NULL) {
   3506 			metafreehspnamelist(*hspnlpp);
   3507 			*hspnlpp = NULL;
   3508 			return (-1);
   3509 		}
   3510 		*tailpp = hspnlp;
   3511 		tailpp = &hspnlp->next;
   3512 	}
   3513 	return (count);
   3514 }
   3515 
   3516 /*
   3517  * append to end of hotspare pool list
   3518  */
   3519 mdhspname_t *
   3520 metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp)
   3521 {
   3522 	mdhspnamelist_t	*hspnlp;
   3523 
   3524 	/* run to end of list */
   3525 	for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next)
   3526 		;
   3527 
   3528 	/* allocate new list element */
   3529 	hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp));
   3530 
   3531 	/* append hotspare pool name */
   3532 	hspnlp->hspnamep = hspnp;
   3533 	return (hspnp);
   3534 }
   3535 
   3536 /*
   3537  * get name from dev
   3538  */
   3539 mdname_t *
   3540 metadevname(
   3541 	mdsetname_t **spp,
   3542 	md_dev64_t dev,
   3543 	md_error_t *ep)
   3544 {
   3545 	char		*device_name;
   3546 	mdname_t	*namep;
   3547 	mdkey_t		key;
   3548 
   3549 	/* short circuit metadevices */
   3550 	assert(dev != NODEV64);
   3551 	if (meta_dev_ismeta(dev))
   3552 		return (metamnumname(spp, meta_getminor(dev), 0, ep));
   3553 
   3554 	/* create local set, if necessary */
   3555 	if (*spp == NULL) {
   3556 		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
   3557 			return (NULL);
   3558 	}
   3559 
   3560 	/* get name from namespace */
   3561 	if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD,
   3562 	    dev, NULL, NULL, &key, ep)) == NULL) {
   3563 		return (NULL);
   3564 	}
   3565 	namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep);
   3566 	if (namep != NULL)
   3567 		namep->key = key;
   3568 
   3569 	Free(device_name);
   3570 	return (namep);
   3571 }
   3572 
   3573 /*
   3574  * return cached name from md_dev64_t
   3575  */
   3576 static char *
   3577 metadevtocachename(md_dev64_t dev)
   3578 {
   3579 	mddrivenamelist_t	*dnlp;
   3580 
   3581 	/* look in cache */
   3582 	for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) {
   3583 		mddrivename_t	*dnp = dnlp->drivenamep;
   3584 		uint_t		i;
   3585 
   3586 		for (i = 0; (i < dnp->parts.parts_len); ++i) {
   3587 			mdname_t	*np = &dnp->parts.parts_val[i];
   3588 
   3589 			if (np->dev == dev)
   3590 				return (np->cname);
   3591 		}
   3592 	}
   3593 
   3594 	/* not found */
   3595 	return (NULL);
   3596 }
   3597 
   3598 /*
   3599  * Ask the driver for the name, which has been stored in the
   3600  * metadevice state database (on behalf of the utilities).
   3601  * (by devno)
   3602  */
   3603 char *
   3604 get_devname(
   3605 	set_t setno,
   3606 	md_dev64_t dev)
   3607 {
   3608 	mdsetname_t	*sp;
   3609 	mdname_t	*np;
   3610 	md_error_t	status = mdnullerror;
   3611 
   3612 	/* get name */
   3613 	if ((setno == MD_SET_BAD) ||
   3614 	    ((sp = metasetnosetname(setno, &status)) == NULL) ||
   3615 	    ((np = metadevname(&sp, dev, &status)) == NULL)) {
   3616 		mdclrerror(&status);
   3617 		return (metadevtocachename(dev));
   3618 	}
   3619 
   3620 	/* return name */
   3621 	return (np->cname);
   3622 }
   3623 
   3624 /*
   3625  * get name from key
   3626  */
   3627 mdname_t *
   3628 metakeyname(
   3629 	mdsetname_t	**spp,
   3630 	mdkey_t		key,
   3631 	int		fast,
   3632 	md_error_t	*ep
   3633 )
   3634 {
   3635 	char		*device_name;
   3636 	md_dev64_t	dev = NODEV64;
   3637 	mdname_t	*namep;
   3638 
   3639 	/* create local set, if necessary */
   3640 	if (*spp == NULL) {
   3641 		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
   3642 			return (NULL);
   3643 	}
   3644 
   3645 	/* get name from namespace */
   3646 	if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD,
   3647 	    key, NULL, NULL, &dev, ep)) == NULL) {
   3648 		return (NULL);
   3649 	}
   3650 	if (fast)
   3651 		namep = metaname_fast(spp, device_name, UNKNOWN, ep);
   3652 	else
   3653 		namep = metaname(spp, device_name, UNKNOWN, ep);
   3654 
   3655 	assert(dev != NODEV64);
   3656 	if (namep)
   3657 		namep->dev = dev;
   3658 	Free(device_name);
   3659 	return (namep);
   3660 }
   3661 
   3662 /*
   3663  * completely flush metadev/hsp caches
   3664  */
   3665 void
   3666 metaflushmetanames()
   3667 {
   3668 	metaflushhspnames();
   3669 	metaflushdrivenames();
   3670 	metaflushfastnames();
   3671 	metaflushstatcache();
   3672 }
   3673 
   3674 /*
   3675  * completely flush the caches
   3676  */
   3677 void
   3678 metaflushnames(int flush_sr_cache)
   3679 {
   3680 	metaflushhspnames();
   3681 	metaflushdrivenames();
   3682 	metaflushsetnames();
   3683 	metaflushctlrcache();
   3684 	metaflushfastnames();
   3685 	metaflushstatcache();
   3686 	if (flush_sr_cache)
   3687 		sr_cache_flush(0);
   3688 }
   3689 
   3690 /*
   3691  * meta_get_hotspare_names
   3692  *  returns an mdnamelist_t of hot spare names
   3693  */
   3694 
   3695 int
   3696 meta_get_hotspare_names(
   3697 	mdsetname_t	*sp,
   3698 	mdnamelist_t	**nlpp,
   3699 	int		options,
   3700 	md_error_t	*ep
   3701 )
   3702 {
   3703 	mdhspnamelist_t		*hspnlp	= NULL;
   3704 	mdhspnamelist_t		*hspp;
   3705 	int			cnt = 0;
   3706 
   3707 	assert(nlpp != NULL);
   3708 
   3709 	/* get hotspare names */
   3710 	if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) {
   3711 		cnt = -1;
   3712 		goto out;
   3713 	}
   3714 
   3715 	/* build name list */
   3716 	for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) {
   3717 		md_hsp_t	*hsp;
   3718 		int		i;
   3719 
   3720 		if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) {
   3721 			cnt = -1;
   3722 			goto out;
   3723 		}
   3724 		for (i = 0; (i < hsp->hotspares.hotspares_len); i++) {
   3725 			md_hs_t	*hs = &hsp->hotspares.hotspares_val[i];
   3726 
   3727 			(void) metanamelist_append(nlpp, hs->hsnamep);
   3728 			++cnt;
   3729 		}
   3730 	}
   3731 
   3732 	/* cleanup and return count or error */
   3733 out:
   3734 	metafreehspnamelist(hspnlp);
   3735 	if ((cnt == -1) && mdisok(ep)) {
   3736 		/*
   3737 		 * At least try to give some sort of meaningful error
   3738 		 */
   3739 		(void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error");
   3740 	}
   3741 
   3742 	return (cnt);
   3743 }
   3744 /*
   3745  * meta_create_non_dup_list
   3746  *    INPUT: mdnp mdname_t pointer to add to the list if a new name
   3747  *           ldevidp list of non-duplicate names.
   3748  *    OUTPUT: ldevidp list of non-duplicate names.
   3749  * meta_create_non_dup_list will take a mdname_t pointer and if the device
   3750  *    is not in the list (ldevidp) will add it to the list.
   3751  *    User needs to free allocated memory.
   3752  */
   3753 void
   3754 meta_create_non_dup_list(
   3755 	mdname_t	*mdnp,
   3756 	mddevid_t	**ldevidpp
   3757 )
   3758 {
   3759 	char		*lcname;
   3760 	mddevid_t	*tmp;
   3761 	mddevid_t	*lastdevidp;
   3762 	mddevid_t	*lldevidp;
   3763 	char		*ctd, *slice;
   3764 	mddevid_t	*ldevidp;
   3765 
   3766 	if (mdnp == NULL)
   3767 		return;
   3768 
   3769 	ldevidp = *ldevidpp;
   3770 	/*
   3771 	 * Grab the name of the device and strip off slice information
   3772 	 */
   3773 	lcname = Strdup(mdnp->cname);
   3774 	if (lcname == NULL) {
   3775 		return;
   3776 	}
   3777 	ctd = strrchr(lcname, '/');
   3778 	if (ctd != NULL)
   3779 		slice = strrchr(ctd, 's');
   3780 	else
   3781 		slice = strrchr(lcname, 's');
   3782 
   3783 	if (slice != NULL)
   3784 		*slice = '\0';
   3785 
   3786 	if (ldevidp == NULL) {
   3787 		/* first item in list */
   3788 		ldevidp = Zalloc(sizeof (mddevid_t));
   3789 		ldevidp->ctdname = lcname;
   3790 		ldevidp->key = mdnp->key;
   3791 		*ldevidpp = ldevidp;
   3792 	} else {
   3793 		for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) {
   3794 			if (strcmp(tmp->ctdname, lcname) == 0) {
   3795 				/* already there so just return */
   3796 				Free(lcname);
   3797 				return;
   3798 			}
   3799 			lastdevidp = tmp;
   3800 		}
   3801 		lldevidp = Zalloc(sizeof (mddevid_t));
   3802 		lldevidp->ctdname = lcname;
   3803 		lldevidp->key = mdnp->key;
   3804 		lastdevidp->next = lldevidp;
   3805 	}
   3806 }
   3807