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