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