7712 mandoc -Tlint does always exit with error code 0
[unleashed.git] / usr / src / lib / lvm / libmeta / common / meta_name.c
blob99211f2fd3b8929dfc11c78d0ee56d08b7d2c1cb
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <meta.h>
28 #include <metad.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <sys/fs/ufs_fsdir.h>
35 * Just in case we're not in a build environment, make sure that
36 * TEXT_DOMAIN gets set to something.
38 #if !defined(TEXT_DOMAIN)
39 #define TEXT_DOMAIN "SYS_TEST"
40 #endif
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.
48 #define QUOTE(x) #x
49 #define VAL2STR(x) QUOTE(x)
51 extern char *getfullblkname();
54 * caches
56 static mdsetnamelist_t *setlistp = NULL;
57 static mddrivenamelist_t *drivelistp = NULL;
58 static mdnamelist_t *fastnmlp = NULL;
59 static mdhspnamelist_t *hsplistp = NULL;
62 * Static definitions
64 static int chksetname(mdsetname_t **spp, char *sname, md_error_t *ep);
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.
74 static char *
75 meta_dsk_to_rdsk(char *str)
77 char *dp = NULL;
78 char *rdskp = NULL;
80 assert(*str == '/');
82 if ((dp = strstr(str, "/rdsk/")) != NULL)
83 return (Strdup(str));
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.
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);
101 dp++;
102 if (*dp == '\0')
103 return (NULL);
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);
110 return (rdskp);
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.
120 static char *
121 rawname(char *uname)
123 char *new_path = NULL;
124 int ret = -1;
125 struct stat statbuf;
127 if (*uname != '/')
128 return (NULL);
130 if ((new_path = meta_dsk_to_rdsk(uname)) == NULL)
131 return (NULL);
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);
141 return (new_path);
144 char *
145 blkname(
146 char *uname
149 char *p;
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);
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.
175 void
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 */
183 char setname[FILENAME_MAX+1];
184 char devname[FILENAME_MAX+1];
185 char *tname = Malloc(strlen(uname) + 1);
187 int len;
188 char *up;
189 char *tp;
190 int lcws; /* last character was slash */
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;
201 if (*up == '/') {
202 lcws = 1;
204 *tp++ = *up; /* ++ is done by for loop */
206 *tp = '\0';
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;
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))) {
227 *snamep = Strdup(setname);
228 *fnamep = Strdup(devname);
229 Free(tname);
230 return;
233 /* without setname specified */
234 *fnamep = tname;
235 if (sp != NULL && !metaislocalset(sp))
236 *snamep = Strdup(sp->setname);
237 else
238 *snamep = NULL;
242 * check for "all"
245 meta_is_all(char *s)
247 if ((strcoll(s, gettext("all")) == 0) ||
248 (strcoll(s, gettext("ALL")) == 0))
249 return (1);
250 return (0);
254 * check for "none"
257 meta_is_none(char *s)
259 if ((strcoll(s, gettext("none")) == 0) ||
260 (strcoll(s, gettext("NONE")) == 0))
261 return (1);
262 return (0);
265 static int
266 valid_name_syntax(char *uname)
268 int i;
269 int uname_len;
271 if (uname == NULL || !isalpha(uname[0]))
272 return (0);
274 uname_len = strlen(uname);
275 if (uname_len > MAXNAMLEN)
276 return (0);
278 /* 'all' and 'none' are reserved */
279 if (meta_is_all(uname) || meta_is_none(uname))
280 return (0);
282 for (i = 1; i < uname_len; i++) {
283 if ((isalnum(uname[i]) || uname[i] == '-' ||
284 uname[i] == '_' || uname[i] == '.'))
285 continue;
286 break;
289 if (i < uname_len)
290 return (0);
292 return (1);
297 * canonicalize name
299 char *
300 meta_canonicalize(
301 mdsetname_t *sp,
302 char *uname
305 char *sname = NULL;
306 char *tname = NULL;
307 char *cname;
309 /* return the dev name and set name */
310 parse_device(sp, uname, &tname, &sname);
312 if (!valid_name_syntax(tname)) {
313 Free(tname);
314 if (sname != NULL)
315 Free(sname);
316 return (NULL);
319 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
320 cname = tname;
321 else {
322 size_t cname_len;
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);
331 if (sname != NULL)
332 Free(sname);
334 return (cname);
338 * canonicalize name and check the set
340 char *
341 meta_canonicalize_check_set(
342 mdsetname_t **spp,
343 char *uname,
344 md_error_t *ep
347 char *sname = NULL;
348 char *tname = NULL;
349 char *cname;
351 /* return the dev name and set name */
352 parse_device(*spp, uname, &tname, &sname);
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);
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);
370 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
371 cname = tname;
372 else {
373 size_t cname_len;
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);
382 if (sname != NULL)
383 Free(sname);
385 return (cname);
389 * Verify that the name is a valid hsp/metadevice name
391 static int
392 parse_meta_hsp_name(char *uname)
394 char *sname = NULL;
395 char *tname = NULL;
396 int ret;
398 /* return the dev name and set name */
399 parse_device(NULL, uname, &tname, &sname);
401 ret = valid_name_syntax(tname);
402 if (sname != NULL)
403 Free(sname);
404 Free(tname);
405 return (ret);
409 * check that name is a metadevice
412 is_metaname(
413 char *uname
416 return (parse_meta_hsp_name(uname));
420 * check that name is a hotspare pool
423 is_hspname(
424 char *uname
427 return (parse_meta_hsp_name(uname));
431 * check to verify that name is an existing metadevice
434 is_existing_metadevice(
435 mdsetname_t *sp,
436 char *uname
439 char *raw_name;
440 char *set_name;
441 char *full_path;
442 char *fname = NULL;
443 int pathlen;
444 int retval = 0;
446 assert(uname != NULL);
448 * If it is an absolute name of a metadevice, then just call rawname
449 * on the input
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);
457 return (0);
460 /* create a fully specified path from the parsed string */
461 parse_device(sp, uname, &fname, &set_name);
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);
475 if ((raw_name = rawname(full_path)) != NULL) {
476 Free(raw_name);
477 retval = 1;
480 if (set_name != NULL)
481 Free(set_name);
483 Free(fname);
484 Free(full_path);
485 return (retval);
489 * check to verify that name is an existing hsp
492 is_existing_hsp(
493 mdsetname_t *sp,
494 char *uname
497 md_error_t status = mdnullerror;
498 hsp_t hsp;
499 set_t cur_set;
501 if (sp != NULL)
502 cur_set = sp->setno;
503 else
504 cur_set = 0;
506 hsp = meta_gethspnmentbyname(cur_set, MD_SIDEWILD, uname, &status);
508 if (hsp == MD_HSP_NONE) {
509 mdclrerror(&status);
510 return (0);
512 return (1);
516 * check to verify that name is an existing metadevice or hotspare pool
519 is_existing_meta_hsp(
520 mdsetname_t *sp,
521 char *uname
524 if (is_existing_metadevice(sp, uname) ||
525 is_existing_hsp(sp, uname))
526 return (1);
528 return (0);
532 * mdsetname_t stuff
536 * initialize setname
538 static void
539 metainitsetname(
540 mdsetname_t *sp
543 (void) memset(sp, '\0', sizeof (*sp));
546 static void
547 metafreesetdesc(md_set_desc *sd)
549 md_mnnode_desc *nd;
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;
559 metafreedrivedesc(&sd->sd_drvs);
560 Free(sd);
564 * free allocated setname
566 static void
567 metafreesetname(
568 mdsetname_t *sp
571 if (sp->setname != NULL)
572 Free(sp->setname);
573 if (sp->setdesc != NULL)
574 metafreesetdesc(sp->setdesc);
575 metainitsetname(sp);
579 * flush the setname cache
581 static void
582 metaflushsetnames()
584 mdsetnamelist_t *p, *n;
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);
592 setlistp = NULL;
596 * get set number
598 static int
599 getsetno(
600 char *sname,
601 set_t *setnop,
602 md_error_t *ep
605 md_set_record *sr;
606 size_t len;
608 /* local set */
609 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
610 *setnop = 0;
611 return (0);
614 /* shared set */
615 if ((sr = getsetbyname(sname, ep)) == NULL) {
616 if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) {
617 char *p;
619 len = strlen(sname) + 30;
620 p = Malloc(len);
622 (void) snprintf(p, len, "setname \"%s\"", sname);
623 (void) mderror(ep, MDE_NO_SET, p);
624 Free(p);
626 return (-1);
628 *setnop = sr->sr_setno;
629 free_sr(sr);
630 return (0);
634 * find setname from name
636 mdsetname_t *
637 metasetname(
638 char *sname,
639 md_error_t *ep
642 mdsetnamelist_t **tail;
643 set_t setno;
644 mdsetname_t *sp;
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);
655 /* setup set */
656 if (getsetno(sname, &setno, ep) != 0)
657 return (NULL);
659 /* allocate new list element and setname */
660 *tail = Zalloc(sizeof (**tail));
661 sp = (*tail)->sp = Zalloc(sizeof (*sp));
663 sp->setname = Strdup(sname);
664 sp->setno = setno;
665 sp->lockfd = MD_NO_LOCK;
667 return (sp);
671 * find setname from setno
673 mdsetname_t *
674 metasetnosetname(
675 set_t setno,
676 md_error_t *ep
679 mdsetnamelist_t *slp;
680 mdsetname_t *sp;
681 md_set_record *sr;
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);
690 /* local set */
691 if (setno == MD_LOCAL_SET)
692 return (metasetname(MD_LOCAL_NAME, ep));
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);
702 mdsetname_t *
703 metafakesetname(
704 set_t setno,
705 char *sname
708 mdsetnamelist_t **tail;
709 mdsetname_t *sp;
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);
721 /* allocate new list element and setname */
722 *tail = Zalloc(sizeof (**tail));
723 sp = (*tail)->sp = Zalloc(sizeof (*sp));
725 if (sname != NULL)
726 sp->setname = Strdup(sname);
727 sp->setno = setno;
728 sp->lockfd = MD_NO_LOCK;
730 return (sp);
735 * setup set record (sr) and cache it in the mdsetname_t struct
737 md_set_desc *
738 sr2setdesc(
739 md_set_record *sr
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;
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;
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;
768 * Get membershiplist from API routine. If there's
769 * an error, just use a NULL nodelist.
771 if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
772 nodecnt = 0; /* no nodes are alive */
773 nl = NULL;
775 nr = mnsr->sr_nodechain;
776 nrcnt = 0;
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.
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;
790 nd->nd_ctime = nr->nr_ctime;
791 nd->nd_genid = nr->nr_genid;
792 nd->nd_flags = nr->nr_flags;
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;
800 if (nd->nd_nodeid == sd->sd_mn_master_nodeid) {
801 sd->sd_mn_masternode = nd;
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.
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;
823 nl2 = nl2->next;
827 nr = nr->nr_next;
828 nrcnt++;
829 nd_prev = nd;
831 sd->sd_mn_numnodes = nrcnt;
832 if (nodecnt)
833 meta_free_nodelist(nl);
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]));
844 sd->sd_med = sr->sr_med; /* structure assignment */
846 return (sd);
849 md_set_desc *
850 metaget_setdesc(
851 mdsetname_t *sp,
852 md_error_t *ep
855 md_set_record *sr;
857 if (sp->setdesc != NULL)
858 return (sp->setdesc);
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);
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);
876 return (NULL);
879 void
880 metaflushsetname(mdsetname_t *sp)
882 if (sp == NULL)
883 return;
885 if (sp->setdesc == NULL)
886 return;
888 metafreesetdesc(sp->setdesc);
889 sp->setdesc = NULL;
893 * check for local set
896 metaislocalset(
897 mdsetname_t *sp
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);
911 * check for same set
914 metaissameset(
915 mdsetname_t *sp1,
916 mdsetname_t *sp2
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);
929 * check to see if set changed
931 static int
932 chkset(
933 mdsetname_t **spp,
934 char *sname,
935 md_error_t *ep
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));
944 return (0);
947 /* otherwise store new set name and number */
948 if ((*spp = metasetname(sname, ep)) == NULL) {
949 return (-1);
952 /* return success */
953 return (0);
957 * check to see if set changed from default
959 static int
960 chksetname(
961 mdsetname_t **spp,
962 char *sname,
963 md_error_t *ep
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;
975 /* see if changed */
976 return (chkset(spp, sname, ep));
980 * check setname from setno
982 static int
983 chksetno(
984 mdsetname_t **spp,
985 set_t setno,
986 md_error_t *ep
989 md_set_record *sr;
990 int rval;
992 /* local set */
993 if (setno == 0)
994 return (chkset(spp, MD_LOCAL_NAME, ep));
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);
1005 * mddrivename_t stuff
1009 * initialize name
1011 static void
1012 metainitname(
1013 mdname_t *np
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;
1024 * free allocated name
1026 static void
1027 metafreename(
1028 mdname_t *np
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);
1043 * initialize drive name
1045 static void
1046 metainitdrivename(
1047 mddrivename_t *dnp
1050 (void) memset(dnp, 0, sizeof (*dnp));
1051 dnp->side_names_key = MD_KEYBAD;
1055 * flush side names
1057 void
1058 metaflushsidenames(
1059 mddrivename_t *dnp
1062 mdsidenames_t *p, *n;
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);
1072 dnp->side_names = NULL;
1076 * free drive name
1078 void
1079 metafreedrivename(
1080 mddrivename_t *dnp
1083 uint_t slice;
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);
1102 * flush the drive name cache
1104 void
1105 metaflushdrivenames()
1107 mddrivenamelist_t *p, *n;
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);
1115 drivelistp = NULL;
1119 * peel off s%u from name
1121 char *
1122 metadiskname(
1123 char *name
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);
1133 * Handle old style names, which are of the form /dev/rXXNN[a-h].
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));
1142 * Handle old style names, which are of the form /dev/XXNN[a-h].
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));
1150 /* gobble number and 's' */
1151 p = e = name + strlen(name) - 1;
1152 for (; (p > name); --p) {
1153 if (!isdigit(*p))
1154 break;
1156 if ((p == e) || (p <= name))
1157 return (Strdup(name));
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--;
1165 if ((p <= name) || (!isdigit(*p)))
1166 return (Strdup(name));
1168 *(++p) = '\0';
1169 e = Strdup(name);
1170 *p = 's';
1172 return (e);
1176 * free list of drivenames
1178 void
1179 metafreedrivenamelist(
1180 mddrivenamelist_t *dnlp
1183 mddrivenamelist_t *next = NULL;
1185 for (/* void */; (dnlp != NULL); dnlp = next) {
1186 next = dnlp->next;
1187 Free(dnlp);
1192 * build list of drivenames
1195 metadrivenamelist(
1196 mdsetname_t **spp,
1197 mddrivenamelist_t **dnlpp,
1198 int argc,
1199 char *argv[],
1200 md_error_t *ep
1203 mddrivenamelist_t **tailpp = dnlpp;
1204 int count = 0;
1206 for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
1207 mddrivenamelist_t *dnlp = Zalloc(sizeof (*dnlp));
1209 if ((dnlp->drivenamep = metadrivename(spp, argv[0],
1210 ep)) == NULL) {
1211 metafreedrivenamelist(*dnlpp);
1212 *dnlpp = NULL;
1213 return (-1);
1215 *tailpp = dnlp;
1216 tailpp = &dnlp->next;
1218 return (count);
1222 * append to end of drivename list
1224 mddrivename_t *
1225 metadrivenamelist_append(
1226 mddrivenamelist_t **dnlpp,
1227 mddrivename_t *dnp
1230 mddrivenamelist_t *dnlp;
1232 /* run to end of list */
1233 for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next)
1236 /* allocate new list element */
1237 dnlp = *dnlpp = Zalloc(sizeof (*dnlp));
1239 /* append drivename */
1240 dnlp->drivenamep = dnp;
1241 return (dnp);
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.
1256 mddrivenamelist_t **
1257 meta_drivenamelist_append_wrapper(
1258 mddrivenamelist_t **tailpp,
1259 mddrivename_t *dnp
1262 (void) metadrivenamelist_append(tailpp, dnp);
1264 /* If it's the first item in the list, return it instead of the next */
1265 if ((*tailpp)->next == NULL)
1266 return (tailpp);
1268 return (&(*tailpp)->next);
1273 * mdname_t stuff
1277 * check set and get comparison name
1279 * NOTE: This function has a side effect of setting *spp if the setname
1280 * has been specified and *spp is not already set.
1282 char *
1283 meta_name_getname(
1284 mdsetname_t **spp,
1285 char *uname,
1286 meta_device_type_t uname_type,
1287 md_error_t *ep
1290 if (uname_type == META_DEVICE || uname_type == HSP_DEVICE ||
1291 (uname_type == UNKNOWN && is_existing_metadevice(*spp, uname))) {
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
1298 return (meta_canonicalize_check_set(spp, uname, ep));
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);
1305 /* if it is not a meta/hsp name then just return uname */
1306 return (Strdup(uname));
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.
1325 static char *
1326 getrname(mdsetname_t **spp, char *uname,
1327 meta_device_type_t *type, md_error_t *ep)
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;
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) {
1341 * If the returned rname does not match with
1342 * the specified uname type, we'll return null.
1344 if (strncmp(rname, "/dev/md", strlen("/dev/md")) == 0) {
1345 if (*type == LOGICAL_DEVICE) {
1346 (void) mdsyserror(ep, ENOENT, uname);
1347 return (NULL);
1349 *type = META_DEVICE;
1350 } else {
1351 if (*type == META_DEVICE) {
1352 (void) mdsyserror(ep, ENOENT, uname);
1353 return (NULL);
1355 *type = LOGICAL_DEVICE;
1357 return (rname);
1360 /* out of luck */
1361 (void) mdsyserror(ep, ENOENT, uname);
1362 return (NULL);
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.
1372 * Check for metadevice before physical device.
1373 * With the introduction of softpartitions it is more
1374 * likely to be a metadevice.
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;
1388 if ((p = strchr(uname, '/')) != NULL) {
1389 ++p;
1390 } else {
1391 p = uname;
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);
1399 rname = rawname(fname);
1401 if (*type == META_DEVICE) {
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.
1411 if (rname == NULL) {
1412 rname = Strdup(fname);
1415 Free(fname);
1416 return (rname);
1419 Free(fname);
1420 if ((rname != NULL) && (*type == UNKNOWN)) {
1421 /* Save this result */
1422 rname_list[rname_cnt] = rname;
1423 rname_cnt ++;
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);
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 ++;
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.
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.
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.
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;
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;
1479 if (rname_cnt == 1) {
1480 rname = Strdup(rname_list[0]);
1481 *type = tmp_type;
1482 } else {
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.
1488 if (strcmp(rname_list[0], rname_list[1]) != 0) {
1489 (void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
1490 if (rname_cnt != 3) {
1492 * For the rname_cnt == 3 case, the
1493 * error was printed above.
1495 (void) printf(dgettext(TEXT_DOMAIN,
1496 "Error: ambiguous device "
1497 "name.\n%s %s\n\n"),
1498 rname_list[0], rname_list[1]);
1500 rname = NULL;
1501 } else {
1502 rname = Strdup(rname_list[0]);
1503 *type = tmp_type;
1506 for (i = 0; i < rname_cnt; i++)
1507 Free(rname_list[i]);
1508 return (rname);
1513 * get raw slice and drive names
1515 static char *
1516 getrawnames(
1517 mdsetname_t **spp,
1518 char *uname,
1519 char **dnamep,
1520 meta_device_type_t *uname_type,
1521 md_error_t *ep
1524 char *rname = NULL;
1525 size_t len;
1528 * Incorrect code path if type is HSP_DEVICE
1530 assert(*uname_type != HSP_DEVICE);
1532 /* initialize */
1533 *dnamep = NULL;
1535 /* get slice name */
1536 if ((rname = getrname(spp, uname, uname_type, ep)) != NULL) {
1537 *dnamep = metadiskname(rname);
1538 return (rname);
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.
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];
1556 * Handle old style raw names
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);
1570 * Handle old style block names
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);
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);
1592 } else {
1594 * If it's not an absolute name but is a valid ctd name,
1595 * guess at /dev/rdsk/...
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);
1610 /* out of luck */
1611 if (!mdiserror(ep, MDE_AMBIGUOUS_DEV))
1612 (void) mderror(ep, MDE_UNIT_NOT_FOUND, uname);
1613 return (NULL);
1617 * get number of slices for name
1619 static int
1620 getnslice(
1621 char *rname,
1622 char *dname,
1623 uint_t *slicep
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;
1634 * get our slice number - works only with names that end in s%u -
1635 * all others return -1.
1637 if (dl >= rl ||
1638 sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl ||
1639 (int)*slicep < 0) {
1640 return (-1);
1644 * go find how many slices there really are
1646 len = strlen(dname) + 20 + 1;
1647 srname = Malloc(len);
1648 for (nslice = 0; /* void */; ++nslice) {
1649 struct stat statbuf;
1651 /* build slice name */
1652 (void) snprintf(srname, len, "%ss%u", dname, nslice);
1654 /* see if it's there */
1655 if ((meta_stat(srname, &statbuf) != 0) ||
1656 (! S_ISCHR(statbuf.st_mode))) {
1657 break;
1660 Free(srname);
1662 /* Need to make sure that we at least have V_NUMPAR */
1663 nslice = max(nslice, V_NUMPAR);
1665 /* make sure we have at least our slice */
1666 if (nslice < *slicep)
1667 return (-1);
1669 /* return number of slices */
1670 return (nslice);
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).
1679 * if successful return 0
1680 * if c[t]dp name return 1
1681 * otherwise return -1
1684 parse_ctd(
1685 char *uname,
1686 uint_t *slice)
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;
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;
1709 partial_ctd_str = uname + l;
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);
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);
1731 Free(target_str);
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);
1743 return (-1);
1746 return (0);
1751 * get number of slices for name
1753 static int
1754 uname2sliceno(
1755 char *uname,
1756 meta_device_type_t uname_type,
1757 uint_t *slicep,
1758 md_error_t *ep
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;
1769 if (uname_type == META_DEVICE)
1770 return (*slicep = 0);
1772 if ((p = strrchr(uname, '/')) != NULL)
1773 p++;
1774 else
1775 p = uname;
1777 cl = strlen(p);
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);
1788 * If we can't get the slice from the name, then we have to do it the
1789 * hard and expensive way.
1791 if ((rname = rawname(uname)) == NULL)
1792 return (-1);
1794 /* get controller info */
1795 if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
1796 Free(rname);
1797 return (-1);
1800 if (ioctl(fd, DKIOCINFO, &cinfo) != 0) {
1801 int save = errno;
1803 if (save == ENOTTY)
1804 (void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname);
1805 else
1806 (void) mdsyserror(ep, save, rname);
1808 Free(rname);
1809 (void) close(fd);
1810 return (-1);
1812 (void) close(fd); /* sd/ssd bug */
1814 if (cinfo.dki_partition < V_NUMPAR) {
1815 Free(rname);
1816 return (*slicep = cinfo.dki_partition);
1819 return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname));
1823 * get partition info
1825 static int
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
1836 int nparts;
1837 uint_t partno;
1838 mdname_t name;
1839 mdvtoc_t *vtocp;
1841 /* metadevice */
1842 if (uname_type == META_DEVICE) {
1843 dnp->type = MDT_META;
1844 nparts = 1;
1845 partno = 0;
1846 goto gotit;
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;
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);
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;
1875 mdclrerror(ep);
1876 /* nparts already setup */
1877 /* partno already setup */
1878 /* dname already setup */
1879 nparts = roundup(nparts, V_NUMPAR);
1880 goto gotit;
1883 /* nothing worked */
1884 dnp->type = MDT_UNKNOWN;
1885 if (mdissyserror(ep, EACCES))
1886 dnp->type = MDT_ACCES;
1888 if (mdanysyserror(ep)) {
1889 dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum;
1890 } else {
1891 dnp->errnum = ENOENT;
1894 mdclrerror(ep);
1895 nparts = V_NUMPAR;
1896 if (uname2sliceno(rname, uname_type, &partno, ep) < 0) {
1897 mdclrerror(ep);
1898 partno = 0;
1901 /* return success */
1902 gotit:
1903 assert(nparts > 0);
1905 if (partno >= nparts)
1906 return (mdsyserror(ep, ENOENT, rname));
1908 *npartsp = nparts;
1909 *partnop = partno;
1910 return (0);
1914 * get block name
1916 static int
1917 getbname(
1918 mdname_t *np,
1919 md_error_t *ep
1922 char *rname = np->rname;
1923 char *bname;
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);
1934 /* out of luck */
1935 return (mdsyserror(ep, ENOENT, rname));
1938 static void
1939 getcname(
1940 mdsetname_t *sp,
1941 mdname_t *np
1944 char *sname = sp->setname;
1945 char *bname = np->bname;
1946 char *p;
1947 size_t len;
1949 assert(sname != NULL);
1950 assert(bname != NULL);
1951 assert(np->drivenamep->type != MDT_FAST_COMP &&
1952 np->drivenamep->type != MDT_FAST_META);
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;
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;
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;
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;
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);
2006 * get dev
2009 meta_getdev(
2010 mdsetname_t *sp,
2011 mdname_t *np,
2012 md_error_t *ep
2015 struct stat statbuf;
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);
2024 assert(np->drivenamep->type != MDT_FAST_META &&
2025 np->drivenamep->type != MDT_FAST_COMP);
2027 /* check set */
2028 assert((np->drivenamep->type == MDT_META) ?
2029 (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1);
2031 /* return sucess */
2032 return (0);
2036 * set up names for a slice
2038 static int
2039 getnames(
2040 mdsetname_t *sp,
2041 mdname_t *np,
2042 char *rname,
2043 md_error_t *ep
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);
2056 /* return success */
2057 return (0);
2061 * fake up names for a slice
2063 static void
2064 getfakenames(
2065 mdsetname_t *sp,
2066 mdname_t *np,
2067 char *rname
2070 char *p;
2071 char onmb[BUFSIZ+1], snm[BUFSIZ+1];
2072 uint_t d = 0;
2073 int l = 0;
2075 /* fake names */
2076 if (np->rname != NULL)
2077 Free(np->rname);
2078 np->rname = Strdup(rname);
2080 if (np->bname != NULL)
2081 Free(np->bname);
2082 np->bname = Strdup(rname);
2085 * Fixup old style names
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);
2093 * Fixup new style names
2095 if ((p = strstr(np->bname, "/rdsk/")) != NULL) {
2096 for (++p; (*(p + 1) != '\0'); ++p)
2097 *p = *(p + 1);
2098 *p = '\0';
2101 if (np->cname != NULL)
2102 Free(np->cname);
2103 getcname(sp, np);
2106 static mdname_t *
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
2118 char *srname = NULL;
2119 mdname_t *np;
2121 /* must have a set */
2122 assert(sp != NULL);
2123 assert(partno < dnp->parts.parts_len);
2124 assert(dname != NULL);
2126 np = &dnp->parts.parts_val[partno];
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;
2138 len = cl + 20 + 1;
2139 srname = Malloc(len);
2142 * Handle /dev/rXXNN.
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);
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;
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;
2181 out:
2182 if ((srname != rname) && (srname != dname))
2183 Free(srname);
2185 /* return name */
2186 return (np);
2188 fixup:
2189 if (mdanysyserror(ep)) {
2190 char *p;
2191 int errnum = ep->info.md_error_info_t_u.sys_error.errnum;
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);
2206 goto out;
2210 * flush the fast name cache
2212 static void
2213 metafreefastnm(mdname_t **np)
2215 mddrivename_t *dnp;
2217 assert(np != NULL && *np != NULL);
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);
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;
2242 * flush the fast name cache
2244 static void
2245 metaflushfastnames()
2247 mdnamelist_t *p, *n;
2249 for (p = fastnmlp, n = NULL; (p != NULL); p = n) {
2250 n = p->next;
2251 metafreefastnm(&p->namep);
2252 Free(p);
2254 fastnmlp = NULL;
2257 static char *
2258 getrname_fast(char *unm, meta_device_type_t uname_type, md_error_t *ep)
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;
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);
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))) {
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);
2294 /* Fully qualified path - error */
2295 if (unm[0] == '/') {
2296 (void) mdsyserror(ep, EINVAL, unm);
2297 return (NULL);
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);
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);
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);
2324 /* NOT Fully qualified path, done */
2325 if (unm[0] != '/') {
2326 (void) mdsyserror(ep, EINVAL, unm);
2327 return (NULL);
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.
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));
2348 /* /.../dsk/... or /.../rdsk/... */
2349 if ((rnm = meta_dsk_to_rdsk(unm)) != NULL)
2350 return (rnm);
2353 * Shouldn't get here but if we do then we have an unrecognized
2354 * fully qualified path - error
2356 (void) mdsyserror(ep, EINVAL, unm);
2357 return (NULL);
2360 static mdname_t *
2361 metainitfastname(
2362 mdsetname_t *sp,
2363 char *uname,
2364 meta_device_type_t uname_type,
2365 md_error_t *ep
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;
2375 for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) {
2376 np = (*fnlpp)->namep;
2378 if (strcmp(np->bname, uname) == 0)
2379 return (np);
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);
2389 /* Metadevices */
2390 if (uname_type == META_DEVICE &&
2391 (cname = meta_canonicalize(sp, uname)) != NULL) {
2393 np->cname = cname;
2394 dnp->type = MDT_FAST_META;
2395 goto done;
2398 /* Others */
2399 dnp->type = MDT_FAST_COMP;
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);
2430 done:
2431 /* Driver always gives us block names */
2432 np->bname = Strdup(uname);
2434 /* canonical disk name */
2435 if ((dnp->cname = metadiskname(np->cname)) == NULL)
2436 dnp->cname = Strdup(np->cname);
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);
2448 /* cleanup, return success */
2449 return (np);
2453 * set up names for a device
2455 static mdname_t *
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
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;
2473 assert(uname != NULL);
2475 /* check setname */
2476 if ((cname = meta_name_getname(spp, uname, uname_type, ep)) == NULL)
2477 return (NULL);
2479 assert(*spp != NULL);
2480 Free(cname);
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);
2488 assert(uname_type != UNKNOWN);
2490 /* look in cache first */
2491 for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
2492 dnp = (*tail)->drivenamep;
2494 /* check to see if the drive name is already in the cache */
2495 if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) {
2497 Free(rname);
2498 if (dname != NULL)
2499 Free(dname);
2501 if (uname2sliceno(uname, uname_type, &partno, ep) < 0)
2502 return (NULL);
2504 return (metaslicename(dnp, partno, ep));
2509 * If a fast names is OK, then get one, and be done.
2511 if (fast) {
2512 Free(rname);
2513 if (dname != NULL)
2514 Free(dname);
2516 return (metainitfastname(*spp, uname, uname_type, ep));
2519 /* allocate new list element and drive */
2520 *tail = Zalloc(sizeof (**tail));
2521 dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
2523 metainitdrivename(dnp);
2525 /* get parts info */
2526 if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
2527 goto out;
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
2534 if (nparts < V_NUMPAR) {
2535 nparts = V_NUMPAR;
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;
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;
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);
2559 /* cleanup, return success */
2560 if (dname != NULL)
2561 Free(dname);
2562 Free(rname);
2563 return (np);
2565 /* cleanup, return error */
2566 out:
2567 if (dname != NULL)
2568 Free(dname);
2569 if (rname != NULL)
2570 Free(rname);
2572 metafreedrivename(dnp);
2573 Free(dnp);
2574 Free(*tail);
2575 *tail = NULL;
2576 return (NULL);
2580 * metaname()
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.
2587 mdname_t *
2588 metaname(
2589 mdsetname_t **spp,
2590 char *uname,
2591 meta_device_type_t uname_type,
2592 md_error_t *ep
2595 return (metaname_common(spp, uname, 0, uname_type, ep));
2598 mdname_t *
2599 metaname_fast(
2600 mdsetname_t **spp,
2601 char *uname,
2602 meta_device_type_t uname_type,
2603 md_error_t *ep
2606 return (metaname_common(spp, uname, 1, uname_type, ep));
2609 * Get the dnp using the device id.
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.
2641 mddrivename_t *
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
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;
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);
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);
2679 devid_free(dnp_devidp);
2682 /* drive not in the cache */
2684 if ((sd = metaget_setdesc(sp, ep)) == NULL) {
2685 return (NULL);
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);
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);
2703 /* allocate new list element and drive */
2704 *tail = Zalloc(sizeof (**tail));
2705 dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
2706 metainitdrivename(dnp);
2708 /* get parts info */
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.
2716 if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
2717 goto out;
2719 dnp->devid = devid_str_encode(devidp, NULL);
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
2726 if (nparts < V_NUMPAR) {
2727 nparts = V_NUMPAR;
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);
2735 for (slice = 0; (slice < nparts); ++slice) {
2736 np = &dnp->parts.parts_val[slice];
2737 metainitname(np);
2738 np->drivenamep = dnp;
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;
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);
2752 if (dname != NULL)
2753 Free(dname);
2754 Free(rname);
2755 return (dnp);
2757 out:
2758 if (dname != NULL)
2759 Free(dname);
2761 if (rname != NULL)
2762 Free(rname);
2764 metafreedrivename(dnp);
2765 Free(dnp);
2766 Free(*tail);
2767 *tail = NULL;
2768 return (NULL);
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.
2775 mddrivename_t *
2776 metadrivenamebydevid(
2777 mdsetname_t **spp,
2778 char *devid,
2779 char *uname,
2780 md_error_t *ep
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;
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;
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);
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);
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);
2821 devid_free(dnp_devidp);
2822 devid_free(in_devidp);
2824 /* not in the cache */
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);
2832 /* allocate new list element and drive */
2833 *tail = Zalloc(sizeof (**tail));
2834 dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
2836 metainitdrivename(dnp);
2838 /* get parts info */
2839 if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
2840 goto out;
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
2847 if (nparts < V_NUMPAR) {
2848 nparts = V_NUMPAR;
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;
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;
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);
2872 /* cleanup, return success */
2873 if (dname != NULL)
2874 Free(dname);
2875 Free(rname);
2876 return (dnp);
2878 /* cleanup, return error */
2879 out:
2880 if (dname != NULL)
2881 Free(dname);
2882 if (rname != NULL)
2883 Free(rname);
2885 metafreedrivename(dnp);
2886 Free(dnp);
2887 Free(*tail);
2888 *tail = NULL;
2889 return (NULL);
2892 * set up names for a drive
2894 mddrivename_t *
2895 metadrivename(
2896 mdsetname_t **spp,
2897 char *uname,
2898 md_error_t *ep
2901 char *slicename;
2902 mdname_t *np;
2904 mddrivenamelist_t **tail;
2905 mddrivename_t *dnp;
2906 char *dname;
2907 int i;
2908 int mplen;
2909 size_t len;
2911 assert(uname != NULL);
2913 if ((dname = metadiskname(uname)) == NULL) {
2914 (void) mdsyserror(ep, ENOENT, uname);
2915 return (NULL);
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);
2929 Free(dname);
2931 /* Check each possible slice name based on MD_MAX_PARTS. */
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).
2939 for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen)
2941 len = strlen(uname) + mplen + 2;
2942 slicename = Malloc(len);
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);
2949 Free(slicename);
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);
2957 return (NULL);
2959 return (np->drivenamep);
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.
2976 mdname_t *
2977 metaslicename_type(
2978 mddrivename_t *dnp,
2979 uint_t sliceno,
2980 meta_device_type_t uname_type,
2981 md_error_t *ep
2984 mdsetname_t *sp = NULL;
2985 char *namep = NULL;
2986 mdname_t *np;
2988 assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
2990 if (sliceno >= dnp->parts.parts_len) {
2991 (void) mderror(ep, MDE_NOSLICE, dnp->cname);
2992 return (NULL);
2995 np = &dnp->parts.parts_val[sliceno];
2997 /* check to see if the struct is already populated */
2998 if (np->cname) {
2999 return (np);
3002 if ((namep = meta_name_getname(&sp, dnp->cname,
3003 uname_type, ep)) == NULL)
3004 return (NULL);
3006 np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname,
3007 sliceno, ep);
3009 Free(namep);
3011 return (np);
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.
3027 mdname_t *
3028 metaslicename(
3029 mddrivename_t *dnp,
3030 uint_t sliceno,
3031 md_error_t *ep
3034 return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep));
3038 * set up metadevice name from id
3040 mdname_t *
3041 metamnumname(
3042 mdsetname_t **spp,
3043 minor_t mnum,
3044 int fast,
3045 md_error_t *ep
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;
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;
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);
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;
3076 } else
3077 np = metaname(spp, uname, META_DEVICE, ep);
3079 Free(uname);
3080 return (np);
3084 * return metadevice name
3086 char *
3087 get_mdname(
3088 mdsetname_t *sp,
3089 minor_t mnum
3092 mdname_t *np;
3093 md_error_t status = mdnullerror;
3094 mdsetname_t **spp = NULL;
3096 if (sp != NULL)
3097 spp = &sp;
3099 /* get name */
3100 if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) {
3101 return (NULL);
3103 assert(meta_getminor(np->dev) == mnum);
3105 /* return name */
3106 return (np->cname);
3110 * check for device type
3113 metaismeta(
3114 mdname_t *np
3117 return (np->drivenamep->type == MDT_META ||
3118 np->drivenamep->type == MDT_FAST_META);
3122 metachkmeta(
3123 mdname_t *np,
3124 md_error_t *ep
3127 if (! metaismeta(np)) {
3128 return (mddeverror(ep, MDE_NOT_META, np->dev,
3129 np->cname));
3131 return (0);
3135 metachkdisk(
3136 mdname_t *np,
3137 md_error_t *ep
3140 mddrivename_t *dnp = np->drivenamep;
3142 assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
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));
3155 return (0);
3159 metachkcomp(
3160 mdname_t *np,
3161 md_error_t *ep
3164 if (metaismeta(np)) {
3165 return (mddeverror(ep, MDE_IS_META, np->dev,
3166 np->cname));
3168 return (metachkdisk(np, ep));
3172 * free list of names
3174 void
3175 metafreenamelist(
3176 mdnamelist_t *nlp
3179 mdnamelist_t *next = NULL;
3181 for (/* void */; (nlp != NULL); nlp = next) {
3182 next = nlp->next;
3183 Free(nlp);
3188 * build list of names
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
3200 mdnamelist_t **tailpp = nlpp;
3201 int count = 0;
3203 for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
3204 mdnamelist_t *nlp = Zalloc(sizeof (*nlp));
3206 if ((nlp->namep = metaname(spp, argv[0],
3207 type, ep)) == NULL) {
3208 metafreenamelist(*nlpp);
3209 *nlpp = NULL;
3210 return (-1);
3212 *tailpp = nlp;
3213 tailpp = &nlp->next;
3215 return (count);
3219 * append to end of name list
3221 mdname_t *
3222 metanamelist_append(
3223 mdnamelist_t **nlpp,
3224 mdname_t *np
3227 mdnamelist_t *nlp;
3229 /* run to end of list */
3230 for (; (*nlpp != NULL); nlpp = &(*nlpp)->next)
3233 /* allocate new list element */
3234 nlp = *nlpp = Zalloc(sizeof (*nlp));
3236 /* append name */
3237 nlp->namep = np;
3238 return (np);
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.
3253 mdnamelist_t **
3254 meta_namelist_append_wrapper(
3255 mdnamelist_t **tailpp,
3256 mdname_t *np
3259 (void) metanamelist_append(tailpp, np);
3261 /* If it's the first item in the list, return it instead of the next */
3262 if ((*tailpp)->next == NULL)
3263 return (tailpp);
3265 return (&(*tailpp)->next);
3270 * mdhspname_t stuff
3274 * initialize hspname
3276 static void
3277 metainithspname(
3278 mdhspname_t *hspnamep
3281 (void) memset(hspnamep, '\0', sizeof (*hspnamep));
3282 hspnamep->hsp = MD_HSP_NONE;
3286 * free allocated hspname
3288 static void
3289 metafreehspname(
3290 mdhspname_t *hspnamep
3293 if (hspnamep->hspname != NULL)
3294 Free(hspnamep->hspname);
3295 if (hspnamep->unitp != NULL)
3296 meta_invalidate_hsp(hspnamep);
3297 metainithspname(hspnamep);
3301 * clear the hspname cache
3303 static void
3304 metaflushhspnames()
3306 mdhspnamelist_t *p, *n;
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);
3314 hsplistp = NULL;
3318 * check set and get comparison name
3320 static char *
3321 gethspname(
3322 mdsetname_t **spp,
3323 char *uname,
3324 md_error_t *ep
3327 char *cname = NULL;
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);
3335 return (cname);
3339 * set up a hotspare pool name structure using both the name
3340 * and the self id
3342 static mdhspname_t *
3343 metahspname_hsp(
3344 mdsetname_t **spp,
3345 char *uname,
3346 hsp_t hsp,
3347 md_error_t *ep
3350 char *cname;
3351 mdhspnamelist_t **tail;
3352 mdhspname_t *hspnp;
3354 /* check setname */
3355 assert(uname != NULL);
3356 if ((cname = gethspname(spp, uname, ep)) == NULL)
3357 return (NULL);
3358 assert(*spp != NULL);
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);
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)) {
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.
3381 if (! mdissyserror(ep, ENOENT)) {
3382 Free(cname);
3383 return (NULL);
3385 mdclrerror(ep);
3389 /* allocate new list element and hspname */
3390 *tail = Zalloc(sizeof (**tail));
3391 hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp));
3392 metainithspname(hspnp);
3394 /* save hspname and number */
3395 hspnp->hspname = cname;
3396 hspnp->hsp = hsp;
3398 /* success */
3399 return (hspnp);
3403 * set up names for a hotspare pool
3405 mdhspname_t *
3406 metahspname(
3407 mdsetname_t **spp,
3408 char *uname,
3409 md_error_t *ep
3412 return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep));
3416 * set up hotspare pool name from key
3418 mdhspname_t *
3419 metahsphspname(
3420 mdsetname_t **spp,
3421 hsp_t hsp,
3422 md_error_t *ep
3425 set_t setno = HSP_SET(hsp);
3426 mdsetname_t *sp = NULL;
3427 char *uname;
3428 mdhspname_t *hspnp;
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;
3438 /* get corresponding hotspare pool name */
3439 if ((uname = meta_gethspnmentbyid(sp->setno,
3440 MD_SIDEWILD, hsp, ep)) == NULL)
3441 return (NULL);
3443 /* setup name */
3444 hspnp = metahspname_hsp(spp, uname, hsp, ep);
3445 Free(uname);
3446 return (hspnp);
3450 * return hotspare pool name
3452 char *
3453 get_hspname(mdsetname_t *sp, hsp_t hsp)
3455 mdhspname_t *hspnp;
3456 md_error_t status = mdnullerror;
3457 mdsetname_t **spp = NULL;
3459 if (sp != NULL)
3460 spp = &sp;
3462 /* get name */
3463 if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) {
3464 mdclrerror(&status);
3465 return (NULL);
3468 /* return name */
3469 return (hspnp->hspname);
3473 * free hotspare pool list
3475 void
3476 metafreehspnamelist(mdhspnamelist_t *hspnlp)
3478 mdhspnamelist_t *next = NULL;
3480 for (/* void */; (hspnlp != NULL); hspnlp = next) {
3481 next = hspnlp->next;
3482 Free(hspnlp);
3487 * build list of hotspare pool names
3490 metahspnamelist(
3491 mdsetname_t **spp,
3492 mdhspnamelist_t **hspnlpp,
3493 int argc,
3494 char *argv[],
3495 md_error_t *ep
3498 mdhspnamelist_t **tailpp = hspnlpp;
3499 int count = 0;
3501 for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
3502 mdhspnamelist_t *hspnlp = Zalloc(sizeof (*hspnlp));
3504 if ((hspnlp->hspnamep = metahspname(spp, argv[0],
3505 ep)) == NULL) {
3506 metafreehspnamelist(*hspnlpp);
3507 *hspnlpp = NULL;
3508 return (-1);
3510 *tailpp = hspnlp;
3511 tailpp = &hspnlp->next;
3513 return (count);
3517 * append to end of hotspare pool list
3519 mdhspname_t *
3520 metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp)
3522 mdhspnamelist_t *hspnlp;
3524 /* run to end of list */
3525 for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next)
3528 /* allocate new list element */
3529 hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp));
3531 /* append hotspare pool name */
3532 hspnlp->hspnamep = hspnp;
3533 return (hspnp);
3537 * get name from dev
3539 mdname_t *
3540 metadevname(
3541 mdsetname_t **spp,
3542 md_dev64_t dev,
3543 md_error_t *ep)
3545 char *device_name;
3546 mdname_t *namep;
3547 mdkey_t key;
3549 /* short circuit metadevices */
3550 assert(dev != NODEV64);
3551 if (meta_dev_ismeta(dev))
3552 return (metamnumname(spp, meta_getminor(dev), 0, ep));
3554 /* create local set, if necessary */
3555 if (*spp == NULL) {
3556 if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
3557 return (NULL);
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);
3565 namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep);
3566 if (namep != NULL)
3567 namep->key = key;
3569 Free(device_name);
3570 return (namep);
3574 * return cached name from md_dev64_t
3576 static char *
3577 metadevtocachename(md_dev64_t dev)
3579 mddrivenamelist_t *dnlp;
3581 /* look in cache */
3582 for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) {
3583 mddrivename_t *dnp = dnlp->drivenamep;
3584 uint_t i;
3586 for (i = 0; (i < dnp->parts.parts_len); ++i) {
3587 mdname_t *np = &dnp->parts.parts_val[i];
3589 if (np->dev == dev)
3590 return (np->cname);
3594 /* not found */
3595 return (NULL);
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)
3603 char *
3604 get_devname(
3605 set_t setno,
3606 md_dev64_t dev)
3608 mdsetname_t *sp;
3609 mdname_t *np;
3610 md_error_t status = mdnullerror;
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));
3620 /* return name */
3621 return (np->cname);
3625 * get name from key
3627 mdname_t *
3628 metakeyname(
3629 mdsetname_t **spp,
3630 mdkey_t key,
3631 int fast,
3632 md_error_t *ep
3635 char *device_name;
3636 md_dev64_t dev = NODEV64;
3637 mdname_t *namep;
3639 /* create local set, if necessary */
3640 if (*spp == NULL) {
3641 if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
3642 return (NULL);
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);
3650 if (fast)
3651 namep = metaname_fast(spp, device_name, UNKNOWN, ep);
3652 else
3653 namep = metaname(spp, device_name, UNKNOWN, ep);
3655 assert(dev != NODEV64);
3656 if (namep)
3657 namep->dev = dev;
3658 Free(device_name);
3659 return (namep);
3663 * completely flush metadev/hsp caches
3665 void
3666 metaflushmetanames()
3668 metaflushhspnames();
3669 metaflushdrivenames();
3670 metaflushfastnames();
3671 metaflushstatcache();
3675 * completely flush the caches
3677 void
3678 metaflushnames(int flush_sr_cache)
3680 metaflushhspnames();
3681 metaflushdrivenames();
3682 metaflushsetnames();
3683 metaflushctlrcache();
3684 metaflushfastnames();
3685 metaflushstatcache();
3686 if (flush_sr_cache)
3687 sr_cache_flush(0);
3691 * meta_get_hotspare_names
3692 * returns an mdnamelist_t of hot spare names
3696 meta_get_hotspare_names(
3697 mdsetname_t *sp,
3698 mdnamelist_t **nlpp,
3699 int options,
3700 md_error_t *ep
3703 mdhspnamelist_t *hspnlp = NULL;
3704 mdhspnamelist_t *hspp;
3705 int cnt = 0;
3707 assert(nlpp != NULL);
3709 /* get hotspare names */
3710 if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) {
3711 cnt = -1;
3712 goto out;
3715 /* build name list */
3716 for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) {
3717 md_hsp_t *hsp;
3718 int i;
3720 if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) {
3721 cnt = -1;
3722 goto out;
3724 for (i = 0; (i < hsp->hotspares.hotspares_len); i++) {
3725 md_hs_t *hs = &hsp->hotspares.hotspares_val[i];
3727 (void) metanamelist_append(nlpp, hs->hsnamep);
3728 ++cnt;
3732 /* cleanup and return count or error */
3733 out:
3734 metafreehspnamelist(hspnlp);
3735 if ((cnt == -1) && mdisok(ep)) {
3737 * At least try to give some sort of meaningful error
3739 (void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error");
3742 return (cnt);
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.
3753 void
3754 meta_create_non_dup_list(
3755 mdname_t *mdnp,
3756 mddevid_t **ldevidpp
3759 char *lcname;
3760 mddevid_t *tmp;
3761 mddevid_t *lastdevidp;
3762 mddevid_t *lldevidp;
3763 char *ctd, *slice;
3764 mddevid_t *ldevidp;
3766 if (mdnp == NULL)
3767 return;
3769 ldevidp = *ldevidpp;
3771 * Grab the name of the device and strip off slice information
3773 lcname = Strdup(mdnp->cname);
3774 if (lcname == NULL) {
3775 return;
3777 ctd = strrchr(lcname, '/');
3778 if (ctd != NULL)
3779 slice = strrchr(ctd, 's');
3780 else
3781 slice = strrchr(lcname, 's');
3783 if (slice != NULL)
3784 *slice = '\0';
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;
3799 lastdevidp = tmp;
3801 lldevidp = Zalloc(sizeof (mddevid_t));
3802 lldevidp->ctdname = lcname;
3803 lldevidp->key = mdnp->key;
3804 lastdevidp->next = lldevidp;