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