10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5908Spetede * Common Development and Distribution License (the "License").
6908Spetede * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*9017SJohn.Wren.Kennedy@Sun.COM
220Sstevel@tonic-gate /*
23*9017SJohn.Wren.Kennedy@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <meta.h>
280Sstevel@tonic-gate #include <metad.h>
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <ctype.h>
310Sstevel@tonic-gate #include <string.h>
321623Stw21770 #include <sys/fs/ufs_fsdir.h>
330Sstevel@tonic-gate
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that
360Sstevel@tonic-gate * TEXT_DOMAIN gets set to something.
370Sstevel@tonic-gate */
380Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
390Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
400Sstevel@tonic-gate #endif
410Sstevel@tonic-gate
420Sstevel@tonic-gate /*
430Sstevel@tonic-gate * Macros to produce a quoted string containing the value of a
440Sstevel@tonic-gate * preprocessor macro. For example, if SIZE is defined to be 256,
450Sstevel@tonic-gate * VAL2STR(SIZE) is "256". This is used to construct format
460Sstevel@tonic-gate * strings for scanf-family functions below.
470Sstevel@tonic-gate */
480Sstevel@tonic-gate #define QUOTE(x) #x
490Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x)
500Sstevel@tonic-gate
510Sstevel@tonic-gate extern char *getfullblkname();
520Sstevel@tonic-gate
530Sstevel@tonic-gate /*
540Sstevel@tonic-gate * caches
550Sstevel@tonic-gate */
560Sstevel@tonic-gate static mdsetnamelist_t *setlistp = NULL;
570Sstevel@tonic-gate static mddrivenamelist_t *drivelistp = NULL;
580Sstevel@tonic-gate static mdnamelist_t *fastnmlp = NULL;
590Sstevel@tonic-gate static mdhspnamelist_t *hsplistp = NULL;
600Sstevel@tonic-gate
610Sstevel@tonic-gate /*
621623Stw21770 * Static definitions
631623Stw21770 */
641623Stw21770 static int chksetname(mdsetname_t **spp, char *sname, md_error_t *ep);
651623Stw21770
661623Stw21770 /*
67*9017SJohn.Wren.Kennedy@Sun.COM * FUNCTION: meta_dsk_to_rdsk()
68*9017SJohn.Wren.Kennedy@Sun.COM * INPUT: str - Fully qualified pathname of a block or character device
69*9017SJohn.Wren.Kennedy@Sun.COM * RETURNS: char * - The pathname of the raw device
70*9017SJohn.Wren.Kennedy@Sun.COM * PURPOSE: Allocation of a new string representing the character device
71*9017SJohn.Wren.Kennedy@Sun.COM * associated with the input string. Note that no checking is
72*9017SJohn.Wren.Kennedy@Sun.COM * done to verify the existence of this device file.
730Sstevel@tonic-gate */
740Sstevel@tonic-gate static char *
meta_dsk_to_rdsk(char * str)75*9017SJohn.Wren.Kennedy@Sun.COM meta_dsk_to_rdsk(char *str)
760Sstevel@tonic-gate {
77*9017SJohn.Wren.Kennedy@Sun.COM char *dp = NULL;
78*9017SJohn.Wren.Kennedy@Sun.COM char *rdskp = NULL;
79*9017SJohn.Wren.Kennedy@Sun.COM
80*9017SJohn.Wren.Kennedy@Sun.COM assert(*str == '/');
81*9017SJohn.Wren.Kennedy@Sun.COM
82*9017SJohn.Wren.Kennedy@Sun.COM if ((dp = strstr(str, "/rdsk/")) != NULL)
83*9017SJohn.Wren.Kennedy@Sun.COM return (Strdup(str));
84*9017SJohn.Wren.Kennedy@Sun.COM
85*9017SJohn.Wren.Kennedy@Sun.COM /*
86*9017SJohn.Wren.Kennedy@Sun.COM * If this is a malformed string, (i.e. containing neither
87*9017SJohn.Wren.Kennedy@Sun.COM * "/rdsk/" nor "/dsk/") then check to see if the caller
88*9017SJohn.Wren.Kennedy@Sun.COM * is passing old school device names like "/dev/[r]sd" or
89*9017SJohn.Wren.Kennedy@Sun.COM * exotic hardware presenting "/dev/[r]dc" names.
90*9017SJohn.Wren.Kennedy@Sun.COM */
91*9017SJohn.Wren.Kennedy@Sun.COM if ((dp = strstr(str, "/dsk/")) == NULL) {
92*9017SJohn.Wren.Kennedy@Sun.COM if (strncmp(str, "/dev/r", 6) == 0) {
93*9017SJohn.Wren.Kennedy@Sun.COM return (Strdup(str));
94*9017SJohn.Wren.Kennedy@Sun.COM } else if (strncmp(str, "/dev/", 5) == 0) {
95*9017SJohn.Wren.Kennedy@Sun.COM dp = str + 4;
96*9017SJohn.Wren.Kennedy@Sun.COM } else {
97*9017SJohn.Wren.Kennedy@Sun.COM return (NULL);
980Sstevel@tonic-gate }
99*9017SJohn.Wren.Kennedy@Sun.COM }
100*9017SJohn.Wren.Kennedy@Sun.COM
101*9017SJohn.Wren.Kennedy@Sun.COM dp++;
102*9017SJohn.Wren.Kennedy@Sun.COM if (*dp == '\0')
103*9017SJohn.Wren.Kennedy@Sun.COM return (NULL);
104*9017SJohn.Wren.Kennedy@Sun.COM
105*9017SJohn.Wren.Kennedy@Sun.COM rdskp = Zalloc(strlen(str) + 2);
106*9017SJohn.Wren.Kennedy@Sun.COM (void) strncpy(rdskp, str, dp - str);
107*9017SJohn.Wren.Kennedy@Sun.COM rdskp[dp - str] = 'r';
108*9017SJohn.Wren.Kennedy@Sun.COM (void) strcpy(rdskp + (dp - str) + 1, dp);
109*9017SJohn.Wren.Kennedy@Sun.COM
110*9017SJohn.Wren.Kennedy@Sun.COM return (rdskp);
111*9017SJohn.Wren.Kennedy@Sun.COM }
112*9017SJohn.Wren.Kennedy@Sun.COM
113*9017SJohn.Wren.Kennedy@Sun.COM /*
114*9017SJohn.Wren.Kennedy@Sun.COM * FUNCTION: rawname()
115*9017SJohn.Wren.Kennedy@Sun.COM * INPUT: uname - Fully qualified pathname of a block or character device
116*9017SJohn.Wren.Kennedy@Sun.COM * RETURNS: char * - The fully qualified character device pathname
117*9017SJohn.Wren.Kennedy@Sun.COM * PURPOSE: Return the fully qualified pathname of the character device
118*9017SJohn.Wren.Kennedy@Sun.COM * corresponding to the block or character device passed in.
119*9017SJohn.Wren.Kennedy@Sun.COM */
120*9017SJohn.Wren.Kennedy@Sun.COM static char *
rawname(char * uname)121*9017SJohn.Wren.Kennedy@Sun.COM rawname(char *uname)
122*9017SJohn.Wren.Kennedy@Sun.COM {
123*9017SJohn.Wren.Kennedy@Sun.COM char *new_path = NULL;
124*9017SJohn.Wren.Kennedy@Sun.COM int ret = -1;
125*9017SJohn.Wren.Kennedy@Sun.COM struct stat statbuf;
126*9017SJohn.Wren.Kennedy@Sun.COM
127*9017SJohn.Wren.Kennedy@Sun.COM if (*uname != '/')
128*9017SJohn.Wren.Kennedy@Sun.COM return (NULL);
129*9017SJohn.Wren.Kennedy@Sun.COM
130*9017SJohn.Wren.Kennedy@Sun.COM if ((new_path = meta_dsk_to_rdsk(uname)) == NULL)
131*9017SJohn.Wren.Kennedy@Sun.COM return (NULL);
132*9017SJohn.Wren.Kennedy@Sun.COM
133*9017SJohn.Wren.Kennedy@Sun.COM if (strncmp("/dev/", new_path, 5) == 0) {
134*9017SJohn.Wren.Kennedy@Sun.COM ret = stat(new_path, &statbuf);
135*9017SJohn.Wren.Kennedy@Sun.COM if (ret != 0 || (! S_ISCHR(statbuf.st_mode))) {
136*9017SJohn.Wren.Kennedy@Sun.COM Free(new_path);
137*9017SJohn.Wren.Kennedy@Sun.COM return (NULL);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate }
140*9017SJohn.Wren.Kennedy@Sun.COM
141*9017SJohn.Wren.Kennedy@Sun.COM return (new_path);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate char *
blkname(char * uname)1450Sstevel@tonic-gate blkname(
1460Sstevel@tonic-gate char *uname
1470Sstevel@tonic-gate )
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate char *p;
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate if ((p = getfullblkname(uname)) == NULL) {
1520Sstevel@tonic-gate return (NULL);
1530Sstevel@tonic-gate } else if (*p == '\0') {
1540Sstevel@tonic-gate Free(p);
1550Sstevel@tonic-gate return (NULL);
1560Sstevel@tonic-gate } else {
1570Sstevel@tonic-gate return (p);
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate * FUNCTION: parse_device()
1630Sstevel@tonic-gate * INPUT: sp - pointer to setname struct
1640Sstevel@tonic-gate * uname - Name of either a hotspare pool or metadevice
1650Sstevel@tonic-gate * This can either be a fully qualified path or
1660Sstevel@tonic-gate * in the form [set name/]device
1671623Stw21770 * OUTPUT: snamep - name of the set that uname is in
1681623Stw21770 * fnamep - metadevice or hsp with path and set name info stripped
1691623Stw21770 * This parameter is dynamically allocated and must be
1701623Stw21770 * freed by the calling function.
1710Sstevel@tonic-gate * PURPOSE: Parse uname and sp into the set name and device name strings.
1720Sstevel@tonic-gate * If the set name is specified as part of uname then use that
1730Sstevel@tonic-gate * otherwise attempt to get the set name from sp.
1740Sstevel@tonic-gate */
1753149Spetede void
parse_device(mdsetname_t * sp,char * uname,char ** fnamep,char ** snamep)1760Sstevel@tonic-gate parse_device(
1770Sstevel@tonic-gate mdsetname_t *sp,
1780Sstevel@tonic-gate char *uname,
1791623Stw21770 char **fnamep, /* dynamically alloced - caller must free */
1801623Stw21770 char **snamep /* dynamically alloced - caller must free */
1810Sstevel@tonic-gate )
1820Sstevel@tonic-gate {
1830Sstevel@tonic-gate char setname[FILENAME_MAX+1];
1841623Stw21770 char devname[FILENAME_MAX+1];
1850Sstevel@tonic-gate char *tname = Malloc(strlen(uname) + 1);
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate int len;
1880Sstevel@tonic-gate char *up;
1890Sstevel@tonic-gate char *tp;
1900Sstevel@tonic-gate int lcws; /* last character was slash */
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate /* Now copy uname to tname by throwing away any duplicate '/' */
1930Sstevel@tonic-gate for (lcws = 0, tp = tname, up = uname; *up; up++) {
1940Sstevel@tonic-gate if (lcws) {
1950Sstevel@tonic-gate if (*up == '/') {
1960Sstevel@tonic-gate continue;
1970Sstevel@tonic-gate } else {
1980Sstevel@tonic-gate lcws = 0;
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate if (*up == '/') {
2020Sstevel@tonic-gate lcws = 1;
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate *tp++ = *up; /* ++ is done by for loop */
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate *tp = '\0';
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate /* fully-qualified - local set */
2090Sstevel@tonic-gate if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
210*9017SJohn.Wren.Kennedy@Sun.COM devname, &len) == 1) && (strlen(tname) == len)) ||
2110Sstevel@tonic-gate ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
212*9017SJohn.Wren.Kennedy@Sun.COM devname, &len) == 1) && (strlen(tname) == len))) {
2131623Stw21770 *snamep = Strdup(MD_LOCAL_NAME);
2141623Stw21770 *fnamep = Strdup(devname);
2150Sstevel@tonic-gate Free(tname);
2160Sstevel@tonic-gate return;
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate /* with setname specified - either fully qualified and relative spec */
2201623Stw21770 if (((sscanf(tname, "%[^/]/%" VAL2STR(FILENAME_MAX) "s%n",
221*9017SJohn.Wren.Kennedy@Sun.COM setname, devname, &len) == 2) && (strlen(tname) == len)) ||
2220Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
223*9017SJohn.Wren.Kennedy@Sun.COM setname, devname, &len) == 2) && (strlen(tname) == len)) ||
2240Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
225*9017SJohn.Wren.Kennedy@Sun.COM setname, devname, &len) == 2) && (strlen(tname) == len))) {
2261623Stw21770
2271623Stw21770 *snamep = Strdup(setname);
2281623Stw21770 *fnamep = Strdup(devname);
2290Sstevel@tonic-gate Free(tname);
2300Sstevel@tonic-gate return;
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /* without setname specified */
2341623Stw21770 *fnamep = tname;
2351623Stw21770 if (sp != NULL && !metaislocalset(sp))
2361623Stw21770 *snamep = Strdup(sp->setname);
2371623Stw21770 else
2381623Stw21770 *snamep = NULL;
2391623Stw21770 }
2401623Stw21770
2411623Stw21770 /*
2421623Stw21770 * check for "all"
2431623Stw21770 */
2441623Stw21770 int
meta_is_all(char * s)2451623Stw21770 meta_is_all(char *s)
2461623Stw21770 {
2471623Stw21770 if ((strcoll(s, gettext("all")) == 0) ||
2481623Stw21770 (strcoll(s, gettext("ALL")) == 0))
2491623Stw21770 return (1);
2501623Stw21770 return (0);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate /*
2541623Stw21770 * check for "none"
2550Sstevel@tonic-gate */
2561623Stw21770 int
meta_is_none(char * s)2571623Stw21770 meta_is_none(char *s)
2581623Stw21770 {
2591623Stw21770 if ((strcoll(s, gettext("none")) == 0) ||
2601623Stw21770 (strcoll(s, gettext("NONE")) == 0))
2611623Stw21770 return (1);
2621623Stw21770 return (0);
2631623Stw21770 }
2641623Stw21770
2650Sstevel@tonic-gate static int
valid_name_syntax(char * uname)2661623Stw21770 valid_name_syntax(char *uname)
2670Sstevel@tonic-gate {
2681623Stw21770 int i;
2691623Stw21770 int uname_len;
2701623Stw21770
2711623Stw21770 if (uname == NULL || !isalpha(uname[0]))
2721623Stw21770 return (0);
2731623Stw21770
2741623Stw21770 uname_len = strlen(uname);
2751623Stw21770 if (uname_len > MAXNAMLEN)
2760Sstevel@tonic-gate return (0);
2771623Stw21770
2781623Stw21770 /* 'all' and 'none' are reserved */
2791623Stw21770 if (meta_is_all(uname) || meta_is_none(uname))
2801623Stw21770 return (0);
2811623Stw21770
2821623Stw21770 for (i = 1; i < uname_len; i++) {
2831623Stw21770 if ((isalnum(uname[i]) || uname[i] == '-' ||
2841623Stw21770 uname[i] == '_' || uname[i] == '.'))
2851623Stw21770 continue;
2861623Stw21770 break;
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate
2891623Stw21770 if (i < uname_len)
2900Sstevel@tonic-gate return (0);
2911623Stw21770
2921623Stw21770 return (1);
2931623Stw21770
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate /*
2971623Stw21770 * canonicalize name
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate char *
meta_canonicalize(mdsetname_t * sp,char * uname)3000Sstevel@tonic-gate meta_canonicalize(
3010Sstevel@tonic-gate mdsetname_t *sp,
3020Sstevel@tonic-gate char *uname
3030Sstevel@tonic-gate )
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate char *sname = NULL;
3061623Stw21770 char *tname = NULL;
3070Sstevel@tonic-gate char *cname;
3080Sstevel@tonic-gate
3091623Stw21770 /* return the dev name and set name */
3101623Stw21770 parse_device(sp, uname, &tname, &sname);
3111623Stw21770
3121623Stw21770 if (!valid_name_syntax(tname)) {
3131623Stw21770 Free(tname);
3141623Stw21770 if (sname != NULL)
315*9017SJohn.Wren.Kennedy@Sun.COM Free(sname);
3161623Stw21770 return (NULL);
3171623Stw21770 }
3181623Stw21770
3191623Stw21770 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
3201623Stw21770 cname = tname;
3210Sstevel@tonic-gate else {
3220Sstevel@tonic-gate size_t cname_len;
3230Sstevel@tonic-gate
3241623Stw21770 cname_len = strlen(tname) + strlen(sname) + 2;
3250Sstevel@tonic-gate cname = Malloc(cname_len);
3260Sstevel@tonic-gate (void) snprintf(
3271623Stw21770 cname, cname_len, "%s/%s", sname, tname);
3281623Stw21770 Free(tname);
3291623Stw21770 }
3301623Stw21770
3311623Stw21770 if (sname != NULL)
332*9017SJohn.Wren.Kennedy@Sun.COM Free(sname);
3331623Stw21770
3341623Stw21770 return (cname);
3351623Stw21770 }
3361623Stw21770
3371623Stw21770 /*
3381623Stw21770 * canonicalize name and check the set
3391623Stw21770 */
3401623Stw21770 char *
meta_canonicalize_check_set(mdsetname_t ** spp,char * uname,md_error_t * ep)3411623Stw21770 meta_canonicalize_check_set(
3421623Stw21770 mdsetname_t **spp,
3431623Stw21770 char *uname,
3441623Stw21770 md_error_t *ep
3451623Stw21770 )
3461623Stw21770 {
3471623Stw21770 char *sname = NULL;
3481623Stw21770 char *tname = NULL;
3491623Stw21770 char *cname;
3501623Stw21770
3511623Stw21770 /* return the dev name and set name */
3521623Stw21770 parse_device(*spp, uname, &tname, &sname);
3531623Stw21770
3541623Stw21770 if (!valid_name_syntax(tname)) {
3551623Stw21770 (void) mderror(ep, MDE_NAME_ILLEGAL, tname);
3561623Stw21770 if (sname != NULL)
3571623Stw21770 Free(sname);
3581623Stw21770 Free(tname);
3591623Stw21770 return (NULL);
3601623Stw21770 }
3611623Stw21770
3621623Stw21770 /* check the set name returned from the name for validity */
3631623Stw21770 if (chksetname(spp, sname, ep) != 0) {
3641623Stw21770 Free(tname);
3651623Stw21770 if (sname != NULL)
366*9017SJohn.Wren.Kennedy@Sun.COM Free(sname);
3671623Stw21770 return (NULL);
3681623Stw21770 }
3691623Stw21770
3701623Stw21770 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
3711623Stw21770 cname = tname;
3721623Stw21770 else {
3731623Stw21770 size_t cname_len;
3741623Stw21770
3751623Stw21770 cname_len = strlen(tname) + strlen(sname) + 2;
3761623Stw21770 cname = Malloc(cname_len);
3771623Stw21770 (void) snprintf(
3781623Stw21770 cname, cname_len, "%s/%s", sname, tname);
3791623Stw21770 Free(tname);
3801623Stw21770 }
3811623Stw21770
3821623Stw21770 if (sname != NULL)
383*9017SJohn.Wren.Kennedy@Sun.COM Free(sname);
3841623Stw21770
3851623Stw21770 return (cname);
3861623Stw21770 }
3871623Stw21770
3881623Stw21770 /*
3891623Stw21770 * Verify that the name is a valid hsp/metadevice name
3901623Stw21770 */
3911623Stw21770 static int
parse_meta_hsp_name(char * uname)3921623Stw21770 parse_meta_hsp_name(char *uname)
3931623Stw21770 {
3941623Stw21770 char *sname = NULL;
3951623Stw21770 char *tname = NULL;
3961623Stw21770 int ret;
3971623Stw21770
3981623Stw21770 /* return the dev name and set name */
3991623Stw21770 parse_device(NULL, uname, &tname, &sname);
4001623Stw21770
4011623Stw21770 ret = valid_name_syntax(tname);
4021623Stw21770 if (sname != NULL)
4030Sstevel@tonic-gate Free(sname);
4041623Stw21770 Free(tname);
4051623Stw21770 return (ret);
4060Sstevel@tonic-gate }
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate /*
4090Sstevel@tonic-gate * check that name is a metadevice
4100Sstevel@tonic-gate */
4110Sstevel@tonic-gate int
is_metaname(char * uname)4120Sstevel@tonic-gate is_metaname(
4130Sstevel@tonic-gate char *uname
4140Sstevel@tonic-gate )
4150Sstevel@tonic-gate {
4161623Stw21770 return (parse_meta_hsp_name(uname));
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate /*
4200Sstevel@tonic-gate * check that name is a hotspare pool
4210Sstevel@tonic-gate */
4220Sstevel@tonic-gate int
is_hspname(char * uname)4230Sstevel@tonic-gate is_hspname(
4240Sstevel@tonic-gate char *uname
4250Sstevel@tonic-gate )
4260Sstevel@tonic-gate {
4271623Stw21770 return (parse_meta_hsp_name(uname));
4281623Stw21770 }
4291623Stw21770
4301623Stw21770 /*
4311623Stw21770 * check to verify that name is an existing metadevice
4321623Stw21770 */
4331623Stw21770 int
is_existing_metadevice(mdsetname_t * sp,char * uname)4341623Stw21770 is_existing_metadevice(
4351623Stw21770 mdsetname_t *sp,
4361623Stw21770 char *uname
4371623Stw21770 )
4381623Stw21770 {
4391623Stw21770 char *raw_name;
4401623Stw21770 char *set_name;
4411623Stw21770 char *full_path;
4421623Stw21770 char *fname = NULL;
4431623Stw21770 int pathlen;
4441623Stw21770 int retval = 0;
4451623Stw21770
4461623Stw21770 assert(uname != NULL);
4471623Stw21770 /*
4481623Stw21770 * If it is an absolute name of a metadevice, then just call rawname
4491623Stw21770 * on the input
4501623Stw21770 */
4511623Stw21770 if (uname[0] == '/') {
4521623Stw21770 if (strncmp("/dev/md", uname, strlen("/dev/md")) == 0 &&
453*9017SJohn.Wren.Kennedy@Sun.COM (raw_name = rawname(uname)) != NULL) {
454*9017SJohn.Wren.Kennedy@Sun.COM Free(raw_name);
455*9017SJohn.Wren.Kennedy@Sun.COM return (1);
4561623Stw21770 }
4571623Stw21770 return (0);
4581623Stw21770 }
4591623Stw21770
4601623Stw21770 /* create a fully specified path from the parsed string */
4611623Stw21770 parse_device(sp, uname, &fname, &set_name);
4621623Stw21770
4631623Stw21770 if ((set_name == NULL) || (strcmp(set_name, MD_LOCAL_NAME) == 0)) {
4641623Stw21770 pathlen = strlen("/dev/md/rdsk/") + strlen(fname) + 1;
4651623Stw21770 full_path = Zalloc(pathlen);
4661623Stw21770 (void) snprintf(full_path, pathlen, "/dev/md/rdsk/%s", fname);
4671623Stw21770 } else {
4681623Stw21770 pathlen = strlen("/dev/md//rdsk/") + strlen(fname) +
4691623Stw21770 strlen(set_name) + 1;
4701623Stw21770 full_path = Zalloc(pathlen);
4711623Stw21770 (void) snprintf(full_path, pathlen, "/dev/md/%s/rdsk/%s",
4721623Stw21770 set_name, fname);
4731623Stw21770 }
4741623Stw21770
4751623Stw21770 if ((raw_name = rawname(full_path)) != NULL) {
476*9017SJohn.Wren.Kennedy@Sun.COM Free(raw_name);
477*9017SJohn.Wren.Kennedy@Sun.COM retval = 1;
4781623Stw21770 }
4791623Stw21770
4801623Stw21770 if (set_name != NULL)
4811623Stw21770 Free(set_name);
4821623Stw21770
4831623Stw21770 Free(fname);
4841623Stw21770 Free(full_path);
4851623Stw21770 return (retval);
4861623Stw21770 }
4871623Stw21770
4881623Stw21770 /*
4891623Stw21770 * check to verify that name is an existing hsp
4901623Stw21770 */
4911623Stw21770 int
is_existing_hsp(mdsetname_t * sp,char * uname)4921623Stw21770 is_existing_hsp(
4931623Stw21770 mdsetname_t *sp,
4941623Stw21770 char *uname
4951623Stw21770 )
4961623Stw21770 {
4971623Stw21770 md_error_t status = mdnullerror;
4981623Stw21770 hsp_t hsp;
4991623Stw21770 set_t cur_set;
5001623Stw21770
5011623Stw21770 if (sp != NULL)
5021623Stw21770 cur_set = sp->setno;
5031623Stw21770 else
5041623Stw21770 cur_set = 0;
5051623Stw21770
5061623Stw21770 hsp = meta_gethspnmentbyname(cur_set, MD_SIDEWILD, uname, &status);
5071623Stw21770
5081623Stw21770 if (hsp == MD_HSP_NONE) {
5091623Stw21770 mdclrerror(&status);
5101623Stw21770 return (0);
5111623Stw21770 }
5121623Stw21770 return (1);
5131623Stw21770 }
5141623Stw21770
5151623Stw21770 /*
5161623Stw21770 * check to verify that name is an existing metadevice or hotspare pool
5171623Stw21770 */
5181623Stw21770 int
is_existing_meta_hsp(mdsetname_t * sp,char * uname)5191623Stw21770 is_existing_meta_hsp(
5201623Stw21770 mdsetname_t *sp,
5211623Stw21770 char *uname
5221623Stw21770 )
5231623Stw21770 {
5241623Stw21770 if (is_existing_metadevice(sp, uname) ||
5251623Stw21770 is_existing_hsp(sp, uname))
5260Sstevel@tonic-gate return (1);
5271623Stw21770
5281623Stw21770 return (0);
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate /*
5320Sstevel@tonic-gate * mdsetname_t stuff
5330Sstevel@tonic-gate */
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate /*
5360Sstevel@tonic-gate * initialize setname
5370Sstevel@tonic-gate */
5380Sstevel@tonic-gate static void
metainitsetname(mdsetname_t * sp)5390Sstevel@tonic-gate metainitsetname(
5400Sstevel@tonic-gate mdsetname_t *sp
5410Sstevel@tonic-gate )
5420Sstevel@tonic-gate {
5430Sstevel@tonic-gate (void) memset(sp, '\0', sizeof (*sp));
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate static void
metafreesetdesc(md_set_desc * sd)5470Sstevel@tonic-gate metafreesetdesc(md_set_desc *sd)
5480Sstevel@tonic-gate {
5490Sstevel@tonic-gate md_mnnode_desc *nd;
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
5520Sstevel@tonic-gate nd = sd->sd_nodelist;
5530Sstevel@tonic-gate while (nd) {
5540Sstevel@tonic-gate sd->sd_nodelist = nd->nd_next;
5550Sstevel@tonic-gate Free(nd);
5560Sstevel@tonic-gate nd = sd->sd_nodelist;
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate metafreedrivedesc(&sd->sd_drvs);
5600Sstevel@tonic-gate Free(sd);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /*
5640Sstevel@tonic-gate * free allocated setname
5650Sstevel@tonic-gate */
5660Sstevel@tonic-gate static void
metafreesetname(mdsetname_t * sp)5670Sstevel@tonic-gate metafreesetname(
5680Sstevel@tonic-gate mdsetname_t *sp
5690Sstevel@tonic-gate )
5700Sstevel@tonic-gate {
5710Sstevel@tonic-gate if (sp->setname != NULL)
5720Sstevel@tonic-gate Free(sp->setname);
5730Sstevel@tonic-gate if (sp->setdesc != NULL)
5740Sstevel@tonic-gate metafreesetdesc(sp->setdesc);
5750Sstevel@tonic-gate metainitsetname(sp);
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate /*
5790Sstevel@tonic-gate * flush the setname cache
5800Sstevel@tonic-gate */
5810Sstevel@tonic-gate static void
metaflushsetnames()5820Sstevel@tonic-gate metaflushsetnames()
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate mdsetnamelist_t *p, *n;
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate for (p = setlistp, n = NULL; (p != NULL); p = n) {
5870Sstevel@tonic-gate n = p->next;
5880Sstevel@tonic-gate metafreesetname(p->sp);
5890Sstevel@tonic-gate Free(p->sp);
5900Sstevel@tonic-gate Free(p);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate setlistp = NULL;
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate /*
5960Sstevel@tonic-gate * get set number
5970Sstevel@tonic-gate */
5980Sstevel@tonic-gate static int
getsetno(char * sname,set_t * setnop,md_error_t * ep)5990Sstevel@tonic-gate getsetno(
6000Sstevel@tonic-gate char *sname,
6010Sstevel@tonic-gate set_t *setnop,
6020Sstevel@tonic-gate md_error_t *ep
6030Sstevel@tonic-gate )
6040Sstevel@tonic-gate {
6050Sstevel@tonic-gate md_set_record *sr;
6060Sstevel@tonic-gate size_t len;
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate /* local set */
6090Sstevel@tonic-gate if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
6100Sstevel@tonic-gate *setnop = 0;
6110Sstevel@tonic-gate return (0);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate /* shared set */
6150Sstevel@tonic-gate if ((sr = getsetbyname(sname, ep)) == NULL) {
6160Sstevel@tonic-gate if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) {
6170Sstevel@tonic-gate char *p;
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate len = strlen(sname) + 30;
6200Sstevel@tonic-gate p = Malloc(len);
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate (void) snprintf(p, len, "setname \"%s\"", sname);
6230Sstevel@tonic-gate (void) mderror(ep, MDE_NO_SET, p);
6240Sstevel@tonic-gate Free(p);
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate return (-1);
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate *setnop = sr->sr_setno;
6290Sstevel@tonic-gate free_sr(sr);
6300Sstevel@tonic-gate return (0);
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate /*
6340Sstevel@tonic-gate * find setname from name
6350Sstevel@tonic-gate */
6360Sstevel@tonic-gate mdsetname_t *
metasetname(char * sname,md_error_t * ep)6370Sstevel@tonic-gate metasetname(
6380Sstevel@tonic-gate char *sname,
6390Sstevel@tonic-gate md_error_t *ep
6400Sstevel@tonic-gate )
6410Sstevel@tonic-gate {
6420Sstevel@tonic-gate mdsetnamelist_t **tail;
6430Sstevel@tonic-gate set_t setno;
6440Sstevel@tonic-gate mdsetname_t *sp;
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate /* look for cached value first */
6470Sstevel@tonic-gate assert(sname != NULL);
6480Sstevel@tonic-gate for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) {
6490Sstevel@tonic-gate sp = (*tail)->sp;
6500Sstevel@tonic-gate if (strcmp(sp->setname, sname) == 0) {
6510Sstevel@tonic-gate return (sp);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate }
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate /* setup set */
6560Sstevel@tonic-gate if (getsetno(sname, &setno, ep) != 0)
6570Sstevel@tonic-gate return (NULL);
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /* allocate new list element and setname */
6600Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail));
6610Sstevel@tonic-gate sp = (*tail)->sp = Zalloc(sizeof (*sp));
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate sp->setname = Strdup(sname);
6640Sstevel@tonic-gate sp->setno = setno;
6650Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK;
6660Sstevel@tonic-gate
6670Sstevel@tonic-gate return (sp);
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate /*
6710Sstevel@tonic-gate * find setname from setno
6720Sstevel@tonic-gate */
6730Sstevel@tonic-gate mdsetname_t *
metasetnosetname(set_t setno,md_error_t * ep)6740Sstevel@tonic-gate metasetnosetname(
6750Sstevel@tonic-gate set_t setno,
6760Sstevel@tonic-gate md_error_t *ep
6770Sstevel@tonic-gate )
6780Sstevel@tonic-gate {
6790Sstevel@tonic-gate mdsetnamelist_t *slp;
6800Sstevel@tonic-gate mdsetname_t *sp;
6810Sstevel@tonic-gate md_set_record *sr;
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate /* look for cached value first */
6840Sstevel@tonic-gate for (slp = setlistp; (slp != NULL); slp = slp->next) {
6850Sstevel@tonic-gate sp = slp->sp;
6860Sstevel@tonic-gate if (sp->setno == setno)
6870Sstevel@tonic-gate return (sp);
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate /* local set */
6910Sstevel@tonic-gate if (setno == MD_LOCAL_SET)
6920Sstevel@tonic-gate return (metasetname(MD_LOCAL_NAME, ep));
6930Sstevel@tonic-gate
6940Sstevel@tonic-gate /* shared set */
6950Sstevel@tonic-gate if ((sr = getsetbynum(setno, ep)) == NULL)
6960Sstevel@tonic-gate return (NULL);
6970Sstevel@tonic-gate sp = metasetname(sr->sr_setname, ep);
6980Sstevel@tonic-gate free_sr(sr);
6990Sstevel@tonic-gate return (sp);
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate mdsetname_t *
metafakesetname(set_t setno,char * sname)7030Sstevel@tonic-gate metafakesetname(
7040Sstevel@tonic-gate set_t setno,
7050Sstevel@tonic-gate char *sname
7060Sstevel@tonic-gate )
7070Sstevel@tonic-gate {
7080Sstevel@tonic-gate mdsetnamelist_t **tail;
7090Sstevel@tonic-gate mdsetname_t *sp;
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate /* look for cached value first */
7120Sstevel@tonic-gate for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) {
7130Sstevel@tonic-gate sp = (*tail)->sp;
7140Sstevel@tonic-gate if (sp->setno == setno) {
7150Sstevel@tonic-gate if ((sp->setname == NULL) && (sname != NULL))
7160Sstevel@tonic-gate sp->setname = Strdup(sname);
7170Sstevel@tonic-gate return (sp);
7180Sstevel@tonic-gate }
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate /* allocate new list element and setname */
7220Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail));
7230Sstevel@tonic-gate sp = (*tail)->sp = Zalloc(sizeof (*sp));
7240Sstevel@tonic-gate
7250Sstevel@tonic-gate if (sname != NULL)
7260Sstevel@tonic-gate sp->setname = Strdup(sname);
7270Sstevel@tonic-gate sp->setno = setno;
7280Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK;
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate return (sp);
7310Sstevel@tonic-gate }
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate /*
7350Sstevel@tonic-gate * setup set record (sr) and cache it in the mdsetname_t struct
7360Sstevel@tonic-gate */
7370Sstevel@tonic-gate md_set_desc *
sr2setdesc(md_set_record * sr)7380Sstevel@tonic-gate sr2setdesc(
7390Sstevel@tonic-gate md_set_record *sr
7400Sstevel@tonic-gate )
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate md_set_desc *sd;
7430Sstevel@tonic-gate int i;
7440Sstevel@tonic-gate md_mnset_record *mnsr;
7450Sstevel@tonic-gate md_mnnode_desc *nd, *nd_prev = 0;
7460Sstevel@tonic-gate md_mnnode_record *nr;
7470Sstevel@tonic-gate md_error_t status = mdnullerror;
7480Sstevel@tonic-gate md_error_t *ep = &status;
7490Sstevel@tonic-gate int nodecnt, nrcnt;
7500Sstevel@tonic-gate mndiskset_membershiplist_t *nl, *nl2;
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate sd = Zalloc(sizeof (*sd));
7530Sstevel@tonic-gate sd->sd_ctime = sr->sr_ctime;
7540Sstevel@tonic-gate sd->sd_genid = sr->sr_genid;
7550Sstevel@tonic-gate sd->sd_setno = sr->sr_setno;
7560Sstevel@tonic-gate sd->sd_flags = sr->sr_flags;
7570Sstevel@tonic-gate
7580Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
7590Sstevel@tonic-gate mnsr = (md_mnset_record *)sr;
7600Sstevel@tonic-gate (void) strlcpy(sd->sd_mn_master_nodenm,
7610Sstevel@tonic-gate mnsr->sr_master_nodenm, sizeof (sd->sd_mn_master_nodenm));
7620Sstevel@tonic-gate sd->sd_mn_master_nodeid = mnsr->sr_master_nodeid;
7630Sstevel@tonic-gate if (strcmp(mnsr->sr_master_nodenm, mynode()) == 0) {
7640Sstevel@tonic-gate sd->sd_mn_am_i_master = 1;
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate /*
7680Sstevel@tonic-gate * Get membershiplist from API routine. If there's
7690Sstevel@tonic-gate * an error, just use a NULL nodelist.
7700Sstevel@tonic-gate */
7710Sstevel@tonic-gate if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
7720Sstevel@tonic-gate nodecnt = 0; /* no nodes are alive */
7730Sstevel@tonic-gate nl = NULL;
7740Sstevel@tonic-gate }
7750Sstevel@tonic-gate nr = mnsr->sr_nodechain;
7760Sstevel@tonic-gate nrcnt = 0;
7770Sstevel@tonic-gate /*
7780Sstevel@tonic-gate * Node descriptor node list must be built in
7790Sstevel@tonic-gate * ascending order of nodeid. The nodechain
7800Sstevel@tonic-gate * in the mnset record is in ascending order,
7810Sstevel@tonic-gate * so just make them the same.
7820Sstevel@tonic-gate */
7830Sstevel@tonic-gate while (nr) {
7840Sstevel@tonic-gate nd = Zalloc(sizeof (*nd));
7850Sstevel@tonic-gate if (nd_prev) {
7860Sstevel@tonic-gate nd_prev->nd_next = nd;
7870Sstevel@tonic-gate } else {
7880Sstevel@tonic-gate sd->sd_nodelist = nd;
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate nd->nd_ctime = nr->nr_ctime;
7910Sstevel@tonic-gate nd->nd_genid = nr->nr_genid;
7920Sstevel@tonic-gate nd->nd_flags = nr->nr_flags;
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate (void) strlcpy(nd->nd_nodename, nr->nr_nodename,
7950Sstevel@tonic-gate sizeof (nd->nd_nodename));
7960Sstevel@tonic-gate nd->nd_nodeid = nr->nr_nodeid;
7970Sstevel@tonic-gate if (strcmp(nd->nd_nodename, mynode()) == 0) {
7980Sstevel@tonic-gate sd->sd_mn_mynode = nd;
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate if (nd->nd_nodeid == sd->sd_mn_master_nodeid) {
8010Sstevel@tonic-gate sd->sd_mn_masternode = nd;
8020Sstevel@tonic-gate }
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate /*
8050Sstevel@tonic-gate * If node is marked ALIVE, then set priv_ic
8060Sstevel@tonic-gate * from membership list. During the early part
8070Sstevel@tonic-gate * of a reconfig cycle, the membership list may
8080Sstevel@tonic-gate * have been changed, (a node entering or leaving
8090Sstevel@tonic-gate * the cluster), but rpc.metad hasn't flushed
8100Sstevel@tonic-gate * its data yet. So, if node is marked alive, but
8110Sstevel@tonic-gate * is no longer in the membership list (node has
8120Sstevel@tonic-gate * left the cluster) then just leave priv_ic to NULL.
8130Sstevel@tonic-gate */
8140Sstevel@tonic-gate if (nd->nd_flags & MD_MN_NODE_ALIVE) {
8150Sstevel@tonic-gate nl2 = nl;
8160Sstevel@tonic-gate while (nl2) {
8170Sstevel@tonic-gate if (nl2->msl_node_id == nd->nd_nodeid) {
8180Sstevel@tonic-gate (void) strlcpy(nd->nd_priv_ic,
8190Sstevel@tonic-gate nl2->msl_node_addr,
8200Sstevel@tonic-gate sizeof (nd->nd_priv_ic));
8210Sstevel@tonic-gate break;
8220Sstevel@tonic-gate }
8230Sstevel@tonic-gate nl2 = nl2->next;
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate
8270Sstevel@tonic-gate nr = nr->nr_next;
8280Sstevel@tonic-gate nrcnt++;
8290Sstevel@tonic-gate nd_prev = nd;
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate sd->sd_mn_numnodes = nrcnt;
8320Sstevel@tonic-gate if (nodecnt)
8330Sstevel@tonic-gate meta_free_nodelist(nl);
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate /* Just copying to keep consistent view between sr & sd */
8360Sstevel@tonic-gate (void) strlcpy(sd->sd_nodes[0], mnsr->sr_nodes_bw_compat[0],
8370Sstevel@tonic-gate sizeof (sd->sd_nodes[0]));
8380Sstevel@tonic-gate } else {
8390Sstevel@tonic-gate for (i = 0; i < MD_MAXSIDES; i++)
8400Sstevel@tonic-gate (void) strlcpy(sd->sd_nodes[i], sr->sr_nodes[i],
8410Sstevel@tonic-gate sizeof (sd->sd_nodes[i]));
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate sd->sd_med = sr->sr_med; /* structure assignment */
8450Sstevel@tonic-gate
8460Sstevel@tonic-gate return (sd);
8470Sstevel@tonic-gate }
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate md_set_desc *
metaget_setdesc(mdsetname_t * sp,md_error_t * ep)8500Sstevel@tonic-gate metaget_setdesc(
8510Sstevel@tonic-gate mdsetname_t *sp,
8520Sstevel@tonic-gate md_error_t *ep
8530Sstevel@tonic-gate )
8540Sstevel@tonic-gate {
8550Sstevel@tonic-gate md_set_record *sr;
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate if (sp->setdesc != NULL)
8580Sstevel@tonic-gate return (sp->setdesc);
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate if (sp->setname != NULL) {
8610Sstevel@tonic-gate if ((sr = getsetbyname(sp->setname, ep)) != NULL) {
8620Sstevel@tonic-gate sp->setdesc = sr2setdesc(sr);
8630Sstevel@tonic-gate free_sr(sr);
8640Sstevel@tonic-gate return (sp->setdesc);
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate if (sp->setno > 0) {
8690Sstevel@tonic-gate if ((sr = getsetbynum(sp->setno, ep)) != NULL) {
8700Sstevel@tonic-gate sp->setdesc = sr2setdesc(sr);
8710Sstevel@tonic-gate free_sr(sr);
8720Sstevel@tonic-gate return (sp->setdesc);
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate return (NULL);
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate void
metaflushsetname(mdsetname_t * sp)8800Sstevel@tonic-gate metaflushsetname(mdsetname_t *sp)
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate if (sp == NULL)
8830Sstevel@tonic-gate return;
8840Sstevel@tonic-gate
8850Sstevel@tonic-gate if (sp->setdesc == NULL)
8860Sstevel@tonic-gate return;
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate metafreesetdesc(sp->setdesc);
8890Sstevel@tonic-gate sp->setdesc = NULL;
8900Sstevel@tonic-gate }
8910Sstevel@tonic-gate
8920Sstevel@tonic-gate /*
8930Sstevel@tonic-gate * check for local set
8940Sstevel@tonic-gate */
8950Sstevel@tonic-gate int
metaislocalset(mdsetname_t * sp)8960Sstevel@tonic-gate metaislocalset(
8970Sstevel@tonic-gate mdsetname_t *sp
8980Sstevel@tonic-gate )
8990Sstevel@tonic-gate {
9000Sstevel@tonic-gate assert(sp->setname != NULL);
9010Sstevel@tonic-gate if (strcmp(sp->setname, MD_LOCAL_NAME) == 0) {
9020Sstevel@tonic-gate assert(sp->setno == MD_LOCAL_SET);
9030Sstevel@tonic-gate return (1);
9040Sstevel@tonic-gate } else {
9050Sstevel@tonic-gate assert(sp->setno != MD_LOCAL_SET);
9060Sstevel@tonic-gate return (0);
9070Sstevel@tonic-gate }
9080Sstevel@tonic-gate }
9090Sstevel@tonic-gate
9100Sstevel@tonic-gate /*
9110Sstevel@tonic-gate * check for same set
9120Sstevel@tonic-gate */
9130Sstevel@tonic-gate int
metaissameset(mdsetname_t * sp1,mdsetname_t * sp2)9140Sstevel@tonic-gate metaissameset(
9150Sstevel@tonic-gate mdsetname_t *sp1,
9160Sstevel@tonic-gate mdsetname_t *sp2
9170Sstevel@tonic-gate )
9180Sstevel@tonic-gate {
9190Sstevel@tonic-gate if (strcmp(sp1->setname, sp2->setname) == 0) {
9200Sstevel@tonic-gate assert(sp1->setno == sp2->setno);
9210Sstevel@tonic-gate return (1);
9220Sstevel@tonic-gate } else {
9230Sstevel@tonic-gate assert(sp1->setno != sp2->setno);
9240Sstevel@tonic-gate return (0);
9250Sstevel@tonic-gate }
9260Sstevel@tonic-gate }
9270Sstevel@tonic-gate
9280Sstevel@tonic-gate /*
9290Sstevel@tonic-gate * check to see if set changed
9300Sstevel@tonic-gate */
9310Sstevel@tonic-gate static int
chkset(mdsetname_t ** spp,char * sname,md_error_t * ep)9320Sstevel@tonic-gate chkset(
9330Sstevel@tonic-gate mdsetname_t **spp,
9340Sstevel@tonic-gate char *sname,
9350Sstevel@tonic-gate md_error_t *ep
9360Sstevel@tonic-gate )
9370Sstevel@tonic-gate {
9380Sstevel@tonic-gate /* if we already have a set, make sure it's the same */
9391623Stw21770 if (*spp != NULL && !metaislocalset(*spp)) {
9400Sstevel@tonic-gate if ((*spp)->setname != sname &&
941*9017SJohn.Wren.Kennedy@Sun.COM strcmp((*spp)->setname, sname) != 0) {
9420Sstevel@tonic-gate return (mderror(ep, MDE_SET_DIFF, sname));
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate return (0);
9450Sstevel@tonic-gate }
9460Sstevel@tonic-gate
9470Sstevel@tonic-gate /* otherwise store new set name and number */
9480Sstevel@tonic-gate if ((*spp = metasetname(sname, ep)) == NULL) {
9490Sstevel@tonic-gate return (-1);
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate
9520Sstevel@tonic-gate /* return success */
9530Sstevel@tonic-gate return (0);
9540Sstevel@tonic-gate }
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate /*
9570Sstevel@tonic-gate * check to see if set changed from default
9580Sstevel@tonic-gate */
9590Sstevel@tonic-gate static int
chksetname(mdsetname_t ** spp,char * sname,md_error_t * ep)9600Sstevel@tonic-gate chksetname(
9610Sstevel@tonic-gate mdsetname_t **spp,
9620Sstevel@tonic-gate char *sname,
9630Sstevel@tonic-gate md_error_t *ep
9640Sstevel@tonic-gate )
9650Sstevel@tonic-gate {
9660Sstevel@tonic-gate /* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */
9670Sstevel@tonic-gate if (sname == NULL) {
9680Sstevel@tonic-gate if (*spp) {
9691623Stw21770 return (0);
9700Sstevel@tonic-gate } else {
9710Sstevel@tonic-gate sname = MD_LOCAL_NAME;
9720Sstevel@tonic-gate }
9730Sstevel@tonic-gate }
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate /* see if changed */
9760Sstevel@tonic-gate return (chkset(spp, sname, ep));
9770Sstevel@tonic-gate }
9780Sstevel@tonic-gate
9790Sstevel@tonic-gate /*
9800Sstevel@tonic-gate * check setname from setno
9810Sstevel@tonic-gate */
9820Sstevel@tonic-gate static int
chksetno(mdsetname_t ** spp,set_t setno,md_error_t * ep)9830Sstevel@tonic-gate chksetno(
9840Sstevel@tonic-gate mdsetname_t **spp,
9850Sstevel@tonic-gate set_t setno,
9860Sstevel@tonic-gate md_error_t *ep
9870Sstevel@tonic-gate )
9880Sstevel@tonic-gate {
9890Sstevel@tonic-gate md_set_record *sr;
9900Sstevel@tonic-gate int rval;
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate /* local set */
9930Sstevel@tonic-gate if (setno == 0)
9940Sstevel@tonic-gate return (chkset(spp, MD_LOCAL_NAME, ep));
9950Sstevel@tonic-gate
9960Sstevel@tonic-gate /* shared set */
9970Sstevel@tonic-gate if ((sr = getsetbynum(setno, ep)) == NULL)
9980Sstevel@tonic-gate return (-1);
9990Sstevel@tonic-gate rval = chkset(spp, sr->sr_setname, ep);
10000Sstevel@tonic-gate free_sr(sr);
10010Sstevel@tonic-gate return (rval);
10020Sstevel@tonic-gate }
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate /*
10050Sstevel@tonic-gate * mddrivename_t stuff
10060Sstevel@tonic-gate */
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate /*
10090Sstevel@tonic-gate * initialize name
10100Sstevel@tonic-gate */
10110Sstevel@tonic-gate static void
metainitname(mdname_t * np)10120Sstevel@tonic-gate metainitname(
10130Sstevel@tonic-gate mdname_t *np
10140Sstevel@tonic-gate )
10150Sstevel@tonic-gate {
10160Sstevel@tonic-gate (void) memset(np, 0, sizeof (*np));
10170Sstevel@tonic-gate np->dev = NODEV64;
10180Sstevel@tonic-gate np->key = MD_KEYBAD;
10190Sstevel@tonic-gate np->end_blk = -1;
10200Sstevel@tonic-gate np->start_blk = -1;
10210Sstevel@tonic-gate }
10220Sstevel@tonic-gate
10230Sstevel@tonic-gate /*
10240Sstevel@tonic-gate * free allocated name
10250Sstevel@tonic-gate */
10260Sstevel@tonic-gate static void
metafreename(mdname_t * np)10270Sstevel@tonic-gate metafreename(
10280Sstevel@tonic-gate mdname_t *np
10290Sstevel@tonic-gate )
10300Sstevel@tonic-gate {
10310Sstevel@tonic-gate if (np->cname != NULL)
10320Sstevel@tonic-gate Free(np->cname);
10330Sstevel@tonic-gate if (np->bname != NULL)
10340Sstevel@tonic-gate Free(np->bname);
10350Sstevel@tonic-gate if (np->rname != NULL)
10360Sstevel@tonic-gate Free(np->rname);
10370Sstevel@tonic-gate if (np->devicesname != NULL)
10380Sstevel@tonic-gate Free(np->devicesname);
10390Sstevel@tonic-gate metainitname(np);
10400Sstevel@tonic-gate }
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate /*
10430Sstevel@tonic-gate * initialize drive name
10440Sstevel@tonic-gate */
10450Sstevel@tonic-gate static void
metainitdrivename(mddrivename_t * dnp)10460Sstevel@tonic-gate metainitdrivename(
10470Sstevel@tonic-gate mddrivename_t *dnp
10480Sstevel@tonic-gate )
10490Sstevel@tonic-gate {
10500Sstevel@tonic-gate (void) memset(dnp, 0, sizeof (*dnp));
10510Sstevel@tonic-gate dnp->side_names_key = MD_KEYBAD;
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate /*
10550Sstevel@tonic-gate * flush side names
10560Sstevel@tonic-gate */
10570Sstevel@tonic-gate void
metaflushsidenames(mddrivename_t * dnp)10580Sstevel@tonic-gate metaflushsidenames(
10590Sstevel@tonic-gate mddrivename_t *dnp
10600Sstevel@tonic-gate )
10610Sstevel@tonic-gate {
10620Sstevel@tonic-gate mdsidenames_t *p, *n;
10630Sstevel@tonic-gate
10640Sstevel@tonic-gate for (p = dnp->side_names, n = NULL; (p != NULL); p = n) {
10650Sstevel@tonic-gate n = p->next;
10660Sstevel@tonic-gate if (p->dname != NULL)
10670Sstevel@tonic-gate Free(p->dname);
10680Sstevel@tonic-gate if (p->cname != NULL)
10690Sstevel@tonic-gate Free(p->cname);
10700Sstevel@tonic-gate Free(p);
10710Sstevel@tonic-gate }
10720Sstevel@tonic-gate dnp->side_names = NULL;
10730Sstevel@tonic-gate }
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate /*
10760Sstevel@tonic-gate * free drive name
10770Sstevel@tonic-gate */
10780Sstevel@tonic-gate void
metafreedrivename(mddrivename_t * dnp)10790Sstevel@tonic-gate metafreedrivename(
10800Sstevel@tonic-gate mddrivename_t *dnp
10810Sstevel@tonic-gate )
10820Sstevel@tonic-gate {
10830Sstevel@tonic-gate uint_t slice;
10840Sstevel@tonic-gate
10850Sstevel@tonic-gate if (dnp->cname != NULL)
10860Sstevel@tonic-gate Free(dnp->cname);
10870Sstevel@tonic-gate if (dnp->rname != NULL)
10880Sstevel@tonic-gate Free(dnp->rname);
10890Sstevel@tonic-gate metafreevtoc(&dnp->vtoc);
10900Sstevel@tonic-gate for (slice = 0; (slice < dnp->parts.parts_len); ++slice)
10910Sstevel@tonic-gate metafreename(&dnp->parts.parts_val[slice]);
10920Sstevel@tonic-gate if (dnp->parts.parts_val != NULL)
10930Sstevel@tonic-gate Free(dnp->parts.parts_val);
10940Sstevel@tonic-gate metaflushsidenames(dnp);
10950Sstevel@tonic-gate if (dnp->miscname != NULL)
10960Sstevel@tonic-gate Free(dnp->miscname);
10970Sstevel@tonic-gate meta_free_unit(dnp);
10980Sstevel@tonic-gate metainitdrivename(dnp);
10990Sstevel@tonic-gate }
11000Sstevel@tonic-gate
11010Sstevel@tonic-gate /*
11020Sstevel@tonic-gate * flush the drive name cache
11030Sstevel@tonic-gate */
11041945Sjeanm void
metaflushdrivenames()11050Sstevel@tonic-gate metaflushdrivenames()
11060Sstevel@tonic-gate {
11070Sstevel@tonic-gate mddrivenamelist_t *p, *n;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate for (p = drivelistp, n = NULL; (p != NULL); p = n) {
11100Sstevel@tonic-gate n = p->next;
11110Sstevel@tonic-gate metafreedrivename(p->drivenamep);
11120Sstevel@tonic-gate Free(p->drivenamep);
11130Sstevel@tonic-gate Free(p);
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate drivelistp = NULL;
11160Sstevel@tonic-gate }
11170Sstevel@tonic-gate
11180Sstevel@tonic-gate /*
11190Sstevel@tonic-gate * peel off s%u from name
11200Sstevel@tonic-gate */
11210Sstevel@tonic-gate char *
metadiskname(char * name)11220Sstevel@tonic-gate metadiskname(
11230Sstevel@tonic-gate char *name
11240Sstevel@tonic-gate )
11250Sstevel@tonic-gate {
11260Sstevel@tonic-gate char *p, *e;
11270Sstevel@tonic-gate char onmb[BUFSIZ+1], cnmb[BUFSIZ];
11280Sstevel@tonic-gate uint_t d = 0;
11290Sstevel@tonic-gate int l = 0;
11300Sstevel@tonic-gate int cl = strlen(name);
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate /*
11330Sstevel@tonic-gate * Handle old style names, which are of the form /dev/rXXNN[a-h].
11340Sstevel@tonic-gate */
11350Sstevel@tonic-gate if (sscanf(name, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n",
11360Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) {
11370Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u", onmb, d);
11380Sstevel@tonic-gate return (Strdup(cnmb));
11390Sstevel@tonic-gate }
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate /*
11420Sstevel@tonic-gate * Handle old style names, which are of the form /dev/XXNN[a-h].
11430Sstevel@tonic-gate */
11440Sstevel@tonic-gate if (sscanf(name, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n",
11450Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) {
11460Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/%s%u", onmb, d);
11470Sstevel@tonic-gate return (Strdup(cnmb));
11480Sstevel@tonic-gate }
11490Sstevel@tonic-gate
11500Sstevel@tonic-gate /* gobble number and 's' */
11510Sstevel@tonic-gate p = e = name + strlen(name) - 1;
11520Sstevel@tonic-gate for (; (p > name); --p) {
11530Sstevel@tonic-gate if (!isdigit(*p))
11540Sstevel@tonic-gate break;
11550Sstevel@tonic-gate }
11560Sstevel@tonic-gate if ((p == e) || (p <= name))
11570Sstevel@tonic-gate return (Strdup(name));
11580Sstevel@tonic-gate
11590Sstevel@tonic-gate if (*p != 's' && strchr("dt", *p) == NULL)
11600Sstevel@tonic-gate return (Strdup(name));
11610Sstevel@tonic-gate else if (strchr("dt", *p) != NULL)
11620Sstevel@tonic-gate return (Strdup(name));
11630Sstevel@tonic-gate p--;
11640Sstevel@tonic-gate
11650Sstevel@tonic-gate if ((p <= name) || (!isdigit(*p)))
11660Sstevel@tonic-gate return (Strdup(name));
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate *(++p) = '\0';
11690Sstevel@tonic-gate e = Strdup(name);
11700Sstevel@tonic-gate *p = 's';
11710Sstevel@tonic-gate
11720Sstevel@tonic-gate return (e);
11730Sstevel@tonic-gate }
11740Sstevel@tonic-gate
11750Sstevel@tonic-gate /*
11760Sstevel@tonic-gate * free list of drivenames
11770Sstevel@tonic-gate */
11780Sstevel@tonic-gate void
metafreedrivenamelist(mddrivenamelist_t * dnlp)11790Sstevel@tonic-gate metafreedrivenamelist(
11800Sstevel@tonic-gate mddrivenamelist_t *dnlp
11810Sstevel@tonic-gate )
11820Sstevel@tonic-gate {
11830Sstevel@tonic-gate mddrivenamelist_t *next = NULL;
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate for (/* void */; (dnlp != NULL); dnlp = next) {
11860Sstevel@tonic-gate next = dnlp->next;
11870Sstevel@tonic-gate Free(dnlp);
11880Sstevel@tonic-gate }
11890Sstevel@tonic-gate }
11900Sstevel@tonic-gate
11910Sstevel@tonic-gate /*
11920Sstevel@tonic-gate * build list of drivenames
11930Sstevel@tonic-gate */
11940Sstevel@tonic-gate int
metadrivenamelist(mdsetname_t ** spp,mddrivenamelist_t ** dnlpp,int argc,char * argv[],md_error_t * ep)11950Sstevel@tonic-gate metadrivenamelist(
11960Sstevel@tonic-gate mdsetname_t **spp,
11970Sstevel@tonic-gate mddrivenamelist_t **dnlpp,
11980Sstevel@tonic-gate int argc,
11990Sstevel@tonic-gate char *argv[],
12000Sstevel@tonic-gate md_error_t *ep
12010Sstevel@tonic-gate )
12020Sstevel@tonic-gate {
12030Sstevel@tonic-gate mddrivenamelist_t **tailpp = dnlpp;
12040Sstevel@tonic-gate int count = 0;
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
12070Sstevel@tonic-gate mddrivenamelist_t *dnlp = Zalloc(sizeof (*dnlp));
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate if ((dnlp->drivenamep = metadrivename(spp, argv[0],
12100Sstevel@tonic-gate ep)) == NULL) {
12110Sstevel@tonic-gate metafreedrivenamelist(*dnlpp);
12120Sstevel@tonic-gate *dnlpp = NULL;
12130Sstevel@tonic-gate return (-1);
12140Sstevel@tonic-gate }
12150Sstevel@tonic-gate *tailpp = dnlp;
12160Sstevel@tonic-gate tailpp = &dnlp->next;
12170Sstevel@tonic-gate }
12180Sstevel@tonic-gate return (count);
12190Sstevel@tonic-gate }
12200Sstevel@tonic-gate
12210Sstevel@tonic-gate /*
12220Sstevel@tonic-gate * append to end of drivename list
12230Sstevel@tonic-gate */
12240Sstevel@tonic-gate mddrivename_t *
metadrivenamelist_append(mddrivenamelist_t ** dnlpp,mddrivename_t * dnp)12250Sstevel@tonic-gate metadrivenamelist_append(
12260Sstevel@tonic-gate mddrivenamelist_t **dnlpp,
12270Sstevel@tonic-gate mddrivename_t *dnp
12280Sstevel@tonic-gate )
12290Sstevel@tonic-gate {
12300Sstevel@tonic-gate mddrivenamelist_t *dnlp;
12310Sstevel@tonic-gate
12320Sstevel@tonic-gate /* run to end of list */
12330Sstevel@tonic-gate for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next)
12340Sstevel@tonic-gate ;
12350Sstevel@tonic-gate
12360Sstevel@tonic-gate /* allocate new list element */
12370Sstevel@tonic-gate dnlp = *dnlpp = Zalloc(sizeof (*dnlp));
12380Sstevel@tonic-gate
12390Sstevel@tonic-gate /* append drivename */
12400Sstevel@tonic-gate dnlp->drivenamep = dnp;
12410Sstevel@tonic-gate return (dnp);
12420Sstevel@tonic-gate }
12430Sstevel@tonic-gate
12440Sstevel@tonic-gate /*
12450Sstevel@tonic-gate * FUNCTION: meta_drivenamelist_append_wrapper()
12460Sstevel@tonic-gate * INPUT: tailpp - pointer to the list tail pointer
12470Sstevel@tonic-gate * dnp - name node to be appended to list
12480Sstevel@tonic-gate * OUTPUT: none
12490Sstevel@tonic-gate * RETURNS: mddrivenamelist_t * - new tail of the list.
12500Sstevel@tonic-gate * PURPOSE: wrapper to meta_namelist_append for performance.
12510Sstevel@tonic-gate * metanamelist_append finds the tail each time which slows
12520Sstevel@tonic-gate * down long lists. By keeping track of the tail ourselves
12530Sstevel@tonic-gate * we can change metadrivenamelist_append into a
12540Sstevel@tonic-gate * constant time operation.
12550Sstevel@tonic-gate */
12560Sstevel@tonic-gate mddrivenamelist_t **
meta_drivenamelist_append_wrapper(mddrivenamelist_t ** tailpp,mddrivename_t * dnp)12570Sstevel@tonic-gate meta_drivenamelist_append_wrapper(
12580Sstevel@tonic-gate mddrivenamelist_t **tailpp,
12590Sstevel@tonic-gate mddrivename_t *dnp
12600Sstevel@tonic-gate )
12610Sstevel@tonic-gate {
12620Sstevel@tonic-gate (void) metadrivenamelist_append(tailpp, dnp);
12630Sstevel@tonic-gate
12640Sstevel@tonic-gate /* If it's the first item in the list, return it instead of the next */
12650Sstevel@tonic-gate if ((*tailpp)->next == NULL)
12660Sstevel@tonic-gate return (tailpp);
12670Sstevel@tonic-gate
12680Sstevel@tonic-gate return (&(*tailpp)->next);
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate
12710Sstevel@tonic-gate
12720Sstevel@tonic-gate /*
12730Sstevel@tonic-gate * mdname_t stuff
12740Sstevel@tonic-gate */
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate /*
12770Sstevel@tonic-gate * check set and get comparison name
12781623Stw21770 *
12791623Stw21770 * NOTE: This function has a side effect of setting *spp if the setname
12801623Stw21770 * has been specified and *spp is not already set.
12810Sstevel@tonic-gate */
12820Sstevel@tonic-gate char *
meta_name_getname(mdsetname_t ** spp,char * uname,meta_device_type_t uname_type,md_error_t * ep)12830Sstevel@tonic-gate meta_name_getname(
12841623Stw21770 mdsetname_t **spp,
12851623Stw21770 char *uname,
12861623Stw21770 meta_device_type_t uname_type,
12871623Stw21770 md_error_t *ep
12880Sstevel@tonic-gate )
12890Sstevel@tonic-gate {
12901623Stw21770 if (uname_type == META_DEVICE || uname_type == HSP_DEVICE ||
12911623Stw21770 (uname_type == UNKNOWN && is_existing_metadevice(*spp, uname))) {
12921623Stw21770
12931623Stw21770 /*
12941623Stw21770 * if the setname is specified in uname, *spp is set,
12951623Stw21770 * and the set names don't agree then canonical name will be
12961623Stw21770 * returned as NULL
12971623Stw21770 */
12981623Stw21770 return (meta_canonicalize_check_set(spp, uname, ep));
12991623Stw21770 }
13001623Stw21770
13011623Stw21770 /* if it is not a meta/hsp and *spp is not set then set it to local */
13021623Stw21770 if (chksetname(spp, NULL, ep) != 0)
13030Sstevel@tonic-gate return (NULL);
13041623Stw21770
13051623Stw21770 /* if it is not a meta/hsp name then just return uname */
13061623Stw21770 return (Strdup(uname));
13070Sstevel@tonic-gate }
13080Sstevel@tonic-gate
13090Sstevel@tonic-gate /*
13100Sstevel@tonic-gate * FUNCTION: getrname()
13110Sstevel@tonic-gate * INPUT: spp - the setname struct
13120Sstevel@tonic-gate * uname - the possibly unqualified device name
13131623Stw21770 * type - ptr to the device type of uname
13140Sstevel@tonic-gate * OUTPUT: ep - return error pointer
13150Sstevel@tonic-gate * RETURNS: char* - character string containing the fully
13160Sstevel@tonic-gate * qualified raw device name
13170Sstevel@tonic-gate * PURPOSE: Create the fully qualified raw name for the possibly
13180Sstevel@tonic-gate * unqualified device name. If uname is an absolute
13190Sstevel@tonic-gate * path the raw name is derived from the input string.
13200Sstevel@tonic-gate * Otherwise, an attempt is made to get the rawname by
13211623Stw21770 * catting "/dev/md/rdsk" and "/dev/rdsk". If the input
13221623Stw21770 * value of type is UNKNOWN and it can be successfully
13231623Stw21770 * determined then update type to the correct value.
13240Sstevel@tonic-gate */
13251623Stw21770 static char *
getrname(mdsetname_t ** spp,char * uname,meta_device_type_t * type,md_error_t * ep)13261623Stw21770 getrname(mdsetname_t **spp, char *uname,
13271623Stw21770 meta_device_type_t *type, md_error_t *ep)
13280Sstevel@tonic-gate {
1329*9017SJohn.Wren.Kennedy@Sun.COM char *rname;
1330*9017SJohn.Wren.Kennedy@Sun.COM char *fname;
13311623Stw21770 int i;
13321623Stw21770 int rname_cnt = 0;
13331623Stw21770 char *rname_list[3];
13341623Stw21770 meta_device_type_t tmp_type;
13350Sstevel@tonic-gate
13360Sstevel@tonic-gate assert(uname != NULL);
13370Sstevel@tonic-gate /* if it is an absolute name then just call rawname on the input */
13380Sstevel@tonic-gate if (uname[0] == '/') {
1339*9017SJohn.Wren.Kennedy@Sun.COM if ((rname = rawname(uname)) != NULL) {
1340*9017SJohn.Wren.Kennedy@Sun.COM /*
1341*9017SJohn.Wren.Kennedy@Sun.COM * If the returned rname does not match with
1342*9017SJohn.Wren.Kennedy@Sun.COM * the specified uname type, we'll return null.
1343*9017SJohn.Wren.Kennedy@Sun.COM */
1344*9017SJohn.Wren.Kennedy@Sun.COM if (strncmp(rname, "/dev/md", strlen("/dev/md")) == 0) {
1345*9017SJohn.Wren.Kennedy@Sun.COM if (*type == LOGICAL_DEVICE) {
1346*9017SJohn.Wren.Kennedy@Sun.COM (void) mdsyserror(ep, ENOENT, uname);
1347*9017SJohn.Wren.Kennedy@Sun.COM return (NULL);
1348*9017SJohn.Wren.Kennedy@Sun.COM }
1349*9017SJohn.Wren.Kennedy@Sun.COM *type = META_DEVICE;
1350*9017SJohn.Wren.Kennedy@Sun.COM } else {
1351*9017SJohn.Wren.Kennedy@Sun.COM if (*type == META_DEVICE) {
1352*9017SJohn.Wren.Kennedy@Sun.COM (void) mdsyserror(ep, ENOENT, uname);
1353*9017SJohn.Wren.Kennedy@Sun.COM return (NULL);
1354*9017SJohn.Wren.Kennedy@Sun.COM }
1355*9017SJohn.Wren.Kennedy@Sun.COM *type = LOGICAL_DEVICE;
13561623Stw21770 }
1357*9017SJohn.Wren.Kennedy@Sun.COM return (rname);
13581623Stw21770 }
1359*9017SJohn.Wren.Kennedy@Sun.COM
1360*9017SJohn.Wren.Kennedy@Sun.COM /* out of luck */
1361*9017SJohn.Wren.Kennedy@Sun.COM (void) mdsyserror(ep, ENOENT, uname);
1362*9017SJohn.Wren.Kennedy@Sun.COM return (NULL);
13630Sstevel@tonic-gate }
13640Sstevel@tonic-gate
13650Sstevel@tonic-gate /*
13661623Stw21770 * Get device that matches the requested type. If
13671623Stw21770 * a match is found, return immediately. If type is
13681623Stw21770 * UNKNOWN, save all the found devices in rname_list
13691623Stw21770 * so we can determine later whether the input uname
13701623Stw21770 * is ambiguous.
13711623Stw21770 *
13720Sstevel@tonic-gate * Check for metadevice before physical device.
13730Sstevel@tonic-gate * With the introduction of softpartitions it is more
13740Sstevel@tonic-gate * likely to be a metadevice.
13750Sstevel@tonic-gate */
13760Sstevel@tonic-gate
13770Sstevel@tonic-gate /* metadevice short form */
13781623Stw21770 if (*type == META_DEVICE || *type == UNKNOWN) {
13791623Stw21770 if (metaislocalset(*spp)) {
13801623Stw21770 fname = Malloc(strlen(uname) +
13811623Stw21770 strlen("/dev/md/rdsk/") + 1);
13821623Stw21770 (void) strcpy(fname, "/dev/md/rdsk/");
13831623Stw21770 (void) strcat(fname, uname);
13840Sstevel@tonic-gate } else {
13851623Stw21770 char *p;
13861623Stw21770 size_t len;
13871623Stw21770
13881623Stw21770 if ((p = strchr(uname, '/')) != NULL) {
13891623Stw21770 ++p;
13901623Stw21770 } else {
13911623Stw21770 p = uname;
13921623Stw21770 }
13931623Stw21770 len = strlen((*spp)->setname) + strlen(p) +
13941623Stw21770 strlen("/dev/md//rdsk/") + 1;
13951623Stw21770 fname = Malloc(len);
13961623Stw21770 (void) snprintf(fname, len, "/dev/md/%s/rdsk/%s",
13971623Stw21770 (*spp)->setname, p);
13980Sstevel@tonic-gate }
13991623Stw21770 rname = rawname(fname);
14001623Stw21770
14011623Stw21770 if (*type == META_DEVICE) {
14021623Stw21770 /*
14031623Stw21770 * Handle the case where we have a new metadevice
14041623Stw21770 * that does not yet exist in the name-space(e.g
14051623Stw21770 * metarecover in MN sets where /dev/md entry is
14061623Stw21770 * not yet created in the non-master nodes). In
14071623Stw21770 * this case we return the constructed metadevice
14081623Stw21770 * name as that will exist after the metainit call
14091623Stw21770 * has created it.
14101623Stw21770 */
14111623Stw21770 if (rname == NULL) {
14121623Stw21770 rname = Strdup(fname);
14131623Stw21770 }
14141623Stw21770
14151623Stw21770 Free(fname);
14161623Stw21770 return (rname);
14171623Stw21770 }
14181623Stw21770
14191623Stw21770 Free(fname);
14201623Stw21770 if ((rname != NULL) && (*type == UNKNOWN)) {
14211623Stw21770 /* Save this result */
14221623Stw21770 rname_list[rname_cnt] = rname;
14231623Stw21770 rname_cnt ++;
14241623Stw21770 }
14250Sstevel@tonic-gate }
14261623Stw21770
14271623Stw21770 if (*type == LOGICAL_DEVICE || *type == UNKNOWN) {
14281623Stw21770 fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1);
14291623Stw21770 (void) strcpy(fname, "/dev/rdsk/");
14301623Stw21770 (void) strcat(fname, uname);
14311623Stw21770 rname = rawname(fname);
14321623Stw21770
14331623Stw21770 Free(fname);
14341623Stw21770 if (rname != NULL) {
14351623Stw21770 /* Simply return if a logical device was requested */
14361623Stw21770 if (*type == LOGICAL_DEVICE) {
14371623Stw21770 return (rname);
14381623Stw21770 } else {
14391623Stw21770 rname_list[rname_cnt] = rname;
14401623Stw21770 rname_cnt ++;
14411623Stw21770 }
14421623Stw21770 }
14430Sstevel@tonic-gate }
14440Sstevel@tonic-gate
14450Sstevel@tonic-gate /*
14461623Stw21770 * At this point, we've searched /dev/md/rdsk, /dev/rdsk and
14471623Stw21770 * ./ for the specified device. rname_list contains all
14481623Stw21770 * the matches we've found and rname_cnt is the number of
14491623Stw21770 * matches.
14501623Stw21770 *
14511623Stw21770 * We know that either we don't have a match if a specific
14521623Stw21770 * type was given, in which case we simply return NULL or
14531623Stw21770 * we have an UNKNOWN device with 1-3 entries in rname_list.
14541623Stw21770 *
14551623Stw21770 * If we get 3 entries, rname_cnt == 3, it's ambiguous.
14561623Stw21770 * If we only get 1 entry, rname_cnt == 1, return rname_list[0].
14571623Stw21770 * If we get 2 entries that are not the same, it's ambigous.
14581623Stw21770 */
14591623Stw21770 rname = NULL;
14601623Stw21770 if (rname_cnt == 0 || *type != UNKNOWN) {
14611623Stw21770 /* out of luck */
14621623Stw21770 (void) mdsyserror(ep, ENOENT, uname);
14631623Stw21770 return (NULL);
14641623Stw21770 } else {
14651623Stw21770 if (rname_cnt == 3) {
14661623Stw21770 (void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
14671623Stw21770 (void) printf(dgettext(TEXT_DOMAIN,
14681623Stw21770 "Error: ambiguous device name.\n%s %s %s\n\n"),
14691623Stw21770 rname_list[0], rname_list[1], rname_list[2]);
14701623Stw21770 rname = NULL;
14711623Stw21770 }
14721623Stw21770
14731623Stw21770 /* grab the type in case it is not ambiguous */
14741623Stw21770 if (strncmp(rname_list[0], "/dev/md", strlen("/dev/md")) == 0)
14751623Stw21770 tmp_type = META_DEVICE;
14761623Stw21770 else
14771623Stw21770 tmp_type = LOGICAL_DEVICE;
14781623Stw21770
14791623Stw21770 if (rname_cnt == 1) {
14801623Stw21770 rname = Strdup(rname_list[0]);
14811623Stw21770 *type = tmp_type;
14821623Stw21770 } else {
14831623Stw21770 /*
14841623Stw21770 * Prevent the case where the command is run in
14851623Stw21770 * either /dev/md/rdsk or /dev/rdsk so the both
14861623Stw21770 * rname_list[0] and rname_list[1] are the same.
14871623Stw21770 */
14881623Stw21770 if (strcmp(rname_list[0], rname_list[1]) != 0) {
14891623Stw21770 (void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
14901623Stw21770 if (rname_cnt != 3) {
14911623Stw21770 /*
14921623Stw21770 * For the rname_cnt == 3 case, the
14931623Stw21770 * error was printed above.
14941623Stw21770 */
14951623Stw21770 (void) printf(dgettext(TEXT_DOMAIN,
1496*9017SJohn.Wren.Kennedy@Sun.COM "Error: ambiguous device "
1497*9017SJohn.Wren.Kennedy@Sun.COM "name.\n%s %s\n\n"),
1498*9017SJohn.Wren.Kennedy@Sun.COM rname_list[0], rname_list[1]);
14991623Stw21770 }
15001623Stw21770 rname = NULL;
15011623Stw21770 } else {
15021623Stw21770 rname = Strdup(rname_list[0]);
15031623Stw21770 *type = tmp_type;
15041623Stw21770 }
15051623Stw21770 }
15061623Stw21770 for (i = 0; i < rname_cnt; i++)
15071623Stw21770 Free(rname_list[i]);
15080Sstevel@tonic-gate return (rname);
15091623Stw21770 }
15100Sstevel@tonic-gate }
15110Sstevel@tonic-gate
15120Sstevel@tonic-gate /*
15130Sstevel@tonic-gate * get raw slice and drive names
15140Sstevel@tonic-gate */
15150Sstevel@tonic-gate static char *
getrawnames(mdsetname_t ** spp,char * uname,char ** dnamep,meta_device_type_t * uname_type,md_error_t * ep)15160Sstevel@tonic-gate getrawnames(
15171623Stw21770 mdsetname_t **spp,
15181623Stw21770 char *uname,
15191623Stw21770 char **dnamep,
15201623Stw21770 meta_device_type_t *uname_type,
15211623Stw21770 md_error_t *ep
15220Sstevel@tonic-gate )
15230Sstevel@tonic-gate {
15241623Stw21770 char *rname = NULL;
15250Sstevel@tonic-gate size_t len;
15260Sstevel@tonic-gate
15271623Stw21770 /*
15281623Stw21770 * Incorrect code path if type is HSP_DEVICE
15291623Stw21770 */
15301623Stw21770 assert(*uname_type != HSP_DEVICE);
15311623Stw21770
15320Sstevel@tonic-gate /* initialize */
15330Sstevel@tonic-gate *dnamep = NULL;
15340Sstevel@tonic-gate
15350Sstevel@tonic-gate /* get slice name */
15361623Stw21770 if ((rname = getrname(spp, uname, uname_type, ep)) != NULL) {
15370Sstevel@tonic-gate *dnamep = metadiskname(rname);
15380Sstevel@tonic-gate return (rname);
15390Sstevel@tonic-gate }
15400Sstevel@tonic-gate
15410Sstevel@tonic-gate /*
15420Sstevel@tonic-gate * If name cannot be found, if may be because is is not accessible.
15430Sstevel@tonic-gate * If it is an absolute name, try all possible disk name formats and
15441623Stw21770 * if it is device name, assume it is /dev/rdsk/..
15451623Stw21770 * Since the code below assumes logical devices, if the given
15461623Stw21770 * uname_type is META_DEVICE, there's nothing to do.
15470Sstevel@tonic-gate */
15481623Stw21770 if (mdissyserror(ep, ENOENT) && *uname_type != META_DEVICE) {
15490Sstevel@tonic-gate if (uname[0] == '/') {
15500Sstevel@tonic-gate /* Absolute name */
15510Sstevel@tonic-gate uint_t d = 0;
15520Sstevel@tonic-gate int l = 0;
15530Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1];
15540Sstevel@tonic-gate
15550Sstevel@tonic-gate /*
15560Sstevel@tonic-gate * Handle old style raw names
15570Sstevel@tonic-gate */
15580Sstevel@tonic-gate if (sscanf(uname,
15590Sstevel@tonic-gate "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
15600Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n",
15610Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(uname)) {
15620Sstevel@tonic-gate mdclrerror(ep);
15630Sstevel@tonic-gate rname = Strdup(uname);
15640Sstevel@tonic-gate *dnamep = metadiskname(rname);
15651623Stw21770 *uname_type = LOGICAL_DEVICE;
15660Sstevel@tonic-gate return (rname);
15670Sstevel@tonic-gate }
15680Sstevel@tonic-gate
15690Sstevel@tonic-gate /*
15700Sstevel@tonic-gate * Handle old style block names
15710Sstevel@tonic-gate */
15720Sstevel@tonic-gate if (sscanf(uname,
15730Sstevel@tonic-gate "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u"
15740Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n",
15750Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(uname)) {
15760Sstevel@tonic-gate len = strlen(uname) + 1 + 1;
15770Sstevel@tonic-gate rname = Malloc(len);
15780Sstevel@tonic-gate (void) snprintf(rname, len, "/dev/r%s%u%s",
15790Sstevel@tonic-gate onmb, d, snm);
15800Sstevel@tonic-gate *dnamep = metadiskname(rname);
15811623Stw21770 *uname_type = LOGICAL_DEVICE;
15820Sstevel@tonic-gate return (rname);
15830Sstevel@tonic-gate }
15840Sstevel@tonic-gate
1585*9017SJohn.Wren.Kennedy@Sun.COM /* /.../dsk/... or /.../rdsk/... */
1586*9017SJohn.Wren.Kennedy@Sun.COM if ((rname = meta_dsk_to_rdsk(uname)) != NULL) {
15870Sstevel@tonic-gate mdclrerror(ep);
15880Sstevel@tonic-gate *dnamep = metadiskname(rname);
15891623Stw21770 *uname_type = LOGICAL_DEVICE;
15900Sstevel@tonic-gate return (rname);
15910Sstevel@tonic-gate }
15920Sstevel@tonic-gate } else {
15930Sstevel@tonic-gate /*
15940Sstevel@tonic-gate * If it's not an absolute name but is a valid ctd name,
15950Sstevel@tonic-gate * guess at /dev/rdsk/...
15960Sstevel@tonic-gate */
15970Sstevel@tonic-gate uint_t s;
15980Sstevel@tonic-gate if (parse_ctd(uname, &s) == 0) {
15990Sstevel@tonic-gate len = strlen(uname) + strlen("/dev/rdsk/") + 1;
16000Sstevel@tonic-gate rname = Malloc(len);
16010Sstevel@tonic-gate (void) snprintf(rname, len, "/dev/rdsk/%s",
16020Sstevel@tonic-gate uname);
16030Sstevel@tonic-gate *dnamep = metadiskname(rname);
16041623Stw21770 *uname_type = LOGICAL_DEVICE;
16050Sstevel@tonic-gate return (rname);
16060Sstevel@tonic-gate }
16070Sstevel@tonic-gate }
16080Sstevel@tonic-gate }
16090Sstevel@tonic-gate
16100Sstevel@tonic-gate /* out of luck */
16111623Stw21770 if (!mdiserror(ep, MDE_AMBIGUOUS_DEV))
16121623Stw21770 (void) mderror(ep, MDE_UNIT_NOT_FOUND, uname);
16130Sstevel@tonic-gate return (NULL);
16140Sstevel@tonic-gate }
16150Sstevel@tonic-gate
16160Sstevel@tonic-gate /*
16170Sstevel@tonic-gate * get number of slices for name
16180Sstevel@tonic-gate */
16190Sstevel@tonic-gate static int
getnslice(char * rname,char * dname,uint_t * slicep)16200Sstevel@tonic-gate getnslice(
16210Sstevel@tonic-gate char *rname,
16220Sstevel@tonic-gate char *dname,
16230Sstevel@tonic-gate uint_t *slicep
16240Sstevel@tonic-gate )
16250Sstevel@tonic-gate {
16260Sstevel@tonic-gate char *srname;
16270Sstevel@tonic-gate uint_t nslice;
16280Sstevel@tonic-gate size_t dl = strlen(dname);
16290Sstevel@tonic-gate size_t rl = strlen(rname);
16300Sstevel@tonic-gate size_t l = 0;
16310Sstevel@tonic-gate size_t len;
16320Sstevel@tonic-gate
16330Sstevel@tonic-gate /*
16340Sstevel@tonic-gate * get our slice number - works only with names that end in s%u -
16350Sstevel@tonic-gate * all others return -1.
16360Sstevel@tonic-gate */
16370Sstevel@tonic-gate if (dl >= rl ||
16380Sstevel@tonic-gate sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl ||
16390Sstevel@tonic-gate (int)*slicep < 0) {
16400Sstevel@tonic-gate return (-1);
16410Sstevel@tonic-gate }
16420Sstevel@tonic-gate
16430Sstevel@tonic-gate /*
16440Sstevel@tonic-gate * go find how many slices there really are
16450Sstevel@tonic-gate */
16460Sstevel@tonic-gate len = strlen(dname) + 20 + 1;
16470Sstevel@tonic-gate srname = Malloc(len);
16480Sstevel@tonic-gate for (nslice = 0; /* void */; ++nslice) {
16490Sstevel@tonic-gate struct stat statbuf;
16500Sstevel@tonic-gate
16510Sstevel@tonic-gate /* build slice name */
16520Sstevel@tonic-gate (void) snprintf(srname, len, "%ss%u", dname, nslice);
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate /* see if it's there */
16550Sstevel@tonic-gate if ((meta_stat(srname, &statbuf) != 0) ||
16560Sstevel@tonic-gate (! S_ISCHR(statbuf.st_mode))) {
16570Sstevel@tonic-gate break;
16580Sstevel@tonic-gate }
16590Sstevel@tonic-gate }
16600Sstevel@tonic-gate Free(srname);
16610Sstevel@tonic-gate
16620Sstevel@tonic-gate /* Need to make sure that we at least have V_NUMPAR */
16630Sstevel@tonic-gate nslice = max(nslice, V_NUMPAR);
16640Sstevel@tonic-gate
16650Sstevel@tonic-gate /* make sure we have at least our slice */
16660Sstevel@tonic-gate if (nslice < *slicep)
16670Sstevel@tonic-gate return (-1);
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate /* return number of slices */
16700Sstevel@tonic-gate return (nslice);
16710Sstevel@tonic-gate }
16720Sstevel@tonic-gate
16730Sstevel@tonic-gate /*
16740Sstevel@tonic-gate * Attempt to parse the input string as a c[t]ds specifier
16750Sstevel@tonic-gate * The target can either be a SCSI target id or if the device
16760Sstevel@tonic-gate * is in a fabric configuration in a fibre channel setup then
16770Sstevel@tonic-gate * the target is a standard WWN (world wide name).
16780Sstevel@tonic-gate *
16790Sstevel@tonic-gate * if successful return 0
16800Sstevel@tonic-gate * if c[t]dp name return 1
16810Sstevel@tonic-gate * otherwise return -1
16820Sstevel@tonic-gate */
16830Sstevel@tonic-gate int
parse_ctd(char * uname,uint_t * slice)16840Sstevel@tonic-gate parse_ctd(
16850Sstevel@tonic-gate char *uname,
16860Sstevel@tonic-gate uint_t *slice)
16870Sstevel@tonic-gate {
16880Sstevel@tonic-gate uint_t channel;
16890Sstevel@tonic-gate uint_t target;
16900Sstevel@tonic-gate uint_t device;
16910Sstevel@tonic-gate int has_target = 1;
16920Sstevel@tonic-gate uint_t cl;
16930Sstevel@tonic-gate uint_t target_str_len;
16940Sstevel@tonic-gate char *partial_ctd_str;
16950Sstevel@tonic-gate char *target_str;
16960Sstevel@tonic-gate char *device_start_pos;
16970Sstevel@tonic-gate int l = -1;
16980Sstevel@tonic-gate
16990Sstevel@tonic-gate /* pull off the channel spec and the 't' for the target */
17000Sstevel@tonic-gate if (sscanf(uname, "c%ut%n", &channel, &l) != 1 || l == -1) {
17010Sstevel@tonic-gate /* check for cds style name */
17020Sstevel@tonic-gate if (sscanf(uname, "c%ud%n", &channel, &l) != 1 || l == -1) {
17030Sstevel@tonic-gate return (-1);
17040Sstevel@tonic-gate } else {
17050Sstevel@tonic-gate l--; /* we want to be on the 'd' */
17060Sstevel@tonic-gate has_target = 0;
17070Sstevel@tonic-gate }
17080Sstevel@tonic-gate }
17090Sstevel@tonic-gate partial_ctd_str = uname + l;
17100Sstevel@tonic-gate
17110Sstevel@tonic-gate /* find the beginning of the device specifier */
17120Sstevel@tonic-gate device_start_pos = strrchr(partial_ctd_str, 'd');
17130Sstevel@tonic-gate if (device_start_pos == NULL) {
17140Sstevel@tonic-gate return (-1);
17150Sstevel@tonic-gate }
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate /* check to see if it is a ctd with a WWN or SCSI target */
17180Sstevel@tonic-gate if (has_target) {
17190Sstevel@tonic-gate /* pull off the target and see if it is a WWN */
17200Sstevel@tonic-gate target_str_len = device_start_pos - partial_ctd_str + 2;
17210Sstevel@tonic-gate target_str = (char *)Malloc(target_str_len+1);
17220Sstevel@tonic-gate (void) strcpy(target_str, "0X");
17230Sstevel@tonic-gate (void) strncpy(target_str+2, partial_ctd_str,
17240Sstevel@tonic-gate target_str_len - 2);
17250Sstevel@tonic-gate target_str[target_str_len] = '\0';
17260Sstevel@tonic-gate if (sscanf(target_str, "%x%n", &target, &l) != 1 ||
17270Sstevel@tonic-gate l != target_str_len) {
17280Sstevel@tonic-gate Free(target_str);
17290Sstevel@tonic-gate return (-1);
17300Sstevel@tonic-gate }
17310Sstevel@tonic-gate Free(target_str);
17320Sstevel@tonic-gate }
17330Sstevel@tonic-gate
17340Sstevel@tonic-gate /* check the device and slice */
17350Sstevel@tonic-gate cl = strlen(device_start_pos);
17360Sstevel@tonic-gate if (sscanf(device_start_pos, "d%us%u%n", &device, slice, &l) != 2 ||
1737*9017SJohn.Wren.Kennedy@Sun.COM l != cl) {
17380Sstevel@tonic-gate /* check the device and partition */
17390Sstevel@tonic-gate if (sscanf(device_start_pos, "d%up%u%n", &device, slice, &l)
17400Sstevel@tonic-gate == 2 && l == cl) {
17410Sstevel@tonic-gate return (1);
17420Sstevel@tonic-gate }
17430Sstevel@tonic-gate return (-1);
17440Sstevel@tonic-gate }
17450Sstevel@tonic-gate
17460Sstevel@tonic-gate return (0);
17470Sstevel@tonic-gate }
17480Sstevel@tonic-gate
17490Sstevel@tonic-gate
17500Sstevel@tonic-gate /*
17510Sstevel@tonic-gate * get number of slices for name
17520Sstevel@tonic-gate */
17530Sstevel@tonic-gate static int
uname2sliceno(char * uname,meta_device_type_t uname_type,uint_t * slicep,md_error_t * ep)17540Sstevel@tonic-gate uname2sliceno(
17551623Stw21770 char *uname,
17561623Stw21770 meta_device_type_t uname_type,
17571623Stw21770 uint_t *slicep,
17581623Stw21770 md_error_t *ep
17590Sstevel@tonic-gate )
17600Sstevel@tonic-gate {
17610Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0;
17620Sstevel@tonic-gate int l = 0, cl = 0;
17630Sstevel@tonic-gate int fd;
17640Sstevel@tonic-gate struct dk_cinfo cinfo;
17650Sstevel@tonic-gate char *p;
17660Sstevel@tonic-gate char *rname = NULL;
17670Sstevel@tonic-gate
17681623Stw21770
17691623Stw21770 if (uname_type == META_DEVICE)
17700Sstevel@tonic-gate return (*slicep = 0);
17710Sstevel@tonic-gate
17720Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL)
17730Sstevel@tonic-gate p++;
17740Sstevel@tonic-gate else
17750Sstevel@tonic-gate p = uname;
17760Sstevel@tonic-gate
17770Sstevel@tonic-gate cl = strlen(p);
17780Sstevel@tonic-gate
17790Sstevel@tonic-gate if (parse_ctd(p, slicep) == 0)
17800Sstevel@tonic-gate return (*slicep);
17810Sstevel@tonic-gate else if (sscanf(p, "mc%ut%ud%us%u%n", &c, &t, &d, slicep, &l) == 4 &&
17820Sstevel@tonic-gate l == cl)
17830Sstevel@tonic-gate return (*slicep);
17840Sstevel@tonic-gate else if (sscanf(p, "d%us%u%n", &d, slicep, &l) == 2 && l == cl)
17850Sstevel@tonic-gate return (*slicep);
17860Sstevel@tonic-gate
17870Sstevel@tonic-gate /*
17880Sstevel@tonic-gate * If we can't get the slice from the name, then we have to do it the
17890Sstevel@tonic-gate * hard and expensive way.
17900Sstevel@tonic-gate */
17910Sstevel@tonic-gate if ((rname = rawname(uname)) == NULL)
17920Sstevel@tonic-gate return (-1);
17930Sstevel@tonic-gate
17940Sstevel@tonic-gate /* get controller info */
17950Sstevel@tonic-gate if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
17960Sstevel@tonic-gate Free(rname);
17970Sstevel@tonic-gate return (-1);
17980Sstevel@tonic-gate }
17990Sstevel@tonic-gate
18000Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &cinfo) != 0) {
18010Sstevel@tonic-gate int save = errno;
18020Sstevel@tonic-gate
18030Sstevel@tonic-gate if (save == ENOTTY)
18040Sstevel@tonic-gate (void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname);
18050Sstevel@tonic-gate else
18060Sstevel@tonic-gate (void) mdsyserror(ep, save, rname);
18070Sstevel@tonic-gate
18080Sstevel@tonic-gate Free(rname);
18090Sstevel@tonic-gate (void) close(fd);
18100Sstevel@tonic-gate return (-1);
18110Sstevel@tonic-gate }
18120Sstevel@tonic-gate (void) close(fd); /* sd/ssd bug */
18130Sstevel@tonic-gate
18140Sstevel@tonic-gate if (cinfo.dki_partition < V_NUMPAR) {
18150Sstevel@tonic-gate Free(rname);
18160Sstevel@tonic-gate return (*slicep = cinfo.dki_partition);
18170Sstevel@tonic-gate }
18180Sstevel@tonic-gate
18190Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname));
18200Sstevel@tonic-gate }
18210Sstevel@tonic-gate
18220Sstevel@tonic-gate /*
18230Sstevel@tonic-gate * get partition info
18240Sstevel@tonic-gate */
18250Sstevel@tonic-gate static int
getparts(mddrivename_t * dnp,char * rname,char * dname,meta_device_type_t uname_type,uint_t * npartsp,uint_t * partnop,md_error_t * ep)18260Sstevel@tonic-gate getparts(
18271623Stw21770 mddrivename_t *dnp,
18281623Stw21770 char *rname,
18291623Stw21770 char *dname,
18301623Stw21770 meta_device_type_t uname_type,
18311623Stw21770 uint_t *npartsp,
18321623Stw21770 uint_t *partnop,
18331623Stw21770 md_error_t *ep
18340Sstevel@tonic-gate )
18350Sstevel@tonic-gate {
18360Sstevel@tonic-gate int nparts;
18370Sstevel@tonic-gate uint_t partno;
18380Sstevel@tonic-gate mdname_t name;
18390Sstevel@tonic-gate mdvtoc_t *vtocp;
18400Sstevel@tonic-gate
18410Sstevel@tonic-gate /* metadevice */
18421623Stw21770 if (uname_type == META_DEVICE) {
18430Sstevel@tonic-gate dnp->type = MDT_META;
18440Sstevel@tonic-gate nparts = 1;
18450Sstevel@tonic-gate partno = 0;
18460Sstevel@tonic-gate goto gotit;
18470Sstevel@tonic-gate }
18480Sstevel@tonic-gate
18490Sstevel@tonic-gate /* see how many partitions in drive, this is really tricky */
18500Sstevel@tonic-gate metainitname(&name);
18510Sstevel@tonic-gate name.rname = rname;
18520Sstevel@tonic-gate name.drivenamep = dnp;
18530Sstevel@tonic-gate if ((vtocp = metagetvtoc(&name, TRUE, &partno, ep)) != NULL) {
18540Sstevel@tonic-gate dnp->type = MDT_COMP;
18550Sstevel@tonic-gate nparts = vtocp->nparts;
18560Sstevel@tonic-gate /* partno already setup */
18570Sstevel@tonic-gate /* dname already setup */
18580Sstevel@tonic-gate goto gotit;
18590Sstevel@tonic-gate }
18600Sstevel@tonic-gate
18610Sstevel@tonic-gate if ((ep->info.errclass == MDEC_DEV) &&
18620Sstevel@tonic-gate (ep->info.md_error_info_t_u.dev_error.errnum == MDE_TOO_MANY_PARTS))
18630Sstevel@tonic-gate return (-1);
18640Sstevel@tonic-gate
18650Sstevel@tonic-gate /* fallback and try and guess (used to check for just EACCES here) */
18660Sstevel@tonic-gate if ((dname != NULL) &&
18670Sstevel@tonic-gate ((nparts = getnslice(rname, dname, &partno)) > 0)) {
18680Sstevel@tonic-gate dnp->type = MDT_ACCES;
18690Sstevel@tonic-gate if (mdanysyserror(ep)) {
18700Sstevel@tonic-gate dnp->errnum =
18710Sstevel@tonic-gate ep->info.md_error_info_t_u.sys_error.errnum;
18720Sstevel@tonic-gate } else {
18730Sstevel@tonic-gate dnp->errnum = ENOENT;
18740Sstevel@tonic-gate }
18750Sstevel@tonic-gate mdclrerror(ep);
18760Sstevel@tonic-gate /* nparts already setup */
18770Sstevel@tonic-gate /* partno already setup */
18780Sstevel@tonic-gate /* dname already setup */
18790Sstevel@tonic-gate nparts = roundup(nparts, V_NUMPAR);
18800Sstevel@tonic-gate goto gotit;
18810Sstevel@tonic-gate }
18820Sstevel@tonic-gate
18830Sstevel@tonic-gate /* nothing worked */
18840Sstevel@tonic-gate dnp->type = MDT_UNKNOWN;
18850Sstevel@tonic-gate if (mdissyserror(ep, EACCES))
18860Sstevel@tonic-gate dnp->type = MDT_ACCES;
18870Sstevel@tonic-gate
18880Sstevel@tonic-gate if (mdanysyserror(ep)) {
18890Sstevel@tonic-gate dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum;
18900Sstevel@tonic-gate } else {
18910Sstevel@tonic-gate dnp->errnum = ENOENT;
18920Sstevel@tonic-gate }
18930Sstevel@tonic-gate
18940Sstevel@tonic-gate mdclrerror(ep);
18950Sstevel@tonic-gate nparts = V_NUMPAR;
18961623Stw21770 if (uname2sliceno(rname, uname_type, &partno, ep) < 0) {
18970Sstevel@tonic-gate mdclrerror(ep);
18980Sstevel@tonic-gate partno = 0;
18990Sstevel@tonic-gate }
19000Sstevel@tonic-gate
19010Sstevel@tonic-gate /* return success */
19020Sstevel@tonic-gate gotit:
19030Sstevel@tonic-gate assert(nparts > 0);
19040Sstevel@tonic-gate
19050Sstevel@tonic-gate if (partno >= nparts)
19060Sstevel@tonic-gate return (mdsyserror(ep, ENOENT, rname));
19070Sstevel@tonic-gate
19080Sstevel@tonic-gate *npartsp = nparts;
19090Sstevel@tonic-gate *partnop = partno;
19100Sstevel@tonic-gate return (0);
19110Sstevel@tonic-gate }
19120Sstevel@tonic-gate
19130Sstevel@tonic-gate /*
19140Sstevel@tonic-gate * get block name
19150Sstevel@tonic-gate */
19160Sstevel@tonic-gate static int
getbname(mdname_t * np,md_error_t * ep)19170Sstevel@tonic-gate getbname(
19180Sstevel@tonic-gate mdname_t *np,
19190Sstevel@tonic-gate md_error_t *ep
19200Sstevel@tonic-gate )
19210Sstevel@tonic-gate {
19220Sstevel@tonic-gate char *rname = np->rname;
19230Sstevel@tonic-gate char *bname;
19240Sstevel@tonic-gate
19250Sstevel@tonic-gate /* fully qualified */
19260Sstevel@tonic-gate assert(rname != NULL);
19270Sstevel@tonic-gate if ((bname = blkname(rname)) != NULL) {
19280Sstevel@tonic-gate if (np->bname)
19290Sstevel@tonic-gate Free(np->bname);
19300Sstevel@tonic-gate np->bname = bname;
19310Sstevel@tonic-gate return (0);
19320Sstevel@tonic-gate }
19330Sstevel@tonic-gate
19340Sstevel@tonic-gate /* out of luck */
19350Sstevel@tonic-gate return (mdsyserror(ep, ENOENT, rname));
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate
19380Sstevel@tonic-gate static void
getcname(mdsetname_t * sp,mdname_t * np)19390Sstevel@tonic-gate getcname(
19400Sstevel@tonic-gate mdsetname_t *sp,
19410Sstevel@tonic-gate mdname_t *np
19420Sstevel@tonic-gate )
19430Sstevel@tonic-gate {
19440Sstevel@tonic-gate char *sname = sp->setname;
19450Sstevel@tonic-gate char *bname = np->bname;
19460Sstevel@tonic-gate char *p;
19470Sstevel@tonic-gate size_t len;
19480Sstevel@tonic-gate
19490Sstevel@tonic-gate assert(sname != NULL);
19500Sstevel@tonic-gate assert(bname != NULL);
19510Sstevel@tonic-gate assert(np->drivenamep->type != MDT_FAST_COMP &&
19520Sstevel@tonic-gate np->drivenamep->type != MDT_FAST_META);
19530Sstevel@tonic-gate
19540Sstevel@tonic-gate /* regular device */
19550Sstevel@tonic-gate if ((strncmp(bname, "/dev/dsk/", strlen("/dev/dsk/")) == 0) &&
19560Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/dsk/")), '/') == NULL)) {
19570Sstevel@tonic-gate if (np->cname)
19580Sstevel@tonic-gate Free(np->cname);
19590Sstevel@tonic-gate np->cname = Strdup(p);
19600Sstevel@tonic-gate return;
19610Sstevel@tonic-gate }
19620Sstevel@tonic-gate
19630Sstevel@tonic-gate if ((strncmp(bname, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) &&
19640Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/ap/dsk/")), '/') == NULL)) {
19650Sstevel@tonic-gate if (np->cname)
19660Sstevel@tonic-gate Free(np->cname);
19670Sstevel@tonic-gate np->cname = Strdup(p);
19680Sstevel@tonic-gate return;
19690Sstevel@tonic-gate }
19700Sstevel@tonic-gate
19710Sstevel@tonic-gate if ((strncmp(bname, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) &&
19720Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/did/dsk/")), '/') == NULL)) {
19730Sstevel@tonic-gate if (np->cname)
19740Sstevel@tonic-gate Free(np->cname);
19750Sstevel@tonic-gate np->cname = Strdup(p);
19760Sstevel@tonic-gate return;
19770Sstevel@tonic-gate }
19780Sstevel@tonic-gate
19790Sstevel@tonic-gate /* anything else but metadevice */
19800Sstevel@tonic-gate if (np->drivenamep->type != MDT_META) {
19810Sstevel@tonic-gate if (np->cname)
19820Sstevel@tonic-gate Free(np->cname);
19830Sstevel@tonic-gate np->cname = Strdup(bname);
19840Sstevel@tonic-gate return;
19850Sstevel@tonic-gate }
19860Sstevel@tonic-gate
19870Sstevel@tonic-gate /* metadevice */
19880Sstevel@tonic-gate p = strrchr(bname, '/');
19890Sstevel@tonic-gate assert(p != NULL);
19900Sstevel@tonic-gate ++p;
19910Sstevel@tonic-gate if (metaislocalset(sp)) {
19920Sstevel@tonic-gate if (np->cname)
19930Sstevel@tonic-gate Free(np->cname);
19940Sstevel@tonic-gate np->cname = Strdup(p);
19950Sstevel@tonic-gate } else {
19960Sstevel@tonic-gate assert(sname[0] != '\0');
19970Sstevel@tonic-gate if (np->cname)
19980Sstevel@tonic-gate Free(np->cname);
19990Sstevel@tonic-gate len = strlen(sname) + 1 + strlen(p) + 1;
20000Sstevel@tonic-gate np->cname = Malloc(len);
20010Sstevel@tonic-gate (void) snprintf(np->cname, len, "%s/%s", sname, p);
20020Sstevel@tonic-gate }
20030Sstevel@tonic-gate }
20040Sstevel@tonic-gate
20050Sstevel@tonic-gate /*
20060Sstevel@tonic-gate * get dev
20070Sstevel@tonic-gate */
20080Sstevel@tonic-gate int
meta_getdev(mdsetname_t * sp,mdname_t * np,md_error_t * ep)20090Sstevel@tonic-gate meta_getdev(
20100Sstevel@tonic-gate mdsetname_t *sp,
20110Sstevel@tonic-gate mdname_t *np,
20120Sstevel@tonic-gate md_error_t *ep
20130Sstevel@tonic-gate )
20140Sstevel@tonic-gate {
20150Sstevel@tonic-gate struct stat statbuf;
20160Sstevel@tonic-gate
20170Sstevel@tonic-gate /* get dev */
20180Sstevel@tonic-gate if (meta_stat(np->rname, &statbuf) != 0)
20190Sstevel@tonic-gate return (mdsyserror(ep, errno, np->rname));
20200Sstevel@tonic-gate else if (! S_ISCHR(statbuf.st_mode))
20210Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, NODEV64, np->rname));
20220Sstevel@tonic-gate np->dev = meta_expldev(statbuf.st_rdev);
20230Sstevel@tonic-gate
20240Sstevel@tonic-gate assert(np->drivenamep->type != MDT_FAST_META &&
20250Sstevel@tonic-gate np->drivenamep->type != MDT_FAST_COMP);
20260Sstevel@tonic-gate
20270Sstevel@tonic-gate /* check set */
20280Sstevel@tonic-gate assert((np->drivenamep->type == MDT_META) ?
20290Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1);
20300Sstevel@tonic-gate
20310Sstevel@tonic-gate /* return sucess */
20320Sstevel@tonic-gate return (0);
20330Sstevel@tonic-gate }
20340Sstevel@tonic-gate
20350Sstevel@tonic-gate /*
20360Sstevel@tonic-gate * set up names for a slice
20370Sstevel@tonic-gate */
20380Sstevel@tonic-gate static int
getnames(mdsetname_t * sp,mdname_t * np,char * rname,md_error_t * ep)20390Sstevel@tonic-gate getnames(
20400Sstevel@tonic-gate mdsetname_t *sp,
20410Sstevel@tonic-gate mdname_t *np,
20420Sstevel@tonic-gate char *rname,
20430Sstevel@tonic-gate md_error_t *ep
20440Sstevel@tonic-gate )
20450Sstevel@tonic-gate {
20460Sstevel@tonic-gate /* get names */
20470Sstevel@tonic-gate if (np->rname)
20480Sstevel@tonic-gate Free(np->rname);
20490Sstevel@tonic-gate np->rname = Strdup(rname);
20500Sstevel@tonic-gate if (getbname(np, ep) != 0)
20510Sstevel@tonic-gate return (-1);
20520Sstevel@tonic-gate getcname(sp, np);
20530Sstevel@tonic-gate if (meta_getdev(sp, np, ep) != 0)
20540Sstevel@tonic-gate return (-1);
20550Sstevel@tonic-gate
20560Sstevel@tonic-gate /* return success */
20570Sstevel@tonic-gate return (0);
20580Sstevel@tonic-gate }
20590Sstevel@tonic-gate
20600Sstevel@tonic-gate /*
20610Sstevel@tonic-gate * fake up names for a slice
20620Sstevel@tonic-gate */
20630Sstevel@tonic-gate static void
getfakenames(mdsetname_t * sp,mdname_t * np,char * rname)20640Sstevel@tonic-gate getfakenames(
20650Sstevel@tonic-gate mdsetname_t *sp,
20660Sstevel@tonic-gate mdname_t *np,
20670Sstevel@tonic-gate char *rname
20680Sstevel@tonic-gate )
20690Sstevel@tonic-gate {
20700Sstevel@tonic-gate char *p;
20710Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1];
20720Sstevel@tonic-gate uint_t d = 0;
20730Sstevel@tonic-gate int l = 0;
20740Sstevel@tonic-gate
20750Sstevel@tonic-gate /* fake names */
20760Sstevel@tonic-gate if (np->rname != NULL)
20770Sstevel@tonic-gate Free(np->rname);
20780Sstevel@tonic-gate np->rname = Strdup(rname);
20790Sstevel@tonic-gate
20800Sstevel@tonic-gate if (np->bname != NULL)
20810Sstevel@tonic-gate Free(np->bname);
20820Sstevel@tonic-gate np->bname = Strdup(rname);
20830Sstevel@tonic-gate
20840Sstevel@tonic-gate /*
20850Sstevel@tonic-gate * Fixup old style names
20860Sstevel@tonic-gate */
20870Sstevel@tonic-gate if (sscanf(rname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
20880Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n",
20890Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(rname))
20900Sstevel@tonic-gate (void) snprintf(np->bname, l, "/dev/%s%u%s", onmb, d, snm);
20910Sstevel@tonic-gate
20920Sstevel@tonic-gate /*
20930Sstevel@tonic-gate * Fixup new style names
20940Sstevel@tonic-gate */
20950Sstevel@tonic-gate if ((p = strstr(np->bname, "/rdsk/")) != NULL) {
20960Sstevel@tonic-gate for (++p; (*(p + 1) != '\0'); ++p)
20970Sstevel@tonic-gate *p = *(p + 1);
20980Sstevel@tonic-gate *p = '\0';
20990Sstevel@tonic-gate }
21000Sstevel@tonic-gate
21010Sstevel@tonic-gate if (np->cname != NULL)
21020Sstevel@tonic-gate Free(np->cname);
21030Sstevel@tonic-gate getcname(sp, np);
21040Sstevel@tonic-gate }
21050Sstevel@tonic-gate
21060Sstevel@tonic-gate static mdname_t *
setup_slice(mdsetname_t * sp,meta_device_type_t uname_type,mddrivename_t * dnp,char * uname,char * rname,char * dname,uint_t partno,md_error_t * ep)21070Sstevel@tonic-gate setup_slice(
21081623Stw21770 mdsetname_t *sp,
21091623Stw21770 meta_device_type_t uname_type,
21101623Stw21770 mddrivename_t *dnp,
21111623Stw21770 char *uname,
21121623Stw21770 char *rname,
21131623Stw21770 char *dname,
21141623Stw21770 uint_t partno,
21151623Stw21770 md_error_t *ep
21160Sstevel@tonic-gate )
21170Sstevel@tonic-gate {
21181623Stw21770 char *srname = NULL;
21191623Stw21770 mdname_t *np;
21200Sstevel@tonic-gate
21210Sstevel@tonic-gate /* must have a set */
21220Sstevel@tonic-gate assert(sp != NULL);
21230Sstevel@tonic-gate assert(partno < dnp->parts.parts_len);
21240Sstevel@tonic-gate assert(dname != NULL);
21250Sstevel@tonic-gate
21260Sstevel@tonic-gate np = &dnp->parts.parts_val[partno];
21270Sstevel@tonic-gate
21280Sstevel@tonic-gate if (rname)
21290Sstevel@tonic-gate srname = rname;
21301623Stw21770 else if (uname_type == META_DEVICE)
21310Sstevel@tonic-gate srname = dname;
21320Sstevel@tonic-gate else {
21330Sstevel@tonic-gate char onmb[BUFSIZ+1];
21340Sstevel@tonic-gate uint_t d = 0;
21350Sstevel@tonic-gate int l = 0, cl = strlen(dname);
21360Sstevel@tonic-gate size_t len;
21370Sstevel@tonic-gate
21380Sstevel@tonic-gate len = cl + 20 + 1;
21390Sstevel@tonic-gate srname = Malloc(len);
21400Sstevel@tonic-gate
21410Sstevel@tonic-gate /*
21420Sstevel@tonic-gate * Handle /dev/rXXNN.
21430Sstevel@tonic-gate */
21440Sstevel@tonic-gate if (sscanf(dname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%n",
21450Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) {
21460Sstevel@tonic-gate (void) snprintf(srname, len, "/dev/r%s%u%c", onmb, d,
21470Sstevel@tonic-gate 'a' + partno);
21480Sstevel@tonic-gate } else if (sscanf(dname, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%n",
21490Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) {
2150*9017SJohn.Wren.Kennedy@Sun.COM (void) snprintf(srname, len, "/dev/%s%u%c", onmb, d,
2151*9017SJohn.Wren.Kennedy@Sun.COM 'a' + partno);
21520Sstevel@tonic-gate } else {
21530Sstevel@tonic-gate /* build the slice that is wanted */
21540Sstevel@tonic-gate (void) snprintf(srname, len, "%ss%u", dname, partno);
21550Sstevel@tonic-gate }
21560Sstevel@tonic-gate }
21570Sstevel@tonic-gate
21580Sstevel@tonic-gate if (getnames(sp, np, srname, ep) != 0) {
21590Sstevel@tonic-gate if (dnp->type == MDT_UNKNOWN) {
21600Sstevel@tonic-gate mdclrerror(ep);
21610Sstevel@tonic-gate getfakenames(sp, np, srname);
21620Sstevel@tonic-gate } else if (dnp->type == MDT_COMP && mdissyserror(ep, ENOENT)) {
21630Sstevel@tonic-gate dnp->type = MDT_UNKNOWN;
21640Sstevel@tonic-gate if (mdanysyserror(ep)) {
21650Sstevel@tonic-gate dnp->errnum =
21660Sstevel@tonic-gate ep->info.md_error_info_t_u.sys_error.errnum;
21670Sstevel@tonic-gate } else {
21680Sstevel@tonic-gate dnp->errnum = ENOENT;
21690Sstevel@tonic-gate }
21700Sstevel@tonic-gate mdclrerror(ep);
21710Sstevel@tonic-gate getfakenames(sp, np, srname);
21720Sstevel@tonic-gate } else {
21730Sstevel@tonic-gate mdclrerror(ep);
21740Sstevel@tonic-gate if (getnames(sp, np, dname, ep) != 0) {
21750Sstevel@tonic-gate np = NULL;
21760Sstevel@tonic-gate goto fixup;
21770Sstevel@tonic-gate }
21780Sstevel@tonic-gate }
21790Sstevel@tonic-gate }
21800Sstevel@tonic-gate
21810Sstevel@tonic-gate out:
21820Sstevel@tonic-gate if ((srname != rname) && (srname != dname))
21830Sstevel@tonic-gate Free(srname);
21840Sstevel@tonic-gate
21850Sstevel@tonic-gate /* return name */
21860Sstevel@tonic-gate return (np);
21870Sstevel@tonic-gate
21880Sstevel@tonic-gate fixup:
21890Sstevel@tonic-gate if (mdanysyserror(ep)) {
21900Sstevel@tonic-gate char *p;
21910Sstevel@tonic-gate int errnum = ep->info.md_error_info_t_u.sys_error.errnum;
21920Sstevel@tonic-gate
21930Sstevel@tonic-gate mdclrerror(ep);
21940Sstevel@tonic-gate if (uname && *uname) {
21950Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL)
21960Sstevel@tonic-gate (void) mdsyserror(ep, errnum, ++p);
21970Sstevel@tonic-gate else
21980Sstevel@tonic-gate (void) mdsyserror(ep, errnum, uname);
21990Sstevel@tonic-gate } else {
22000Sstevel@tonic-gate if ((p = strrchr(srname, '/')) != NULL)
22010Sstevel@tonic-gate (void) mdsyserror(ep, errnum, ++p);
22020Sstevel@tonic-gate else
22030Sstevel@tonic-gate (void) mdsyserror(ep, errnum, srname);
22040Sstevel@tonic-gate }
22050Sstevel@tonic-gate }
22060Sstevel@tonic-gate goto out;
22070Sstevel@tonic-gate }
22080Sstevel@tonic-gate
22090Sstevel@tonic-gate /*
22100Sstevel@tonic-gate * flush the fast name cache
22110Sstevel@tonic-gate */
22120Sstevel@tonic-gate static void
metafreefastnm(mdname_t ** np)22130Sstevel@tonic-gate metafreefastnm(mdname_t **np)
22140Sstevel@tonic-gate {
22150Sstevel@tonic-gate mddrivename_t *dnp;
22160Sstevel@tonic-gate
22170Sstevel@tonic-gate assert(np != NULL && *np != NULL);
22180Sstevel@tonic-gate
22190Sstevel@tonic-gate if ((dnp = (*np)->drivenamep) != NULL) {
22200Sstevel@tonic-gate if (dnp->cname != NULL)
22210Sstevel@tonic-gate Free(dnp->cname);
22220Sstevel@tonic-gate if (dnp->rname != NULL)
22230Sstevel@tonic-gate Free(dnp->rname);
22240Sstevel@tonic-gate if (dnp->miscname != NULL)
22250Sstevel@tonic-gate Free(dnp->miscname);
22260Sstevel@tonic-gate meta_free_unit(dnp);
22270Sstevel@tonic-gate Free(dnp);
22280Sstevel@tonic-gate }
22290Sstevel@tonic-gate if ((*np)->cname != NULL)
22300Sstevel@tonic-gate Free((*np)->cname);
22310Sstevel@tonic-gate if ((*np)->bname != NULL)
22320Sstevel@tonic-gate Free((*np)->bname);
22330Sstevel@tonic-gate if ((*np)->rname != NULL)
22340Sstevel@tonic-gate Free((*np)->rname);
22350Sstevel@tonic-gate if ((*np)->devicesname != NULL)
22360Sstevel@tonic-gate Free((*np)->devicesname);
22370Sstevel@tonic-gate Free(*np);
22380Sstevel@tonic-gate *np = NULL;
22390Sstevel@tonic-gate }
22400Sstevel@tonic-gate
22410Sstevel@tonic-gate /*
22420Sstevel@tonic-gate * flush the fast name cache
22430Sstevel@tonic-gate */
22440Sstevel@tonic-gate static void
metaflushfastnames()22450Sstevel@tonic-gate metaflushfastnames()
22460Sstevel@tonic-gate {
22470Sstevel@tonic-gate mdnamelist_t *p, *n;
22480Sstevel@tonic-gate
22490Sstevel@tonic-gate for (p = fastnmlp, n = NULL; (p != NULL); p = n) {
22500Sstevel@tonic-gate n = p->next;
22510Sstevel@tonic-gate metafreefastnm(&p->namep);
22520Sstevel@tonic-gate Free(p);
22530Sstevel@tonic-gate }
22540Sstevel@tonic-gate fastnmlp = NULL;
22550Sstevel@tonic-gate }
2256*9017SJohn.Wren.Kennedy@Sun.COM
22570Sstevel@tonic-gate static char *
getrname_fast(char * unm,meta_device_type_t uname_type,md_error_t * ep)22581623Stw21770 getrname_fast(char *unm, meta_device_type_t uname_type, md_error_t *ep)
22590Sstevel@tonic-gate {
22600Sstevel@tonic-gate uint_t d = 0;
22610Sstevel@tonic-gate int l = 0;
22620Sstevel@tonic-gate int cl = strlen(unm);
22630Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1], cnmb[BUFSIZ];
22640Sstevel@tonic-gate char *rnm;
22650Sstevel@tonic-gate size_t len;
22660Sstevel@tonic-gate
22671623Stw21770 if (uname_type == META_DEVICE) {
22681623Stw21770 /* fully qualified - local set */
22691623Stw21770 if (((sscanf(unm, "/dev/md/dsk/%" VAL2STR(BUFSIZ) "s%n",
2270*9017SJohn.Wren.Kennedy@Sun.COM onmb, &len) == 1) && (cl == len)) || ((sscanf(unm,
2271*9017SJohn.Wren.Kennedy@Sun.COM "/dev/md/rdsk/%" VAL2STR(BUFSIZ) "s%n",
2272*9017SJohn.Wren.Kennedy@Sun.COM onmb, &len) == 1) && (cl == len))) {
22731623Stw21770 len = strlen("/dev/md/rdsk/") + strlen(onmb) + 1;
22741623Stw21770 rnm = Zalloc(len);
22751623Stw21770 (void) snprintf(rnm, len, "/dev/md/rdsk/%s", onmb);
22761623Stw21770 return (rnm);
22771623Stw21770 }
22781623Stw21770
22791623Stw21770 /* fully qualified - setname specified */
22801623Stw21770 if (((sscanf(unm, "/dev/md/%[^/]/dsk/%"
2281*9017SJohn.Wren.Kennedy@Sun.COM VAL2STR(BUFSIZ) "s%n", snm, onmb, &len) == 2) &&
2282*9017SJohn.Wren.Kennedy@Sun.COM (cl == len)) || ((sscanf(unm, "/dev/md/%[^/]/rdsk/%"
2283*9017SJohn.Wren.Kennedy@Sun.COM VAL2STR(BUFSIZ) "s%n", snm, onmb, &len) == 2) &&
2284*9017SJohn.Wren.Kennedy@Sun.COM (cl == len))) {
22851623Stw21770
22861623Stw21770 len = strlen("/dev/md//rdsk/") + strlen(snm) +
2287*9017SJohn.Wren.Kennedy@Sun.COM strlen(onmb) + 1;
22881623Stw21770 rnm = Zalloc(len);
22891623Stw21770 (void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s",
22901623Stw21770 snm, onmb);
22910Sstevel@tonic-gate return (rnm);
22920Sstevel@tonic-gate }
22930Sstevel@tonic-gate
22941623Stw21770 /* Fully qualified path - error */
22951623Stw21770 if (unm[0] == '/') {
22961623Stw21770 (void) mdsyserror(ep, EINVAL, unm);
22971623Stw21770 return (NULL);
22981623Stw21770 }
22991623Stw21770
23001623Stw21770 /* setname specified <setname>/<metadev> */
23011623Stw21770 if (((sscanf(unm, "%[^/]/%" VAL2STR(BUFSIZ) "s%n",
2302*9017SJohn.Wren.Kennedy@Sun.COM snm, onmb, &len) == 2) && (cl == len))) {
23031623Stw21770 /* Not <setname>/<metadev> - error */
23041623Stw21770 if (strchr(onmb, '/') != NULL) {
23051623Stw21770 (void) mdsyserror(ep, EINVAL, unm);
23061623Stw21770 return (NULL);
23071623Stw21770 }
23081623Stw21770
23091623Stw21770 len = strlen("/dev/md//rdsk/") + strlen(snm) +
2310*9017SJohn.Wren.Kennedy@Sun.COM strlen(onmb) + 1;
23111623Stw21770 rnm = Zalloc(len);
23121623Stw21770 (void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s",
23131623Stw21770 snm, onmb);
23140Sstevel@tonic-gate return (rnm);
23150Sstevel@tonic-gate }
23160Sstevel@tonic-gate
23171623Stw21770 /* Must be simple metaname/hsp pool name */
23181623Stw21770 len = strlen("/dev/md/rdsk/") + strlen(unm) + 1;
23191623Stw21770 rnm = Zalloc(len);
23201623Stw21770 (void) snprintf(rnm, len, "/dev/md/rdsk/%s", unm);
23211623Stw21770 return (rnm);
23220Sstevel@tonic-gate }
23230Sstevel@tonic-gate
23240Sstevel@tonic-gate /* NOT Fully qualified path, done */
23250Sstevel@tonic-gate if (unm[0] != '/') {
23260Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, unm);
23270Sstevel@tonic-gate return (NULL);
23280Sstevel@tonic-gate }
23290Sstevel@tonic-gate
23300Sstevel@tonic-gate /*
23310Sstevel@tonic-gate * Get slice information from old style names of the form
23320Sstevel@tonic-gate * /dev/rXXNN[a-h] or /dev/XXNN[a-h], must be done before regular
23330Sstevel@tonic-gate * devices, but after metadevices.
23340Sstevel@tonic-gate */
23350Sstevel@tonic-gate if ((sscanf(unm, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u"
23360Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n",
23370Sstevel@tonic-gate onmb, &d, snm, &l) == 3 ||
23380Sstevel@tonic-gate sscanf(unm, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u"
23390Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n",
23400Sstevel@tonic-gate onmb, &d, snm, &l) == 3) && l == cl) {
2341*9017SJohn.Wren.Kennedy@Sun.COM if (strchr("abcdefgh", snm[0]) != NULL) {
23420Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u%s",
23430Sstevel@tonic-gate onmb, d, snm);
23440Sstevel@tonic-gate return (Strdup(cnmb));
23450Sstevel@tonic-gate }
23460Sstevel@tonic-gate }
23470Sstevel@tonic-gate
2348*9017SJohn.Wren.Kennedy@Sun.COM /* /.../dsk/... or /.../rdsk/... */
2349*9017SJohn.Wren.Kennedy@Sun.COM if ((rnm = meta_dsk_to_rdsk(unm)) != NULL)
23500Sstevel@tonic-gate return (rnm);
23510Sstevel@tonic-gate
23520Sstevel@tonic-gate /*
23530Sstevel@tonic-gate * Shouldn't get here but if we do then we have an unrecognized
23540Sstevel@tonic-gate * fully qualified path - error
23550Sstevel@tonic-gate */
23560Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, unm);
23570Sstevel@tonic-gate return (NULL);
23580Sstevel@tonic-gate }
23590Sstevel@tonic-gate
23600Sstevel@tonic-gate static mdname_t *
metainitfastname(mdsetname_t * sp,char * uname,meta_device_type_t uname_type,md_error_t * ep)23610Sstevel@tonic-gate metainitfastname(
23621623Stw21770 mdsetname_t *sp,
23631623Stw21770 char *uname,
23641623Stw21770 meta_device_type_t uname_type,
23651623Stw21770 md_error_t *ep
23660Sstevel@tonic-gate )
23670Sstevel@tonic-gate {
23680Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0, s = 0;
23690Sstevel@tonic-gate int l = 0;
23700Sstevel@tonic-gate mddrivename_t *dnp;
23710Sstevel@tonic-gate mdname_t *np;
23720Sstevel@tonic-gate mdnamelist_t **fnlpp;
23731623Stw21770 char *cname;
23740Sstevel@tonic-gate
23750Sstevel@tonic-gate for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) {
23760Sstevel@tonic-gate np = (*fnlpp)->namep;
23770Sstevel@tonic-gate
23780Sstevel@tonic-gate if (strcmp(np->bname, uname) == 0)
23790Sstevel@tonic-gate return (np);
23800Sstevel@tonic-gate }
23810Sstevel@tonic-gate
23820Sstevel@tonic-gate *fnlpp = Zalloc(sizeof (**fnlpp));
23830Sstevel@tonic-gate np = (*fnlpp)->namep = Zalloc(sizeof (mdname_t));
23840Sstevel@tonic-gate metainitname(np);
23850Sstevel@tonic-gate dnp = np->drivenamep = Zalloc(sizeof (mddrivename_t));
23860Sstevel@tonic-gate metainitdrivename(dnp);
23870Sstevel@tonic-gate
23880Sstevel@tonic-gate
23890Sstevel@tonic-gate /* Metadevices */
23901623Stw21770 if (uname_type == META_DEVICE &&
23911623Stw21770 (cname = meta_canonicalize(sp, uname)) != NULL) {
23921623Stw21770
23931623Stw21770 np->cname = cname;
23940Sstevel@tonic-gate dnp->type = MDT_FAST_META;
23950Sstevel@tonic-gate goto done;
23960Sstevel@tonic-gate }
23970Sstevel@tonic-gate
23980Sstevel@tonic-gate /* Others */
23990Sstevel@tonic-gate dnp->type = MDT_FAST_COMP;
24000Sstevel@tonic-gate
24010Sstevel@tonic-gate if (((sscanf(uname, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d,
2402*9017SJohn.Wren.Kennedy@Sun.COM &s, &l) == 4 ||
24030Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d,
2404*9017SJohn.Wren.Kennedy@Sun.COM &s, &l) == 4 ||
24050Sstevel@tonic-gate sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c, &t, &d,
2406*9017SJohn.Wren.Kennedy@Sun.COM &s, &l) == 4 ||
24070Sstevel@tonic-gate sscanf(uname, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c, &t, &d,
2408*9017SJohn.Wren.Kennedy@Sun.COM &s, &l) == 4 ||
24090Sstevel@tonic-gate sscanf(uname, "/dev/did/rdsk/d%us%u%n", &t, &s, &l) == 2 ||
24100Sstevel@tonic-gate sscanf(uname, "/dev/did/dsk/d%us%u%n", &t, &s, &l) == 2||
24110Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
24120Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
24130Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
24140Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
24150Sstevel@tonic-gate sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
24160Sstevel@tonic-gate sscanf(uname, "/dev/ap/dsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
24170Sstevel@tonic-gate sscanf(uname, "/dev/did/rdsk/d%u%n", &t, &l) == 1 ||
24180Sstevel@tonic-gate sscanf(uname, "/dev/did/dsk/d%u%n", &t, &l) == 1 ||
24190Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ud%u%n", &c, &d, &l) == 2 ||
24200Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2) &&
2421*9017SJohn.Wren.Kennedy@Sun.COM l == strlen(uname))) {
24220Sstevel@tonic-gate if ((np->cname = strrchr(uname, '/')) == NULL)
24230Sstevel@tonic-gate np->cname = Strdup(uname);
24240Sstevel@tonic-gate else
24250Sstevel@tonic-gate np->cname = Strdup(++np->cname);
24260Sstevel@tonic-gate } else {
24270Sstevel@tonic-gate np->cname = Strdup(uname);
24280Sstevel@tonic-gate }
24290Sstevel@tonic-gate
24300Sstevel@tonic-gate done:
24310Sstevel@tonic-gate /* Driver always gives us block names */
24320Sstevel@tonic-gate np->bname = Strdup(uname);
24330Sstevel@tonic-gate
24340Sstevel@tonic-gate /* canonical disk name */
24350Sstevel@tonic-gate if ((dnp->cname = metadiskname(np->cname)) == NULL)
24360Sstevel@tonic-gate dnp->cname = Strdup(np->cname);
24370Sstevel@tonic-gate
24381623Stw21770 if ((np->rname = getrname_fast(uname, uname_type, ep)) != NULL) {
24390Sstevel@tonic-gate if ((dnp->rname = metadiskname(np->rname)) == NULL)
24400Sstevel@tonic-gate dnp->rname = Strdup(np->rname);
24410Sstevel@tonic-gate } else {
24420Sstevel@tonic-gate metafreefastnm(&(*fnlpp)->namep);
24430Sstevel@tonic-gate Free(*fnlpp);
24440Sstevel@tonic-gate *fnlpp = NULL;
24450Sstevel@tonic-gate return (NULL);
24460Sstevel@tonic-gate }
24470Sstevel@tonic-gate
24480Sstevel@tonic-gate /* cleanup, return success */
24490Sstevel@tonic-gate return (np);
24500Sstevel@tonic-gate }
24510Sstevel@tonic-gate
24520Sstevel@tonic-gate /*
24530Sstevel@tonic-gate * set up names for a device
24540Sstevel@tonic-gate */
24550Sstevel@tonic-gate static mdname_t *
metaname_common(mdsetname_t ** spp,char * uname,int fast,meta_device_type_t uname_type,md_error_t * ep)24560Sstevel@tonic-gate metaname_common(
24570Sstevel@tonic-gate mdsetname_t **spp,
24580Sstevel@tonic-gate char *uname,
24590Sstevel@tonic-gate int fast,
24601623Stw21770 meta_device_type_t uname_type,
24610Sstevel@tonic-gate md_error_t *ep
24620Sstevel@tonic-gate )
24630Sstevel@tonic-gate {
24640Sstevel@tonic-gate mddrivenamelist_t **tail;
24650Sstevel@tonic-gate mddrivename_t *dnp;
24660Sstevel@tonic-gate uint_t slice;
24670Sstevel@tonic-gate mdname_t *np;
24680Sstevel@tonic-gate char *rname = NULL;
24690Sstevel@tonic-gate char *dname = NULL;
24700Sstevel@tonic-gate char *cname = NULL;
24710Sstevel@tonic-gate uint_t nparts, partno;
24720Sstevel@tonic-gate
24730Sstevel@tonic-gate assert(uname != NULL);
24740Sstevel@tonic-gate
24750Sstevel@tonic-gate /* check setname */
24761623Stw21770 if ((cname = meta_name_getname(spp, uname, uname_type, ep)) == NULL)
24770Sstevel@tonic-gate return (NULL);
24780Sstevel@tonic-gate
24790Sstevel@tonic-gate assert(*spp != NULL);
24800Sstevel@tonic-gate Free(cname);
24810Sstevel@tonic-gate
24820Sstevel@tonic-gate /* get raw name (rname) of the slice and drive (dname) we have */
24831623Stw21770 if ((rname = getrawnames(spp, uname,
2484*9017SJohn.Wren.Kennedy@Sun.COM &dname, &uname_type, ep)) == NULL) {
24850Sstevel@tonic-gate return (NULL);
24860Sstevel@tonic-gate }
24870Sstevel@tonic-gate
24881623Stw21770 assert(uname_type != UNKNOWN);
24891623Stw21770
24900Sstevel@tonic-gate /* look in cache first */
24910Sstevel@tonic-gate for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
24920Sstevel@tonic-gate dnp = (*tail)->drivenamep;
24930Sstevel@tonic-gate
24940Sstevel@tonic-gate /* check to see if the drive name is already in the cache */
24950Sstevel@tonic-gate if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) {
24960Sstevel@tonic-gate
24970Sstevel@tonic-gate Free(rname);
24980Sstevel@tonic-gate if (dname != NULL)
24990Sstevel@tonic-gate Free(dname);
25000Sstevel@tonic-gate
25011623Stw21770 if (uname2sliceno(uname, uname_type, &partno, ep) < 0)
25020Sstevel@tonic-gate return (NULL);
25030Sstevel@tonic-gate
25040Sstevel@tonic-gate return (metaslicename(dnp, partno, ep));
25050Sstevel@tonic-gate }
25060Sstevel@tonic-gate }
25070Sstevel@tonic-gate
25080Sstevel@tonic-gate /*
25090Sstevel@tonic-gate * If a fast names is OK, then get one, and be done.
25100Sstevel@tonic-gate */
25110Sstevel@tonic-gate if (fast) {
25120Sstevel@tonic-gate Free(rname);
25130Sstevel@tonic-gate if (dname != NULL)
25140Sstevel@tonic-gate Free(dname);
25150Sstevel@tonic-gate
25161623Stw21770 return (metainitfastname(*spp, uname, uname_type, ep));
25170Sstevel@tonic-gate }
25180Sstevel@tonic-gate
25190Sstevel@tonic-gate /* allocate new list element and drive */
25200Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail));
25210Sstevel@tonic-gate dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
25220Sstevel@tonic-gate
25230Sstevel@tonic-gate metainitdrivename(dnp);
25240Sstevel@tonic-gate
25250Sstevel@tonic-gate /* get parts info */
25261623Stw21770 if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
25270Sstevel@tonic-gate goto out;
25280Sstevel@tonic-gate
25290Sstevel@tonic-gate /*
25300Sstevel@tonic-gate * libmeta needs at least V_NUMPAR partitions.
25310Sstevel@tonic-gate * If we have an EFI partition with less than V_NUMPAR slices,
25320Sstevel@tonic-gate * we nevertheless reserve space for V_NUMPAR
25330Sstevel@tonic-gate */
25340Sstevel@tonic-gate if (nparts < V_NUMPAR) {
25350Sstevel@tonic-gate nparts = V_NUMPAR;
25360Sstevel@tonic-gate }
25370Sstevel@tonic-gate
25380Sstevel@tonic-gate /* allocate and link in parts */
25390Sstevel@tonic-gate dnp->parts.parts_len = nparts;
25400Sstevel@tonic-gate dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) *
25410Sstevel@tonic-gate dnp->parts.parts_len);
25420Sstevel@tonic-gate for (slice = 0; (slice < nparts); ++slice) {
25430Sstevel@tonic-gate np = &dnp->parts.parts_val[slice];
25440Sstevel@tonic-gate metainitname(np);
25450Sstevel@tonic-gate np->drivenamep = dnp;
25460Sstevel@tonic-gate }
25470Sstevel@tonic-gate
25480Sstevel@tonic-gate /* setup name_t (or slice) wanted */
25491623Stw21770 if ((np = setup_slice(*spp, uname_type, dnp, uname, rname,
25501623Stw21770 dname, partno, ep)) == NULL)
25510Sstevel@tonic-gate goto out;
25520Sstevel@tonic-gate
25530Sstevel@tonic-gate /* canonical disk name */
25540Sstevel@tonic-gate if ((dnp->cname = metadiskname(np->cname)) == NULL)
25550Sstevel@tonic-gate dnp->cname = Strdup(np->cname);
25560Sstevel@tonic-gate if ((dnp->rname = metadiskname(np->rname)) == NULL)
25570Sstevel@tonic-gate dnp->rname = Strdup(np->rname);
25580Sstevel@tonic-gate
25590Sstevel@tonic-gate /* cleanup, return success */
25600Sstevel@tonic-gate if (dname != NULL)
25610Sstevel@tonic-gate Free(dname);
25620Sstevel@tonic-gate Free(rname);
25630Sstevel@tonic-gate return (np);
25640Sstevel@tonic-gate
25650Sstevel@tonic-gate /* cleanup, return error */
25660Sstevel@tonic-gate out:
25670Sstevel@tonic-gate if (dname != NULL)
25680Sstevel@tonic-gate Free(dname);
25690Sstevel@tonic-gate if (rname != NULL)
25700Sstevel@tonic-gate Free(rname);
25710Sstevel@tonic-gate
25720Sstevel@tonic-gate metafreedrivename(dnp);
25730Sstevel@tonic-gate Free(dnp);
25740Sstevel@tonic-gate Free(*tail);
25750Sstevel@tonic-gate *tail = NULL;
25760Sstevel@tonic-gate return (NULL);
25770Sstevel@tonic-gate }
25780Sstevel@tonic-gate
25794150Sjmf /*
25804150Sjmf * metaname()
25814150Sjmf *
25824150Sjmf * Wrapper function for metaname_common()
25834150Sjmf * If the second arg is a metadevice name then it is important that this should
25844150Sjmf * be a canonical name (eg d30 rather than /dev/md/dsk/d30). If this is not the
25854150Sjmf * case then a bad entry may be placed into the drivelistp cache.
25864150Sjmf */
25870Sstevel@tonic-gate mdname_t *
metaname(mdsetname_t ** spp,char * uname,meta_device_type_t uname_type,md_error_t * ep)25880Sstevel@tonic-gate metaname(
25890Sstevel@tonic-gate mdsetname_t **spp,
25900Sstevel@tonic-gate char *uname,
25911623Stw21770 meta_device_type_t uname_type,
25920Sstevel@tonic-gate md_error_t *ep
25930Sstevel@tonic-gate )
25940Sstevel@tonic-gate {
25951623Stw21770 return (metaname_common(spp, uname, 0, uname_type, ep));
25960Sstevel@tonic-gate }
25970Sstevel@tonic-gate
25980Sstevel@tonic-gate mdname_t *
metaname_fast(mdsetname_t ** spp,char * uname,meta_device_type_t uname_type,md_error_t * ep)25990Sstevel@tonic-gate metaname_fast(
26000Sstevel@tonic-gate mdsetname_t **spp,
26010Sstevel@tonic-gate char *uname,
26021623Stw21770 meta_device_type_t uname_type,
26030Sstevel@tonic-gate md_error_t *ep
26040Sstevel@tonic-gate )
26050Sstevel@tonic-gate {
26061623Stw21770 return (metaname_common(spp, uname, 1, uname_type, ep));
26070Sstevel@tonic-gate }
26081945Sjeanm /*
26091945Sjeanm * Get the dnp using the device id.
26101945Sjeanm *
26111945Sjeanm * We have the potential to have more than 1 dnp with the same disk name but
26121945Sjeanm * have different device ids. This would happen in the case of a partial
26131945Sjeanm * diskset. The unavailable disk name is relative to the prior host and could
26141945Sjeanm * possibly be the same as a disk on this system. The only way to tell which
26151945Sjeanm * dnp belongs with this disk is by searching by device id. We have the
26161945Sjeanm * potential to have the case where 1) the disk who's device id we pass in is
26171945Sjeanm * in the system. In this case the name and the device id are both valid for
26181945Sjeanm * the disk. 2) The disk whose device id we've been passed is not in the
26191945Sjeanm * system and no disk with the same name has a dnp on the list. And 3) The
26201945Sjeanm * disk whose device id we've been passed is not on the system but there is
26211945Sjeanm * a disk with the same name (different devid) that is on the system. Here's
26221945Sjeanm * what we return for each of those cases:
26231945Sjeanm * 1) If disk is in system:
26241945Sjeanm * disk is found on drivelistp or we create a new drivename and it's
26251945Sjeanm * fully populated as expected.
26261945Sjeanm * 2) If disk not in system, no collision
26271945Sjeanm * Disk with the same devid is not found on drivelistp, we create a new
26281945Sjeanm * drivename structure and the dnp->devid is filled in not from getparts
26291945Sjeanm * but from the devidp passed in. No other disk in the system has the
26301945Sjeanm * same "name" or devid.
26311945Sjeanm * This situation would be caused by the import of a partial diskset.
26321945Sjeanm * 3) If disk not in system, collision
26331945Sjeanm * Disk with the same devid is not found on the drivelistp, we create a
26341945Sjeanm * new drivename struct but getparts will use the information from the
26351945Sjeanm * name which is actually in reference to another disk of the same name
26361945Sjeanm * in the system. getparts will fill in the dnp->devid with the value
26371945Sjeanm * from the other disk and we overwrite this with the value of this disk.
26381945Sjeanm * To get into this situation one of the disks is actually unavailable
26391945Sjeanm * as in the case of a partial import.
26401945Sjeanm */
26411945Sjeanm mddrivename_t *
meta_getdnp_bydevid(mdsetname_t * sp,side_t sideno,ddi_devid_t devidp,mdkey_t key,md_error_t * ep)26421945Sjeanm meta_getdnp_bydevid(
26431945Sjeanm mdsetname_t *sp,
26441945Sjeanm side_t sideno,
26451945Sjeanm ddi_devid_t devidp,
26461945Sjeanm mdkey_t key,
26471945Sjeanm md_error_t *ep
26481945Sjeanm )
26491945Sjeanm {
26501945Sjeanm ddi_devid_t dnp_devidp;
26511945Sjeanm char *nm;
26521945Sjeanm mddrivenamelist_t **tail;
26531945Sjeanm mddrivename_t *dnp;
26541945Sjeanm uint_t slice;
26551945Sjeanm mdname_t *np;
26561945Sjeanm char *rname = NULL;
26571945Sjeanm char *dname = NULL;
26581945Sjeanm uint_t nparts, partno;
26591945Sjeanm int ret;
26601945Sjeanm md_set_desc *sd = NULL;
26611945Sjeanm meta_device_type_t uname_type = LOGICAL_DEVICE;
26621945Sjeanm
26631945Sjeanm /* look in the cache first */
26641945Sjeanm for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
26651945Sjeanm dnp = (*tail)->drivenamep;
26661945Sjeanm if (dnp->type != MDT_COMP)
26671945Sjeanm continue;
26681945Sjeanm ret = devid_str_decode(dnp->devid, &dnp_devidp, NULL);
26691945Sjeanm if (ret != 0) {
26701945Sjeanm /* unable to decode the devid */
26711945Sjeanm return (NULL);
26721945Sjeanm }
26731945Sjeanm /* compare with the devid passed in. */
26741945Sjeanm if (devid_compare(devidp, dnp_devidp) == 0) {
26751945Sjeanm /* match! We have the same disk */
26761945Sjeanm devid_free(dnp_devidp);
26771945Sjeanm return (dnp);
26781945Sjeanm }
26791945Sjeanm devid_free(dnp_devidp);
26801945Sjeanm }
26811945Sjeanm
26821945Sjeanm /* drive not in the cache */
26831945Sjeanm
26841945Sjeanm if ((sd = metaget_setdesc(sp, ep)) == NULL) {
26851945Sjeanm return (NULL);
26861945Sjeanm }
26871945Sjeanm /* get namespace info */
26881945Sjeanm if (MD_MNSET_DESC(sd)) {
26891945Sjeanm if ((nm = meta_getnmbykey(MD_LOCAL_SET, sideno,
26901945Sjeanm key, ep)) == NULL)
26911945Sjeanm return (NULL);
26921945Sjeanm } else {
26931945Sjeanm if ((nm = meta_getnmbykey(MD_LOCAL_SET,
26941945Sjeanm sideno+SKEW, key, ep)) == NULL)
26951945Sjeanm return (NULL);
26961945Sjeanm }
26971945Sjeanm
26981945Sjeanm /* get raw name (rname) of the slice and drive name (dname) */
26991945Sjeanm if ((rname = getrawnames(&sp, nm, &dname, &uname_type, ep)) == NULL) {
27001945Sjeanm return (NULL);
27011945Sjeanm }
27021945Sjeanm
27031945Sjeanm /* allocate new list element and drive */
27041945Sjeanm *tail = Zalloc(sizeof (**tail));
27051945Sjeanm dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
27061945Sjeanm metainitdrivename(dnp);
27071945Sjeanm
27081945Sjeanm /* get parts info */
27091945Sjeanm /*
27101945Sjeanm * Note that if the disk is unavailable this name will point to
27111945Sjeanm * either a nonexistent disk and thus the part info and devid will
27121945Sjeanm * be empty or the name will point to the wrong disk and this
27131945Sjeanm * information will be invalid. Because of this, we overwrite the
27141945Sjeanm * dnp->devid with the correct one after getparts returns.
27151945Sjeanm */
27161945Sjeanm if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
27171945Sjeanm goto out;
27181945Sjeanm
27191945Sjeanm dnp->devid = devid_str_encode(devidp, NULL);
27201945Sjeanm
27211945Sjeanm /*
27221945Sjeanm * libmeta needs at least V_NUMPAR partitions.
27231945Sjeanm * If we have an EFI partition with less than V_NUMPAR slices,
27241945Sjeanm * we nevertheless reserve space for V_NUMPAR
27251945Sjeanm */
27261945Sjeanm if (nparts < V_NUMPAR) {
27271945Sjeanm nparts = V_NUMPAR;
27281945Sjeanm }
27291945Sjeanm
27301945Sjeanm /* allocate and link in parts */
27311945Sjeanm dnp->parts.parts_len = nparts;
27321945Sjeanm dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) *
27331945Sjeanm dnp->parts.parts_len);
27341945Sjeanm
27351945Sjeanm for (slice = 0; (slice < nparts); ++slice) {
27361945Sjeanm np = &dnp->parts.parts_val[slice];
27371945Sjeanm metainitname(np);
27381945Sjeanm np->drivenamep = dnp;
27391945Sjeanm }
27401945Sjeanm
27411945Sjeanm /* setup name_t (or slice) wanted */
27421945Sjeanm if ((np = setup_slice(sp, uname_type, dnp, nm, rname,
27431945Sjeanm dname, partno, ep)) == NULL)
27441945Sjeanm goto out;
27451945Sjeanm
27461945Sjeanm /* canonical disk name */
27471945Sjeanm if ((dnp->cname = metadiskname(np->cname)) == NULL)
27481945Sjeanm dnp->cname = Strdup(np->cname);
27491945Sjeanm if ((dnp->rname = metadiskname(np->rname)) == NULL)
27501945Sjeanm dnp->rname = Strdup(np->rname);
27511945Sjeanm
27521945Sjeanm if (dname != NULL)
27531945Sjeanm Free(dname);
27541945Sjeanm Free(rname);
27551945Sjeanm return (dnp);
27561945Sjeanm
27571945Sjeanm out:
27581945Sjeanm if (dname != NULL)
27591945Sjeanm Free(dname);
27601945Sjeanm
27611945Sjeanm if (rname != NULL)
27621945Sjeanm Free(rname);
27631945Sjeanm
27641945Sjeanm metafreedrivename(dnp);
27651945Sjeanm Free(dnp);
27661945Sjeanm Free(*tail);
27671945Sjeanm *tail = NULL;
27681945Sjeanm return (NULL);
27691945Sjeanm }
27701945Sjeanm
27711945Sjeanm /*
27721945Sjeanm * Search the drivename list by devid instead of name. If you don't find
27731945Sjeanm * an entry with the same device id, create one for the uname passed in.
27741945Sjeanm */
27751945Sjeanm mddrivename_t *
metadrivenamebydevid(mdsetname_t ** spp,char * devid,char * uname,md_error_t * ep)27761945Sjeanm metadrivenamebydevid(
27771945Sjeanm mdsetname_t **spp,
27781945Sjeanm char *devid,
27791945Sjeanm char *uname,
27801945Sjeanm md_error_t *ep
27811945Sjeanm )
27821945Sjeanm {
27831945Sjeanm ddi_devid_t dnp_devidp, in_devidp;
27841945Sjeanm mdname_t *np;
27851945Sjeanm mddrivenamelist_t **tail;
27861945Sjeanm char *rname = NULL;
27871945Sjeanm mddrivename_t *dnp;
27881945Sjeanm char *dname;
27891945Sjeanm int ret;
27901945Sjeanm uint_t nparts, partno;
27911945Sjeanm uint_t slice;
27921945Sjeanm meta_device_type_t uname_type = LOGICAL_DEVICE;
27931945Sjeanm
27941945Sjeanm /* look in the cache first */
27951945Sjeanm for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
27961945Sjeanm dnp = (*tail)->drivenamep;
27971945Sjeanm if (dnp->type != MDT_COMP)
27981945Sjeanm continue;
27991945Sjeanm
28001945Sjeanm /* decode the dnp devid */
28011945Sjeanm ret = devid_str_decode(dnp->devid, &dnp_devidp, NULL);
28021945Sjeanm if (ret != 0) {
28031945Sjeanm /* unable to decode the devid */
28041945Sjeanm return (NULL);
28051945Sjeanm }
28061945Sjeanm /* decode the passed in devid */
28071945Sjeanm ret = devid_str_decode(devid, &in_devidp, NULL);
28081945Sjeanm if (ret != 0) {
28091945Sjeanm /* unable to decode the devid */
28101945Sjeanm devid_free(dnp_devidp);
28111945Sjeanm return (NULL);
28121945Sjeanm }
28131945Sjeanm /* compare with the devids */
28141945Sjeanm if (devid_compare(in_devidp, dnp_devidp) == 0) {
28151945Sjeanm /* match! We have the same disk */
28161945Sjeanm devid_free(dnp_devidp);
28171945Sjeanm devid_free(in_devidp);
28181945Sjeanm return (dnp);
28191945Sjeanm }
28201945Sjeanm }
28211945Sjeanm devid_free(dnp_devidp);
28221945Sjeanm devid_free(in_devidp);
28231945Sjeanm
28241945Sjeanm /* not in the cache */
28251945Sjeanm
28261945Sjeanm /* get raw name (rname) of the slice and drive (dname) we have */
28271945Sjeanm if ((rname = getrawnames(spp, uname, &dname, &uname_type,
28281945Sjeanm ep)) == NULL) {
28291945Sjeanm return (NULL);
28301945Sjeanm }
28311945Sjeanm
28321945Sjeanm /* allocate new list element and drive */
28331945Sjeanm *tail = Zalloc(sizeof (**tail));
28341945Sjeanm dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp));
28351945Sjeanm
28361945Sjeanm metainitdrivename(dnp);
28371945Sjeanm
28381945Sjeanm /* get parts info */
28391945Sjeanm if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
28401945Sjeanm goto out;
28411945Sjeanm
28421945Sjeanm /*
28431945Sjeanm * libmeta needs at least V_NUMPAR partitions.
28441945Sjeanm * If we have an EFI partition with less than V_NUMPAR slices,
28451945Sjeanm * we nevertheless reserve space for V_NUMPAR
28461945Sjeanm */
28471945Sjeanm if (nparts < V_NUMPAR) {
28481945Sjeanm nparts = V_NUMPAR;
28491945Sjeanm }
28501945Sjeanm
28511945Sjeanm /* allocate and link in parts */
28521945Sjeanm dnp->parts.parts_len = nparts;
28531945Sjeanm dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) *
28541945Sjeanm dnp->parts.parts_len);
28551945Sjeanm for (slice = 0; (slice < nparts); ++slice) {
28561945Sjeanm np = &dnp->parts.parts_val[slice];
28571945Sjeanm metainitname(np);
28581945Sjeanm np->drivenamep = dnp;
28591945Sjeanm }
28601945Sjeanm
28611945Sjeanm /* setup name_t (or slice) wanted */
28621945Sjeanm if ((np = setup_slice(*spp, uname_type, dnp, uname, rname,
28631945Sjeanm dname, partno, ep)) == NULL)
28641945Sjeanm goto out;
28651945Sjeanm
28661945Sjeanm /* canonical disk name */
28671945Sjeanm if ((dnp->cname = metadiskname(np->cname)) == NULL)
28681945Sjeanm dnp->cname = Strdup(np->cname);
28691945Sjeanm if ((dnp->rname = metadiskname(np->rname)) == NULL)
28701945Sjeanm dnp->rname = Strdup(np->rname);
28711945Sjeanm
28721945Sjeanm /* cleanup, return success */
28731945Sjeanm if (dname != NULL)
28741945Sjeanm Free(dname);
28751945Sjeanm Free(rname);
28761945Sjeanm return (dnp);
28771945Sjeanm
28781945Sjeanm /* cleanup, return error */
28791945Sjeanm out:
28801945Sjeanm if (dname != NULL)
28811945Sjeanm Free(dname);
28821945Sjeanm if (rname != NULL)
28831945Sjeanm Free(rname);
28841945Sjeanm
28851945Sjeanm metafreedrivename(dnp);
28861945Sjeanm Free(dnp);
28871945Sjeanm Free(*tail);
28881945Sjeanm *tail = NULL;
28891945Sjeanm return (NULL);
28901945Sjeanm }
28910Sstevel@tonic-gate /*
28920Sstevel@tonic-gate * set up names for a drive
28930Sstevel@tonic-gate */
28940Sstevel@tonic-gate mddrivename_t *
metadrivename(mdsetname_t ** spp,char * uname,md_error_t * ep)28950Sstevel@tonic-gate metadrivename(
28961623Stw21770 mdsetname_t **spp,
28971623Stw21770 char *uname,
28981623Stw21770 md_error_t *ep
28990Sstevel@tonic-gate )
29000Sstevel@tonic-gate {
29010Sstevel@tonic-gate char *slicename;
29020Sstevel@tonic-gate mdname_t *np;
29030Sstevel@tonic-gate
29040Sstevel@tonic-gate mddrivenamelist_t **tail;
29050Sstevel@tonic-gate mddrivename_t *dnp;
29060Sstevel@tonic-gate char *dname;
29070Sstevel@tonic-gate int i;
29080Sstevel@tonic-gate int mplen;
29090Sstevel@tonic-gate size_t len;
29100Sstevel@tonic-gate
29110Sstevel@tonic-gate assert(uname != NULL);
29121623Stw21770
29131623Stw21770 if ((dname = metadiskname(uname)) == NULL) {
29140Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname);
29150Sstevel@tonic-gate return (NULL);
29160Sstevel@tonic-gate }
29170Sstevel@tonic-gate
29180Sstevel@tonic-gate /* look in cache first */
29190Sstevel@tonic-gate for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
29200Sstevel@tonic-gate dnp = (*tail)->drivenamep;
29210Sstevel@tonic-gate if ((dnp->cname != NULL &&
29220Sstevel@tonic-gate (strcmp(dnp->cname, dname) == 0)) ||
29230Sstevel@tonic-gate (dnp->rname != NULL &&
29240Sstevel@tonic-gate (strcmp(dnp->rname, dname) == 0))) {
29250Sstevel@tonic-gate Free(dname);
29260Sstevel@tonic-gate return (dnp);
29270Sstevel@tonic-gate }
29280Sstevel@tonic-gate }
29291623Stw21770 Free(dname);
29300Sstevel@tonic-gate
29310Sstevel@tonic-gate /* Check each possible slice name based on MD_MAX_PARTS. */
29320Sstevel@tonic-gate
29330Sstevel@tonic-gate /*
29340Sstevel@tonic-gate * Figure out how much string space to reserve to fit
29350Sstevel@tonic-gate * (MD_MAX_PARTS - 1) into the name string; the loop will
29360Sstevel@tonic-gate * increment the mplen counter once for each decimal digit in
29370Sstevel@tonic-gate * (MD_MAX_PARTS - 1).
29380Sstevel@tonic-gate */
2939*9017SJohn.Wren.Kennedy@Sun.COM for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen)
2940*9017SJohn.Wren.Kennedy@Sun.COM ;
29410Sstevel@tonic-gate len = strlen(uname) + mplen + 2;
29420Sstevel@tonic-gate slicename = Malloc(len);
29430Sstevel@tonic-gate
29440Sstevel@tonic-gate /* Check for each slice in turn until we find one */
29450Sstevel@tonic-gate for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) {
29460Sstevel@tonic-gate (void) snprintf(slicename, len, "%ss%d", uname, i);
29471623Stw21770 np = metaname(spp, slicename, LOGICAL_DEVICE, ep);
29480Sstevel@tonic-gate }
29490Sstevel@tonic-gate Free(slicename);
29500Sstevel@tonic-gate
29510Sstevel@tonic-gate if (np == NULL) {
29521623Stw21770 if ((mdiserror(ep, MDE_UNIT_NOT_FOUND)) &&
29530Sstevel@tonic-gate ((dname = metadiskname(uname)) != NULL)) {
29540Sstevel@tonic-gate Free(dname);
29550Sstevel@tonic-gate (void) mderror(ep, MDE_NOT_DRIVENAME, uname);
29560Sstevel@tonic-gate }
29570Sstevel@tonic-gate return (NULL);
29580Sstevel@tonic-gate }
29590Sstevel@tonic-gate return (np->drivenamep);
29600Sstevel@tonic-gate }
29610Sstevel@tonic-gate
29620Sstevel@tonic-gate /*
29631623Stw21770 * FUNCTION: metaslicename_type()
29641623Stw21770 * INPUT: dnp - the drivename structure
29651623Stw21770 * sliceno - the slice on the drive to return
29661623Stw21770 * type - LOGICAL_DEVICE or META_DEVICE
29671623Stw21770 * OUTPUT: ep - return error pointer
29681623Stw21770 * RETURNS: mdname_t- pointer the the slice name structure
29691623Stw21770 * PURPOSE: interface to the parts struct in the drive name struct
29701623Stw21770 * Since there is no guarantee that the slice name
29711623Stw21770 * structures are populated users should call this
29721623Stw21770 * function rather than accessing the structure directly
29731623Stw21770 * since it will populate the structure values if they
29741623Stw21770 * haven't already been populated before returning.
29751623Stw21770 */
29761623Stw21770 mdname_t *
metaslicename_type(mddrivename_t * dnp,uint_t sliceno,meta_device_type_t uname_type,md_error_t * ep)29771623Stw21770 metaslicename_type(
29781623Stw21770 mddrivename_t *dnp,
29791623Stw21770 uint_t sliceno,
29801623Stw21770 meta_device_type_t uname_type,
29811623Stw21770 md_error_t *ep
29821623Stw21770 )
29831623Stw21770 {
29841623Stw21770 mdsetname_t *sp = NULL;
29851623Stw21770 char *namep = NULL;
29861623Stw21770 mdname_t *np;
29871623Stw21770
29881623Stw21770 assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
29891623Stw21770
29901623Stw21770 if (sliceno >= dnp->parts.parts_len) {
29911623Stw21770 (void) mderror(ep, MDE_NOSLICE, dnp->cname);
29921623Stw21770 return (NULL);
29931623Stw21770 }
29941623Stw21770
29951623Stw21770 np = &dnp->parts.parts_val[sliceno];
29961623Stw21770
29971623Stw21770 /* check to see if the struct is already populated */
29981623Stw21770 if (np->cname) {
29991623Stw21770 return (np);
30001623Stw21770 }
30011623Stw21770
30021623Stw21770 if ((namep = meta_name_getname(&sp, dnp->cname,
3003*9017SJohn.Wren.Kennedy@Sun.COM uname_type, ep)) == NULL)
30041623Stw21770 return (NULL);
30051623Stw21770
30061623Stw21770 np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname,
30071623Stw21770 sliceno, ep);
30081623Stw21770
30091623Stw21770 Free(namep);
30101623Stw21770
30111623Stw21770 return (np);
30121623Stw21770 }
30131623Stw21770
30141623Stw21770 /*
30150Sstevel@tonic-gate * FUNCTION: metaslicename()
30160Sstevel@tonic-gate * INPUT: dnp - the drivename structure
30170Sstevel@tonic-gate * sliceno - the slice on the drive to return
30180Sstevel@tonic-gate * OUTPUT: ep - return error pointer
30190Sstevel@tonic-gate * RETURNS: mdname_t- pointer the the slice name structure
30200Sstevel@tonic-gate * PURPOSE: interface to the parts struct in the drive name struct
30210Sstevel@tonic-gate * Since there is no guarantee that the slice name
30220Sstevel@tonic-gate * structures are populated users should call this
30230Sstevel@tonic-gate * function rather than accessing the structure directly
30240Sstevel@tonic-gate * since it will populate the structure values if they
30250Sstevel@tonic-gate * haven't already been populated before returning.
30260Sstevel@tonic-gate */
30270Sstevel@tonic-gate mdname_t *
metaslicename(mddrivename_t * dnp,uint_t sliceno,md_error_t * ep)30280Sstevel@tonic-gate metaslicename(
30290Sstevel@tonic-gate mddrivename_t *dnp,
30300Sstevel@tonic-gate uint_t sliceno,
30310Sstevel@tonic-gate md_error_t *ep
30320Sstevel@tonic-gate )
30330Sstevel@tonic-gate {
30341623Stw21770 return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep));
30350Sstevel@tonic-gate }
30360Sstevel@tonic-gate
30370Sstevel@tonic-gate /*
30380Sstevel@tonic-gate * set up metadevice name from id
30390Sstevel@tonic-gate */
30400Sstevel@tonic-gate mdname_t *
metamnumname(mdsetname_t ** spp,minor_t mnum,int fast,md_error_t * ep)30410Sstevel@tonic-gate metamnumname(
30420Sstevel@tonic-gate mdsetname_t **spp,
30430Sstevel@tonic-gate minor_t mnum,
30440Sstevel@tonic-gate int fast,
30450Sstevel@tonic-gate md_error_t *ep
30460Sstevel@tonic-gate )
30470Sstevel@tonic-gate {
30480Sstevel@tonic-gate set_t setno = MD_MIN2SET(mnum);
30490Sstevel@tonic-gate mdsetname_t *sp = NULL;
30500Sstevel@tonic-gate char *uname;
30510Sstevel@tonic-gate mdname_t *np;
30521623Stw21770 md_dev64_t dev;
30531623Stw21770 mdkey_t key;
30540Sstevel@tonic-gate
30550Sstevel@tonic-gate /* check set first */
30560Sstevel@tonic-gate if (spp == NULL)
30570Sstevel@tonic-gate spp = &sp;
30580Sstevel@tonic-gate if (chksetno(spp, setno, ep) != 0)
30590Sstevel@tonic-gate return (NULL);
30600Sstevel@tonic-gate assert(*spp != NULL);
30610Sstevel@tonic-gate sp = *spp;
30620Sstevel@tonic-gate
30631623Stw21770 /* get corresponding device name */
30641623Stw21770 dev = metamakedev(mnum);
30651623Stw21770 if ((uname = meta_getnmentbydev(sp->setno, MD_SIDEWILD, dev,
30661623Stw21770 NULL, NULL, &key, ep)) == NULL)
30671623Stw21770 return (NULL);
30680Sstevel@tonic-gate
30690Sstevel@tonic-gate /* setup name */
30700Sstevel@tonic-gate if (fast) {
30711623Stw21770 np = metaname_fast(spp, uname, META_DEVICE, ep);
30721623Stw21770 if (np) {
30731623Stw21770 np->dev = dev;
30741623Stw21770 np->key = key;
30751623Stw21770 }
30760Sstevel@tonic-gate } else
30771623Stw21770 np = metaname(spp, uname, META_DEVICE, ep);
30780Sstevel@tonic-gate
30790Sstevel@tonic-gate Free(uname);
30800Sstevel@tonic-gate return (np);
30810Sstevel@tonic-gate }
30820Sstevel@tonic-gate
30830Sstevel@tonic-gate /*
30840Sstevel@tonic-gate * return metadevice name
30850Sstevel@tonic-gate */
30860Sstevel@tonic-gate char *
get_mdname(mdsetname_t * sp,minor_t mnum)30870Sstevel@tonic-gate get_mdname(
30881623Stw21770 mdsetname_t *sp,
30890Sstevel@tonic-gate minor_t mnum
30900Sstevel@tonic-gate )
30910Sstevel@tonic-gate {
30920Sstevel@tonic-gate mdname_t *np;
30930Sstevel@tonic-gate md_error_t status = mdnullerror;
30941623Stw21770 mdsetname_t **spp = NULL;
30951623Stw21770
30961623Stw21770 if (sp != NULL)
30971623Stw21770 spp = &sp;
30980Sstevel@tonic-gate
30990Sstevel@tonic-gate /* get name */
31001623Stw21770 if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) {
31010Sstevel@tonic-gate return (NULL);
31020Sstevel@tonic-gate }
31030Sstevel@tonic-gate assert(meta_getminor(np->dev) == mnum);
31040Sstevel@tonic-gate
31050Sstevel@tonic-gate /* return name */
31060Sstevel@tonic-gate return (np->cname);
31070Sstevel@tonic-gate }
31080Sstevel@tonic-gate
31090Sstevel@tonic-gate /*
31100Sstevel@tonic-gate * check for device type
31110Sstevel@tonic-gate */
31120Sstevel@tonic-gate int
metaismeta(mdname_t * np)31130Sstevel@tonic-gate metaismeta(
31140Sstevel@tonic-gate mdname_t *np
31150Sstevel@tonic-gate )
31160Sstevel@tonic-gate {
31170Sstevel@tonic-gate return (np->drivenamep->type == MDT_META ||
3118*9017SJohn.Wren.Kennedy@Sun.COM np->drivenamep->type == MDT_FAST_META);
31190Sstevel@tonic-gate }
31200Sstevel@tonic-gate
31210Sstevel@tonic-gate int
metachkmeta(mdname_t * np,md_error_t * ep)31220Sstevel@tonic-gate metachkmeta(
31230Sstevel@tonic-gate mdname_t *np,
31240Sstevel@tonic-gate md_error_t *ep
31250Sstevel@tonic-gate )
31260Sstevel@tonic-gate {
31270Sstevel@tonic-gate if (! metaismeta(np)) {
31280Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_META, np->dev,
31290Sstevel@tonic-gate np->cname));
31300Sstevel@tonic-gate }
31310Sstevel@tonic-gate return (0);
31320Sstevel@tonic-gate }
31330Sstevel@tonic-gate
31340Sstevel@tonic-gate int
metachkdisk(mdname_t * np,md_error_t * ep)31350Sstevel@tonic-gate metachkdisk(
31360Sstevel@tonic-gate mdname_t *np,
31370Sstevel@tonic-gate md_error_t *ep
31380Sstevel@tonic-gate )
31390Sstevel@tonic-gate {
31400Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep;
31410Sstevel@tonic-gate
31420Sstevel@tonic-gate assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
31430Sstevel@tonic-gate
31440Sstevel@tonic-gate if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) {
31450Sstevel@tonic-gate switch (dnp->type) {
3146*9017SJohn.Wren.Kennedy@Sun.COM case MDT_ACCES:
3147*9017SJohn.Wren.Kennedy@Sun.COM case MDT_UNKNOWN:
3148*9017SJohn.Wren.Kennedy@Sun.COM return (mdsyserror(ep, dnp->errnum, np->bname));
3149*9017SJohn.Wren.Kennedy@Sun.COM default:
3150*9017SJohn.Wren.Kennedy@Sun.COM assert(0);
3151*9017SJohn.Wren.Kennedy@Sun.COM return (mddeverror(ep, MDE_NOT_DISK, np->dev,
3152*9017SJohn.Wren.Kennedy@Sun.COM np->cname));
31530Sstevel@tonic-gate }
31540Sstevel@tonic-gate }
31550Sstevel@tonic-gate return (0);
31560Sstevel@tonic-gate }
31570Sstevel@tonic-gate
31580Sstevel@tonic-gate int
metachkcomp(mdname_t * np,md_error_t * ep)31590Sstevel@tonic-gate metachkcomp(
31600Sstevel@tonic-gate mdname_t *np,
31610Sstevel@tonic-gate md_error_t *ep
31620Sstevel@tonic-gate )
31630Sstevel@tonic-gate {
31640Sstevel@tonic-gate if (metaismeta(np)) {
31650Sstevel@tonic-gate return (mddeverror(ep, MDE_IS_META, np->dev,
31660Sstevel@tonic-gate np->cname));
31670Sstevel@tonic-gate }
31680Sstevel@tonic-gate return (metachkdisk(np, ep));
31690Sstevel@tonic-gate }
31700Sstevel@tonic-gate
31710Sstevel@tonic-gate /*
31720Sstevel@tonic-gate * free list of names
31730Sstevel@tonic-gate */
31740Sstevel@tonic-gate void
metafreenamelist(mdnamelist_t * nlp)31750Sstevel@tonic-gate metafreenamelist(
31760Sstevel@tonic-gate mdnamelist_t *nlp
31770Sstevel@tonic-gate )
31780Sstevel@tonic-gate {
31790Sstevel@tonic-gate mdnamelist_t *next = NULL;
31800Sstevel@tonic-gate
31810Sstevel@tonic-gate for (/* void */; (nlp != NULL); nlp = next) {
31820Sstevel@tonic-gate next = nlp->next;
31830Sstevel@tonic-gate Free(nlp);
31840Sstevel@tonic-gate }
31850Sstevel@tonic-gate }
31860Sstevel@tonic-gate
31870Sstevel@tonic-gate /*
31880Sstevel@tonic-gate * build list of names
31890Sstevel@tonic-gate */
31900Sstevel@tonic-gate int
metanamelist(mdsetname_t ** spp,mdnamelist_t ** nlpp,int argc,char * argv[],meta_device_type_t type,md_error_t * ep)31910Sstevel@tonic-gate metanamelist(
31920Sstevel@tonic-gate mdsetname_t **spp,
31930Sstevel@tonic-gate mdnamelist_t **nlpp,
31940Sstevel@tonic-gate int argc,
31950Sstevel@tonic-gate char *argv[],
31961623Stw21770 meta_device_type_t type,
31970Sstevel@tonic-gate md_error_t *ep
31980Sstevel@tonic-gate )
31990Sstevel@tonic-gate {
32000Sstevel@tonic-gate mdnamelist_t **tailpp = nlpp;
32010Sstevel@tonic-gate int count = 0;
32020Sstevel@tonic-gate
32030Sstevel@tonic-gate for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
32040Sstevel@tonic-gate mdnamelist_t *nlp = Zalloc(sizeof (*nlp));
32050Sstevel@tonic-gate
32061623Stw21770 if ((nlp->namep = metaname(spp, argv[0],
32071623Stw21770 type, ep)) == NULL) {
32080Sstevel@tonic-gate metafreenamelist(*nlpp);
32090Sstevel@tonic-gate *nlpp = NULL;
32100Sstevel@tonic-gate return (-1);
32110Sstevel@tonic-gate }
32120Sstevel@tonic-gate *tailpp = nlp;
32130Sstevel@tonic-gate tailpp = &nlp->next;
32140Sstevel@tonic-gate }
32150Sstevel@tonic-gate return (count);
32160Sstevel@tonic-gate }
32170Sstevel@tonic-gate
32180Sstevel@tonic-gate /*
32190Sstevel@tonic-gate * append to end of name list
32200Sstevel@tonic-gate */
32210Sstevel@tonic-gate mdname_t *
metanamelist_append(mdnamelist_t ** nlpp,mdname_t * np)32220Sstevel@tonic-gate metanamelist_append(
32230Sstevel@tonic-gate mdnamelist_t **nlpp,
32240Sstevel@tonic-gate mdname_t *np
32250Sstevel@tonic-gate )
32260Sstevel@tonic-gate {
32270Sstevel@tonic-gate mdnamelist_t *nlp;
32280Sstevel@tonic-gate
32290Sstevel@tonic-gate /* run to end of list */
32300Sstevel@tonic-gate for (; (*nlpp != NULL); nlpp = &(*nlpp)->next)
32310Sstevel@tonic-gate ;
32320Sstevel@tonic-gate
32330Sstevel@tonic-gate /* allocate new list element */
32340Sstevel@tonic-gate nlp = *nlpp = Zalloc(sizeof (*nlp));
32350Sstevel@tonic-gate
32360Sstevel@tonic-gate /* append name */
32370Sstevel@tonic-gate nlp->namep = np;
32380Sstevel@tonic-gate return (np);
32390Sstevel@tonic-gate }
32400Sstevel@tonic-gate
32410Sstevel@tonic-gate /*
32420Sstevel@tonic-gate * FUNCTION: meta_namelist_append_wrapper()
32430Sstevel@tonic-gate * INPUT: tailpp - pointer to the list tail pointer
32440Sstevel@tonic-gate * np - name node to be appended to list
32450Sstevel@tonic-gate * OUTPUT: none
32460Sstevel@tonic-gate * RETURNS: mdnamelist_t * - new tail of the list.
32470Sstevel@tonic-gate * PURPOSE: wrapper to meta_namelist_append for performance.
32480Sstevel@tonic-gate * metanamelist_append finds the tail each time which slows
32490Sstevel@tonic-gate * down long lists. By keeping track of the tail ourselves
32500Sstevel@tonic-gate * we can change metanamelist_append into a constant time
32510Sstevel@tonic-gate * operation.
32520Sstevel@tonic-gate */
32530Sstevel@tonic-gate mdnamelist_t **
meta_namelist_append_wrapper(mdnamelist_t ** tailpp,mdname_t * np)32540Sstevel@tonic-gate meta_namelist_append_wrapper(
32550Sstevel@tonic-gate mdnamelist_t **tailpp,
32560Sstevel@tonic-gate mdname_t *np
32570Sstevel@tonic-gate )
32580Sstevel@tonic-gate {
32590Sstevel@tonic-gate (void) metanamelist_append(tailpp, np);
32600Sstevel@tonic-gate
32610Sstevel@tonic-gate /* If it's the first item in the list, return it instead of the next */
32620Sstevel@tonic-gate if ((*tailpp)->next == NULL)
32630Sstevel@tonic-gate return (tailpp);
32640Sstevel@tonic-gate
32650Sstevel@tonic-gate return (&(*tailpp)->next);
32660Sstevel@tonic-gate }
32670Sstevel@tonic-gate
32680Sstevel@tonic-gate
32690Sstevel@tonic-gate /*
32700Sstevel@tonic-gate * mdhspname_t stuff
32710Sstevel@tonic-gate */
32720Sstevel@tonic-gate
32730Sstevel@tonic-gate /*
32740Sstevel@tonic-gate * initialize hspname
32750Sstevel@tonic-gate */
32760Sstevel@tonic-gate static void
metainithspname(mdhspname_t * hspnamep)32770Sstevel@tonic-gate metainithspname(
32780Sstevel@tonic-gate mdhspname_t *hspnamep
32790Sstevel@tonic-gate )
32800Sstevel@tonic-gate {
32810Sstevel@tonic-gate (void) memset(hspnamep, '\0', sizeof (*hspnamep));
32820Sstevel@tonic-gate hspnamep->hsp = MD_HSP_NONE;
32830Sstevel@tonic-gate }
32840Sstevel@tonic-gate
32850Sstevel@tonic-gate /*
32860Sstevel@tonic-gate * free allocated hspname
32870Sstevel@tonic-gate */
32880Sstevel@tonic-gate static void
metafreehspname(mdhspname_t * hspnamep)32890Sstevel@tonic-gate metafreehspname(
32900Sstevel@tonic-gate mdhspname_t *hspnamep
32910Sstevel@tonic-gate )
32920Sstevel@tonic-gate {
32930Sstevel@tonic-gate if (hspnamep->hspname != NULL)
32940Sstevel@tonic-gate Free(hspnamep->hspname);
32950Sstevel@tonic-gate if (hspnamep->unitp != NULL)
32960Sstevel@tonic-gate meta_invalidate_hsp(hspnamep);
32970Sstevel@tonic-gate metainithspname(hspnamep);
32980Sstevel@tonic-gate }
32990Sstevel@tonic-gate
33000Sstevel@tonic-gate /*
33010Sstevel@tonic-gate * clear the hspname cache
33020Sstevel@tonic-gate */
33030Sstevel@tonic-gate static void
metaflushhspnames()33040Sstevel@tonic-gate metaflushhspnames()
33050Sstevel@tonic-gate {
33060Sstevel@tonic-gate mdhspnamelist_t *p, *n;
33070Sstevel@tonic-gate
33080Sstevel@tonic-gate for (p = hsplistp, n = NULL; (p != NULL); p = n) {
33090Sstevel@tonic-gate n = p->next;
33100Sstevel@tonic-gate metafreehspname(p->hspnamep);
33110Sstevel@tonic-gate Free(p->hspnamep);
33120Sstevel@tonic-gate Free(p);
33130Sstevel@tonic-gate }
33140Sstevel@tonic-gate hsplistp = NULL;
33150Sstevel@tonic-gate }
33160Sstevel@tonic-gate
33170Sstevel@tonic-gate /*
33180Sstevel@tonic-gate * check set and get comparison name
33190Sstevel@tonic-gate */
33200Sstevel@tonic-gate static char *
gethspname(mdsetname_t ** spp,char * uname,md_error_t * ep)33210Sstevel@tonic-gate gethspname(
33220Sstevel@tonic-gate mdsetname_t **spp,
33230Sstevel@tonic-gate char *uname,
33240Sstevel@tonic-gate md_error_t *ep
33250Sstevel@tonic-gate )
33260Sstevel@tonic-gate {
33271623Stw21770 char *cname = NULL;
33281623Stw21770
33291623Stw21770 cname = meta_canonicalize(*spp, uname);
33301623Stw21770 /* if it is not a meta/hsp name then flag an error */
33311623Stw21770 if (cname == NULL) {
33321623Stw21770 (void) mdsyserror(ep, ENOENT, uname);
33331623Stw21770 return (NULL);
33341623Stw21770 }
33351623Stw21770 return (cname);
33361623Stw21770 }
33371623Stw21770
33381623Stw21770 /*
33391623Stw21770 * set up a hotspare pool name structure using both the name
33401623Stw21770 * and the self id
33411623Stw21770 */
33421623Stw21770 static mdhspname_t *
metahspname_hsp(mdsetname_t ** spp,char * uname,hsp_t hsp,md_error_t * ep)33431623Stw21770 metahspname_hsp(
33441623Stw21770 mdsetname_t **spp,
33451623Stw21770 char *uname,
33461623Stw21770 hsp_t hsp,
33471623Stw21770 md_error_t *ep
33481623Stw21770 )
33491623Stw21770 {
33501623Stw21770 char *cname;
33511623Stw21770 mdhspnamelist_t **tail;
33521623Stw21770 mdhspname_t *hspnp;
33530Sstevel@tonic-gate
33540Sstevel@tonic-gate /* check setname */
33550Sstevel@tonic-gate assert(uname != NULL);
33561623Stw21770 if ((cname = gethspname(spp, uname, ep)) == NULL)
33570Sstevel@tonic-gate return (NULL);
33581623Stw21770 assert(*spp != NULL);
33591623Stw21770
33601623Stw21770 /* look in cache first */
33611623Stw21770 for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) {
33621623Stw21770 hspnp = (*tail)->hspnamep;
33631623Stw21770 if (strcmp(hspnp->hspname, cname) == 0) {
33641623Stw21770 Free(cname);
33651623Stw21770 /* if the hsp value has not been set then set it now */
33661623Stw21770 if (hspnp->hsp == MD_HSP_NONE)
33671623Stw21770 hspnp->hsp = hsp;
33681623Stw21770 return (hspnp);
33691623Stw21770 }
33700Sstevel@tonic-gate }
33711623Stw21770
33721623Stw21770 /* if the hsp number isn't specified then attempt to get it */
33731623Stw21770 if (hsp == MD_HSP_NONE && (hsp = meta_gethspnmentbyname((*spp)->setno,
33741623Stw21770 MD_SIDEWILD, cname, ep)) == MD_HSP_NONE) {
33751623Stw21770 if (! mdisok(ep)) {
33761623Stw21770 /*
33771623Stw21770 * If the error is ENOENT, then we will continue on,
33781623Stw21770 * because the device does not yet exist.
33791623Stw21770 * For other types of errors, however, we'll bail out.
33801623Stw21770 */
33811623Stw21770 if (! mdissyserror(ep, ENOENT)) {
33821623Stw21770 Free(cname);
33831623Stw21770 return (NULL);
33841623Stw21770 }
33851623Stw21770 mdclrerror(ep);
33861623Stw21770 }
33870Sstevel@tonic-gate }
33881623Stw21770
33891623Stw21770 /* allocate new list element and hspname */
33901623Stw21770 *tail = Zalloc(sizeof (**tail));
33911623Stw21770 hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp));
33921623Stw21770 metainithspname(hspnp);
33931623Stw21770
33941623Stw21770 /* save hspname and number */
33951623Stw21770 hspnp->hspname = cname;
33961623Stw21770 hspnp->hsp = hsp;
33971623Stw21770
33981623Stw21770 /* success */
33991623Stw21770 return (hspnp);
34000Sstevel@tonic-gate }
34010Sstevel@tonic-gate
34020Sstevel@tonic-gate /*
34030Sstevel@tonic-gate * set up names for a hotspare pool
34040Sstevel@tonic-gate */
34050Sstevel@tonic-gate mdhspname_t *
metahspname(mdsetname_t ** spp,char * uname,md_error_t * ep)34060Sstevel@tonic-gate metahspname(
34070Sstevel@tonic-gate mdsetname_t **spp,
34080Sstevel@tonic-gate char *uname,
34090Sstevel@tonic-gate md_error_t *ep
34100Sstevel@tonic-gate )
34110Sstevel@tonic-gate {
34121623Stw21770 return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep));
34130Sstevel@tonic-gate }
34140Sstevel@tonic-gate
34150Sstevel@tonic-gate /*
34161623Stw21770 * set up hotspare pool name from key
34170Sstevel@tonic-gate */
34180Sstevel@tonic-gate mdhspname_t *
metahsphspname(mdsetname_t ** spp,hsp_t hsp,md_error_t * ep)34190Sstevel@tonic-gate metahsphspname(
34200Sstevel@tonic-gate mdsetname_t **spp,
34210Sstevel@tonic-gate hsp_t hsp,
34220Sstevel@tonic-gate md_error_t *ep
34230Sstevel@tonic-gate )
34240Sstevel@tonic-gate {
34250Sstevel@tonic-gate set_t setno = HSP_SET(hsp);
34260Sstevel@tonic-gate mdsetname_t *sp = NULL;
34270Sstevel@tonic-gate char *uname;
34280Sstevel@tonic-gate mdhspname_t *hspnp;
34290Sstevel@tonic-gate
34300Sstevel@tonic-gate /* check set first */
34310Sstevel@tonic-gate if (spp == NULL)
34320Sstevel@tonic-gate spp = &sp;
34330Sstevel@tonic-gate if (chksetno(spp, setno, ep) != 0)
34340Sstevel@tonic-gate return (NULL);
34350Sstevel@tonic-gate assert(*spp != NULL);
34360Sstevel@tonic-gate sp = *spp;
34370Sstevel@tonic-gate
34381623Stw21770 /* get corresponding hotspare pool name */
34391623Stw21770 if ((uname = meta_gethspnmentbyid(sp->setno,
3440*9017SJohn.Wren.Kennedy@Sun.COM MD_SIDEWILD, hsp, ep)) == NULL)
34411623Stw21770 return (NULL);
34420Sstevel@tonic-gate
34430Sstevel@tonic-gate /* setup name */
34441623Stw21770 hspnp = metahspname_hsp(spp, uname, hsp, ep);
34450Sstevel@tonic-gate Free(uname);
34460Sstevel@tonic-gate return (hspnp);
34470Sstevel@tonic-gate }
34480Sstevel@tonic-gate
34490Sstevel@tonic-gate /*
34500Sstevel@tonic-gate * return hotspare pool name
34510Sstevel@tonic-gate */
34520Sstevel@tonic-gate char *
get_hspname(mdsetname_t * sp,hsp_t hsp)34531623Stw21770 get_hspname(mdsetname_t *sp, hsp_t hsp)
34540Sstevel@tonic-gate {
34550Sstevel@tonic-gate mdhspname_t *hspnp;
34560Sstevel@tonic-gate md_error_t status = mdnullerror;
34571623Stw21770 mdsetname_t **spp = NULL;
34581623Stw21770
34591623Stw21770 if (sp != NULL)
34601623Stw21770 spp = &sp;
34610Sstevel@tonic-gate
34620Sstevel@tonic-gate /* get name */
34631623Stw21770 if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) {
34640Sstevel@tonic-gate mdclrerror(&status);
34650Sstevel@tonic-gate return (NULL);
34660Sstevel@tonic-gate }
34670Sstevel@tonic-gate
34680Sstevel@tonic-gate /* return name */
34690Sstevel@tonic-gate return (hspnp->hspname);
34700Sstevel@tonic-gate }
34710Sstevel@tonic-gate
34720Sstevel@tonic-gate /*
34730Sstevel@tonic-gate * free hotspare pool list
34740Sstevel@tonic-gate */
34750Sstevel@tonic-gate void
metafreehspnamelist(mdhspnamelist_t * hspnlp)34760Sstevel@tonic-gate metafreehspnamelist(mdhspnamelist_t *hspnlp)
34770Sstevel@tonic-gate {
34780Sstevel@tonic-gate mdhspnamelist_t *next = NULL;
34790Sstevel@tonic-gate
34800Sstevel@tonic-gate for (/* void */; (hspnlp != NULL); hspnlp = next) {
34810Sstevel@tonic-gate next = hspnlp->next;
34820Sstevel@tonic-gate Free(hspnlp);
34830Sstevel@tonic-gate }
34840Sstevel@tonic-gate }
34850Sstevel@tonic-gate
34860Sstevel@tonic-gate /*
34870Sstevel@tonic-gate * build list of hotspare pool names
34880Sstevel@tonic-gate */
34890Sstevel@tonic-gate int
metahspnamelist(mdsetname_t ** spp,mdhspnamelist_t ** hspnlpp,int argc,char * argv[],md_error_t * ep)34900Sstevel@tonic-gate metahspnamelist(
34910Sstevel@tonic-gate mdsetname_t **spp,
34920Sstevel@tonic-gate mdhspnamelist_t **hspnlpp,
34930Sstevel@tonic-gate int argc,
34940Sstevel@tonic-gate char *argv[],
34950Sstevel@tonic-gate md_error_t *ep
34960Sstevel@tonic-gate )
34970Sstevel@tonic-gate {
34980Sstevel@tonic-gate mdhspnamelist_t **tailpp = hspnlpp;
34990Sstevel@tonic-gate int count = 0;
35000Sstevel@tonic-gate
35010Sstevel@tonic-gate for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
35020Sstevel@tonic-gate mdhspnamelist_t *hspnlp = Zalloc(sizeof (*hspnlp));
35030Sstevel@tonic-gate
35040Sstevel@tonic-gate if ((hspnlp->hspnamep = metahspname(spp, argv[0],
35050Sstevel@tonic-gate ep)) == NULL) {
35060Sstevel@tonic-gate metafreehspnamelist(*hspnlpp);
35070Sstevel@tonic-gate *hspnlpp = NULL;
35080Sstevel@tonic-gate return (-1);
35090Sstevel@tonic-gate }
35100Sstevel@tonic-gate *tailpp = hspnlp;
35110Sstevel@tonic-gate tailpp = &hspnlp->next;
35120Sstevel@tonic-gate }
35130Sstevel@tonic-gate return (count);
35140Sstevel@tonic-gate }
35150Sstevel@tonic-gate
35160Sstevel@tonic-gate /*
35170Sstevel@tonic-gate * append to end of hotspare pool list
35180Sstevel@tonic-gate */
35190Sstevel@tonic-gate mdhspname_t *
metahspnamelist_append(mdhspnamelist_t ** hspnlpp,mdhspname_t * hspnp)35200Sstevel@tonic-gate metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp)
35210Sstevel@tonic-gate {
35220Sstevel@tonic-gate mdhspnamelist_t *hspnlp;
35230Sstevel@tonic-gate
35240Sstevel@tonic-gate /* run to end of list */
35250Sstevel@tonic-gate for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next)
35260Sstevel@tonic-gate ;
35270Sstevel@tonic-gate
35280Sstevel@tonic-gate /* allocate new list element */
35290Sstevel@tonic-gate hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp));
35300Sstevel@tonic-gate
35310Sstevel@tonic-gate /* append hotspare pool name */
35320Sstevel@tonic-gate hspnlp->hspnamep = hspnp;
35330Sstevel@tonic-gate return (hspnp);
35340Sstevel@tonic-gate }
35350Sstevel@tonic-gate
35360Sstevel@tonic-gate /*
35370Sstevel@tonic-gate * get name from dev
35380Sstevel@tonic-gate */
35390Sstevel@tonic-gate mdname_t *
metadevname(mdsetname_t ** spp,md_dev64_t dev,md_error_t * ep)35400Sstevel@tonic-gate metadevname(
35410Sstevel@tonic-gate mdsetname_t **spp,
35420Sstevel@tonic-gate md_dev64_t dev,
35430Sstevel@tonic-gate md_error_t *ep)
35440Sstevel@tonic-gate {
35450Sstevel@tonic-gate char *device_name;
35460Sstevel@tonic-gate mdname_t *namep;
35470Sstevel@tonic-gate mdkey_t key;
35480Sstevel@tonic-gate
35490Sstevel@tonic-gate /* short circuit metadevices */
35500Sstevel@tonic-gate assert(dev != NODEV64);
35510Sstevel@tonic-gate if (meta_dev_ismeta(dev))
35520Sstevel@tonic-gate return (metamnumname(spp, meta_getminor(dev), 0, ep));
35530Sstevel@tonic-gate
35540Sstevel@tonic-gate /* create local set, if necessary */
35550Sstevel@tonic-gate if (*spp == NULL) {
35560Sstevel@tonic-gate if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
35570Sstevel@tonic-gate return (NULL);
35580Sstevel@tonic-gate }
35590Sstevel@tonic-gate
35600Sstevel@tonic-gate /* get name from namespace */
35610Sstevel@tonic-gate if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD,
35620Sstevel@tonic-gate dev, NULL, NULL, &key, ep)) == NULL) {
35630Sstevel@tonic-gate return (NULL);
35640Sstevel@tonic-gate }
35651623Stw21770 namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep);
35660Sstevel@tonic-gate if (namep != NULL)
35670Sstevel@tonic-gate namep->key = key;
35680Sstevel@tonic-gate
35690Sstevel@tonic-gate Free(device_name);
35700Sstevel@tonic-gate return (namep);
35710Sstevel@tonic-gate }
35720Sstevel@tonic-gate
35730Sstevel@tonic-gate /*
35740Sstevel@tonic-gate * return cached name from md_dev64_t
35750Sstevel@tonic-gate */
35760Sstevel@tonic-gate static char *
metadevtocachename(md_dev64_t dev)35770Sstevel@tonic-gate metadevtocachename(md_dev64_t dev)
35780Sstevel@tonic-gate {
35790Sstevel@tonic-gate mddrivenamelist_t *dnlp;
35800Sstevel@tonic-gate
35810Sstevel@tonic-gate /* look in cache */
35820Sstevel@tonic-gate for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) {
35830Sstevel@tonic-gate mddrivename_t *dnp = dnlp->drivenamep;
35840Sstevel@tonic-gate uint_t i;
35850Sstevel@tonic-gate
35860Sstevel@tonic-gate for (i = 0; (i < dnp->parts.parts_len); ++i) {
35870Sstevel@tonic-gate mdname_t *np = &dnp->parts.parts_val[i];
35880Sstevel@tonic-gate
35890Sstevel@tonic-gate if (np->dev == dev)
35900Sstevel@tonic-gate return (np->cname);
35910Sstevel@tonic-gate }
35920Sstevel@tonic-gate }
35930Sstevel@tonic-gate
35940Sstevel@tonic-gate /* not found */
35950Sstevel@tonic-gate return (NULL);
35960Sstevel@tonic-gate }
35970Sstevel@tonic-gate
35980Sstevel@tonic-gate /*
35990Sstevel@tonic-gate * Ask the driver for the name, which has been stored in the
36000Sstevel@tonic-gate * metadevice state database (on behalf of the utilities).
36010Sstevel@tonic-gate * (by devno)
36020Sstevel@tonic-gate */
36030Sstevel@tonic-gate char *
get_devname(set_t setno,md_dev64_t dev)36040Sstevel@tonic-gate get_devname(
36050Sstevel@tonic-gate set_t setno,
36060Sstevel@tonic-gate md_dev64_t dev)
36070Sstevel@tonic-gate {
36080Sstevel@tonic-gate mdsetname_t *sp;
36090Sstevel@tonic-gate mdname_t *np;
36100Sstevel@tonic-gate md_error_t status = mdnullerror;
36110Sstevel@tonic-gate
36120Sstevel@tonic-gate /* get name */
36130Sstevel@tonic-gate if ((setno == MD_SET_BAD) ||
36140Sstevel@tonic-gate ((sp = metasetnosetname(setno, &status)) == NULL) ||
36150Sstevel@tonic-gate ((np = metadevname(&sp, dev, &status)) == NULL)) {
36160Sstevel@tonic-gate mdclrerror(&status);
36170Sstevel@tonic-gate return (metadevtocachename(dev));
36180Sstevel@tonic-gate }
36190Sstevel@tonic-gate
36200Sstevel@tonic-gate /* return name */
36210Sstevel@tonic-gate return (np->cname);
36220Sstevel@tonic-gate }
36230Sstevel@tonic-gate
36240Sstevel@tonic-gate /*
36250Sstevel@tonic-gate * get name from key
36260Sstevel@tonic-gate */
36270Sstevel@tonic-gate mdname_t *
metakeyname(mdsetname_t ** spp,mdkey_t key,int fast,md_error_t * ep)36280Sstevel@tonic-gate metakeyname(
36290Sstevel@tonic-gate mdsetname_t **spp,
36300Sstevel@tonic-gate mdkey_t key,
36310Sstevel@tonic-gate int fast,
36320Sstevel@tonic-gate md_error_t *ep
36330Sstevel@tonic-gate )
36340Sstevel@tonic-gate {
36350Sstevel@tonic-gate char *device_name;
36360Sstevel@tonic-gate md_dev64_t dev = NODEV64;
36370Sstevel@tonic-gate mdname_t *namep;
36380Sstevel@tonic-gate
36390Sstevel@tonic-gate /* create local set, if necessary */
36400Sstevel@tonic-gate if (*spp == NULL) {
36410Sstevel@tonic-gate if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
36420Sstevel@tonic-gate return (NULL);
36430Sstevel@tonic-gate }
36440Sstevel@tonic-gate
36450Sstevel@tonic-gate /* get name from namespace */
36460Sstevel@tonic-gate if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD,
36470Sstevel@tonic-gate key, NULL, NULL, &dev, ep)) == NULL) {
36480Sstevel@tonic-gate return (NULL);
36490Sstevel@tonic-gate }
36500Sstevel@tonic-gate if (fast)
36511623Stw21770 namep = metaname_fast(spp, device_name, UNKNOWN, ep);
36520Sstevel@tonic-gate else
36531623Stw21770 namep = metaname(spp, device_name, UNKNOWN, ep);
36540Sstevel@tonic-gate
36550Sstevel@tonic-gate assert(dev != NODEV64);
36560Sstevel@tonic-gate if (namep)
36570Sstevel@tonic-gate namep->dev = dev;
36580Sstevel@tonic-gate Free(device_name);
36590Sstevel@tonic-gate return (namep);
36600Sstevel@tonic-gate }
36610Sstevel@tonic-gate
36620Sstevel@tonic-gate /*
36631623Stw21770 * completely flush metadev/hsp caches
36641623Stw21770 */
36651623Stw21770 void
metaflushmetanames()36661623Stw21770 metaflushmetanames()
36671623Stw21770 {
36681623Stw21770 metaflushhspnames();
36691623Stw21770 metaflushdrivenames();
36701623Stw21770 metaflushfastnames();
36711623Stw21770 metaflushstatcache();
36721623Stw21770 }
36731623Stw21770
36741623Stw21770 /*
36750Sstevel@tonic-gate * completely flush the caches
36760Sstevel@tonic-gate */
36770Sstevel@tonic-gate void
metaflushnames(int flush_sr_cache)36780Sstevel@tonic-gate metaflushnames(int flush_sr_cache)
36790Sstevel@tonic-gate {
36800Sstevel@tonic-gate metaflushhspnames();
36810Sstevel@tonic-gate metaflushdrivenames();
36820Sstevel@tonic-gate metaflushsetnames();
36830Sstevel@tonic-gate metaflushctlrcache();
36840Sstevel@tonic-gate metaflushfastnames();
36850Sstevel@tonic-gate metaflushstatcache();
36860Sstevel@tonic-gate if (flush_sr_cache)
36870Sstevel@tonic-gate sr_cache_flush(0);
36880Sstevel@tonic-gate }
36890Sstevel@tonic-gate
36900Sstevel@tonic-gate /*
36910Sstevel@tonic-gate * meta_get_hotspare_names
36920Sstevel@tonic-gate * returns an mdnamelist_t of hot spare names
36930Sstevel@tonic-gate */
36940Sstevel@tonic-gate
36950Sstevel@tonic-gate int
meta_get_hotspare_names(mdsetname_t * sp,mdnamelist_t ** nlpp,int options,md_error_t * ep)36960Sstevel@tonic-gate meta_get_hotspare_names(
36970Sstevel@tonic-gate mdsetname_t *sp,
36980Sstevel@tonic-gate mdnamelist_t **nlpp,
36990Sstevel@tonic-gate int options,
37000Sstevel@tonic-gate md_error_t *ep
37010Sstevel@tonic-gate )
37020Sstevel@tonic-gate {
37030Sstevel@tonic-gate mdhspnamelist_t *hspnlp = NULL;
37040Sstevel@tonic-gate mdhspnamelist_t *hspp;
37050Sstevel@tonic-gate int cnt = 0;
37060Sstevel@tonic-gate
37070Sstevel@tonic-gate assert(nlpp != NULL);
37080Sstevel@tonic-gate
37090Sstevel@tonic-gate /* get hotspare names */
37100Sstevel@tonic-gate if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) {
37110Sstevel@tonic-gate cnt = -1;
37120Sstevel@tonic-gate goto out;
37130Sstevel@tonic-gate }
37140Sstevel@tonic-gate
37150Sstevel@tonic-gate /* build name list */
37160Sstevel@tonic-gate for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) {
37170Sstevel@tonic-gate md_hsp_t *hsp;
37180Sstevel@tonic-gate int i;
37190Sstevel@tonic-gate
37200Sstevel@tonic-gate if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) {
37210Sstevel@tonic-gate cnt = -1;
37220Sstevel@tonic-gate goto out;
37230Sstevel@tonic-gate }
37240Sstevel@tonic-gate for (i = 0; (i < hsp->hotspares.hotspares_len); i++) {
37250Sstevel@tonic-gate md_hs_t *hs = &hsp->hotspares.hotspares_val[i];
37260Sstevel@tonic-gate
37270Sstevel@tonic-gate (void) metanamelist_append(nlpp, hs->hsnamep);
37280Sstevel@tonic-gate ++cnt;
37290Sstevel@tonic-gate }
37300Sstevel@tonic-gate }
37310Sstevel@tonic-gate
37320Sstevel@tonic-gate /* cleanup and return count or error */
37330Sstevel@tonic-gate out:
37340Sstevel@tonic-gate metafreehspnamelist(hspnlp);
37350Sstevel@tonic-gate if ((cnt == -1) && mdisok(ep)) {
37360Sstevel@tonic-gate /*
37370Sstevel@tonic-gate * At least try to give some sort of meaningful error
37380Sstevel@tonic-gate */
37390Sstevel@tonic-gate (void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error");
37400Sstevel@tonic-gate }
37410Sstevel@tonic-gate
37420Sstevel@tonic-gate return (cnt);
37430Sstevel@tonic-gate }
37440Sstevel@tonic-gate /*
37450Sstevel@tonic-gate * meta_create_non_dup_list
37460Sstevel@tonic-gate * INPUT: mdnp mdname_t pointer to add to the list if a new name
37470Sstevel@tonic-gate * ldevidp list of non-duplicate names.
37480Sstevel@tonic-gate * OUTPUT: ldevidp list of non-duplicate names.
37490Sstevel@tonic-gate * meta_create_non_dup_list will take a mdname_t pointer and if the device
37500Sstevel@tonic-gate * is not in the list (ldevidp) will add it to the list.
37510Sstevel@tonic-gate * User needs to free allocated memory.
37520Sstevel@tonic-gate */
37530Sstevel@tonic-gate void
meta_create_non_dup_list(mdname_t * mdnp,mddevid_t ** ldevidpp)37540Sstevel@tonic-gate meta_create_non_dup_list(
37550Sstevel@tonic-gate mdname_t *mdnp,
37560Sstevel@tonic-gate mddevid_t **ldevidpp
37570Sstevel@tonic-gate )
37580Sstevel@tonic-gate {
37590Sstevel@tonic-gate char *lcname;
37600Sstevel@tonic-gate mddevid_t *tmp;
37610Sstevel@tonic-gate mddevid_t *lastdevidp;
37620Sstevel@tonic-gate mddevid_t *lldevidp;
37630Sstevel@tonic-gate char *ctd, *slice;
37640Sstevel@tonic-gate mddevid_t *ldevidp;
37650Sstevel@tonic-gate
37660Sstevel@tonic-gate if (mdnp == NULL)
37670Sstevel@tonic-gate return;
37680Sstevel@tonic-gate
37690Sstevel@tonic-gate ldevidp = *ldevidpp;
37700Sstevel@tonic-gate /*
37710Sstevel@tonic-gate * Grab the name of the device and strip off slice information
37720Sstevel@tonic-gate */
37730Sstevel@tonic-gate lcname = Strdup(mdnp->cname);
37740Sstevel@tonic-gate if (lcname == NULL) {
37750Sstevel@tonic-gate return;
37760Sstevel@tonic-gate }
37770Sstevel@tonic-gate ctd = strrchr(lcname, '/');
37780Sstevel@tonic-gate if (ctd != NULL)
37790Sstevel@tonic-gate slice = strrchr(ctd, 's');
37800Sstevel@tonic-gate else
37810Sstevel@tonic-gate slice = strrchr(lcname, 's');
37820Sstevel@tonic-gate
37830Sstevel@tonic-gate if (slice != NULL)
37840Sstevel@tonic-gate *slice = '\0';
37850Sstevel@tonic-gate
37860Sstevel@tonic-gate if (ldevidp == NULL) {
37870Sstevel@tonic-gate /* first item in list */
37880Sstevel@tonic-gate ldevidp = Zalloc(sizeof (mddevid_t));
37890Sstevel@tonic-gate ldevidp->ctdname = lcname;
37900Sstevel@tonic-gate ldevidp->key = mdnp->key;
37910Sstevel@tonic-gate *ldevidpp = ldevidp;
37920Sstevel@tonic-gate } else {
37930Sstevel@tonic-gate for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) {
37940Sstevel@tonic-gate if (strcmp(tmp->ctdname, lcname) == 0) {
37950Sstevel@tonic-gate /* already there so just return */
37960Sstevel@tonic-gate Free(lcname);
37970Sstevel@tonic-gate return;
37980Sstevel@tonic-gate }
37990Sstevel@tonic-gate lastdevidp = tmp;
38000Sstevel@tonic-gate }
38010Sstevel@tonic-gate lldevidp = Zalloc(sizeof (mddevid_t));
38020Sstevel@tonic-gate lldevidp->ctdname = lcname;
38030Sstevel@tonic-gate lldevidp->key = mdnp->key;
38040Sstevel@tonic-gate lastdevidp->next = lldevidp;
38050Sstevel@tonic-gate }
38060Sstevel@tonic-gate }
3807