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