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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
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"
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.
49 #define VAL2STR(x) QUOTE(x)
51 extern char *getfullblkname();
56 static mdsetnamelist_t
*setlistp
= NULL
;
57 static mddrivenamelist_t
*drivelistp
= NULL
;
58 static mdnamelist_t
*fastnmlp
= NULL
;
59 static mdhspnamelist_t
*hsplistp
= NULL
;
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.
75 meta_dsk_to_rdsk(char *str
)
82 if ((dp
= strstr(str
, "/rdsk/")) != NULL
)
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) {
94 } else if (strncmp(str
, "/dev/", 5) == 0) {
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
);
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.
123 char *new_path
= NULL
;
130 if ((new_path
= meta_dsk_to_rdsk(uname
)) == NULL
)
133 if (strncmp("/dev/", new_path
, 5) == 0) {
134 ret
= stat(new_path
, &statbuf
);
135 if (ret
!= 0 || (! S_ISCHR(statbuf
.st_mode
))) {
151 if ((p
= getfullblkname(uname
)) == NULL
) {
153 } else if (*p
== '\0') {
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.
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);
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
++) {
204 *tp
++ = *up
; /* ++ is done by for loop */
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
);
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
);
233 /* without setname specified */
235 if (sp
!= NULL
&& !metaislocalset(sp
))
236 *snamep
= Strdup(sp
->setname
);
247 if ((strcoll(s
, gettext("all")) == 0) ||
248 (strcoll(s
, gettext("ALL")) == 0))
257 meta_is_none(char *s
)
259 if ((strcoll(s
, gettext("none")) == 0) ||
260 (strcoll(s
, gettext("NONE")) == 0))
266 valid_name_syntax(char *uname
)
271 if (uname
== NULL
|| !isalpha(uname
[0]))
274 uname_len
= strlen(uname
);
275 if (uname_len
> MAXNAMLEN
)
278 /* 'all' and 'none' are reserved */
279 if (meta_is_all(uname
) || meta_is_none(uname
))
282 for (i
= 1; i
< uname_len
; i
++) {
283 if ((isalnum(uname
[i
]) || uname
[i
] == '-' ||
284 uname
[i
] == '_' || uname
[i
] == '.'))
309 /* return the dev name and set name */
310 parse_device(sp
, uname
, &tname
, &sname
);
312 if (!valid_name_syntax(tname
)) {
319 if ((sname
== NULL
) || (strcmp(sname
, MD_LOCAL_NAME
) == 0))
324 cname_len
= strlen(tname
) + strlen(sname
) + 2;
325 cname
= Malloc(cname_len
);
327 cname
, cname_len
, "%s/%s", sname
, tname
);
338 * canonicalize name and check the set
341 meta_canonicalize_check_set(
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
);
362 /* check the set name returned from the name for validity */
363 if (chksetname(spp
, sname
, ep
) != 0) {
370 if ((sname
== NULL
) || (strcmp(sname
, MD_LOCAL_NAME
) == 0))
375 cname_len
= strlen(tname
) + strlen(sname
) + 2;
376 cname
= Malloc(cname_len
);
378 cname
, cname_len
, "%s/%s", sname
, tname
);
389 * Verify that the name is a valid hsp/metadevice name
392 parse_meta_hsp_name(char *uname
)
398 /* return the dev name and set name */
399 parse_device(NULL
, uname
, &tname
, &sname
);
401 ret
= valid_name_syntax(tname
);
409 * check that name is a metadevice
416 return (parse_meta_hsp_name(uname
));
420 * check that name is a hotspare pool
427 return (parse_meta_hsp_name(uname
));
431 * check to verify that name is an existing metadevice
434 is_existing_metadevice(
446 assert(uname
!= NULL
);
448 * If it is an absolute name of a metadevice, then just call rawname
451 if (uname
[0] == '/') {
452 if (strncmp("/dev/md", uname
, strlen("/dev/md")) == 0 &&
453 (raw_name
= rawname(uname
)) != NULL
) {
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
);
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",
475 if ((raw_name
= rawname(full_path
)) != NULL
) {
480 if (set_name
!= NULL
)
489 * check to verify that name is an existing hsp
497 md_error_t status
= mdnullerror
;
506 hsp
= meta_gethspnmentbyname(cur_set
, MD_SIDEWILD
, uname
, &status
);
508 if (hsp
== MD_HSP_NONE
) {
516 * check to verify that name is an existing metadevice or hotspare pool
519 is_existing_meta_hsp(
524 if (is_existing_metadevice(sp
, uname
) ||
525 is_existing_hsp(sp
, uname
))
543 (void) memset(sp
, '\0', sizeof (*sp
));
547 metafreesetdesc(md_set_desc
*sd
)
551 if (MD_MNSET_DESC(sd
)) {
552 nd
= sd
->sd_nodelist
;
554 sd
->sd_nodelist
= nd
->nd_next
;
556 nd
= sd
->sd_nodelist
;
559 metafreedrivedesc(&sd
->sd_drvs
);
564 * free allocated setname
571 if (sp
->setname
!= NULL
)
573 if (sp
->setdesc
!= NULL
)
574 metafreesetdesc(sp
->setdesc
);
579 * flush the setname cache
584 mdsetnamelist_t
*p
, *n
;
586 for (p
= setlistp
, n
= NULL
; (p
!= NULL
); p
= n
) {
588 metafreesetname(p
->sp
);
609 if ((sname
== NULL
) || (strcmp(sname
, MD_LOCAL_NAME
) == 0)) {
615 if ((sr
= getsetbyname(sname
, ep
)) == NULL
) {
616 if (mdisrpcerror(ep
, RPC_PROGNOTREGISTERED
)) {
619 len
= strlen(sname
) + 30;
622 (void) snprintf(p
, len
, "setname \"%s\"", sname
);
623 (void) mderror(ep
, MDE_NO_SET
, p
);
628 *setnop
= sr
->sr_setno
;
634 * find setname from name
642 mdsetnamelist_t
**tail
;
646 /* look for cached value first */
647 assert(sname
!= NULL
);
648 for (tail
= &setlistp
; (*tail
!= NULL
); tail
= &(*tail
)->next
) {
650 if (strcmp(sp
->setname
, sname
) == 0) {
656 if (getsetno(sname
, &setno
, ep
) != 0)
659 /* allocate new list element and setname */
660 *tail
= Zalloc(sizeof (**tail
));
661 sp
= (*tail
)->sp
= Zalloc(sizeof (*sp
));
663 sp
->setname
= Strdup(sname
);
665 sp
->lockfd
= MD_NO_LOCK
;
671 * find setname from setno
679 mdsetnamelist_t
*slp
;
683 /* look for cached value first */
684 for (slp
= setlistp
; (slp
!= NULL
); slp
= slp
->next
) {
686 if (sp
->setno
== setno
)
691 if (setno
== MD_LOCAL_SET
)
692 return (metasetname(MD_LOCAL_NAME
, ep
));
695 if ((sr
= getsetbynum(setno
, ep
)) == NULL
)
697 sp
= metasetname(sr
->sr_setname
, ep
);
708 mdsetnamelist_t
**tail
;
711 /* look for cached value first */
712 for (tail
= &setlistp
; (*tail
!= NULL
); tail
= &(*tail
)->next
) {
714 if (sp
->setno
== setno
) {
715 if ((sp
->setname
== NULL
) && (sname
!= NULL
))
716 sp
->setname
= Strdup(sname
);
721 /* allocate new list element and setname */
722 *tail
= Zalloc(sizeof (**tail
));
723 sp
= (*tail
)->sp
= Zalloc(sizeof (*sp
));
726 sp
->setname
= Strdup(sname
);
728 sp
->lockfd
= MD_NO_LOCK
;
735 * setup set record (sr) and cache it in the mdsetname_t struct
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
;
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 */
775 nr
= mnsr
->sr_nodechain
;
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.
784 nd
= Zalloc(sizeof (*nd
));
786 nd_prev
->nd_next
= nd
;
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
) {
817 if (nl2
->msl_node_id
== nd
->nd_nodeid
) {
818 (void) strlcpy(nd
->nd_priv_ic
,
820 sizeof (nd
->nd_priv_ic
));
831 sd
->sd_mn_numnodes
= nrcnt
;
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]));
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 */
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
);
864 return (sp
->setdesc
);
869 if ((sr
= getsetbynum(sp
->setno
, ep
)) != NULL
) {
870 sp
->setdesc
= sr2setdesc(sr
);
872 return (sp
->setdesc
);
880 metaflushsetname(mdsetname_t
*sp
)
885 if (sp
->setdesc
== NULL
)
888 metafreesetdesc(sp
->setdesc
);
893 * check for local set
900 assert(sp
->setname
!= NULL
);
901 if (strcmp(sp
->setname
, MD_LOCAL_NAME
) == 0) {
902 assert(sp
->setno
== MD_LOCAL_SET
);
905 assert(sp
->setno
!= MD_LOCAL_SET
);
919 if (strcmp(sp1
->setname
, sp2
->setname
) == 0) {
920 assert(sp1
->setno
== sp2
->setno
);
923 assert(sp1
->setno
!= sp2
->setno
);
929 * check to see if set changed
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
));
947 /* otherwise store new set name and number */
948 if ((*spp
= metasetname(sname
, ep
)) == NULL
) {
957 * check to see if set changed from default
966 /* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */
971 sname
= MD_LOCAL_NAME
;
976 return (chkset(spp
, sname
, ep
));
980 * check setname from setno
994 return (chkset(spp
, MD_LOCAL_NAME
, ep
));
997 if ((sr
= getsetbynum(setno
, ep
)) == NULL
)
999 rval
= chkset(spp
, sr
->sr_setname
, ep
);
1005 * mddrivename_t stuff
1016 (void) memset(np
, 0, sizeof (*np
));
1018 np
->key
= MD_KEYBAD
;
1024 * free allocated name
1031 if (np
->cname
!= NULL
)
1033 if (np
->bname
!= NULL
)
1035 if (np
->rname
!= NULL
)
1037 if (np
->devicesname
!= NULL
)
1038 Free(np
->devicesname
);
1043 * initialize drive name
1050 (void) memset(dnp
, 0, sizeof (*dnp
));
1051 dnp
->side_names_key
= MD_KEYBAD
;
1062 mdsidenames_t
*p
, *n
;
1064 for (p
= dnp
->side_names
, n
= NULL
; (p
!= NULL
); p
= n
) {
1066 if (p
->dname
!= NULL
)
1068 if (p
->cname
!= NULL
)
1072 dnp
->side_names
= NULL
;
1085 if (dnp
->cname
!= NULL
)
1087 if (dnp
->rname
!= NULL
)
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
1105 metaflushdrivenames()
1107 mddrivenamelist_t
*p
, *n
;
1109 for (p
= drivelistp
, n
= NULL
; (p
!= NULL
); p
= n
) {
1111 metafreedrivename(p
->drivenamep
);
1112 Free(p
->drivenamep
);
1119 * peel off s%u from name
1127 char onmb
[BUFSIZ
+1], cnmb
[BUFSIZ
];
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
) {
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
));
1165 if ((p
<= name
) || (!isdigit(*p
)))
1166 return (Strdup(name
));
1176 * free list of drivenames
1179 metafreedrivenamelist(
1180 mddrivenamelist_t
*dnlp
1183 mddrivenamelist_t
*next
= NULL
;
1185 for (/* void */; (dnlp
!= NULL
); dnlp
= next
) {
1192 * build list of drivenames
1197 mddrivenamelist_t
**dnlpp
,
1203 mddrivenamelist_t
**tailpp
= dnlpp
;
1206 for (*dnlpp
= NULL
; (argc
> 0); ++count
, --argc
, ++argv
) {
1207 mddrivenamelist_t
*dnlp
= Zalloc(sizeof (*dnlp
));
1209 if ((dnlp
->drivenamep
= metadrivename(spp
, argv
[0],
1211 metafreedrivenamelist(*dnlpp
);
1216 tailpp
= &dnlp
->next
;
1222 * append to end of drivename list
1225 metadrivenamelist_append(
1226 mddrivenamelist_t
**dnlpp
,
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
;
1245 * FUNCTION: meta_drivenamelist_append_wrapper()
1246 * INPUT: tailpp - pointer to the list tail pointer
1247 * dnp - name node to be appended to list
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
,
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
)
1268 return (&(*tailpp
)->next
);
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.
1286 meta_device_type_t uname_type
,
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
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)
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.
1326 getrname(mdsetname_t
**spp
, char *uname
,
1327 meta_device_type_t
*type
, md_error_t
*ep
)
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
);
1349 *type
= META_DEVICE
;
1351 if (*type
== META_DEVICE
) {
1352 (void) mdsyserror(ep
, ENOENT
, uname
);
1355 *type
= LOGICAL_DEVICE
;
1361 (void) mdsyserror(ep
, ENOENT
, uname
);
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
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
);
1388 if ((p
= strchr(uname
, '/')) != NULL
) {
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
1411 if (rname
== NULL
) {
1412 rname
= Strdup(fname
);
1420 if ((rname
!= NULL
) && (*type
== UNKNOWN
)) {
1421 /* Save this result */
1422 rname_list
[rname_cnt
] = rname
;
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
);
1434 if (rname
!= NULL
) {
1435 /* Simply return if a logical device was requested */
1436 if (*type
== LOGICAL_DEVICE
) {
1439 rname_list
[rname_cnt
] = rname
;
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
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.
1460 if (rname_cnt
== 0 || *type
!= UNKNOWN
) {
1462 (void) mdsyserror(ep
, ENOENT
, uname
);
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]);
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
;
1477 tmp_type
= LOGICAL_DEVICE
;
1479 if (rname_cnt
== 1) {
1480 rname
= Strdup(rname_list
[0]);
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]);
1502 rname
= Strdup(rname_list
[0]);
1506 for (i
= 0; i
< rname_cnt
; i
++)
1507 Free(rname_list
[i
]);
1513 * get raw slice and drive names
1520 meta_device_type_t
*uname_type
,
1528 * Incorrect code path if type is HSP_DEVICE
1530 assert(*uname_type
!= HSP_DEVICE
);
1535 /* get slice name */
1536 if ((rname
= getrname(spp
, uname
, uname_type
, ep
)) != NULL
) {
1537 *dnamep
= metadiskname(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] == '/') {
1553 char onmb
[BUFSIZ
+1], snm
[BUFSIZ
+1];
1556 * Handle old style raw names
1559 "/dev/r%" VAL2STR(BUFSIZ
) "[^0-9/]%u"
1560 "%" VAL2STR(BUFSIZ
) "[a-h]%n",
1561 onmb
, &d
, snm
, &l
) == 3 && l
== strlen(uname
)) {
1563 rname
= Strdup(uname
);
1564 *dnamep
= metadiskname(rname
);
1565 *uname_type
= LOGICAL_DEVICE
;
1570 * Handle old style block names
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",
1580 *dnamep
= metadiskname(rname
);
1581 *uname_type
= LOGICAL_DEVICE
;
1585 /* /.../dsk/... or /.../rdsk/... */
1586 if ((rname
= meta_dsk_to_rdsk(uname
)) != NULL
) {
1588 *dnamep
= metadiskname(rname
);
1589 *uname_type
= LOGICAL_DEVICE
;
1594 * If it's not an absolute name but is a valid ctd name,
1595 * guess at /dev/rdsk/...
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",
1603 *dnamep
= metadiskname(rname
);
1604 *uname_type
= LOGICAL_DEVICE
;
1611 if (!mdiserror(ep
, MDE_AMBIGUOUS_DEV
))
1612 (void) mderror(ep
, MDE_UNIT_NOT_FOUND
, uname
);
1617 * get number of slices for name
1628 size_t dl
= strlen(dname
);
1629 size_t rl
= strlen(rname
);
1634 * get our slice number - works only with names that end in s%u -
1635 * all others return -1.
1638 sscanf(&rname
[dl
], "s%u%n", slicep
, &l
) != 1 || l
!= rl
||
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
))) {
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
)
1669 /* return number of slices */
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
1693 uint_t target_str_len
;
1694 char *partial_ctd_str
;
1696 char *device_start_pos
;
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) {
1705 l
--; /* we want to be on the 'd' */
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
) {
1717 /* check to see if it is a ctd with a WWN or SCSI 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
) {
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 ||
1738 /* check the device and partition */
1739 if (sscanf(device_start_pos
, "d%up%u%n", &device
, slice
, &l
)
1751 * get number of slices for name
1756 meta_device_type_t uname_type
,
1761 uint_t c
= 0, t
= 0, d
= 0;
1764 struct dk_cinfo cinfo
;
1769 if (uname_type
== META_DEVICE
)
1770 return (*slicep
= 0);
1772 if ((p
= strrchr(uname
, '/')) != NULL
)
1779 if (parse_ctd(p
, slicep
) == 0)
1781 else if (sscanf(p
, "mc%ut%ud%us%u%n", &c
, &t
, &d
, slicep
, &l
) == 4 &&
1784 else if (sscanf(p
, "d%us%u%n", &d
, slicep
, &l
) == 2 && l
== cl
)
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
)
1794 /* get controller info */
1795 if ((fd
= open(rname
, (O_RDONLY
|O_NDELAY
), 0)) < 0) {
1800 if (ioctl(fd
, DKIOCINFO
, &cinfo
) != 0) {
1804 (void) mddeverror(ep
, MDE_NOT_DISK
, NODEV64
, rname
);
1806 (void) mdsyserror(ep
, save
, rname
);
1812 (void) close(fd
); /* sd/ssd bug */
1814 if (cinfo
.dki_partition
< V_NUMPAR
) {
1816 return (*slicep
= cinfo
.dki_partition
);
1819 return (mddeverror(ep
, MDE_NOT_DISK
, NODEV64
, rname
));
1823 * get partition info
1830 meta_device_type_t uname_type
,
1842 if (uname_type
== META_DEVICE
) {
1843 dnp
->type
= MDT_META
;
1849 /* see how many partitions in drive, this is really tricky */
1850 metainitname(&name
);
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 */
1861 if ((ep
->info
.errclass
== MDEC_DEV
) &&
1862 (ep
->info
.md_error_info_t_u
.dev_error
.errnum
== MDE_TOO_MANY_PARTS
))
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
)) {
1871 ep
->info
.md_error_info_t_u
.sys_error
.errnum
;
1873 dnp
->errnum
= ENOENT
;
1876 /* nparts already setup */
1877 /* partno already setup */
1878 /* dname already setup */
1879 nparts
= roundup(nparts
, V_NUMPAR
);
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
;
1891 dnp
->errnum
= ENOENT
;
1896 if (uname2sliceno(rname
, uname_type
, &partno
, ep
) < 0) {
1901 /* return success */
1905 if (partno
>= nparts
)
1906 return (mdsyserror(ep
, ENOENT
, rname
));
1922 char *rname
= np
->rname
;
1925 /* fully qualified */
1926 assert(rname
!= NULL
);
1927 if ((bname
= blkname(rname
)) != NULL
) {
1935 return (mdsyserror(ep
, ENOENT
, rname
));
1944 char *sname
= sp
->setname
;
1945 char *bname
= np
->bname
;
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
)) {
1959 np
->cname
= Strdup(p
);
1963 if ((strncmp(bname
, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) &&
1964 (strchr((p
= bname
+ strlen("/dev/ap/dsk/")), '/') == NULL
)) {
1967 np
->cname
= Strdup(p
);
1971 if ((strncmp(bname
, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) &&
1972 (strchr((p
= bname
+ strlen("/dev/did/dsk/")), '/') == NULL
)) {
1975 np
->cname
= Strdup(p
);
1979 /* anything else but metadevice */
1980 if (np
->drivenamep
->type
!= MDT_META
) {
1983 np
->cname
= Strdup(bname
);
1988 p
= strrchr(bname
, '/');
1991 if (metaislocalset(sp
)) {
1994 np
->cname
= Strdup(p
);
1996 assert(sname
[0] != '\0');
1999 len
= strlen(sname
) + 1 + strlen(p
) + 1;
2000 np
->cname
= Malloc(len
);
2001 (void) snprintf(np
->cname
, len
, "%s/%s", sname
, p
);
2015 struct stat statbuf
;
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
);
2028 assert((np
->drivenamep
->type
== MDT_META
) ?
2029 (sp
->setno
== MD_MIN2SET(meta_getminor(np
->dev
))) : 1);
2036 * set up names for a slice
2049 np
->rname
= Strdup(rname
);
2050 if (getbname(np
, ep
) != 0)
2053 if (meta_getdev(sp
, np
, ep
) != 0)
2056 /* return success */
2061 * fake up names for a slice
2071 char onmb
[BUFSIZ
+1], snm
[BUFSIZ
+1];
2076 if (np
->rname
!= NULL
)
2078 np
->rname
= Strdup(rname
);
2080 if (np
->bname
!= NULL
)
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
)
2101 if (np
->cname
!= NULL
)
2109 meta_device_type_t uname_type
,
2118 char *srname
= NULL
;
2121 /* must have a set */
2123 assert(partno
< dnp
->parts
.parts_len
);
2124 assert(dname
!= NULL
);
2126 np
= &dnp
->parts
.parts_val
[partno
];
2130 else if (uname_type
== META_DEVICE
)
2133 char onmb
[BUFSIZ
+1];
2135 int l
= 0, cl
= strlen(dname
);
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
,
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
,
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
) {
2161 getfakenames(sp
, np
, srname
);
2162 } else if (dnp
->type
== MDT_COMP
&& mdissyserror(ep
, ENOENT
)) {
2163 dnp
->type
= MDT_UNKNOWN
;
2164 if (mdanysyserror(ep
)) {
2166 ep
->info
.md_error_info_t_u
.sys_error
.errnum
;
2168 dnp
->errnum
= ENOENT
;
2171 getfakenames(sp
, np
, srname
);
2174 if (getnames(sp
, np
, dname
, ep
) != 0) {
2182 if ((srname
!= rname
) && (srname
!= dname
))
2189 if (mdanysyserror(ep
)) {
2191 int errnum
= ep
->info
.md_error_info_t_u
.sys_error
.errnum
;
2194 if (uname
&& *uname
) {
2195 if ((p
= strrchr(uname
, '/')) != NULL
)
2196 (void) mdsyserror(ep
, errnum
, ++p
);
2198 (void) mdsyserror(ep
, errnum
, uname
);
2200 if ((p
= strrchr(srname
, '/')) != NULL
)
2201 (void) mdsyserror(ep
, errnum
, ++p
);
2203 (void) mdsyserror(ep
, errnum
, srname
);
2210 * flush the fast name cache
2213 metafreefastnm(mdname_t
**np
)
2217 assert(np
!= NULL
&& *np
!= NULL
);
2219 if ((dnp
= (*np
)->drivenamep
) != NULL
) {
2220 if (dnp
->cname
!= NULL
)
2222 if (dnp
->rname
!= NULL
)
2224 if (dnp
->miscname
!= NULL
)
2225 Free(dnp
->miscname
);
2226 meta_free_unit(dnp
);
2229 if ((*np
)->cname
!= NULL
)
2231 if ((*np
)->bname
!= NULL
)
2233 if ((*np
)->rname
!= NULL
)
2235 if ((*np
)->devicesname
!= NULL
)
2236 Free((*np
)->devicesname
);
2242 * flush the fast name cache
2245 metaflushfastnames()
2247 mdnamelist_t
*p
, *n
;
2249 for (p
= fastnmlp
, n
= NULL
; (p
!= NULL
); p
= n
) {
2251 metafreefastnm(&p
->namep
);
2258 getrname_fast(char *unm
, meta_device_type_t uname_type
, md_error_t
*ep
)
2262 int cl
= strlen(unm
);
2263 char onmb
[BUFSIZ
+1], snm
[BUFSIZ
+1], cnmb
[BUFSIZ
];
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;
2275 (void) snprintf(rnm
, len
, "/dev/md/rdsk/%s", onmb
);
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) &&
2286 len
= strlen("/dev/md//rdsk/") + strlen(snm
) +
2289 (void) snprintf(rnm
, len
, "/dev/md/%s/rdsk/%s",
2294 /* Fully qualified path - error */
2295 if (unm
[0] == '/') {
2296 (void) mdsyserror(ep
, EINVAL
, unm
);
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
);
2309 len
= strlen("/dev/md//rdsk/") + strlen(snm
) +
2312 (void) snprintf(rnm
, len
, "/dev/md/%s/rdsk/%s",
2317 /* Must be simple metaname/hsp pool name */
2318 len
= strlen("/dev/md/rdsk/") + strlen(unm
) + 1;
2320 (void) snprintf(rnm
, len
, "/dev/md/rdsk/%s", unm
);
2324 /* NOT Fully qualified path, done */
2325 if (unm
[0] != '/') {
2326 (void) mdsyserror(ep
, EINVAL
, unm
);
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",
2344 return (Strdup(cnmb
));
2348 /* /.../dsk/... or /.../rdsk/... */
2349 if ((rnm
= meta_dsk_to_rdsk(unm
)) != NULL
)
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
);
2364 meta_device_type_t uname_type
,
2368 uint_t c
= 0, t
= 0, d
= 0, s
= 0;
2372 mdnamelist_t
**fnlpp
;
2375 for (fnlpp
= &fastnmlp
; (*fnlpp
!= NULL
); fnlpp
= &(*fnlpp
)->next
) {
2376 np
= (*fnlpp
)->namep
;
2378 if (strcmp(np
->bname
, uname
) == 0)
2382 *fnlpp
= Zalloc(sizeof (**fnlpp
));
2383 np
= (*fnlpp
)->namep
= Zalloc(sizeof (mdname_t
));
2385 dnp
= np
->drivenamep
= Zalloc(sizeof (mddrivename_t
));
2386 metainitdrivename(dnp
);
2390 if (uname_type
== META_DEVICE
&&
2391 (cname
= meta_canonicalize(sp
, uname
)) != NULL
) {
2394 dnp
->type
= MDT_FAST_META
;
2399 dnp
->type
= MDT_FAST_COMP
;
2401 if (((sscanf(uname
, "/dev/rdsk/c%ut%ud%us%u%n", &c
, &t
, &d
,
2403 sscanf(uname
, "/dev/dsk/c%ut%ud%us%u%n", &c
, &t
, &d
,
2405 sscanf(uname
, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c
, &t
, &d
,
2407 sscanf(uname
, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c
, &t
, &d
,
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
);
2425 np
->cname
= Strdup(++np
->cname
);
2427 np
->cname
= Strdup(uname
);
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
);
2442 metafreefastnm(&(*fnlpp
)->namep
);
2448 /* cleanup, return success */
2453 * set up names for a device
2460 meta_device_type_t uname_type
,
2464 mddrivenamelist_t
**tail
;
2471 uint_t nparts
, partno
;
2473 assert(uname
!= NULL
);
2476 if ((cname
= meta_name_getname(spp
, uname
, uname_type
, ep
)) == NULL
)
2479 assert(*spp
!= NULL
);
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
) {
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) {
2501 if (uname2sliceno(uname
, uname_type
, &partno
, ep
) < 0)
2504 return (metaslicename(dnp
, partno
, ep
));
2509 * If a fast names is OK, then get one, and be done.
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)
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
) {
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
];
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
)
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 */
2565 /* cleanup, return error */
2572 metafreedrivename(dnp
);
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.
2591 meta_device_type_t uname_type
,
2595 return (metaname_common(spp
, uname
, 0, uname_type
, ep
));
2602 meta_device_type_t uname_type
,
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.
2642 meta_getdnp_bydevid(
2650 ddi_devid_t dnp_devidp
;
2652 mddrivenamelist_t
**tail
;
2658 uint_t nparts
, partno
;
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
)
2668 ret
= devid_str_decode(dnp
->devid
, &dnp_devidp
, NULL
);
2670 /* unable to decode the devid */
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
);
2679 devid_free(dnp_devidp
);
2682 /* drive not in the cache */
2684 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
2687 /* get namespace info */
2688 if (MD_MNSET_DESC(sd
)) {
2689 if ((nm
= meta_getnmbykey(MD_LOCAL_SET
, sideno
,
2693 if ((nm
= meta_getnmbykey(MD_LOCAL_SET
,
2694 sideno
+SKEW
, key
, ep
)) == NULL
)
2698 /* get raw name (rname) of the slice and drive name (dname) */
2699 if ((rname
= getrawnames(&sp
, nm
, &dname
, &uname_type
, ep
)) == 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)
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
) {
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
];
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
)
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
);
2764 metafreedrivename(dnp
);
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.
2776 metadrivenamebydevid(
2783 ddi_devid_t dnp_devidp
, in_devidp
;
2785 mddrivenamelist_t
**tail
;
2790 uint_t nparts
, partno
;
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
)
2800 /* decode the dnp devid */
2801 ret
= devid_str_decode(dnp
->devid
, &dnp_devidp
, NULL
);
2803 /* unable to decode the devid */
2806 /* decode the passed in devid */
2807 ret
= devid_str_decode(devid
, &in_devidp
, NULL
);
2809 /* unable to decode the devid */
2810 devid_free(dnp_devidp
);
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
);
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
,
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)
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
) {
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
];
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
)
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 */
2878 /* cleanup, return error */
2885 metafreedrivename(dnp
);
2892 * set up names for a drive
2904 mddrivenamelist_t
**tail
;
2911 assert(uname
!= NULL
);
2913 if ((dname
= metadiskname(uname
)) == NULL
) {
2914 (void) mdsyserror(ep
, ENOENT
, uname
);
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))) {
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
);
2952 if ((mdiserror(ep
, MDE_UNIT_NOT_FOUND
)) &&
2953 ((dname
= metadiskname(uname
)) != NULL
)) {
2955 (void) mderror(ep
, MDE_NOT_DRIVENAME
, uname
);
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.
2980 meta_device_type_t uname_type
,
2984 mdsetname_t
*sp
= NULL
;
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
);
2995 np
= &dnp
->parts
.parts_val
[sliceno
];
2997 /* check to see if the struct is already populated */
3002 if ((namep
= meta_name_getname(&sp
, dnp
->cname
,
3003 uname_type
, ep
)) == NULL
)
3006 np
= setup_slice(sp
, uname_type
, dnp
, NULL
, NULL
, dnp
->rname
,
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.
3034 return (metaslicename_type(dnp
, sliceno
, LOGICAL_DEVICE
, ep
));
3038 * set up metadevice name from id
3048 set_t setno
= MD_MIN2SET(mnum
);
3049 mdsetname_t
*sp
= NULL
;
3055 /* check set first */
3058 if (chksetno(spp
, setno
, ep
) != 0)
3060 assert(*spp
!= NULL
);
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
)
3071 np
= metaname_fast(spp
, uname
, META_DEVICE
, ep
);
3077 np
= metaname(spp
, uname
, META_DEVICE
, ep
);
3084 * return metadevice name
3093 md_error_t status
= mdnullerror
;
3094 mdsetname_t
**spp
= NULL
;
3100 if ((np
= metamnumname(spp
, mnum
, 0, &status
)) == NULL
) {
3103 assert(meta_getminor(np
->dev
) == mnum
);
3110 * check for device type
3117 return (np
->drivenamep
->type
== MDT_META
||
3118 np
->drivenamep
->type
== MDT_FAST_META
);
3127 if (! metaismeta(np
)) {
3128 return (mddeverror(ep
, MDE_NOT_META
, np
->dev
,
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
) {
3148 return (mdsyserror(ep
, dnp
->errnum
, np
->bname
));
3151 return (mddeverror(ep
, MDE_NOT_DISK
, np
->dev
,
3164 if (metaismeta(np
)) {
3165 return (mddeverror(ep
, MDE_IS_META
, np
->dev
,
3168 return (metachkdisk(np
, ep
));
3172 * free list of names
3179 mdnamelist_t
*next
= NULL
;
3181 for (/* void */; (nlp
!= NULL
); nlp
= next
) {
3188 * build list of names
3193 mdnamelist_t
**nlpp
,
3196 meta_device_type_t type
,
3200 mdnamelist_t
**tailpp
= nlpp
;
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
);
3213 tailpp
= &nlp
->next
;
3219 * append to end of name list
3222 metanamelist_append(
3223 mdnamelist_t
**nlpp
,
3229 /* run to end of list */
3230 for (; (*nlpp
!= NULL
); nlpp
= &(*nlpp
)->next
)
3233 /* allocate new list element */
3234 nlp
= *nlpp
= Zalloc(sizeof (*nlp
));
3242 * FUNCTION: meta_namelist_append_wrapper()
3243 * INPUT: tailpp - pointer to the list tail pointer
3244 * np - name node to be appended to list
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
3254 meta_namelist_append_wrapper(
3255 mdnamelist_t
**tailpp
,
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
)
3265 return (&(*tailpp
)->next
);
3274 * initialize hspname
3278 mdhspname_t
*hspnamep
3281 (void) memset(hspnamep
, '\0', sizeof (*hspnamep
));
3282 hspnamep
->hsp
= MD_HSP_NONE
;
3286 * free allocated hspname
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
3306 mdhspnamelist_t
*p
, *n
;
3308 for (p
= hsplistp
, n
= NULL
; (p
!= NULL
); p
= n
) {
3310 metafreehspname(p
->hspnamep
);
3318 * check set and get comparison name
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
);
3339 * set up a hotspare pool name structure using both the name
3342 static mdhspname_t
*
3351 mdhspnamelist_t
**tail
;
3355 assert(uname
!= NULL
);
3356 if ((cname
= gethspname(spp
, uname
, ep
)) == 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) {
3365 /* if the hsp value has not been set then set it now */
3366 if (hspnp
->hsp
== MD_HSP_NONE
)
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
) {
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
)) {
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
;
3403 * set up names for a hotspare pool
3412 return (metahspname_hsp(spp
, uname
, MD_HSP_NONE
, ep
));
3416 * set up hotspare pool name from key
3425 set_t setno
= HSP_SET(hsp
);
3426 mdsetname_t
*sp
= NULL
;
3430 /* check set first */
3433 if (chksetno(spp
, setno
, ep
) != 0)
3435 assert(*spp
!= NULL
);
3438 /* get corresponding hotspare pool name */
3439 if ((uname
= meta_gethspnmentbyid(sp
->setno
,
3440 MD_SIDEWILD
, hsp
, ep
)) == NULL
)
3444 hspnp
= metahspname_hsp(spp
, uname
, hsp
, ep
);
3450 * return hotspare pool name
3453 get_hspname(mdsetname_t
*sp
, hsp_t hsp
)
3456 md_error_t status
= mdnullerror
;
3457 mdsetname_t
**spp
= NULL
;
3463 if ((hspnp
= metahsphspname(spp
, hsp
, &status
)) == NULL
) {
3464 mdclrerror(&status
);
3469 return (hspnp
->hspname
);
3473 * free hotspare pool list
3476 metafreehspnamelist(mdhspnamelist_t
*hspnlp
)
3478 mdhspnamelist_t
*next
= NULL
;
3480 for (/* void */; (hspnlp
!= NULL
); hspnlp
= next
) {
3481 next
= hspnlp
->next
;
3487 * build list of hotspare pool names
3492 mdhspnamelist_t
**hspnlpp
,
3498 mdhspnamelist_t
**tailpp
= hspnlpp
;
3501 for (*hspnlpp
= NULL
; (argc
> 0); ++count
, --argc
, ++argv
) {
3502 mdhspnamelist_t
*hspnlp
= Zalloc(sizeof (*hspnlp
));
3504 if ((hspnlp
->hspnamep
= metahspname(spp
, argv
[0],
3506 metafreehspnamelist(*hspnlpp
);
3511 tailpp
= &hspnlp
->next
;
3517 * append to end of hotspare pool list
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
;
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 */
3556 if ((*spp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
)
3560 /* get name from namespace */
3561 if ((device_name
= meta_getnmentbydev((*spp
)->setno
, MD_SIDEWILD
,
3562 dev
, NULL
, NULL
, &key
, ep
)) == NULL
) {
3565 namep
= metaname_fast(spp
, device_name
, LOGICAL_DEVICE
, ep
);
3574 * return cached name from md_dev64_t
3577 metadevtocachename(md_dev64_t dev
)
3579 mddrivenamelist_t
*dnlp
;
3582 for (dnlp
= drivelistp
; (dnlp
!= NULL
); dnlp
= dnlp
->next
) {
3583 mddrivename_t
*dnp
= dnlp
->drivenamep
;
3586 for (i
= 0; (i
< dnp
->parts
.parts_len
); ++i
) {
3587 mdname_t
*np
= &dnp
->parts
.parts_val
[i
];
3599 * Ask the driver for the name, which has been stored in the
3600 * metadevice state database (on behalf of the utilities).
3610 md_error_t status
= mdnullerror
;
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
));
3636 md_dev64_t dev
= NODEV64
;
3639 /* create local set, if necessary */
3641 if ((*spp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
)
3645 /* get name from namespace */
3646 if ((device_name
= meta_getnmentbykey((*spp
)->setno
, MD_SIDEWILD
,
3647 key
, NULL
, NULL
, &dev
, ep
)) == NULL
) {
3651 namep
= metaname_fast(spp
, device_name
, UNKNOWN
, ep
);
3653 namep
= metaname(spp
, device_name
, UNKNOWN
, ep
);
3655 assert(dev
!= NODEV64
);
3663 * completely flush metadev/hsp caches
3666 metaflushmetanames()
3668 metaflushhspnames();
3669 metaflushdrivenames();
3670 metaflushfastnames();
3671 metaflushstatcache();
3675 * completely flush the caches
3678 metaflushnames(int flush_sr_cache
)
3680 metaflushhspnames();
3681 metaflushdrivenames();
3682 metaflushsetnames();
3683 metaflushctlrcache();
3684 metaflushfastnames();
3685 metaflushstatcache();
3691 * meta_get_hotspare_names
3692 * returns an mdnamelist_t of hot spare names
3696 meta_get_hotspare_names(
3698 mdnamelist_t
**nlpp
,
3703 mdhspnamelist_t
*hspnlp
= NULL
;
3704 mdhspnamelist_t
*hspp
;
3707 assert(nlpp
!= NULL
);
3709 /* get hotspare names */
3710 if (meta_get_hsp_names(sp
, &hspnlp
, options
, ep
) < 0) {
3715 /* build name list */
3716 for (hspp
= hspnlp
; (hspp
!= NULL
); hspp
= hspp
->next
) {
3720 if ((hsp
= meta_get_hsp(sp
, hspp
->hspnamep
, ep
)) == NULL
) {
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
);
3732 /* cleanup and return count or error */
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");
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.
3754 meta_create_non_dup_list(
3756 mddevid_t
**ldevidpp
3761 mddevid_t
*lastdevidp
;
3762 mddevid_t
*lldevidp
;
3769 ldevidp
= *ldevidpp
;
3771 * Grab the name of the device and strip off slice information
3773 lcname
= Strdup(mdnp
->cname
);
3774 if (lcname
== NULL
) {
3777 ctd
= strrchr(lcname
, '/');
3779 slice
= strrchr(ctd
, 's');
3781 slice
= strrchr(lcname
, 's');
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
;
3793 for (tmp
= ldevidp
; (tmp
!= NULL
); tmp
= tmp
->next
) {
3794 if (strcmp(tmp
->ctdname
, lcname
) == 0) {
3795 /* already there so just return */
3801 lldevidp
= Zalloc(sizeof (mddevid_t
));
3802 lldevidp
->ctdname
= lcname
;
3803 lldevidp
->key
= mdnp
->key
;
3804 lastdevidp
->next
= lldevidp
;