xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_name.c (revision d89fccd8788afe1e920f842edd883fe192a1b8fe)
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 static 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 /*
2626  * set up names for a drive
2627  */
2628 mddrivename_t *
2629 metadrivename(
2630 	mdsetname_t		**spp,
2631 	char			*uname,
2632 	md_error_t		*ep
2633 )
2634 {
2635 	char		*slicename;
2636 	mdname_t	*np;
2637 
2638 	mddrivenamelist_t **tail;
2639 	mddrivename_t	*dnp;
2640 	char		*dname;
2641 	int		i;
2642 	int		mplen;
2643 	size_t		len;
2644 
2645 	assert(uname != NULL);
2646 
2647 	if ((dname = metadiskname(uname)) == NULL) {
2648 		(void) mdsyserror(ep, ENOENT, uname);
2649 		return (NULL);
2650 	}
2651 
2652 	/* look in cache first */
2653 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
2654 		dnp = (*tail)->drivenamep;
2655 		if ((dnp->cname != NULL &&
2656 		    (strcmp(dnp->cname, dname) == 0)) ||
2657 		    (dnp->rname != NULL &&
2658 		    (strcmp(dnp->rname, dname) == 0))) {
2659 			Free(dname);
2660 			return (dnp);
2661 		}
2662 	}
2663 	Free(dname);
2664 
2665 	/* Check each possible slice name based on MD_MAX_PARTS. */
2666 
2667 	/*
2668 	 * Figure out how much string space to reserve to fit
2669 	 * (MD_MAX_PARTS - 1) into the name string; the loop will
2670 	 * increment the mplen counter once for each decimal digit in
2671 	 * (MD_MAX_PARTS - 1).
2672 	 */
2673 	for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen);
2674 	len = strlen(uname) + mplen + 2;
2675 	slicename = Malloc(len);
2676 
2677 	/* Check for each slice in turn until we find one */
2678 	for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) {
2679 		(void) snprintf(slicename, len, "%ss%d", uname, i);
2680 		np = metaname(spp, slicename, LOGICAL_DEVICE, ep);
2681 	}
2682 	Free(slicename);
2683 
2684 	if (np == NULL) {
2685 		if ((mdiserror(ep, MDE_UNIT_NOT_FOUND)) &&
2686 		    ((dname = metadiskname(uname)) != NULL)) {
2687 			Free(dname);
2688 			(void) mderror(ep, MDE_NOT_DRIVENAME, uname);
2689 		}
2690 		return (NULL);
2691 	}
2692 	return (np->drivenamep);
2693 }
2694 
2695 /*
2696  * FUNCTION:	metaslicename_type()
2697  * INPUT:	dnp	- the drivename structure
2698  *		sliceno	- the slice on the drive to return
2699  *		type - LOGICAL_DEVICE or META_DEVICE
2700  * OUTPUT:	ep	- return error pointer
2701  * RETURNS:	mdname_t- pointer the the slice name structure
2702  * PURPOSE:	interface to the parts struct in the drive name struct
2703  *		Since there is no guarantee that the slice name
2704  *		structures are populated users should call this
2705  *		function rather than accessing the structure directly
2706  *		since it will populate the structure values if they
2707  *		haven't already been populated before returning.
2708  */
2709 mdname_t *
2710 metaslicename_type(
2711 	mddrivename_t		*dnp,
2712 	uint_t			sliceno,
2713 	meta_device_type_t	uname_type,
2714 	md_error_t		*ep
2715 )
2716 {
2717 	mdsetname_t	*sp = NULL;
2718 	char		*namep = NULL;
2719 	mdname_t	*np;
2720 
2721 	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
2722 
2723 	if (sliceno >= dnp->parts.parts_len) {
2724 		(void) mderror(ep, MDE_NOSLICE, dnp->cname);
2725 		return (NULL);
2726 	}
2727 
2728 	np = &dnp->parts.parts_val[sliceno];
2729 
2730 	/* check to see if the struct is already populated */
2731 	if (np->cname) {
2732 		return (np);
2733 	}
2734 
2735 	if ((namep = meta_name_getname(&sp, dnp->cname,
2736 					uname_type, ep)) == NULL)
2737 		return (NULL);
2738 
2739 	np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname,
2740 	    sliceno, ep);
2741 
2742 	Free(namep);
2743 
2744 	return (np);
2745 }
2746 
2747 /*
2748  * FUNCTION:	metaslicename()
2749  * INPUT:	dnp	- the drivename structure
2750  *		sliceno	- the slice on the drive to return
2751  * OUTPUT:	ep	- return error pointer
2752  * RETURNS:	mdname_t- pointer the the slice name structure
2753  * PURPOSE:	interface to the parts struct in the drive name struct
2754  *		Since there is no guarantee that the slice name
2755  *		structures are populated users should call this
2756  *		function rather than accessing the structure directly
2757  *		since it will populate the structure values if they
2758  *		haven't already been populated before returning.
2759  */
2760 mdname_t *
2761 metaslicename(
2762 	mddrivename_t	*dnp,
2763 	uint_t		sliceno,
2764 	md_error_t	*ep
2765 )
2766 {
2767 	return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep));
2768 }
2769 
2770 /*
2771  * set up metadevice name from id
2772  */
2773 mdname_t *
2774 metamnumname(
2775 	mdsetname_t	**spp,
2776 	minor_t		mnum,
2777 	int		fast,
2778 	md_error_t	*ep
2779 )
2780 {
2781 	set_t		setno = MD_MIN2SET(mnum);
2782 	mdsetname_t	*sp = NULL;
2783 	char		*uname;
2784 	mdname_t	*np;
2785 	md_dev64_t	dev;
2786 	mdkey_t		key;
2787 
2788 	/* check set first */
2789 	if (spp == NULL)
2790 		spp = &sp;
2791 	if (chksetno(spp, setno, ep) != 0)
2792 		return (NULL);
2793 	assert(*spp != NULL);
2794 	sp = *spp;
2795 
2796 	/* get corresponding device name */
2797 	dev = metamakedev(mnum);
2798 	if ((uname = meta_getnmentbydev(sp->setno, MD_SIDEWILD, dev,
2799 	    NULL, NULL, &key, ep)) == NULL)
2800 		return (NULL);
2801 
2802 	/* setup name */
2803 	if (fast) {
2804 		np = metaname_fast(spp, uname, META_DEVICE, ep);
2805 		if (np) {
2806 			np->dev = dev;
2807 			np->key = key;
2808 		}
2809 	} else
2810 		np = metaname(spp, uname, META_DEVICE, ep);
2811 
2812 	Free(uname);
2813 	return (np);
2814 }
2815 
2816 /*
2817  * return metadevice name
2818  */
2819 char *
2820 get_mdname(
2821 	mdsetname_t	*sp,
2822 	minor_t		mnum
2823 )
2824 {
2825 	mdname_t	*np;
2826 	md_error_t	status = mdnullerror;
2827 	mdsetname_t	**spp = NULL;
2828 
2829 	if (sp != NULL)
2830 		spp = &sp;
2831 
2832 	/* get name */
2833 	if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) {
2834 		return (NULL);
2835 	}
2836 	assert(meta_getminor(np->dev) == mnum);
2837 
2838 	/* return name */
2839 	return (np->cname);
2840 }
2841 
2842 /*
2843  * check for device type
2844  */
2845 int
2846 metaismeta(
2847 	mdname_t	*np
2848 )
2849 {
2850 	return (np->drivenamep->type == MDT_META ||
2851 		np->drivenamep->type == MDT_FAST_META);
2852 }
2853 
2854 int
2855 metachkmeta(
2856 	mdname_t	*np,
2857 	md_error_t	*ep
2858 )
2859 {
2860 	if (! metaismeta(np)) {
2861 		return (mddeverror(ep, MDE_NOT_META, np->dev,
2862 		    np->cname));
2863 	}
2864 	return (0);
2865 }
2866 
2867 int
2868 metachkdisk(
2869 	mdname_t	*np,
2870 	md_error_t	*ep
2871 )
2872 {
2873 	mddrivename_t	*dnp = np->drivenamep;
2874 
2875 	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
2876 
2877 	if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) {
2878 		switch (dnp->type) {
2879 		    case MDT_ACCES:
2880 		    case MDT_UNKNOWN:
2881 			    return (mdsyserror(ep, dnp->errnum, np->bname));
2882 		    default:
2883 			    assert(0);
2884 			    return (mddeverror(ep, MDE_NOT_DISK, np->dev,
2885 				np->cname));
2886 		}
2887 	}
2888 	return (0);
2889 }
2890 
2891 int
2892 metachkcomp(
2893 	mdname_t	*np,
2894 	md_error_t	*ep
2895 )
2896 {
2897 	if (metaismeta(np)) {
2898 		return (mddeverror(ep, MDE_IS_META, np->dev,
2899 		    np->cname));
2900 	}
2901 	return (metachkdisk(np, ep));
2902 }
2903 
2904 /*
2905  * free list of names
2906  */
2907 void
2908 metafreenamelist(
2909 	mdnamelist_t	*nlp
2910 )
2911 {
2912 	mdnamelist_t	*next = NULL;
2913 
2914 	for (/* void */; (nlp != NULL); nlp = next) {
2915 		next = nlp->next;
2916 		Free(nlp);
2917 	}
2918 }
2919 
2920 /*
2921  * build list of names
2922  */
2923 int
2924 metanamelist(
2925 	mdsetname_t	**spp,
2926 	mdnamelist_t	**nlpp,
2927 	int		argc,
2928 	char		*argv[],
2929 	meta_device_type_t	type,
2930 	md_error_t	*ep
2931 )
2932 {
2933 	mdnamelist_t	**tailpp = nlpp;
2934 	int		count = 0;
2935 
2936 	for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
2937 		mdnamelist_t	*nlp = Zalloc(sizeof (*nlp));
2938 
2939 		if ((nlp->namep = metaname(spp, argv[0],
2940 		    type, ep)) == NULL) {
2941 			metafreenamelist(*nlpp);
2942 			*nlpp = NULL;
2943 			return (-1);
2944 		}
2945 		*tailpp = nlp;
2946 		tailpp = &nlp->next;
2947 	}
2948 	return (count);
2949 }
2950 
2951 /*
2952  * append to end of name list
2953  */
2954 mdname_t *
2955 metanamelist_append(
2956 	mdnamelist_t	**nlpp,
2957 	mdname_t	*np
2958 )
2959 {
2960 	mdnamelist_t	*nlp;
2961 
2962 	/* run to end of list */
2963 	for (; (*nlpp != NULL); nlpp = &(*nlpp)->next)
2964 		;
2965 
2966 	/* allocate new list element */
2967 	nlp = *nlpp = Zalloc(sizeof (*nlp));
2968 
2969 	/* append name */
2970 	nlp->namep = np;
2971 	return (np);
2972 }
2973 
2974 /*
2975  * FUNCTION:	meta_namelist_append_wrapper()
2976  * INPUT:	tailpp	- pointer to the list tail pointer
2977  *		np	- name node to be appended to list
2978  * OUTPUT:	none
2979  * RETURNS:	mdnamelist_t * - new tail of the list.
2980  * PURPOSE:	wrapper to meta_namelist_append for performance.
2981  *		metanamelist_append finds the tail each time which slows
2982  *		down long lists.  By keeping track of the tail ourselves
2983  *		we can change metanamelist_append into a constant time
2984  *		operation.
2985  */
2986 mdnamelist_t **
2987 meta_namelist_append_wrapper(
2988 	mdnamelist_t	**tailpp,
2989 	mdname_t	*np
2990 )
2991 {
2992 	(void) metanamelist_append(tailpp, np);
2993 
2994 	/* If it's the first item in the list, return it instead of the next */
2995 	if ((*tailpp)->next == NULL)
2996 		return (tailpp);
2997 
2998 	return (&(*tailpp)->next);
2999 }
3000 
3001 
3002 /*
3003  *	mdhspname_t stuff
3004  */
3005 
3006 /*
3007  * initialize hspname
3008  */
3009 static void
3010 metainithspname(
3011 	mdhspname_t	*hspnamep
3012 )
3013 {
3014 	(void) memset(hspnamep, '\0', sizeof (*hspnamep));
3015 	hspnamep->hsp = MD_HSP_NONE;
3016 }
3017 
3018 /*
3019  * free allocated hspname
3020  */
3021 static void
3022 metafreehspname(
3023 	mdhspname_t	*hspnamep
3024 )
3025 {
3026 	if (hspnamep->hspname != NULL)
3027 		Free(hspnamep->hspname);
3028 	if (hspnamep->unitp != NULL)
3029 		meta_invalidate_hsp(hspnamep);
3030 	metainithspname(hspnamep);
3031 }
3032 
3033 /*
3034  * clear the hspname cache
3035  */
3036 static void
3037 metaflushhspnames()
3038 {
3039 	mdhspnamelist_t		*p, *n;
3040 
3041 	for (p = hsplistp, n = NULL; (p != NULL); p = n) {
3042 		n = p->next;
3043 		metafreehspname(p->hspnamep);
3044 		Free(p->hspnamep);
3045 		Free(p);
3046 	}
3047 	hsplistp = NULL;
3048 }
3049 
3050 /*
3051  * check set and get comparison name
3052  */
3053 static char *
3054 gethspname(
3055 	mdsetname_t	**spp,
3056 	char		*uname,
3057 	md_error_t	*ep
3058 )
3059 {
3060 	char		*cname = NULL;
3061 
3062 	cname = meta_canonicalize(*spp, uname);
3063 	/* if it is not a meta/hsp name then flag an error */
3064 	if (cname == NULL) {
3065 		(void) mdsyserror(ep, ENOENT, uname);
3066 		return (NULL);
3067 	}
3068 	return (cname);
3069 }
3070 
3071 /*
3072  * set up a hotspare pool name structure using both the name
3073  * and the self id
3074  */
3075 static mdhspname_t *
3076 metahspname_hsp(
3077 	mdsetname_t	**spp,
3078 	char		*uname,
3079 	hsp_t		hsp,
3080 	md_error_t	*ep
3081 )
3082 {
3083 	char		*cname;
3084 	mdhspnamelist_t	**tail;
3085 	mdhspname_t	*hspnp;
3086 
3087 	/* check setname */
3088 	assert(uname != NULL);
3089 	if ((cname = gethspname(spp, uname, ep)) == NULL)
3090 		return (NULL);
3091 	assert(*spp != NULL);
3092 
3093 	/* look in cache first */
3094 	for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) {
3095 		hspnp = (*tail)->hspnamep;
3096 		if (strcmp(hspnp->hspname, cname) == 0) {
3097 			Free(cname);
3098 			/* if the hsp value has not been set then set it now */
3099 			if (hspnp->hsp == MD_HSP_NONE)
3100 				hspnp->hsp = hsp;
3101 			return (hspnp);
3102 		}
3103 	}
3104 
3105 	/* if the hsp number isn't specified then attempt to get it */
3106 	if (hsp == MD_HSP_NONE && (hsp = meta_gethspnmentbyname((*spp)->setno,
3107 	    MD_SIDEWILD, cname, ep)) == MD_HSP_NONE) {
3108 		if (! mdisok(ep)) {
3109 			/*
3110 			 * If the error is ENOENT, then we will continue on,
3111 			 * because the device does not yet exist.
3112 			 * For other types of errors, however, we'll bail out.
3113 			 */
3114 			if (! mdissyserror(ep, ENOENT)) {
3115 				Free(cname);
3116 				return (NULL);
3117 			}
3118 			mdclrerror(ep);
3119 		}
3120 	}
3121 
3122 	/* allocate new list element and hspname */
3123 	*tail = Zalloc(sizeof (**tail));
3124 	hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp));
3125 	metainithspname(hspnp);
3126 
3127 	/* save hspname and number */
3128 	hspnp->hspname = cname;
3129 	hspnp->hsp = hsp;
3130 
3131 	/* success */
3132 	return (hspnp);
3133 }
3134 
3135 /*
3136  * set up names for a hotspare pool
3137  */
3138 mdhspname_t *
3139 metahspname(
3140 	mdsetname_t	**spp,
3141 	char		*uname,
3142 	md_error_t	*ep
3143 )
3144 {
3145 	return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep));
3146 }
3147 
3148 /*
3149  * set up hotspare pool name from key
3150  */
3151 mdhspname_t *
3152 metahsphspname(
3153 	mdsetname_t	**spp,
3154 	hsp_t		hsp,
3155 	md_error_t	*ep
3156 )
3157 {
3158 	set_t		setno = HSP_SET(hsp);
3159 	mdsetname_t	*sp = NULL;
3160 	char		*uname;
3161 	mdhspname_t	*hspnp;
3162 
3163 	/* check set first */
3164 	if (spp == NULL)
3165 		spp = &sp;
3166 	if (chksetno(spp, setno, ep) != 0)
3167 		return (NULL);
3168 	assert(*spp != NULL);
3169 	sp = *spp;
3170 
3171 	/* get corresponding hotspare pool name */
3172 	if ((uname = meta_gethspnmentbyid(sp->setno,
3173 			MD_SIDEWILD, hsp, ep)) == NULL)
3174 		return (NULL);
3175 
3176 	/* setup name */
3177 	hspnp = metahspname_hsp(spp, uname, hsp, ep);
3178 	Free(uname);
3179 	return (hspnp);
3180 }
3181 
3182 /*
3183  * return hotspare pool name
3184  */
3185 char *
3186 get_hspname(mdsetname_t *sp, hsp_t hsp)
3187 {
3188 	mdhspname_t	*hspnp;
3189 	md_error_t	status = mdnullerror;
3190 	mdsetname_t	**spp = NULL;
3191 
3192 	if (sp != NULL)
3193 		spp = &sp;
3194 
3195 	/* get name */
3196 	if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) {
3197 		mdclrerror(&status);
3198 		return (NULL);
3199 	}
3200 
3201 	/* return name */
3202 	return (hspnp->hspname);
3203 }
3204 
3205 /*
3206  * free hotspare pool list
3207  */
3208 void
3209 metafreehspnamelist(mdhspnamelist_t *hspnlp)
3210 {
3211 	mdhspnamelist_t	*next = NULL;
3212 
3213 	for (/* void */; (hspnlp != NULL); hspnlp = next) {
3214 		next = hspnlp->next;
3215 		Free(hspnlp);
3216 	}
3217 }
3218 
3219 /*
3220  * build list of hotspare pool names
3221  */
3222 int
3223 metahspnamelist(
3224 	mdsetname_t	**spp,
3225 	mdhspnamelist_t	**hspnlpp,
3226 	int		argc,
3227 	char		*argv[],
3228 	md_error_t	*ep
3229 )
3230 {
3231 	mdhspnamelist_t	**tailpp = hspnlpp;
3232 	int		count = 0;
3233 
3234 	for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
3235 		mdhspnamelist_t	*hspnlp = Zalloc(sizeof (*hspnlp));
3236 
3237 		if ((hspnlp->hspnamep = metahspname(spp, argv[0],
3238 		    ep)) == NULL) {
3239 			metafreehspnamelist(*hspnlpp);
3240 			*hspnlpp = NULL;
3241 			return (-1);
3242 		}
3243 		*tailpp = hspnlp;
3244 		tailpp = &hspnlp->next;
3245 	}
3246 	return (count);
3247 }
3248 
3249 /*
3250  * append to end of hotspare pool list
3251  */
3252 mdhspname_t *
3253 metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp)
3254 {
3255 	mdhspnamelist_t	*hspnlp;
3256 
3257 	/* run to end of list */
3258 	for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next)
3259 		;
3260 
3261 	/* allocate new list element */
3262 	hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp));
3263 
3264 	/* append hotspare pool name */
3265 	hspnlp->hspnamep = hspnp;
3266 	return (hspnp);
3267 }
3268 
3269 /*
3270  * get name from dev
3271  */
3272 mdname_t *
3273 metadevname(
3274 	mdsetname_t **spp,
3275 	md_dev64_t dev,
3276 	md_error_t *ep)
3277 {
3278 	char		*device_name;
3279 	mdname_t	*namep;
3280 	mdkey_t		key;
3281 
3282 	/* short circuit metadevices */
3283 	assert(dev != NODEV64);
3284 	if (meta_dev_ismeta(dev))
3285 		return (metamnumname(spp, meta_getminor(dev), 0, ep));
3286 
3287 	/* create local set, if necessary */
3288 	if (*spp == NULL) {
3289 		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
3290 			return (NULL);
3291 	}
3292 
3293 	/* get name from namespace */
3294 	if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD,
3295 	    dev, NULL, NULL, &key, ep)) == NULL) {
3296 		return (NULL);
3297 	}
3298 	namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep);
3299 	if (namep != NULL)
3300 		namep->key = key;
3301 
3302 	Free(device_name);
3303 	return (namep);
3304 }
3305 
3306 /*
3307  * return cached name from md_dev64_t
3308  */
3309 static char *
3310 metadevtocachename(md_dev64_t dev)
3311 {
3312 	mddrivenamelist_t	*dnlp;
3313 
3314 	/* look in cache */
3315 	for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) {
3316 		mddrivename_t	*dnp = dnlp->drivenamep;
3317 		uint_t		i;
3318 
3319 		for (i = 0; (i < dnp->parts.parts_len); ++i) {
3320 			mdname_t	*np = &dnp->parts.parts_val[i];
3321 
3322 			if (np->dev == dev)
3323 				return (np->cname);
3324 		}
3325 	}
3326 
3327 	/* not found */
3328 	return (NULL);
3329 }
3330 
3331 /*
3332  * Ask the driver for the name, which has been stored in the
3333  * metadevice state database (on behalf of the utilities).
3334  * (by devno)
3335  */
3336 char *
3337 get_devname(
3338 	set_t setno,
3339 	md_dev64_t dev)
3340 {
3341 	mdsetname_t	*sp;
3342 	mdname_t	*np;
3343 	md_error_t	status = mdnullerror;
3344 
3345 	/* get name */
3346 	if ((setno == MD_SET_BAD) ||
3347 	    ((sp = metasetnosetname(setno, &status)) == NULL) ||
3348 	    ((np = metadevname(&sp, dev, &status)) == NULL)) {
3349 		mdclrerror(&status);
3350 		return (metadevtocachename(dev));
3351 	}
3352 
3353 	/* return name */
3354 	return (np->cname);
3355 }
3356 
3357 /*
3358  * get name from key
3359  */
3360 mdname_t *
3361 metakeyname(
3362 	mdsetname_t	**spp,
3363 	mdkey_t		key,
3364 	int		fast,
3365 	md_error_t	*ep
3366 )
3367 {
3368 	char		*device_name;
3369 	md_dev64_t	dev = NODEV64;
3370 	mdname_t	*namep;
3371 
3372 	/* create local set, if necessary */
3373 	if (*spp == NULL) {
3374 		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
3375 			return (NULL);
3376 	}
3377 
3378 	/* get name from namespace */
3379 	if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD,
3380 	    key, NULL, NULL, &dev, ep)) == NULL) {
3381 		return (NULL);
3382 	}
3383 	if (fast)
3384 		namep = metaname_fast(spp, device_name, UNKNOWN, ep);
3385 	else
3386 		namep = metaname(spp, device_name, UNKNOWN, ep);
3387 
3388 	assert(dev != NODEV64);
3389 	if (namep)
3390 		namep->dev = dev;
3391 	Free(device_name);
3392 	return (namep);
3393 }
3394 
3395 /*
3396  * completely flush metadev/hsp caches
3397  */
3398 void
3399 metaflushmetanames()
3400 {
3401 	metaflushhspnames();
3402 	metaflushdrivenames();
3403 	metaflushfastnames();
3404 	metaflushstatcache();
3405 }
3406 
3407 /*
3408  * completely flush the caches
3409  */
3410 void
3411 metaflushnames(int flush_sr_cache)
3412 {
3413 	metaflushhspnames();
3414 	metaflushdrivenames();
3415 	metaflushsetnames();
3416 	metaflushctlrcache();
3417 	metaflushfastnames();
3418 	metaflushstatcache();
3419 	if (flush_sr_cache)
3420 		sr_cache_flush(0);
3421 }
3422 
3423 /*
3424  * meta_get_hotspare_names
3425  *  returns an mdnamelist_t of hot spare names
3426  */
3427 
3428 int
3429 meta_get_hotspare_names(
3430 	mdsetname_t	*sp,
3431 	mdnamelist_t	**nlpp,
3432 	int		options,
3433 	md_error_t	*ep
3434 )
3435 {
3436 	mdhspnamelist_t		*hspnlp	= NULL;
3437 	mdhspnamelist_t		*hspp;
3438 	int			cnt = 0;
3439 
3440 	assert(nlpp != NULL);
3441 
3442 	/* get hotspare names */
3443 	if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) {
3444 		cnt = -1;
3445 		goto out;
3446 	}
3447 
3448 	/* build name list */
3449 	for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) {
3450 		md_hsp_t	*hsp;
3451 		int		i;
3452 
3453 		if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) {
3454 			cnt = -1;
3455 			goto out;
3456 		}
3457 		for (i = 0; (i < hsp->hotspares.hotspares_len); i++) {
3458 			md_hs_t	*hs = &hsp->hotspares.hotspares_val[i];
3459 
3460 			(void) metanamelist_append(nlpp, hs->hsnamep);
3461 			++cnt;
3462 		}
3463 	}
3464 
3465 	/* cleanup and return count or error */
3466 out:
3467 	metafreehspnamelist(hspnlp);
3468 	if ((cnt == -1) && mdisok(ep)) {
3469 		/*
3470 		 * At least try to give some sort of meaningful error
3471 		 */
3472 		(void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error");
3473 	}
3474 
3475 	return (cnt);
3476 }
3477 /*
3478  * meta_create_non_dup_list
3479  *    INPUT: mdnp mdname_t pointer to add to the list if a new name
3480  *           ldevidp list of non-duplicate names.
3481  *    OUTPUT: ldevidp list of non-duplicate names.
3482  * meta_create_non_dup_list will take a mdname_t pointer and if the device
3483  *    is not in the list (ldevidp) will add it to the list.
3484  *    User needs to free allocated memory.
3485  */
3486 void
3487 meta_create_non_dup_list(
3488 	mdname_t	*mdnp,
3489 	mddevid_t	**ldevidpp
3490 )
3491 {
3492 	char		*lcname;
3493 	mddevid_t	*tmp;
3494 	mddevid_t	*lastdevidp;
3495 	mddevid_t	*lldevidp;
3496 	char		*ctd, *slice;
3497 	mddevid_t	*ldevidp;
3498 
3499 	if (mdnp == NULL)
3500 		return;
3501 
3502 	ldevidp = *ldevidpp;
3503 	/*
3504 	 * Grab the name of the device and strip off slice information
3505 	 */
3506 	lcname = Strdup(mdnp->cname);
3507 	if (lcname == NULL) {
3508 		return;
3509 	}
3510 	ctd = strrchr(lcname, '/');
3511 	if (ctd != NULL)
3512 		slice = strrchr(ctd, 's');
3513 	else
3514 		slice = strrchr(lcname, 's');
3515 
3516 	if (slice != NULL)
3517 		*slice = '\0';
3518 
3519 	if (ldevidp == NULL) {
3520 		/* first item in list */
3521 		ldevidp = Zalloc(sizeof (mddevid_t));
3522 		ldevidp->ctdname = lcname;
3523 		ldevidp->key = mdnp->key;
3524 		*ldevidpp = ldevidp;
3525 	} else {
3526 		for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) {
3527 			if (strcmp(tmp->ctdname, lcname) == 0) {
3528 				/* already there so just return */
3529 				Free(lcname);
3530 				return;
3531 			}
3532 			lastdevidp = tmp;
3533 		}
3534 		lldevidp = Zalloc(sizeof (mddevid_t));
3535 		lldevidp->ctdname = lcname;
3536 		lldevidp->key = mdnp->key;
3537 		lastdevidp->next = lldevidp;
3538 	}
3539 }
3540