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