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 * 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 * 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 * 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 * 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 ** 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 * 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 * 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 * 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 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 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 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 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 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 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 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 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 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 * 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 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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 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 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 * 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 ** 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 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 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 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 * 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 * 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 * 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 * 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 * 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 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 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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