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