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 */ 210Sstevel@tonic-gate /* 22*1623Stw21770 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <meta.h> 290Sstevel@tonic-gate #include <metad.h> 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include <ctype.h> 320Sstevel@tonic-gate #include <string.h> 33*1623Stw21770 #include <sys/fs/ufs_fsdir.h> 340Sstevel@tonic-gate 350Sstevel@tonic-gate /* 360Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that 370Sstevel@tonic-gate * TEXT_DOMAIN gets set to something. 380Sstevel@tonic-gate */ 390Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 400Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 410Sstevel@tonic-gate #endif 420Sstevel@tonic-gate 430Sstevel@tonic-gate /* 440Sstevel@tonic-gate * Macros to produce a quoted string containing the value of a 450Sstevel@tonic-gate * preprocessor macro. For example, if SIZE is defined to be 256, 460Sstevel@tonic-gate * VAL2STR(SIZE) is "256". This is used to construct format 470Sstevel@tonic-gate * strings for scanf-family functions below. 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate #define QUOTE(x) #x 500Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x) 510Sstevel@tonic-gate 520Sstevel@tonic-gate extern char *getfullblkname(); 530Sstevel@tonic-gate extern char *getfullrawname(); 540Sstevel@tonic-gate 550Sstevel@tonic-gate /* 560Sstevel@tonic-gate * caches 570Sstevel@tonic-gate */ 580Sstevel@tonic-gate static mdsetnamelist_t *setlistp = NULL; 590Sstevel@tonic-gate static mddrivenamelist_t *drivelistp = NULL; 600Sstevel@tonic-gate static mdnamelist_t *fastnmlp = NULL; 610Sstevel@tonic-gate static mdhspnamelist_t *hsplistp = NULL; 620Sstevel@tonic-gate 630Sstevel@tonic-gate /* 64*1623Stw21770 * Static definitions 65*1623Stw21770 */ 66*1623Stw21770 static int chksetname(mdsetname_t **spp, char *sname, md_error_t *ep); 67*1623Stw21770 68*1623Stw21770 /* 690Sstevel@tonic-gate * leak proof name conversion 700Sstevel@tonic-gate */ 710Sstevel@tonic-gate static char * 720Sstevel@tonic-gate rawname( 730Sstevel@tonic-gate char *uname 740Sstevel@tonic-gate ) 750Sstevel@tonic-gate { 760Sstevel@tonic-gate char *p; 770Sstevel@tonic-gate struct stat sbuf1, sbuf2; 780Sstevel@tonic-gate 790Sstevel@tonic-gate if ((p = getfullrawname(uname)) == NULL) { 800Sstevel@tonic-gate return (NULL); 810Sstevel@tonic-gate } else if (*p == '\0') { 820Sstevel@tonic-gate Free(p); 830Sstevel@tonic-gate return (NULL); 840Sstevel@tonic-gate } else { 850Sstevel@tonic-gate if (stat(uname, &sbuf1) != 0) { 860Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 870Sstevel@tonic-gate "device to mount in /etc/vfstab is " 880Sstevel@tonic-gate "invalid for device %s\n"), uname); 890Sstevel@tonic-gate exit(1); 900Sstevel@tonic-gate } 910Sstevel@tonic-gate if (stat(p, &sbuf2) != 0) { 920Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 930Sstevel@tonic-gate "device to fsck in /etc/vfstab is " 940Sstevel@tonic-gate "invalid for raw device %s\n"), p); 950Sstevel@tonic-gate exit(1); 960Sstevel@tonic-gate } 970Sstevel@tonic-gate if (sbuf1.st_rdev != sbuf2.st_rdev) { 980Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 990Sstevel@tonic-gate "/etc/vfstab entries inconsistent on " 1000Sstevel@tonic-gate "line containing device %s\n"), uname); 1010Sstevel@tonic-gate exit(1); 1020Sstevel@tonic-gate } 103871Scasper if (!S_ISCHR(sbuf2.st_mode)) { 1040Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1050Sstevel@tonic-gate "/etc/vfstab device to fsck is not a " 1060Sstevel@tonic-gate "raw device for device %s\n"), p); 1070Sstevel@tonic-gate exit(1); 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate return (p); 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate char * 1140Sstevel@tonic-gate blkname( 1150Sstevel@tonic-gate char *uname 1160Sstevel@tonic-gate ) 1170Sstevel@tonic-gate { 1180Sstevel@tonic-gate char *p; 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate if ((p = getfullblkname(uname)) == NULL) { 1210Sstevel@tonic-gate return (NULL); 1220Sstevel@tonic-gate } else if (*p == '\0') { 1230Sstevel@tonic-gate Free(p); 1240Sstevel@tonic-gate return (NULL); 1250Sstevel@tonic-gate } else { 1260Sstevel@tonic-gate return (p); 1270Sstevel@tonic-gate } 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate /* 1310Sstevel@tonic-gate * FUNCTION: parse_device() 1320Sstevel@tonic-gate * INPUT: sp - pointer to setname struct 1330Sstevel@tonic-gate * uname - Name of either a hotspare pool or metadevice 1340Sstevel@tonic-gate * This can either be a fully qualified path or 1350Sstevel@tonic-gate * in the form [set name/]device 136*1623Stw21770 * OUTPUT: snamep - name of the set that uname is in 137*1623Stw21770 * fnamep - metadevice or hsp with path and set name info stripped 138*1623Stw21770 * This parameter is dynamically allocated and must be 139*1623Stw21770 * freed by the calling function. 1400Sstevel@tonic-gate * PURPOSE: Parse uname and sp into the set name and device name strings. 1410Sstevel@tonic-gate * If the set name is specified as part of uname then use that 1420Sstevel@tonic-gate * otherwise attempt to get the set name from sp. 1430Sstevel@tonic-gate */ 1440Sstevel@tonic-gate static void 1450Sstevel@tonic-gate parse_device( 1460Sstevel@tonic-gate mdsetname_t *sp, 1470Sstevel@tonic-gate char *uname, 148*1623Stw21770 char **fnamep, /* dynamically alloced - caller must free */ 149*1623Stw21770 char **snamep /* dynamically alloced - caller must free */ 1500Sstevel@tonic-gate ) 1510Sstevel@tonic-gate { 1520Sstevel@tonic-gate char setname[FILENAME_MAX+1]; 153*1623Stw21770 char devname[FILENAME_MAX+1]; 1540Sstevel@tonic-gate char *tname = Malloc(strlen(uname) + 1); 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate int len; 1570Sstevel@tonic-gate char *up; 1580Sstevel@tonic-gate char *tp; 1590Sstevel@tonic-gate int lcws; /* last character was slash */ 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate /* Now copy uname to tname by throwing away any duplicate '/' */ 1620Sstevel@tonic-gate for (lcws = 0, tp = tname, up = uname; *up; up++) { 1630Sstevel@tonic-gate if (lcws) { 1640Sstevel@tonic-gate if (*up == '/') { 1650Sstevel@tonic-gate continue; 1660Sstevel@tonic-gate } else { 1670Sstevel@tonic-gate lcws = 0; 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate if (*up == '/') { 1710Sstevel@tonic-gate lcws = 1; 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate *tp++ = *up; /* ++ is done by for loop */ 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate *tp = '\0'; 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate /* fully-qualified - local set */ 1780Sstevel@tonic-gate if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n", 179*1623Stw21770 devname, &len) == 1) && (strlen(tname) == len)) || 1800Sstevel@tonic-gate ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", 181*1623Stw21770 devname, &len) == 1) && (strlen(tname) == len))) { 182*1623Stw21770 *snamep = Strdup(MD_LOCAL_NAME); 183*1623Stw21770 *fnamep = Strdup(devname); 1840Sstevel@tonic-gate Free(tname); 1850Sstevel@tonic-gate return; 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* with setname specified - either fully qualified and relative spec */ 189*1623Stw21770 if (((sscanf(tname, "%[^/]/%" VAL2STR(FILENAME_MAX) "s%n", 190*1623Stw21770 setname, devname, &len) == 2) && (strlen(tname) == len)) || 1910Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n", 192*1623Stw21770 setname, devname, &len) == 2) && (strlen(tname) == len)) || 1930Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", 194*1623Stw21770 setname, devname, &len) == 2) && (strlen(tname) == len))) { 195*1623Stw21770 196*1623Stw21770 *snamep = Strdup(setname); 197*1623Stw21770 *fnamep = Strdup(devname); 1980Sstevel@tonic-gate Free(tname); 1990Sstevel@tonic-gate return; 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate /* without setname specified */ 203*1623Stw21770 *fnamep = tname; 204*1623Stw21770 if (sp != NULL && !metaislocalset(sp)) 205*1623Stw21770 *snamep = Strdup(sp->setname); 206*1623Stw21770 else 207*1623Stw21770 *snamep = NULL; 208*1623Stw21770 } 209*1623Stw21770 210*1623Stw21770 /* 211*1623Stw21770 * check for "all" 212*1623Stw21770 */ 213*1623Stw21770 int 214*1623Stw21770 meta_is_all(char *s) 215*1623Stw21770 { 216*1623Stw21770 if ((strcoll(s, gettext("all")) == 0) || 217*1623Stw21770 (strcoll(s, gettext("ALL")) == 0)) 218*1623Stw21770 return (1); 219*1623Stw21770 return (0); 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate /* 223*1623Stw21770 * check for "none" 2240Sstevel@tonic-gate */ 225*1623Stw21770 int 226*1623Stw21770 meta_is_none(char *s) 227*1623Stw21770 { 228*1623Stw21770 if ((strcoll(s, gettext("none")) == 0) || 229*1623Stw21770 (strcoll(s, gettext("NONE")) == 0)) 230*1623Stw21770 return (1); 231*1623Stw21770 return (0); 232*1623Stw21770 } 233*1623Stw21770 2340Sstevel@tonic-gate static int 235*1623Stw21770 valid_name_syntax(char *uname) 2360Sstevel@tonic-gate { 237*1623Stw21770 int i; 238*1623Stw21770 int uname_len; 239*1623Stw21770 240*1623Stw21770 if (uname == NULL || !isalpha(uname[0])) 241*1623Stw21770 return (0); 242*1623Stw21770 243*1623Stw21770 uname_len = strlen(uname); 244*1623Stw21770 if (uname_len > MAXNAMLEN) 2450Sstevel@tonic-gate return (0); 246*1623Stw21770 247*1623Stw21770 /* 'all' and 'none' are reserved */ 248*1623Stw21770 if (meta_is_all(uname) || meta_is_none(uname)) 249*1623Stw21770 return (0); 250*1623Stw21770 251*1623Stw21770 for (i = 1; i < uname_len; i++) { 252*1623Stw21770 if ((isalnum(uname[i]) || uname[i] == '-' || 253*1623Stw21770 uname[i] == '_' || uname[i] == '.')) 254*1623Stw21770 continue; 255*1623Stw21770 break; 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate 258*1623Stw21770 if (i < uname_len) 2590Sstevel@tonic-gate return (0); 260*1623Stw21770 261*1623Stw21770 return (1); 262*1623Stw21770 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate /* 266*1623Stw21770 * canonicalize name 2670Sstevel@tonic-gate */ 2680Sstevel@tonic-gate char * 2690Sstevel@tonic-gate meta_canonicalize( 2700Sstevel@tonic-gate mdsetname_t *sp, 2710Sstevel@tonic-gate char *uname 2720Sstevel@tonic-gate ) 2730Sstevel@tonic-gate { 2740Sstevel@tonic-gate char *sname = NULL; 275*1623Stw21770 char *tname = NULL; 2760Sstevel@tonic-gate char *cname; 2770Sstevel@tonic-gate 278*1623Stw21770 /* return the dev name and set name */ 279*1623Stw21770 parse_device(sp, uname, &tname, &sname); 280*1623Stw21770 281*1623Stw21770 if (!valid_name_syntax(tname)) { 282*1623Stw21770 Free(tname); 283*1623Stw21770 if (sname != NULL) 284*1623Stw21770 Free(sname); 285*1623Stw21770 return (NULL); 286*1623Stw21770 } 287*1623Stw21770 288*1623Stw21770 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) 289*1623Stw21770 cname = tname; 2900Sstevel@tonic-gate else { 2910Sstevel@tonic-gate size_t cname_len; 2920Sstevel@tonic-gate 293*1623Stw21770 cname_len = strlen(tname) + strlen(sname) + 2; 2940Sstevel@tonic-gate cname = Malloc(cname_len); 2950Sstevel@tonic-gate (void) snprintf( 296*1623Stw21770 cname, cname_len, "%s/%s", sname, tname); 297*1623Stw21770 Free(tname); 298*1623Stw21770 } 299*1623Stw21770 300*1623Stw21770 if (sname != NULL) 301*1623Stw21770 Free(sname); 302*1623Stw21770 303*1623Stw21770 return (cname); 304*1623Stw21770 } 305*1623Stw21770 306*1623Stw21770 /* 307*1623Stw21770 * canonicalize name and check the set 308*1623Stw21770 */ 309*1623Stw21770 char * 310*1623Stw21770 meta_canonicalize_check_set( 311*1623Stw21770 mdsetname_t **spp, 312*1623Stw21770 char *uname, 313*1623Stw21770 md_error_t *ep 314*1623Stw21770 ) 315*1623Stw21770 { 316*1623Stw21770 char *sname = NULL; 317*1623Stw21770 char *tname = NULL; 318*1623Stw21770 char *cname; 319*1623Stw21770 320*1623Stw21770 /* return the dev name and set name */ 321*1623Stw21770 parse_device(*spp, uname, &tname, &sname); 322*1623Stw21770 323*1623Stw21770 if (!valid_name_syntax(tname)) { 324*1623Stw21770 (void) mderror(ep, MDE_NAME_ILLEGAL, tname); 325*1623Stw21770 if (sname != NULL) 326*1623Stw21770 Free(sname); 327*1623Stw21770 Free(tname); 328*1623Stw21770 return (NULL); 329*1623Stw21770 } 330*1623Stw21770 331*1623Stw21770 /* check the set name returned from the name for validity */ 332*1623Stw21770 if (chksetname(spp, sname, ep) != 0) { 333*1623Stw21770 Free(tname); 334*1623Stw21770 if (sname != NULL) 335*1623Stw21770 Free(sname); 336*1623Stw21770 return (NULL); 337*1623Stw21770 } 338*1623Stw21770 339*1623Stw21770 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) 340*1623Stw21770 cname = tname; 341*1623Stw21770 else { 342*1623Stw21770 size_t cname_len; 343*1623Stw21770 344*1623Stw21770 cname_len = strlen(tname) + strlen(sname) + 2; 345*1623Stw21770 cname = Malloc(cname_len); 346*1623Stw21770 (void) snprintf( 347*1623Stw21770 cname, cname_len, "%s/%s", sname, tname); 348*1623Stw21770 Free(tname); 349*1623Stw21770 } 350*1623Stw21770 351*1623Stw21770 if (sname != NULL) 352*1623Stw21770 Free(sname); 353*1623Stw21770 354*1623Stw21770 return (cname); 355*1623Stw21770 } 356*1623Stw21770 357*1623Stw21770 /* 358*1623Stw21770 * Verify that the name is a valid hsp/metadevice name 359*1623Stw21770 */ 360*1623Stw21770 static int 361*1623Stw21770 parse_meta_hsp_name(char *uname) 362*1623Stw21770 { 363*1623Stw21770 char *sname = NULL; 364*1623Stw21770 char *tname = NULL; 365*1623Stw21770 int ret; 366*1623Stw21770 367*1623Stw21770 /* return the dev name and set name */ 368*1623Stw21770 parse_device(NULL, uname, &tname, &sname); 369*1623Stw21770 370*1623Stw21770 ret = valid_name_syntax(tname); 371*1623Stw21770 if (sname != NULL) 3720Sstevel@tonic-gate Free(sname); 373*1623Stw21770 Free(tname); 374*1623Stw21770 return (ret); 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 3780Sstevel@tonic-gate * check that name is a metadevice 3790Sstevel@tonic-gate */ 3800Sstevel@tonic-gate int 3810Sstevel@tonic-gate is_metaname( 3820Sstevel@tonic-gate char *uname 3830Sstevel@tonic-gate ) 3840Sstevel@tonic-gate { 385*1623Stw21770 return (parse_meta_hsp_name(uname)); 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate /* 3890Sstevel@tonic-gate * check that name is a hotspare pool 3900Sstevel@tonic-gate */ 3910Sstevel@tonic-gate int 3920Sstevel@tonic-gate is_hspname( 3930Sstevel@tonic-gate char *uname 3940Sstevel@tonic-gate ) 3950Sstevel@tonic-gate { 396*1623Stw21770 return (parse_meta_hsp_name(uname)); 397*1623Stw21770 } 398*1623Stw21770 399*1623Stw21770 /* 400*1623Stw21770 * check to verify that name is an existing metadevice 401*1623Stw21770 */ 402*1623Stw21770 int 403*1623Stw21770 is_existing_metadevice( 404*1623Stw21770 mdsetname_t *sp, 405*1623Stw21770 char *uname 406*1623Stw21770 ) 407*1623Stw21770 { 408*1623Stw21770 char *raw_name; 409*1623Stw21770 char *set_name; 410*1623Stw21770 char *full_path; 411*1623Stw21770 char *fname = NULL; 412*1623Stw21770 int pathlen; 413*1623Stw21770 int retval = 0; 414*1623Stw21770 415*1623Stw21770 assert(uname != NULL); 416*1623Stw21770 /* 417*1623Stw21770 * If it is an absolute name of a metadevice, then just call rawname 418*1623Stw21770 * on the input 419*1623Stw21770 */ 420*1623Stw21770 if (uname[0] == '/') { 421*1623Stw21770 if (strncmp("/dev/md", uname, strlen("/dev/md")) == 0 && 422*1623Stw21770 (raw_name = rawname(uname)) != NULL) { 423*1623Stw21770 Free(raw_name); 424*1623Stw21770 return (1); 425*1623Stw21770 } 426*1623Stw21770 return (0); 427*1623Stw21770 } 428*1623Stw21770 429*1623Stw21770 /* create a fully specified path from the parsed string */ 430*1623Stw21770 parse_device(sp, uname, &fname, &set_name); 431*1623Stw21770 432*1623Stw21770 if ((set_name == NULL) || (strcmp(set_name, MD_LOCAL_NAME) == 0)) { 433*1623Stw21770 pathlen = strlen("/dev/md/rdsk/") + strlen(fname) + 1; 434*1623Stw21770 full_path = Zalloc(pathlen); 435*1623Stw21770 (void) snprintf(full_path, pathlen, "/dev/md/rdsk/%s", fname); 436*1623Stw21770 } else { 437*1623Stw21770 pathlen = strlen("/dev/md//rdsk/") + strlen(fname) + 438*1623Stw21770 strlen(set_name) + 1; 439*1623Stw21770 full_path = Zalloc(pathlen); 440*1623Stw21770 (void) snprintf(full_path, pathlen, "/dev/md/%s/rdsk/%s", 441*1623Stw21770 set_name, fname); 442*1623Stw21770 } 443*1623Stw21770 444*1623Stw21770 if ((raw_name = rawname(full_path)) != NULL) { 445*1623Stw21770 Free(raw_name); 446*1623Stw21770 retval = 1; 447*1623Stw21770 } 448*1623Stw21770 449*1623Stw21770 if (set_name != NULL) 450*1623Stw21770 Free(set_name); 451*1623Stw21770 452*1623Stw21770 Free(fname); 453*1623Stw21770 Free(full_path); 454*1623Stw21770 return (retval); 455*1623Stw21770 } 456*1623Stw21770 457*1623Stw21770 /* 458*1623Stw21770 * check to verify that name is an existing hsp 459*1623Stw21770 */ 460*1623Stw21770 int 461*1623Stw21770 is_existing_hsp( 462*1623Stw21770 mdsetname_t *sp, 463*1623Stw21770 char *uname 464*1623Stw21770 ) 465*1623Stw21770 { 466*1623Stw21770 md_error_t status = mdnullerror; 467*1623Stw21770 hsp_t hsp; 468*1623Stw21770 set_t cur_set; 469*1623Stw21770 470*1623Stw21770 if (sp != NULL) 471*1623Stw21770 cur_set = sp->setno; 472*1623Stw21770 else 473*1623Stw21770 cur_set = 0; 474*1623Stw21770 475*1623Stw21770 hsp = meta_gethspnmentbyname(cur_set, MD_SIDEWILD, uname, &status); 476*1623Stw21770 477*1623Stw21770 if (hsp == MD_HSP_NONE) { 478*1623Stw21770 mdclrerror(&status); 479*1623Stw21770 return (0); 480*1623Stw21770 } 481*1623Stw21770 return (1); 482*1623Stw21770 } 483*1623Stw21770 484*1623Stw21770 /* 485*1623Stw21770 * check to verify that name is an existing metadevice or hotspare pool 486*1623Stw21770 */ 487*1623Stw21770 int 488*1623Stw21770 is_existing_meta_hsp( 489*1623Stw21770 mdsetname_t *sp, 490*1623Stw21770 char *uname 491*1623Stw21770 ) 492*1623Stw21770 { 493*1623Stw21770 if (is_existing_metadevice(sp, uname) || 494*1623Stw21770 is_existing_hsp(sp, uname)) 4950Sstevel@tonic-gate return (1); 496*1623Stw21770 497*1623Stw21770 return (0); 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate /* 5010Sstevel@tonic-gate * mdsetname_t stuff 5020Sstevel@tonic-gate */ 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate /* 5050Sstevel@tonic-gate * initialize setname 5060Sstevel@tonic-gate */ 5070Sstevel@tonic-gate static void 5080Sstevel@tonic-gate metainitsetname( 5090Sstevel@tonic-gate mdsetname_t *sp 5100Sstevel@tonic-gate ) 5110Sstevel@tonic-gate { 5120Sstevel@tonic-gate (void) memset(sp, '\0', sizeof (*sp)); 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate static void 5160Sstevel@tonic-gate metafreesetdesc(md_set_desc *sd) 5170Sstevel@tonic-gate { 5180Sstevel@tonic-gate md_mnnode_desc *nd; 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) { 5210Sstevel@tonic-gate nd = sd->sd_nodelist; 5220Sstevel@tonic-gate while (nd) { 5230Sstevel@tonic-gate sd->sd_nodelist = nd->nd_next; 5240Sstevel@tonic-gate Free(nd); 5250Sstevel@tonic-gate nd = sd->sd_nodelist; 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate metafreedrivedesc(&sd->sd_drvs); 5290Sstevel@tonic-gate Free(sd); 5300Sstevel@tonic-gate } 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate /* 5330Sstevel@tonic-gate * free allocated setname 5340Sstevel@tonic-gate */ 5350Sstevel@tonic-gate static void 5360Sstevel@tonic-gate metafreesetname( 5370Sstevel@tonic-gate mdsetname_t *sp 5380Sstevel@tonic-gate ) 5390Sstevel@tonic-gate { 5400Sstevel@tonic-gate if (sp->setname != NULL) 5410Sstevel@tonic-gate Free(sp->setname); 5420Sstevel@tonic-gate if (sp->setdesc != NULL) 5430Sstevel@tonic-gate metafreesetdesc(sp->setdesc); 5440Sstevel@tonic-gate metainitsetname(sp); 5450Sstevel@tonic-gate } 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate /* 5480Sstevel@tonic-gate * flush the setname cache 5490Sstevel@tonic-gate */ 5500Sstevel@tonic-gate static void 5510Sstevel@tonic-gate metaflushsetnames() 5520Sstevel@tonic-gate { 5530Sstevel@tonic-gate mdsetnamelist_t *p, *n; 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate for (p = setlistp, n = NULL; (p != NULL); p = n) { 5560Sstevel@tonic-gate n = p->next; 5570Sstevel@tonic-gate metafreesetname(p->sp); 5580Sstevel@tonic-gate Free(p->sp); 5590Sstevel@tonic-gate Free(p); 5600Sstevel@tonic-gate } 5610Sstevel@tonic-gate setlistp = NULL; 5620Sstevel@tonic-gate } 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate /* 5650Sstevel@tonic-gate * get set number 5660Sstevel@tonic-gate */ 5670Sstevel@tonic-gate static int 5680Sstevel@tonic-gate getsetno( 5690Sstevel@tonic-gate char *sname, 5700Sstevel@tonic-gate set_t *setnop, 5710Sstevel@tonic-gate md_error_t *ep 5720Sstevel@tonic-gate ) 5730Sstevel@tonic-gate { 5740Sstevel@tonic-gate md_set_record *sr; 5750Sstevel@tonic-gate size_t len; 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate /* local set */ 5780Sstevel@tonic-gate if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 5790Sstevel@tonic-gate *setnop = 0; 5800Sstevel@tonic-gate return (0); 5810Sstevel@tonic-gate } 5820Sstevel@tonic-gate 5830Sstevel@tonic-gate /* shared set */ 5840Sstevel@tonic-gate if ((sr = getsetbyname(sname, ep)) == NULL) { 5850Sstevel@tonic-gate if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) { 5860Sstevel@tonic-gate char *p; 5870Sstevel@tonic-gate 5880Sstevel@tonic-gate len = strlen(sname) + 30; 5890Sstevel@tonic-gate p = Malloc(len); 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate (void) snprintf(p, len, "setname \"%s\"", sname); 5920Sstevel@tonic-gate (void) mderror(ep, MDE_NO_SET, p); 5930Sstevel@tonic-gate Free(p); 5940Sstevel@tonic-gate } 5950Sstevel@tonic-gate return (-1); 5960Sstevel@tonic-gate } 5970Sstevel@tonic-gate *setnop = sr->sr_setno; 5980Sstevel@tonic-gate free_sr(sr); 5990Sstevel@tonic-gate return (0); 6000Sstevel@tonic-gate } 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate /* 6030Sstevel@tonic-gate * find setname from name 6040Sstevel@tonic-gate */ 6050Sstevel@tonic-gate mdsetname_t * 6060Sstevel@tonic-gate metasetname( 6070Sstevel@tonic-gate char *sname, 6080Sstevel@tonic-gate md_error_t *ep 6090Sstevel@tonic-gate ) 6100Sstevel@tonic-gate { 6110Sstevel@tonic-gate mdsetnamelist_t **tail; 6120Sstevel@tonic-gate set_t setno; 6130Sstevel@tonic-gate mdsetname_t *sp; 6140Sstevel@tonic-gate 6150Sstevel@tonic-gate /* look for cached value first */ 6160Sstevel@tonic-gate assert(sname != NULL); 6170Sstevel@tonic-gate for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) { 6180Sstevel@tonic-gate sp = (*tail)->sp; 6190Sstevel@tonic-gate if (strcmp(sp->setname, sname) == 0) { 6200Sstevel@tonic-gate return (sp); 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate } 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate /* setup set */ 6250Sstevel@tonic-gate if (getsetno(sname, &setno, ep) != 0) 6260Sstevel@tonic-gate return (NULL); 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate /* allocate new list element and setname */ 6290Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 6300Sstevel@tonic-gate sp = (*tail)->sp = Zalloc(sizeof (*sp)); 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate sp->setname = Strdup(sname); 6330Sstevel@tonic-gate sp->setno = setno; 6340Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK; 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate return (sp); 6370Sstevel@tonic-gate } 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate /* 6400Sstevel@tonic-gate * find setname from setno 6410Sstevel@tonic-gate */ 6420Sstevel@tonic-gate mdsetname_t * 6430Sstevel@tonic-gate metasetnosetname( 6440Sstevel@tonic-gate set_t setno, 6450Sstevel@tonic-gate md_error_t *ep 6460Sstevel@tonic-gate ) 6470Sstevel@tonic-gate { 6480Sstevel@tonic-gate mdsetnamelist_t *slp; 6490Sstevel@tonic-gate mdsetname_t *sp; 6500Sstevel@tonic-gate md_set_record *sr; 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate /* look for cached value first */ 6530Sstevel@tonic-gate for (slp = setlistp; (slp != NULL); slp = slp->next) { 6540Sstevel@tonic-gate sp = slp->sp; 6550Sstevel@tonic-gate if (sp->setno == setno) 6560Sstevel@tonic-gate return (sp); 6570Sstevel@tonic-gate } 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate /* local set */ 6600Sstevel@tonic-gate if (setno == MD_LOCAL_SET) 6610Sstevel@tonic-gate return (metasetname(MD_LOCAL_NAME, ep)); 6620Sstevel@tonic-gate 6630Sstevel@tonic-gate /* shared set */ 6640Sstevel@tonic-gate if ((sr = getsetbynum(setno, ep)) == NULL) 6650Sstevel@tonic-gate return (NULL); 6660Sstevel@tonic-gate sp = metasetname(sr->sr_setname, ep); 6670Sstevel@tonic-gate free_sr(sr); 6680Sstevel@tonic-gate return (sp); 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate mdsetname_t * 6720Sstevel@tonic-gate metafakesetname( 6730Sstevel@tonic-gate set_t setno, 6740Sstevel@tonic-gate char *sname 6750Sstevel@tonic-gate ) 6760Sstevel@tonic-gate { 6770Sstevel@tonic-gate mdsetnamelist_t **tail; 6780Sstevel@tonic-gate mdsetname_t *sp; 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate /* look for cached value first */ 6810Sstevel@tonic-gate for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) { 6820Sstevel@tonic-gate sp = (*tail)->sp; 6830Sstevel@tonic-gate if (sp->setno == setno) { 6840Sstevel@tonic-gate if ((sp->setname == NULL) && (sname != NULL)) 6850Sstevel@tonic-gate sp->setname = Strdup(sname); 6860Sstevel@tonic-gate return (sp); 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate } 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate /* allocate new list element and setname */ 6910Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 6920Sstevel@tonic-gate sp = (*tail)->sp = Zalloc(sizeof (*sp)); 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate if (sname != NULL) 6950Sstevel@tonic-gate sp->setname = Strdup(sname); 6960Sstevel@tonic-gate sp->setno = setno; 6970Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK; 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate return (sp); 7000Sstevel@tonic-gate } 7010Sstevel@tonic-gate 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate /* 7040Sstevel@tonic-gate * setup set record (sr) and cache it in the mdsetname_t struct 7050Sstevel@tonic-gate */ 7060Sstevel@tonic-gate md_set_desc * 7070Sstevel@tonic-gate sr2setdesc( 7080Sstevel@tonic-gate md_set_record *sr 7090Sstevel@tonic-gate ) 7100Sstevel@tonic-gate { 7110Sstevel@tonic-gate md_set_desc *sd; 7120Sstevel@tonic-gate int i; 7130Sstevel@tonic-gate md_mnset_record *mnsr; 7140Sstevel@tonic-gate md_mnnode_desc *nd, *nd_prev = 0; 7150Sstevel@tonic-gate md_mnnode_record *nr; 7160Sstevel@tonic-gate md_error_t status = mdnullerror; 7170Sstevel@tonic-gate md_error_t *ep = &status; 7180Sstevel@tonic-gate int nodecnt, nrcnt; 7190Sstevel@tonic-gate mndiskset_membershiplist_t *nl, *nl2; 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate sd = Zalloc(sizeof (*sd)); 7220Sstevel@tonic-gate sd->sd_ctime = sr->sr_ctime; 7230Sstevel@tonic-gate sd->sd_genid = sr->sr_genid; 7240Sstevel@tonic-gate sd->sd_setno = sr->sr_setno; 7250Sstevel@tonic-gate sd->sd_flags = sr->sr_flags; 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) { 7280Sstevel@tonic-gate mnsr = (md_mnset_record *)sr; 7290Sstevel@tonic-gate (void) strlcpy(sd->sd_mn_master_nodenm, 7300Sstevel@tonic-gate mnsr->sr_master_nodenm, sizeof (sd->sd_mn_master_nodenm)); 7310Sstevel@tonic-gate sd->sd_mn_master_nodeid = mnsr->sr_master_nodeid; 7320Sstevel@tonic-gate if (strcmp(mnsr->sr_master_nodenm, mynode()) == 0) { 7330Sstevel@tonic-gate sd->sd_mn_am_i_master = 1; 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate /* 7370Sstevel@tonic-gate * Get membershiplist from API routine. If there's 7380Sstevel@tonic-gate * an error, just use a NULL nodelist. 7390Sstevel@tonic-gate */ 7400Sstevel@tonic-gate if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) { 7410Sstevel@tonic-gate nodecnt = 0; /* no nodes are alive */ 7420Sstevel@tonic-gate nl = NULL; 7430Sstevel@tonic-gate } 7440Sstevel@tonic-gate nr = mnsr->sr_nodechain; 7450Sstevel@tonic-gate nrcnt = 0; 7460Sstevel@tonic-gate /* 7470Sstevel@tonic-gate * Node descriptor node list must be built in 7480Sstevel@tonic-gate * ascending order of nodeid. The nodechain 7490Sstevel@tonic-gate * in the mnset record is in ascending order, 7500Sstevel@tonic-gate * so just make them the same. 7510Sstevel@tonic-gate */ 7520Sstevel@tonic-gate while (nr) { 7530Sstevel@tonic-gate nd = Zalloc(sizeof (*nd)); 7540Sstevel@tonic-gate if (nd_prev) { 7550Sstevel@tonic-gate nd_prev->nd_next = nd; 7560Sstevel@tonic-gate } else { 7570Sstevel@tonic-gate sd->sd_nodelist = nd; 7580Sstevel@tonic-gate } 7590Sstevel@tonic-gate nd->nd_ctime = nr->nr_ctime; 7600Sstevel@tonic-gate nd->nd_genid = nr->nr_genid; 7610Sstevel@tonic-gate nd->nd_flags = nr->nr_flags; 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate (void) strlcpy(nd->nd_nodename, nr->nr_nodename, 7640Sstevel@tonic-gate sizeof (nd->nd_nodename)); 7650Sstevel@tonic-gate nd->nd_nodeid = nr->nr_nodeid; 7660Sstevel@tonic-gate if (strcmp(nd->nd_nodename, mynode()) == 0) { 7670Sstevel@tonic-gate sd->sd_mn_mynode = nd; 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate if (nd->nd_nodeid == sd->sd_mn_master_nodeid) { 7700Sstevel@tonic-gate sd->sd_mn_masternode = nd; 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate /* 7740Sstevel@tonic-gate * If node is marked ALIVE, then set priv_ic 7750Sstevel@tonic-gate * from membership list. During the early part 7760Sstevel@tonic-gate * of a reconfig cycle, the membership list may 7770Sstevel@tonic-gate * have been changed, (a node entering or leaving 7780Sstevel@tonic-gate * the cluster), but rpc.metad hasn't flushed 7790Sstevel@tonic-gate * its data yet. So, if node is marked alive, but 7800Sstevel@tonic-gate * is no longer in the membership list (node has 7810Sstevel@tonic-gate * left the cluster) then just leave priv_ic to NULL. 7820Sstevel@tonic-gate */ 7830Sstevel@tonic-gate if (nd->nd_flags & MD_MN_NODE_ALIVE) { 7840Sstevel@tonic-gate nl2 = nl; 7850Sstevel@tonic-gate while (nl2) { 7860Sstevel@tonic-gate if (nl2->msl_node_id == nd->nd_nodeid) { 7870Sstevel@tonic-gate (void) strlcpy(nd->nd_priv_ic, 7880Sstevel@tonic-gate nl2->msl_node_addr, 7890Sstevel@tonic-gate sizeof (nd->nd_priv_ic)); 7900Sstevel@tonic-gate break; 7910Sstevel@tonic-gate } 7920Sstevel@tonic-gate nl2 = nl2->next; 7930Sstevel@tonic-gate } 7940Sstevel@tonic-gate } 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate nr = nr->nr_next; 7970Sstevel@tonic-gate nrcnt++; 7980Sstevel@tonic-gate nd_prev = nd; 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate sd->sd_mn_numnodes = nrcnt; 8010Sstevel@tonic-gate if (nodecnt) 8020Sstevel@tonic-gate meta_free_nodelist(nl); 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate /* Just copying to keep consistent view between sr & sd */ 8050Sstevel@tonic-gate (void) strlcpy(sd->sd_nodes[0], mnsr->sr_nodes_bw_compat[0], 8060Sstevel@tonic-gate sizeof (sd->sd_nodes[0])); 8070Sstevel@tonic-gate } else { 8080Sstevel@tonic-gate for (i = 0; i < MD_MAXSIDES; i++) 8090Sstevel@tonic-gate (void) strlcpy(sd->sd_nodes[i], sr->sr_nodes[i], 8100Sstevel@tonic-gate sizeof (sd->sd_nodes[i])); 8110Sstevel@tonic-gate } 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate sd->sd_med = sr->sr_med; /* structure assignment */ 8140Sstevel@tonic-gate 8150Sstevel@tonic-gate return (sd); 8160Sstevel@tonic-gate } 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate md_set_desc * 8190Sstevel@tonic-gate metaget_setdesc( 8200Sstevel@tonic-gate mdsetname_t *sp, 8210Sstevel@tonic-gate md_error_t *ep 8220Sstevel@tonic-gate ) 8230Sstevel@tonic-gate { 8240Sstevel@tonic-gate md_set_record *sr; 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate if (sp->setdesc != NULL) 8270Sstevel@tonic-gate return (sp->setdesc); 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate if (sp->setname != NULL) { 8300Sstevel@tonic-gate if ((sr = getsetbyname(sp->setname, ep)) != NULL) { 8310Sstevel@tonic-gate sp->setdesc = sr2setdesc(sr); 8320Sstevel@tonic-gate free_sr(sr); 8330Sstevel@tonic-gate return (sp->setdesc); 8340Sstevel@tonic-gate } 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate if (sp->setno > 0) { 8380Sstevel@tonic-gate if ((sr = getsetbynum(sp->setno, ep)) != NULL) { 8390Sstevel@tonic-gate sp->setdesc = sr2setdesc(sr); 8400Sstevel@tonic-gate free_sr(sr); 8410Sstevel@tonic-gate return (sp->setdesc); 8420Sstevel@tonic-gate } 8430Sstevel@tonic-gate } 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate return (NULL); 8460Sstevel@tonic-gate } 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate void 8490Sstevel@tonic-gate metaflushsetname(mdsetname_t *sp) 8500Sstevel@tonic-gate { 8510Sstevel@tonic-gate if (sp == NULL) 8520Sstevel@tonic-gate return; 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate if (sp->setdesc == NULL) 8550Sstevel@tonic-gate return; 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate metafreesetdesc(sp->setdesc); 8580Sstevel@tonic-gate sp->setdesc = NULL; 8590Sstevel@tonic-gate } 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate /* 8620Sstevel@tonic-gate * check for local set 8630Sstevel@tonic-gate */ 8640Sstevel@tonic-gate int 8650Sstevel@tonic-gate metaislocalset( 8660Sstevel@tonic-gate mdsetname_t *sp 8670Sstevel@tonic-gate ) 8680Sstevel@tonic-gate { 8690Sstevel@tonic-gate assert(sp->setname != NULL); 8700Sstevel@tonic-gate if (strcmp(sp->setname, MD_LOCAL_NAME) == 0) { 8710Sstevel@tonic-gate assert(sp->setno == MD_LOCAL_SET); 8720Sstevel@tonic-gate return (1); 8730Sstevel@tonic-gate } else { 8740Sstevel@tonic-gate assert(sp->setno != MD_LOCAL_SET); 8750Sstevel@tonic-gate return (0); 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate } 8780Sstevel@tonic-gate 8790Sstevel@tonic-gate /* 8800Sstevel@tonic-gate * check for same set 8810Sstevel@tonic-gate */ 8820Sstevel@tonic-gate int 8830Sstevel@tonic-gate metaissameset( 8840Sstevel@tonic-gate mdsetname_t *sp1, 8850Sstevel@tonic-gate mdsetname_t *sp2 8860Sstevel@tonic-gate ) 8870Sstevel@tonic-gate { 8880Sstevel@tonic-gate if (strcmp(sp1->setname, sp2->setname) == 0) { 8890Sstevel@tonic-gate assert(sp1->setno == sp2->setno); 8900Sstevel@tonic-gate return (1); 8910Sstevel@tonic-gate } else { 8920Sstevel@tonic-gate assert(sp1->setno != sp2->setno); 8930Sstevel@tonic-gate return (0); 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate /* 8980Sstevel@tonic-gate * check to see if set changed 8990Sstevel@tonic-gate */ 9000Sstevel@tonic-gate static int 9010Sstevel@tonic-gate chkset( 9020Sstevel@tonic-gate mdsetname_t **spp, 9030Sstevel@tonic-gate char *sname, 9040Sstevel@tonic-gate md_error_t *ep 9050Sstevel@tonic-gate ) 9060Sstevel@tonic-gate { 9070Sstevel@tonic-gate /* if we already have a set, make sure it's the same */ 908*1623Stw21770 if (*spp != NULL && !metaislocalset(*spp)) { 9090Sstevel@tonic-gate if ((*spp)->setname != sname && 9100Sstevel@tonic-gate strcmp((*spp)->setname, sname) != 0) { 9110Sstevel@tonic-gate return (mderror(ep, MDE_SET_DIFF, sname)); 9120Sstevel@tonic-gate } 9130Sstevel@tonic-gate return (0); 9140Sstevel@tonic-gate } 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate /* otherwise store new set name and number */ 9170Sstevel@tonic-gate if ((*spp = metasetname(sname, ep)) == NULL) { 9180Sstevel@tonic-gate return (-1); 9190Sstevel@tonic-gate } 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate /* return success */ 9220Sstevel@tonic-gate return (0); 9230Sstevel@tonic-gate } 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate /* 9260Sstevel@tonic-gate * check to see if set changed from default 9270Sstevel@tonic-gate */ 9280Sstevel@tonic-gate static int 9290Sstevel@tonic-gate chksetname( 9300Sstevel@tonic-gate mdsetname_t **spp, 9310Sstevel@tonic-gate char *sname, 9320Sstevel@tonic-gate md_error_t *ep 9330Sstevel@tonic-gate ) 9340Sstevel@tonic-gate { 9350Sstevel@tonic-gate /* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */ 9360Sstevel@tonic-gate if (sname == NULL) { 9370Sstevel@tonic-gate if (*spp) { 938*1623Stw21770 return (0); 9390Sstevel@tonic-gate } else { 9400Sstevel@tonic-gate sname = MD_LOCAL_NAME; 9410Sstevel@tonic-gate } 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate /* see if changed */ 9450Sstevel@tonic-gate return (chkset(spp, sname, ep)); 9460Sstevel@tonic-gate } 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate /* 9490Sstevel@tonic-gate * check setname from setno 9500Sstevel@tonic-gate */ 9510Sstevel@tonic-gate static int 9520Sstevel@tonic-gate chksetno( 9530Sstevel@tonic-gate mdsetname_t **spp, 9540Sstevel@tonic-gate set_t setno, 9550Sstevel@tonic-gate md_error_t *ep 9560Sstevel@tonic-gate ) 9570Sstevel@tonic-gate { 9580Sstevel@tonic-gate md_set_record *sr; 9590Sstevel@tonic-gate int rval; 9600Sstevel@tonic-gate 9610Sstevel@tonic-gate /* local set */ 9620Sstevel@tonic-gate if (setno == 0) 9630Sstevel@tonic-gate return (chkset(spp, MD_LOCAL_NAME, ep)); 9640Sstevel@tonic-gate 9650Sstevel@tonic-gate /* shared set */ 9660Sstevel@tonic-gate if ((sr = getsetbynum(setno, ep)) == NULL) 9670Sstevel@tonic-gate return (-1); 9680Sstevel@tonic-gate rval = chkset(spp, sr->sr_setname, ep); 9690Sstevel@tonic-gate free_sr(sr); 9700Sstevel@tonic-gate return (rval); 9710Sstevel@tonic-gate } 9720Sstevel@tonic-gate 9730Sstevel@tonic-gate /* 9740Sstevel@tonic-gate * mddrivename_t stuff 9750Sstevel@tonic-gate */ 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate /* 9780Sstevel@tonic-gate * initialize name 9790Sstevel@tonic-gate */ 9800Sstevel@tonic-gate static void 9810Sstevel@tonic-gate metainitname( 9820Sstevel@tonic-gate mdname_t *np 9830Sstevel@tonic-gate ) 9840Sstevel@tonic-gate { 9850Sstevel@tonic-gate (void) memset(np, 0, sizeof (*np)); 9860Sstevel@tonic-gate np->dev = NODEV64; 9870Sstevel@tonic-gate np->key = MD_KEYBAD; 9880Sstevel@tonic-gate np->end_blk = -1; 9890Sstevel@tonic-gate np->start_blk = -1; 9900Sstevel@tonic-gate } 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate /* 9930Sstevel@tonic-gate * free allocated name 9940Sstevel@tonic-gate */ 9950Sstevel@tonic-gate static void 9960Sstevel@tonic-gate metafreename( 9970Sstevel@tonic-gate mdname_t *np 9980Sstevel@tonic-gate ) 9990Sstevel@tonic-gate { 10000Sstevel@tonic-gate if (np->cname != NULL) 10010Sstevel@tonic-gate Free(np->cname); 10020Sstevel@tonic-gate if (np->bname != NULL) 10030Sstevel@tonic-gate Free(np->bname); 10040Sstevel@tonic-gate if (np->rname != NULL) 10050Sstevel@tonic-gate Free(np->rname); 10060Sstevel@tonic-gate if (np->devicesname != NULL) 10070Sstevel@tonic-gate Free(np->devicesname); 10080Sstevel@tonic-gate metainitname(np); 10090Sstevel@tonic-gate } 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate /* 10120Sstevel@tonic-gate * initialize drive name 10130Sstevel@tonic-gate */ 10140Sstevel@tonic-gate static void 10150Sstevel@tonic-gate metainitdrivename( 10160Sstevel@tonic-gate mddrivename_t *dnp 10170Sstevel@tonic-gate ) 10180Sstevel@tonic-gate { 10190Sstevel@tonic-gate (void) memset(dnp, 0, sizeof (*dnp)); 10200Sstevel@tonic-gate dnp->side_names_key = MD_KEYBAD; 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate 10230Sstevel@tonic-gate /* 10240Sstevel@tonic-gate * flush side names 10250Sstevel@tonic-gate */ 10260Sstevel@tonic-gate void 10270Sstevel@tonic-gate metaflushsidenames( 10280Sstevel@tonic-gate mddrivename_t *dnp 10290Sstevel@tonic-gate ) 10300Sstevel@tonic-gate { 10310Sstevel@tonic-gate mdsidenames_t *p, *n; 10320Sstevel@tonic-gate 10330Sstevel@tonic-gate for (p = dnp->side_names, n = NULL; (p != NULL); p = n) { 10340Sstevel@tonic-gate n = p->next; 10350Sstevel@tonic-gate if (p->dname != NULL) 10360Sstevel@tonic-gate Free(p->dname); 10370Sstevel@tonic-gate if (p->cname != NULL) 10380Sstevel@tonic-gate Free(p->cname); 10390Sstevel@tonic-gate Free(p); 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate dnp->side_names = NULL; 10420Sstevel@tonic-gate } 10430Sstevel@tonic-gate 10440Sstevel@tonic-gate /* 10450Sstevel@tonic-gate * free drive name 10460Sstevel@tonic-gate */ 10470Sstevel@tonic-gate void 10480Sstevel@tonic-gate metafreedrivename( 10490Sstevel@tonic-gate mddrivename_t *dnp 10500Sstevel@tonic-gate ) 10510Sstevel@tonic-gate { 10520Sstevel@tonic-gate uint_t slice; 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate if (dnp->cname != NULL) 10550Sstevel@tonic-gate Free(dnp->cname); 10560Sstevel@tonic-gate if (dnp->rname != NULL) 10570Sstevel@tonic-gate Free(dnp->rname); 10580Sstevel@tonic-gate metafreevtoc(&dnp->vtoc); 10590Sstevel@tonic-gate for (slice = 0; (slice < dnp->parts.parts_len); ++slice) 10600Sstevel@tonic-gate metafreename(&dnp->parts.parts_val[slice]); 10610Sstevel@tonic-gate if (dnp->parts.parts_val != NULL) 10620Sstevel@tonic-gate Free(dnp->parts.parts_val); 10630Sstevel@tonic-gate metaflushsidenames(dnp); 10640Sstevel@tonic-gate if (dnp->miscname != NULL) 10650Sstevel@tonic-gate Free(dnp->miscname); 10660Sstevel@tonic-gate meta_free_unit(dnp); 10670Sstevel@tonic-gate metainitdrivename(dnp); 10680Sstevel@tonic-gate } 10690Sstevel@tonic-gate 10700Sstevel@tonic-gate /* 10710Sstevel@tonic-gate * flush the drive name cache 10720Sstevel@tonic-gate */ 10730Sstevel@tonic-gate static void 10740Sstevel@tonic-gate metaflushdrivenames() 10750Sstevel@tonic-gate { 10760Sstevel@tonic-gate mddrivenamelist_t *p, *n; 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate for (p = drivelistp, n = NULL; (p != NULL); p = n) { 10790Sstevel@tonic-gate n = p->next; 10800Sstevel@tonic-gate metafreedrivename(p->drivenamep); 10810Sstevel@tonic-gate Free(p->drivenamep); 10820Sstevel@tonic-gate Free(p); 10830Sstevel@tonic-gate } 10840Sstevel@tonic-gate drivelistp = NULL; 10850Sstevel@tonic-gate } 10860Sstevel@tonic-gate 10870Sstevel@tonic-gate /* 10880Sstevel@tonic-gate * peel off s%u from name 10890Sstevel@tonic-gate */ 10900Sstevel@tonic-gate char * 10910Sstevel@tonic-gate metadiskname( 10920Sstevel@tonic-gate char *name 10930Sstevel@tonic-gate ) 10940Sstevel@tonic-gate { 10950Sstevel@tonic-gate char *p, *e; 10960Sstevel@tonic-gate char onmb[BUFSIZ+1], cnmb[BUFSIZ]; 10970Sstevel@tonic-gate uint_t d = 0; 10980Sstevel@tonic-gate int l = 0; 10990Sstevel@tonic-gate int cl = strlen(name); 11000Sstevel@tonic-gate 11010Sstevel@tonic-gate /* 11020Sstevel@tonic-gate * Handle old style names, which are of the form /dev/rXXNN[a-h]. 11030Sstevel@tonic-gate */ 11040Sstevel@tonic-gate if (sscanf(name, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n", 11050Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 11060Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u", onmb, d); 11070Sstevel@tonic-gate return (Strdup(cnmb)); 11080Sstevel@tonic-gate } 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate /* 11110Sstevel@tonic-gate * Handle old style names, which are of the form /dev/XXNN[a-h]. 11120Sstevel@tonic-gate */ 11130Sstevel@tonic-gate if (sscanf(name, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n", 11140Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 11150Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/%s%u", onmb, d); 11160Sstevel@tonic-gate return (Strdup(cnmb)); 11170Sstevel@tonic-gate } 11180Sstevel@tonic-gate 11190Sstevel@tonic-gate /* gobble number and 's' */ 11200Sstevel@tonic-gate p = e = name + strlen(name) - 1; 11210Sstevel@tonic-gate for (; (p > name); --p) { 11220Sstevel@tonic-gate if (!isdigit(*p)) 11230Sstevel@tonic-gate break; 11240Sstevel@tonic-gate } 11250Sstevel@tonic-gate if ((p == e) || (p <= name)) 11260Sstevel@tonic-gate return (Strdup(name)); 11270Sstevel@tonic-gate 11280Sstevel@tonic-gate if (*p != 's' && strchr("dt", *p) == NULL) 11290Sstevel@tonic-gate return (Strdup(name)); 11300Sstevel@tonic-gate else if (strchr("dt", *p) != NULL) 11310Sstevel@tonic-gate return (Strdup(name)); 11320Sstevel@tonic-gate p--; 11330Sstevel@tonic-gate 11340Sstevel@tonic-gate if ((p <= name) || (!isdigit(*p))) 11350Sstevel@tonic-gate return (Strdup(name)); 11360Sstevel@tonic-gate 11370Sstevel@tonic-gate *(++p) = '\0'; 11380Sstevel@tonic-gate e = Strdup(name); 11390Sstevel@tonic-gate *p = 's'; 11400Sstevel@tonic-gate 11410Sstevel@tonic-gate return (e); 11420Sstevel@tonic-gate } 11430Sstevel@tonic-gate 11440Sstevel@tonic-gate /* 11450Sstevel@tonic-gate * free list of drivenames 11460Sstevel@tonic-gate */ 11470Sstevel@tonic-gate void 11480Sstevel@tonic-gate metafreedrivenamelist( 11490Sstevel@tonic-gate mddrivenamelist_t *dnlp 11500Sstevel@tonic-gate ) 11510Sstevel@tonic-gate { 11520Sstevel@tonic-gate mddrivenamelist_t *next = NULL; 11530Sstevel@tonic-gate 11540Sstevel@tonic-gate for (/* void */; (dnlp != NULL); dnlp = next) { 11550Sstevel@tonic-gate next = dnlp->next; 11560Sstevel@tonic-gate Free(dnlp); 11570Sstevel@tonic-gate } 11580Sstevel@tonic-gate } 11590Sstevel@tonic-gate 11600Sstevel@tonic-gate /* 11610Sstevel@tonic-gate * build list of drivenames 11620Sstevel@tonic-gate */ 11630Sstevel@tonic-gate int 11640Sstevel@tonic-gate metadrivenamelist( 11650Sstevel@tonic-gate mdsetname_t **spp, 11660Sstevel@tonic-gate mddrivenamelist_t **dnlpp, 11670Sstevel@tonic-gate int argc, 11680Sstevel@tonic-gate char *argv[], 11690Sstevel@tonic-gate md_error_t *ep 11700Sstevel@tonic-gate ) 11710Sstevel@tonic-gate { 11720Sstevel@tonic-gate mddrivenamelist_t **tailpp = dnlpp; 11730Sstevel@tonic-gate int count = 0; 11740Sstevel@tonic-gate 11750Sstevel@tonic-gate for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 11760Sstevel@tonic-gate mddrivenamelist_t *dnlp = Zalloc(sizeof (*dnlp)); 11770Sstevel@tonic-gate 11780Sstevel@tonic-gate if ((dnlp->drivenamep = metadrivename(spp, argv[0], 11790Sstevel@tonic-gate ep)) == NULL) { 11800Sstevel@tonic-gate metafreedrivenamelist(*dnlpp); 11810Sstevel@tonic-gate *dnlpp = NULL; 11820Sstevel@tonic-gate return (-1); 11830Sstevel@tonic-gate } 11840Sstevel@tonic-gate *tailpp = dnlp; 11850Sstevel@tonic-gate tailpp = &dnlp->next; 11860Sstevel@tonic-gate } 11870Sstevel@tonic-gate return (count); 11880Sstevel@tonic-gate } 11890Sstevel@tonic-gate 11900Sstevel@tonic-gate /* 11910Sstevel@tonic-gate * append to end of drivename list 11920Sstevel@tonic-gate */ 11930Sstevel@tonic-gate mddrivename_t * 11940Sstevel@tonic-gate metadrivenamelist_append( 11950Sstevel@tonic-gate mddrivenamelist_t **dnlpp, 11960Sstevel@tonic-gate mddrivename_t *dnp 11970Sstevel@tonic-gate ) 11980Sstevel@tonic-gate { 11990Sstevel@tonic-gate mddrivenamelist_t *dnlp; 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate /* run to end of list */ 12020Sstevel@tonic-gate for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next) 12030Sstevel@tonic-gate ; 12040Sstevel@tonic-gate 12050Sstevel@tonic-gate /* allocate new list element */ 12060Sstevel@tonic-gate dnlp = *dnlpp = Zalloc(sizeof (*dnlp)); 12070Sstevel@tonic-gate 12080Sstevel@tonic-gate /* append drivename */ 12090Sstevel@tonic-gate dnlp->drivenamep = dnp; 12100Sstevel@tonic-gate return (dnp); 12110Sstevel@tonic-gate } 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate /* 12140Sstevel@tonic-gate * FUNCTION: meta_drivenamelist_append_wrapper() 12150Sstevel@tonic-gate * INPUT: tailpp - pointer to the list tail pointer 12160Sstevel@tonic-gate * dnp - name node to be appended to list 12170Sstevel@tonic-gate * OUTPUT: none 12180Sstevel@tonic-gate * RETURNS: mddrivenamelist_t * - new tail of the list. 12190Sstevel@tonic-gate * PURPOSE: wrapper to meta_namelist_append for performance. 12200Sstevel@tonic-gate * metanamelist_append finds the tail each time which slows 12210Sstevel@tonic-gate * down long lists. By keeping track of the tail ourselves 12220Sstevel@tonic-gate * we can change metadrivenamelist_append into a 12230Sstevel@tonic-gate * constant time operation. 12240Sstevel@tonic-gate */ 12250Sstevel@tonic-gate mddrivenamelist_t ** 12260Sstevel@tonic-gate meta_drivenamelist_append_wrapper( 12270Sstevel@tonic-gate mddrivenamelist_t **tailpp, 12280Sstevel@tonic-gate mddrivename_t *dnp 12290Sstevel@tonic-gate ) 12300Sstevel@tonic-gate { 12310Sstevel@tonic-gate (void) metadrivenamelist_append(tailpp, dnp); 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate /* If it's the first item in the list, return it instead of the next */ 12340Sstevel@tonic-gate if ((*tailpp)->next == NULL) 12350Sstevel@tonic-gate return (tailpp); 12360Sstevel@tonic-gate 12370Sstevel@tonic-gate return (&(*tailpp)->next); 12380Sstevel@tonic-gate } 12390Sstevel@tonic-gate 12400Sstevel@tonic-gate 12410Sstevel@tonic-gate /* 12420Sstevel@tonic-gate * mdname_t stuff 12430Sstevel@tonic-gate */ 12440Sstevel@tonic-gate 12450Sstevel@tonic-gate /* 12460Sstevel@tonic-gate * check set and get comparison name 1247*1623Stw21770 * 1248*1623Stw21770 * NOTE: This function has a side effect of setting *spp if the setname 1249*1623Stw21770 * has been specified and *spp is not already set. 12500Sstevel@tonic-gate */ 12510Sstevel@tonic-gate char * 12520Sstevel@tonic-gate meta_name_getname( 1253*1623Stw21770 mdsetname_t **spp, 1254*1623Stw21770 char *uname, 1255*1623Stw21770 meta_device_type_t uname_type, 1256*1623Stw21770 md_error_t *ep 12570Sstevel@tonic-gate ) 12580Sstevel@tonic-gate { 1259*1623Stw21770 if (uname_type == META_DEVICE || uname_type == HSP_DEVICE || 1260*1623Stw21770 (uname_type == UNKNOWN && is_existing_metadevice(*spp, uname))) { 1261*1623Stw21770 1262*1623Stw21770 /* 1263*1623Stw21770 * if the setname is specified in uname, *spp is set, 1264*1623Stw21770 * and the set names don't agree then canonical name will be 1265*1623Stw21770 * returned as NULL 1266*1623Stw21770 */ 1267*1623Stw21770 return (meta_canonicalize_check_set(spp, uname, ep)); 1268*1623Stw21770 } 1269*1623Stw21770 1270*1623Stw21770 /* if it is not a meta/hsp and *spp is not set then set it to local */ 1271*1623Stw21770 if (chksetname(spp, NULL, ep) != 0) 12720Sstevel@tonic-gate return (NULL); 1273*1623Stw21770 1274*1623Stw21770 /* if it is not a meta/hsp name then just return uname */ 1275*1623Stw21770 return (Strdup(uname)); 12760Sstevel@tonic-gate } 12770Sstevel@tonic-gate 12780Sstevel@tonic-gate /* 12790Sstevel@tonic-gate * FUNCTION: getrname() 12800Sstevel@tonic-gate * INPUT: spp - the setname struct 12810Sstevel@tonic-gate * uname - the possibly unqualified device name 1282*1623Stw21770 * type - ptr to the device type of uname 12830Sstevel@tonic-gate * OUTPUT: ep - return error pointer 12840Sstevel@tonic-gate * RETURNS: char* - character string containing the fully 12850Sstevel@tonic-gate * qualified raw device name 12860Sstevel@tonic-gate * PURPOSE: Create the fully qualified raw name for the possibly 12870Sstevel@tonic-gate * unqualified device name. If uname is an absolute 12880Sstevel@tonic-gate * path the raw name is derived from the input string. 12890Sstevel@tonic-gate * Otherwise, an attempt is made to get the rawname by 1290*1623Stw21770 * catting "/dev/md/rdsk" and "/dev/rdsk". If the input 1291*1623Stw21770 * value of type is UNKNOWN and it can be successfully 1292*1623Stw21770 * determined then update type to the correct value. 12930Sstevel@tonic-gate */ 1294*1623Stw21770 static char * 1295*1623Stw21770 getrname(mdsetname_t **spp, char *uname, 1296*1623Stw21770 meta_device_type_t *type, md_error_t *ep) 12970Sstevel@tonic-gate { 1298*1623Stw21770 char *rname, 1299*1623Stw21770 *fname; 1300*1623Stw21770 int i; 1301*1623Stw21770 int rname_cnt = 0; 1302*1623Stw21770 char *rname_list[3]; 1303*1623Stw21770 meta_device_type_t tmp_type; 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate assert(uname != NULL); 13060Sstevel@tonic-gate /* if it is an absolute name then just call rawname on the input */ 13070Sstevel@tonic-gate if (uname[0] == '/') { 1308*1623Stw21770 if ((rname = rawname(uname)) != NULL) { 1309*1623Stw21770 /* 1310*1623Stw21770 * If the returned rname does not match with 1311*1623Stw21770 * the specified uname type, we'll return null. 1312*1623Stw21770 */ 1313*1623Stw21770 if (strncmp(rname, "/dev/md", strlen("/dev/md")) == 0) { 1314*1623Stw21770 if (*type == LOGICAL_DEVICE) { 1315*1623Stw21770 (void) mdsyserror(ep, ENOENT, uname); 1316*1623Stw21770 return (NULL); 1317*1623Stw21770 } 1318*1623Stw21770 *type = META_DEVICE; 1319*1623Stw21770 } else { 1320*1623Stw21770 if (*type == META_DEVICE) { 1321*1623Stw21770 (void) mdsyserror(ep, ENOENT, uname); 1322*1623Stw21770 return (NULL); 1323*1623Stw21770 } 1324*1623Stw21770 *type = LOGICAL_DEVICE; 1325*1623Stw21770 } 13260Sstevel@tonic-gate return (rname); 1327*1623Stw21770 } 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate /* out of luck */ 13300Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 13310Sstevel@tonic-gate return (NULL); 13320Sstevel@tonic-gate } 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate /* 1335*1623Stw21770 * Get device that matches the requested type. If 1336*1623Stw21770 * a match is found, return immediately. If type is 1337*1623Stw21770 * UNKNOWN, save all the found devices in rname_list 1338*1623Stw21770 * so we can determine later whether the input uname 1339*1623Stw21770 * is ambiguous. 1340*1623Stw21770 * 13410Sstevel@tonic-gate * Check for metadevice before physical device. 13420Sstevel@tonic-gate * With the introduction of softpartitions it is more 13430Sstevel@tonic-gate * likely to be a metadevice. 13440Sstevel@tonic-gate */ 13450Sstevel@tonic-gate 13460Sstevel@tonic-gate /* metadevice short form */ 1347*1623Stw21770 if (*type == META_DEVICE || *type == UNKNOWN) { 1348*1623Stw21770 if (metaislocalset(*spp)) { 1349*1623Stw21770 fname = Malloc(strlen(uname) + 1350*1623Stw21770 strlen("/dev/md/rdsk/") + 1); 1351*1623Stw21770 (void) strcpy(fname, "/dev/md/rdsk/"); 1352*1623Stw21770 (void) strcat(fname, uname); 13530Sstevel@tonic-gate } else { 1354*1623Stw21770 char *p; 1355*1623Stw21770 size_t len; 1356*1623Stw21770 1357*1623Stw21770 if ((p = strchr(uname, '/')) != NULL) { 1358*1623Stw21770 ++p; 1359*1623Stw21770 } else { 1360*1623Stw21770 p = uname; 1361*1623Stw21770 } 1362*1623Stw21770 len = strlen((*spp)->setname) + strlen(p) + 1363*1623Stw21770 strlen("/dev/md//rdsk/") + 1; 1364*1623Stw21770 fname = Malloc(len); 1365*1623Stw21770 (void) snprintf(fname, len, "/dev/md/%s/rdsk/%s", 1366*1623Stw21770 (*spp)->setname, p); 13670Sstevel@tonic-gate } 1368*1623Stw21770 rname = rawname(fname); 1369*1623Stw21770 1370*1623Stw21770 if (*type == META_DEVICE) { 1371*1623Stw21770 /* 1372*1623Stw21770 * Handle the case where we have a new metadevice 1373*1623Stw21770 * that does not yet exist in the name-space(e.g 1374*1623Stw21770 * metarecover in MN sets where /dev/md entry is 1375*1623Stw21770 * not yet created in the non-master nodes). In 1376*1623Stw21770 * this case we return the constructed metadevice 1377*1623Stw21770 * name as that will exist after the metainit call 1378*1623Stw21770 * has created it. 1379*1623Stw21770 */ 1380*1623Stw21770 if (rname == NULL) { 1381*1623Stw21770 rname = Strdup(fname); 1382*1623Stw21770 } 1383*1623Stw21770 1384*1623Stw21770 Free(fname); 1385*1623Stw21770 return (rname); 1386*1623Stw21770 } 1387*1623Stw21770 1388*1623Stw21770 Free(fname); 1389*1623Stw21770 if ((rname != NULL) && (*type == UNKNOWN)) { 1390*1623Stw21770 /* Save this result */ 1391*1623Stw21770 rname_list[rname_cnt] = rname; 1392*1623Stw21770 rname_cnt ++; 1393*1623Stw21770 } 13940Sstevel@tonic-gate } 1395*1623Stw21770 1396*1623Stw21770 if (*type == LOGICAL_DEVICE || *type == UNKNOWN) { 1397*1623Stw21770 fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1); 1398*1623Stw21770 (void) strcpy(fname, "/dev/rdsk/"); 1399*1623Stw21770 (void) strcat(fname, uname); 1400*1623Stw21770 rname = rawname(fname); 1401*1623Stw21770 1402*1623Stw21770 Free(fname); 1403*1623Stw21770 if (rname != NULL) { 1404*1623Stw21770 /* Simply return if a logical device was requested */ 1405*1623Stw21770 if (*type == LOGICAL_DEVICE) { 1406*1623Stw21770 return (rname); 1407*1623Stw21770 } else { 1408*1623Stw21770 rname_list[rname_cnt] = rname; 1409*1623Stw21770 rname_cnt ++; 1410*1623Stw21770 } 1411*1623Stw21770 } 14120Sstevel@tonic-gate } 14130Sstevel@tonic-gate 14140Sstevel@tonic-gate /* 14150Sstevel@tonic-gate * If all else fails try the straight uname. 14160Sstevel@tonic-gate * NOTE: This check was at the beginning of getrname instead 14170Sstevel@tonic-gate * of here. It was moved to avoid a conflict with SC3.0. If 14180Sstevel@tonic-gate * a diskset was mounted with the same name it would hang 14190Sstevel@tonic-gate * the cluster in a loop. Example: 14200Sstevel@tonic-gate * 14210Sstevel@tonic-gate * fubar/d10 -m fubar/d0 fubar/d1 14220Sstevel@tonic-gate * mount /dev/md/fubar/dsk/d10 /fubar 14230Sstevel@tonic-gate * 1424*1623Stw21770 * When the system was booted SVM would try to take ownership 14250Sstevel@tonic-gate * of diskset fubar. This would cause rawname("fubar/d10") to be 14260Sstevel@tonic-gate * called. rawname() stats the string which caused the cluster 14270Sstevel@tonic-gate * reservation code to try and take ownership which it was already 14280Sstevel@tonic-gate * doing and a deadlock would occur. By moving this final attempt 14290Sstevel@tonic-gate * at resolving the rawname to the end we avoid this deadlock. 14300Sstevel@tonic-gate */ 1431*1623Stw21770 if (rname = rawname(uname)) { 1432*1623Stw21770 /* 1433*1623Stw21770 * It's only possible to get a logical device from this 1434*1623Stw21770 * rawname call since a metadevice would have been 1435*1623Stw21770 * detected earlier. 1436*1623Stw21770 */ 1437*1623Stw21770 if (*type == LOGICAL_DEVICE && 1438*1623Stw21770 (strncmp(rname, "/dev/md/", strlen("/dev/md"))) != 1) 1439*1623Stw21770 return (rname); 1440*1623Stw21770 else { 1441*1623Stw21770 rname_list[rname_cnt] = rname; 1442*1623Stw21770 rname_cnt++; 1443*1623Stw21770 } 1444*1623Stw21770 } 1445*1623Stw21770 1446*1623Stw21770 /* 1447*1623Stw21770 * At this point, we've searched /dev/md/rdsk, /dev/rdsk and 1448*1623Stw21770 * ./ for the specified device. rname_list contains all 1449*1623Stw21770 * the matches we've found and rname_cnt is the number of 1450*1623Stw21770 * matches. 1451*1623Stw21770 * 1452*1623Stw21770 * We know that either we don't have a match if a specific 1453*1623Stw21770 * type was given, in which case we simply return NULL or 1454*1623Stw21770 * we have an UNKNOWN device with 1-3 entries in rname_list. 1455*1623Stw21770 * 1456*1623Stw21770 * If we get 3 entries, rname_cnt == 3, it's ambiguous. 1457*1623Stw21770 * If we only get 1 entry, rname_cnt == 1, return rname_list[0]. 1458*1623Stw21770 * If we get 2 entries that are not the same, it's ambigous. 1459*1623Stw21770 */ 1460*1623Stw21770 rname = NULL; 1461*1623Stw21770 if (rname_cnt == 0 || *type != UNKNOWN) { 1462*1623Stw21770 /* out of luck */ 1463*1623Stw21770 (void) mdsyserror(ep, ENOENT, uname); 1464*1623Stw21770 return (NULL); 1465*1623Stw21770 } else { 1466*1623Stw21770 if (rname_cnt == 3) { 1467*1623Stw21770 (void) mderror(ep, MDE_AMBIGUOUS_DEV, uname); 1468*1623Stw21770 (void) printf(dgettext(TEXT_DOMAIN, 1469*1623Stw21770 "Error: ambiguous device name.\n%s %s %s\n\n"), 1470*1623Stw21770 rname_list[0], rname_list[1], rname_list[2]); 1471*1623Stw21770 rname = NULL; 1472*1623Stw21770 } 1473*1623Stw21770 1474*1623Stw21770 /* grab the type in case it is not ambiguous */ 1475*1623Stw21770 if (strncmp(rname_list[0], "/dev/md", strlen("/dev/md")) == 0) 1476*1623Stw21770 tmp_type = META_DEVICE; 1477*1623Stw21770 else 1478*1623Stw21770 tmp_type = LOGICAL_DEVICE; 1479*1623Stw21770 1480*1623Stw21770 if (rname_cnt == 1) { 1481*1623Stw21770 rname = Strdup(rname_list[0]); 1482*1623Stw21770 *type = tmp_type; 1483*1623Stw21770 } else { 1484*1623Stw21770 /* 1485*1623Stw21770 * Prevent the case where the command is run in 1486*1623Stw21770 * either /dev/md/rdsk or /dev/rdsk so the both 1487*1623Stw21770 * rname_list[0] and rname_list[1] are the same. 1488*1623Stw21770 */ 1489*1623Stw21770 if (strcmp(rname_list[0], rname_list[1]) != 0) { 1490*1623Stw21770 (void) mderror(ep, MDE_AMBIGUOUS_DEV, uname); 1491*1623Stw21770 if (rname_cnt != 3) { 1492*1623Stw21770 /* 1493*1623Stw21770 * For the rname_cnt == 3 case, the 1494*1623Stw21770 * error was printed above. 1495*1623Stw21770 */ 1496*1623Stw21770 (void) printf(dgettext(TEXT_DOMAIN, 1497*1623Stw21770 "Error: ambiguous device " 1498*1623Stw21770 "name.\n%s %s\n\n"), 1499*1623Stw21770 rname_list[0], rname_list[1]); 1500*1623Stw21770 } 1501*1623Stw21770 rname = NULL; 1502*1623Stw21770 } else { 1503*1623Stw21770 rname = Strdup(rname_list[0]); 1504*1623Stw21770 *type = tmp_type; 1505*1623Stw21770 } 1506*1623Stw21770 } 1507*1623Stw21770 for (i = 0; i < rname_cnt; i++) 1508*1623Stw21770 Free(rname_list[i]); 15090Sstevel@tonic-gate return (rname); 1510*1623Stw21770 } 15110Sstevel@tonic-gate } 15120Sstevel@tonic-gate 15130Sstevel@tonic-gate /* 15140Sstevel@tonic-gate * get raw slice and drive names 15150Sstevel@tonic-gate */ 15160Sstevel@tonic-gate static char * 15170Sstevel@tonic-gate getrawnames( 1518*1623Stw21770 mdsetname_t **spp, 1519*1623Stw21770 char *uname, 1520*1623Stw21770 char **dnamep, 1521*1623Stw21770 meta_device_type_t *uname_type, 1522*1623Stw21770 md_error_t *ep 15230Sstevel@tonic-gate ) 15240Sstevel@tonic-gate { 1525*1623Stw21770 char *rname = NULL; 15260Sstevel@tonic-gate size_t len; 15270Sstevel@tonic-gate 1528*1623Stw21770 /* 1529*1623Stw21770 * Incorrect code path if type is HSP_DEVICE 1530*1623Stw21770 */ 1531*1623Stw21770 assert(*uname_type != HSP_DEVICE); 1532*1623Stw21770 15330Sstevel@tonic-gate /* initialize */ 15340Sstevel@tonic-gate *dnamep = NULL; 15350Sstevel@tonic-gate 15360Sstevel@tonic-gate /* get slice name */ 1537*1623Stw21770 if ((rname = getrname(spp, uname, uname_type, ep)) != NULL) { 15380Sstevel@tonic-gate *dnamep = metadiskname(rname); 15390Sstevel@tonic-gate return (rname); 15400Sstevel@tonic-gate } 15410Sstevel@tonic-gate 15420Sstevel@tonic-gate /* 15430Sstevel@tonic-gate * If name cannot be found, if may be because is is not accessible. 15440Sstevel@tonic-gate * If it is an absolute name, try all possible disk name formats and 1545*1623Stw21770 * if it is device name, assume it is /dev/rdsk/.. 1546*1623Stw21770 * Since the code below assumes logical devices, if the given 1547*1623Stw21770 * uname_type is META_DEVICE, there's nothing to do. 15480Sstevel@tonic-gate */ 1549*1623Stw21770 if (mdissyserror(ep, ENOENT) && *uname_type != META_DEVICE) { 15500Sstevel@tonic-gate if (uname[0] == '/') { 15510Sstevel@tonic-gate /* Absolute name */ 15520Sstevel@tonic-gate char *p; 15530Sstevel@tonic-gate uint_t d = 0; 15540Sstevel@tonic-gate int l = 0; 15550Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1]; 15560Sstevel@tonic-gate 15570Sstevel@tonic-gate /* 15580Sstevel@tonic-gate * Handle old style raw names 15590Sstevel@tonic-gate */ 15600Sstevel@tonic-gate if (sscanf(uname, 15610Sstevel@tonic-gate "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 15620Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 15630Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(uname)) { 15640Sstevel@tonic-gate mdclrerror(ep); 15650Sstevel@tonic-gate rname = Strdup(uname); 15660Sstevel@tonic-gate *dnamep = metadiskname(rname); 1567*1623Stw21770 *uname_type = LOGICAL_DEVICE; 15680Sstevel@tonic-gate return (rname); 15690Sstevel@tonic-gate } 15700Sstevel@tonic-gate 15710Sstevel@tonic-gate /* 15720Sstevel@tonic-gate * Handle old style block names 15730Sstevel@tonic-gate */ 15740Sstevel@tonic-gate if (sscanf(uname, 15750Sstevel@tonic-gate "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u" 15760Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 15770Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(uname)) { 15780Sstevel@tonic-gate len = strlen(uname) + 1 + 1; 15790Sstevel@tonic-gate rname = Malloc(len); 15800Sstevel@tonic-gate (void) snprintf(rname, len, "/dev/r%s%u%s", 15810Sstevel@tonic-gate onmb, d, snm); 15820Sstevel@tonic-gate *dnamep = metadiskname(rname); 1583*1623Stw21770 *uname_type = LOGICAL_DEVICE; 15840Sstevel@tonic-gate return (rname); 15850Sstevel@tonic-gate } 15860Sstevel@tonic-gate 15870Sstevel@tonic-gate /* /.../dsk/... */ 15880Sstevel@tonic-gate if ((p = strstr(uname, "/dsk/")) != NULL) { 15890Sstevel@tonic-gate mdclrerror(ep); 15900Sstevel@tonic-gate ++p; 15910Sstevel@tonic-gate rname = Malloc(strlen(uname) + 1 + 1); 15920Sstevel@tonic-gate (void) strncpy(rname, uname, (p - uname)); 15930Sstevel@tonic-gate rname[(p - uname)] = 'r'; 15940Sstevel@tonic-gate (void) strcpy(&rname[(p - uname) + 1], p); 15950Sstevel@tonic-gate *dnamep = metadiskname(rname); 1596*1623Stw21770 *uname_type = LOGICAL_DEVICE; 15970Sstevel@tonic-gate return (rname); 15980Sstevel@tonic-gate } 15990Sstevel@tonic-gate 16000Sstevel@tonic-gate /* /.../rdsk/... */ 16010Sstevel@tonic-gate else if (strstr(uname, "/rdsk/") != NULL) { 16020Sstevel@tonic-gate mdclrerror(ep); 16030Sstevel@tonic-gate rname = Strdup(uname); 16040Sstevel@tonic-gate *dnamep = metadiskname(rname); 1605*1623Stw21770 *uname_type = LOGICAL_DEVICE; 16060Sstevel@tonic-gate return (rname); 16070Sstevel@tonic-gate } 16080Sstevel@tonic-gate } else { 16090Sstevel@tonic-gate /* 16100Sstevel@tonic-gate * If it's not an absolute name but is a valid ctd name, 16110Sstevel@tonic-gate * guess at /dev/rdsk/... 16120Sstevel@tonic-gate */ 16130Sstevel@tonic-gate uint_t s; 16140Sstevel@tonic-gate if (parse_ctd(uname, &s) == 0) { 16150Sstevel@tonic-gate len = strlen(uname) + strlen("/dev/rdsk/") + 1; 16160Sstevel@tonic-gate rname = Malloc(len); 16170Sstevel@tonic-gate (void) snprintf(rname, len, "/dev/rdsk/%s", 16180Sstevel@tonic-gate uname); 16190Sstevel@tonic-gate *dnamep = metadiskname(rname); 1620*1623Stw21770 *uname_type = LOGICAL_DEVICE; 16210Sstevel@tonic-gate return (rname); 16220Sstevel@tonic-gate } 16230Sstevel@tonic-gate } 16240Sstevel@tonic-gate } 16250Sstevel@tonic-gate 16260Sstevel@tonic-gate /* out of luck */ 1627*1623Stw21770 if (!mdiserror(ep, MDE_AMBIGUOUS_DEV)) 1628*1623Stw21770 (void) mderror(ep, MDE_UNIT_NOT_FOUND, uname); 16290Sstevel@tonic-gate return (NULL); 16300Sstevel@tonic-gate } 16310Sstevel@tonic-gate 16320Sstevel@tonic-gate /* 16330Sstevel@tonic-gate * get number of slices for name 16340Sstevel@tonic-gate */ 16350Sstevel@tonic-gate static int 16360Sstevel@tonic-gate getnslice( 16370Sstevel@tonic-gate char *rname, 16380Sstevel@tonic-gate char *dname, 16390Sstevel@tonic-gate uint_t *slicep 16400Sstevel@tonic-gate ) 16410Sstevel@tonic-gate { 16420Sstevel@tonic-gate char *srname; 16430Sstevel@tonic-gate uint_t nslice; 16440Sstevel@tonic-gate size_t dl = strlen(dname); 16450Sstevel@tonic-gate size_t rl = strlen(rname); 16460Sstevel@tonic-gate size_t l = 0; 16470Sstevel@tonic-gate size_t len; 16480Sstevel@tonic-gate 16490Sstevel@tonic-gate /* 16500Sstevel@tonic-gate * get our slice number - works only with names that end in s%u - 16510Sstevel@tonic-gate * all others return -1. 16520Sstevel@tonic-gate */ 16530Sstevel@tonic-gate if (dl >= rl || 16540Sstevel@tonic-gate sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl || 16550Sstevel@tonic-gate (int)*slicep < 0) { 16560Sstevel@tonic-gate return (-1); 16570Sstevel@tonic-gate } 16580Sstevel@tonic-gate 16590Sstevel@tonic-gate /* 16600Sstevel@tonic-gate * go find how many slices there really are 16610Sstevel@tonic-gate */ 16620Sstevel@tonic-gate len = strlen(dname) + 20 + 1; 16630Sstevel@tonic-gate srname = Malloc(len); 16640Sstevel@tonic-gate for (nslice = 0; /* void */; ++nslice) { 16650Sstevel@tonic-gate struct stat statbuf; 16660Sstevel@tonic-gate 16670Sstevel@tonic-gate /* build slice name */ 16680Sstevel@tonic-gate (void) snprintf(srname, len, "%ss%u", dname, nslice); 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate /* see if it's there */ 16710Sstevel@tonic-gate if ((meta_stat(srname, &statbuf) != 0) || 16720Sstevel@tonic-gate (! S_ISCHR(statbuf.st_mode))) { 16730Sstevel@tonic-gate break; 16740Sstevel@tonic-gate } 16750Sstevel@tonic-gate } 16760Sstevel@tonic-gate Free(srname); 16770Sstevel@tonic-gate 16780Sstevel@tonic-gate /* Need to make sure that we at least have V_NUMPAR */ 16790Sstevel@tonic-gate nslice = max(nslice, V_NUMPAR); 16800Sstevel@tonic-gate 16810Sstevel@tonic-gate /* make sure we have at least our slice */ 16820Sstevel@tonic-gate if (nslice < *slicep) 16830Sstevel@tonic-gate return (-1); 16840Sstevel@tonic-gate 16850Sstevel@tonic-gate /* return number of slices */ 16860Sstevel@tonic-gate return (nslice); 16870Sstevel@tonic-gate } 16880Sstevel@tonic-gate 16890Sstevel@tonic-gate /* 16900Sstevel@tonic-gate * Attempt to parse the input string as a c[t]ds specifier 16910Sstevel@tonic-gate * The target can either be a SCSI target id or if the device 16920Sstevel@tonic-gate * is in a fabric configuration in a fibre channel setup then 16930Sstevel@tonic-gate * the target is a standard WWN (world wide name). 16940Sstevel@tonic-gate * 16950Sstevel@tonic-gate * if successful return 0 16960Sstevel@tonic-gate * if c[t]dp name return 1 16970Sstevel@tonic-gate * otherwise return -1 16980Sstevel@tonic-gate */ 16990Sstevel@tonic-gate int 17000Sstevel@tonic-gate parse_ctd( 17010Sstevel@tonic-gate char *uname, 17020Sstevel@tonic-gate uint_t *slice) 17030Sstevel@tonic-gate { 17040Sstevel@tonic-gate uint_t channel; 17050Sstevel@tonic-gate uint_t target; 17060Sstevel@tonic-gate uint_t device; 17070Sstevel@tonic-gate int has_target = 1; 17080Sstevel@tonic-gate uint_t cl; 17090Sstevel@tonic-gate uint_t target_str_len; 17100Sstevel@tonic-gate char *partial_ctd_str; 17110Sstevel@tonic-gate char *target_str; 17120Sstevel@tonic-gate char *device_start_pos; 17130Sstevel@tonic-gate int l = -1; 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate /* pull off the channel spec and the 't' for the target */ 17160Sstevel@tonic-gate if (sscanf(uname, "c%ut%n", &channel, &l) != 1 || l == -1) { 17170Sstevel@tonic-gate /* check for cds style name */ 17180Sstevel@tonic-gate if (sscanf(uname, "c%ud%n", &channel, &l) != 1 || l == -1) { 17190Sstevel@tonic-gate return (-1); 17200Sstevel@tonic-gate } else { 17210Sstevel@tonic-gate l--; /* we want to be on the 'd' */ 17220Sstevel@tonic-gate has_target = 0; 17230Sstevel@tonic-gate } 17240Sstevel@tonic-gate } 17250Sstevel@tonic-gate partial_ctd_str = uname + l; 17260Sstevel@tonic-gate 17270Sstevel@tonic-gate /* find the beginning of the device specifier */ 17280Sstevel@tonic-gate device_start_pos = strrchr(partial_ctd_str, 'd'); 17290Sstevel@tonic-gate if (device_start_pos == NULL) { 17300Sstevel@tonic-gate return (-1); 17310Sstevel@tonic-gate } 17320Sstevel@tonic-gate 17330Sstevel@tonic-gate /* check to see if it is a ctd with a WWN or SCSI target */ 17340Sstevel@tonic-gate if (has_target) { 17350Sstevel@tonic-gate /* pull off the target and see if it is a WWN */ 17360Sstevel@tonic-gate target_str_len = device_start_pos - partial_ctd_str + 2; 17370Sstevel@tonic-gate target_str = (char *)Malloc(target_str_len+1); 17380Sstevel@tonic-gate (void) strcpy(target_str, "0X"); 17390Sstevel@tonic-gate (void) strncpy(target_str+2, partial_ctd_str, 17400Sstevel@tonic-gate target_str_len - 2); 17410Sstevel@tonic-gate target_str[target_str_len] = '\0'; 17420Sstevel@tonic-gate if (sscanf(target_str, "%x%n", &target, &l) != 1 || 17430Sstevel@tonic-gate l != target_str_len) { 17440Sstevel@tonic-gate Free(target_str); 17450Sstevel@tonic-gate return (-1); 17460Sstevel@tonic-gate } 17470Sstevel@tonic-gate Free(target_str); 17480Sstevel@tonic-gate } 17490Sstevel@tonic-gate 17500Sstevel@tonic-gate /* check the device and slice */ 17510Sstevel@tonic-gate cl = strlen(device_start_pos); 17520Sstevel@tonic-gate if (sscanf(device_start_pos, "d%us%u%n", &device, slice, &l) != 2 || 17530Sstevel@tonic-gate l != cl) { 17540Sstevel@tonic-gate /* check the device and partition */ 17550Sstevel@tonic-gate if (sscanf(device_start_pos, "d%up%u%n", &device, slice, &l) 17560Sstevel@tonic-gate == 2 && l == cl) { 17570Sstevel@tonic-gate return (1); 17580Sstevel@tonic-gate } 17590Sstevel@tonic-gate return (-1); 17600Sstevel@tonic-gate } 17610Sstevel@tonic-gate 17620Sstevel@tonic-gate return (0); 17630Sstevel@tonic-gate } 17640Sstevel@tonic-gate 17650Sstevel@tonic-gate 17660Sstevel@tonic-gate /* 17670Sstevel@tonic-gate * get number of slices for name 17680Sstevel@tonic-gate */ 17690Sstevel@tonic-gate static int 17700Sstevel@tonic-gate uname2sliceno( 1771*1623Stw21770 char *uname, 1772*1623Stw21770 meta_device_type_t uname_type, 1773*1623Stw21770 uint_t *slicep, 1774*1623Stw21770 md_error_t *ep 17750Sstevel@tonic-gate ) 17760Sstevel@tonic-gate { 17770Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0; 17780Sstevel@tonic-gate int l = 0, cl = 0; 17790Sstevel@tonic-gate int fd; 17800Sstevel@tonic-gate struct dk_cinfo cinfo; 17810Sstevel@tonic-gate char *p; 17820Sstevel@tonic-gate char *rname = NULL; 17830Sstevel@tonic-gate 1784*1623Stw21770 1785*1623Stw21770 if (uname_type == META_DEVICE) 17860Sstevel@tonic-gate return (*slicep = 0); 17870Sstevel@tonic-gate 17880Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL) 17890Sstevel@tonic-gate p++; 17900Sstevel@tonic-gate else 17910Sstevel@tonic-gate p = uname; 17920Sstevel@tonic-gate 17930Sstevel@tonic-gate cl = strlen(p); 17940Sstevel@tonic-gate 17950Sstevel@tonic-gate if (parse_ctd(p, slicep) == 0) 17960Sstevel@tonic-gate return (*slicep); 17970Sstevel@tonic-gate else if (sscanf(p, "mc%ut%ud%us%u%n", &c, &t, &d, slicep, &l) == 4 && 17980Sstevel@tonic-gate l == cl) 17990Sstevel@tonic-gate return (*slicep); 18000Sstevel@tonic-gate else if (sscanf(p, "d%us%u%n", &d, slicep, &l) == 2 && l == cl) 18010Sstevel@tonic-gate return (*slicep); 18020Sstevel@tonic-gate 18030Sstevel@tonic-gate /* 18040Sstevel@tonic-gate * If we can't get the slice from the name, then we have to do it the 18050Sstevel@tonic-gate * hard and expensive way. 18060Sstevel@tonic-gate */ 18070Sstevel@tonic-gate if ((rname = rawname(uname)) == NULL) 18080Sstevel@tonic-gate return (-1); 18090Sstevel@tonic-gate 18100Sstevel@tonic-gate /* get controller info */ 18110Sstevel@tonic-gate if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) { 18120Sstevel@tonic-gate Free(rname); 18130Sstevel@tonic-gate return (-1); 18140Sstevel@tonic-gate } 18150Sstevel@tonic-gate 18160Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &cinfo) != 0) { 18170Sstevel@tonic-gate int save = errno; 18180Sstevel@tonic-gate 18190Sstevel@tonic-gate if (save == ENOTTY) 18200Sstevel@tonic-gate (void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname); 18210Sstevel@tonic-gate else 18220Sstevel@tonic-gate (void) mdsyserror(ep, save, rname); 18230Sstevel@tonic-gate 18240Sstevel@tonic-gate Free(rname); 18250Sstevel@tonic-gate (void) close(fd); 18260Sstevel@tonic-gate return (-1); 18270Sstevel@tonic-gate } 18280Sstevel@tonic-gate (void) close(fd); /* sd/ssd bug */ 18290Sstevel@tonic-gate 18300Sstevel@tonic-gate if (cinfo.dki_partition < V_NUMPAR) { 18310Sstevel@tonic-gate Free(rname); 18320Sstevel@tonic-gate return (*slicep = cinfo.dki_partition); 18330Sstevel@tonic-gate } 18340Sstevel@tonic-gate 18350Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname)); 18360Sstevel@tonic-gate } 18370Sstevel@tonic-gate 18380Sstevel@tonic-gate /* 18390Sstevel@tonic-gate * get partition info 18400Sstevel@tonic-gate */ 18410Sstevel@tonic-gate static int 18420Sstevel@tonic-gate getparts( 1843*1623Stw21770 mddrivename_t *dnp, 1844*1623Stw21770 char *rname, 1845*1623Stw21770 char *dname, 1846*1623Stw21770 meta_device_type_t uname_type, 1847*1623Stw21770 uint_t *npartsp, 1848*1623Stw21770 uint_t *partnop, 1849*1623Stw21770 md_error_t *ep 18500Sstevel@tonic-gate ) 18510Sstevel@tonic-gate { 18520Sstevel@tonic-gate int nparts; 18530Sstevel@tonic-gate uint_t partno; 18540Sstevel@tonic-gate mdname_t name; 18550Sstevel@tonic-gate mdvtoc_t *vtocp; 18560Sstevel@tonic-gate 18570Sstevel@tonic-gate /* metadevice */ 1858*1623Stw21770 if (uname_type == META_DEVICE) { 18590Sstevel@tonic-gate dnp->type = MDT_META; 18600Sstevel@tonic-gate nparts = 1; 18610Sstevel@tonic-gate partno = 0; 18620Sstevel@tonic-gate goto gotit; 18630Sstevel@tonic-gate } 18640Sstevel@tonic-gate 18650Sstevel@tonic-gate /* see how many partitions in drive, this is really tricky */ 18660Sstevel@tonic-gate metainitname(&name); 18670Sstevel@tonic-gate name.rname = rname; 18680Sstevel@tonic-gate name.drivenamep = dnp; 18690Sstevel@tonic-gate if ((vtocp = metagetvtoc(&name, TRUE, &partno, ep)) != NULL) { 18700Sstevel@tonic-gate dnp->type = MDT_COMP; 18710Sstevel@tonic-gate nparts = vtocp->nparts; 18720Sstevel@tonic-gate /* partno already setup */ 18730Sstevel@tonic-gate /* dname already setup */ 18740Sstevel@tonic-gate goto gotit; 18750Sstevel@tonic-gate } 18760Sstevel@tonic-gate 18770Sstevel@tonic-gate if ((ep->info.errclass == MDEC_DEV) && 18780Sstevel@tonic-gate (ep->info.md_error_info_t_u.dev_error.errnum == MDE_TOO_MANY_PARTS)) 18790Sstevel@tonic-gate return (-1); 18800Sstevel@tonic-gate 18810Sstevel@tonic-gate /* fallback and try and guess (used to check for just EACCES here) */ 18820Sstevel@tonic-gate if ((dname != NULL) && 18830Sstevel@tonic-gate ((nparts = getnslice(rname, dname, &partno)) > 0)) { 18840Sstevel@tonic-gate dnp->type = MDT_ACCES; 18850Sstevel@tonic-gate if (mdanysyserror(ep)) { 18860Sstevel@tonic-gate dnp->errnum = 18870Sstevel@tonic-gate ep->info.md_error_info_t_u.sys_error.errnum; 18880Sstevel@tonic-gate } else { 18890Sstevel@tonic-gate dnp->errnum = ENOENT; 18900Sstevel@tonic-gate } 18910Sstevel@tonic-gate mdclrerror(ep); 18920Sstevel@tonic-gate /* nparts already setup */ 18930Sstevel@tonic-gate /* partno already setup */ 18940Sstevel@tonic-gate /* dname already setup */ 18950Sstevel@tonic-gate nparts = roundup(nparts, V_NUMPAR); 18960Sstevel@tonic-gate goto gotit; 18970Sstevel@tonic-gate } 18980Sstevel@tonic-gate 18990Sstevel@tonic-gate /* nothing worked */ 19000Sstevel@tonic-gate dnp->type = MDT_UNKNOWN; 19010Sstevel@tonic-gate if (mdissyserror(ep, EACCES)) 19020Sstevel@tonic-gate dnp->type = MDT_ACCES; 19030Sstevel@tonic-gate 19040Sstevel@tonic-gate if (mdanysyserror(ep)) { 19050Sstevel@tonic-gate dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum; 19060Sstevel@tonic-gate } else { 19070Sstevel@tonic-gate dnp->errnum = ENOENT; 19080Sstevel@tonic-gate } 19090Sstevel@tonic-gate 19100Sstevel@tonic-gate mdclrerror(ep); 19110Sstevel@tonic-gate nparts = V_NUMPAR; 1912*1623Stw21770 if (uname2sliceno(rname, uname_type, &partno, ep) < 0) { 19130Sstevel@tonic-gate mdclrerror(ep); 19140Sstevel@tonic-gate partno = 0; 19150Sstevel@tonic-gate } 19160Sstevel@tonic-gate 19170Sstevel@tonic-gate /* return success */ 19180Sstevel@tonic-gate gotit: 19190Sstevel@tonic-gate assert(nparts > 0); 19200Sstevel@tonic-gate 19210Sstevel@tonic-gate if (partno >= nparts) 19220Sstevel@tonic-gate return (mdsyserror(ep, ENOENT, rname)); 19230Sstevel@tonic-gate 19240Sstevel@tonic-gate *npartsp = nparts; 19250Sstevel@tonic-gate *partnop = partno; 19260Sstevel@tonic-gate return (0); 19270Sstevel@tonic-gate } 19280Sstevel@tonic-gate 19290Sstevel@tonic-gate /* 19300Sstevel@tonic-gate * get block name 19310Sstevel@tonic-gate */ 19320Sstevel@tonic-gate static int 19330Sstevel@tonic-gate getbname( 19340Sstevel@tonic-gate mdname_t *np, 19350Sstevel@tonic-gate md_error_t *ep 19360Sstevel@tonic-gate ) 19370Sstevel@tonic-gate { 19380Sstevel@tonic-gate char *rname = np->rname; 19390Sstevel@tonic-gate char *bname; 19400Sstevel@tonic-gate 19410Sstevel@tonic-gate /* fully qualified */ 19420Sstevel@tonic-gate assert(rname != NULL); 19430Sstevel@tonic-gate if ((bname = blkname(rname)) != NULL) { 19440Sstevel@tonic-gate if (np->bname) 19450Sstevel@tonic-gate Free(np->bname); 19460Sstevel@tonic-gate np->bname = bname; 19470Sstevel@tonic-gate return (0); 19480Sstevel@tonic-gate } 19490Sstevel@tonic-gate 19500Sstevel@tonic-gate /* out of luck */ 19510Sstevel@tonic-gate return (mdsyserror(ep, ENOENT, rname)); 19520Sstevel@tonic-gate } 19530Sstevel@tonic-gate 19540Sstevel@tonic-gate static void 19550Sstevel@tonic-gate getcname( 19560Sstevel@tonic-gate mdsetname_t *sp, 19570Sstevel@tonic-gate mdname_t *np 19580Sstevel@tonic-gate ) 19590Sstevel@tonic-gate { 19600Sstevel@tonic-gate char *sname = sp->setname; 19610Sstevel@tonic-gate char *bname = np->bname; 19620Sstevel@tonic-gate char *p; 19630Sstevel@tonic-gate size_t len; 19640Sstevel@tonic-gate 19650Sstevel@tonic-gate assert(sname != NULL); 19660Sstevel@tonic-gate assert(bname != NULL); 19670Sstevel@tonic-gate assert(np->drivenamep->type != MDT_FAST_COMP && 19680Sstevel@tonic-gate np->drivenamep->type != MDT_FAST_META); 19690Sstevel@tonic-gate 19700Sstevel@tonic-gate /* regular device */ 19710Sstevel@tonic-gate if ((strncmp(bname, "/dev/dsk/", strlen("/dev/dsk/")) == 0) && 19720Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/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 if ((strncmp(bname, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) && 19800Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/ap/dsk/")), '/') == NULL)) { 19810Sstevel@tonic-gate if (np->cname) 19820Sstevel@tonic-gate Free(np->cname); 19830Sstevel@tonic-gate np->cname = Strdup(p); 19840Sstevel@tonic-gate return; 19850Sstevel@tonic-gate } 19860Sstevel@tonic-gate 19870Sstevel@tonic-gate if ((strncmp(bname, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) && 19880Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/did/dsk/")), '/') == NULL)) { 19890Sstevel@tonic-gate if (np->cname) 19900Sstevel@tonic-gate Free(np->cname); 19910Sstevel@tonic-gate np->cname = Strdup(p); 19920Sstevel@tonic-gate return; 19930Sstevel@tonic-gate } 19940Sstevel@tonic-gate 19950Sstevel@tonic-gate /* anything else but metadevice */ 19960Sstevel@tonic-gate if (np->drivenamep->type != MDT_META) { 19970Sstevel@tonic-gate if (np->cname) 19980Sstevel@tonic-gate Free(np->cname); 19990Sstevel@tonic-gate np->cname = Strdup(bname); 20000Sstevel@tonic-gate return; 20010Sstevel@tonic-gate } 20020Sstevel@tonic-gate 20030Sstevel@tonic-gate /* metadevice */ 20040Sstevel@tonic-gate p = strrchr(bname, '/'); 20050Sstevel@tonic-gate assert(p != NULL); 20060Sstevel@tonic-gate ++p; 20070Sstevel@tonic-gate if (metaislocalset(sp)) { 20080Sstevel@tonic-gate if (np->cname) 20090Sstevel@tonic-gate Free(np->cname); 20100Sstevel@tonic-gate np->cname = Strdup(p); 20110Sstevel@tonic-gate } else { 20120Sstevel@tonic-gate assert(sname[0] != '\0'); 20130Sstevel@tonic-gate if (np->cname) 20140Sstevel@tonic-gate Free(np->cname); 20150Sstevel@tonic-gate len = strlen(sname) + 1 + strlen(p) + 1; 20160Sstevel@tonic-gate np->cname = Malloc(len); 20170Sstevel@tonic-gate (void) snprintf(np->cname, len, "%s/%s", sname, p); 20180Sstevel@tonic-gate } 20190Sstevel@tonic-gate } 20200Sstevel@tonic-gate 20210Sstevel@tonic-gate /* 20220Sstevel@tonic-gate * get dev 20230Sstevel@tonic-gate */ 20240Sstevel@tonic-gate int 20250Sstevel@tonic-gate meta_getdev( 20260Sstevel@tonic-gate mdsetname_t *sp, 20270Sstevel@tonic-gate mdname_t *np, 20280Sstevel@tonic-gate md_error_t *ep 20290Sstevel@tonic-gate ) 20300Sstevel@tonic-gate { 20310Sstevel@tonic-gate struct stat statbuf; 20320Sstevel@tonic-gate 20330Sstevel@tonic-gate /* get dev */ 20340Sstevel@tonic-gate if (meta_stat(np->rname, &statbuf) != 0) 20350Sstevel@tonic-gate return (mdsyserror(ep, errno, np->rname)); 20360Sstevel@tonic-gate else if (! S_ISCHR(statbuf.st_mode)) 20370Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, NODEV64, np->rname)); 20380Sstevel@tonic-gate np->dev = meta_expldev(statbuf.st_rdev); 20390Sstevel@tonic-gate 20400Sstevel@tonic-gate assert(np->drivenamep->type != MDT_FAST_META && 20410Sstevel@tonic-gate np->drivenamep->type != MDT_FAST_COMP); 20420Sstevel@tonic-gate 20430Sstevel@tonic-gate /* check set */ 20440Sstevel@tonic-gate assert((np->drivenamep->type == MDT_META) ? 20450Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1); 20460Sstevel@tonic-gate 20470Sstevel@tonic-gate /* return sucess */ 20480Sstevel@tonic-gate return (0); 20490Sstevel@tonic-gate } 20500Sstevel@tonic-gate 20510Sstevel@tonic-gate /* 20520Sstevel@tonic-gate * set up names for a slice 20530Sstevel@tonic-gate */ 20540Sstevel@tonic-gate static int 20550Sstevel@tonic-gate getnames( 20560Sstevel@tonic-gate mdsetname_t *sp, 20570Sstevel@tonic-gate mdname_t *np, 20580Sstevel@tonic-gate char *rname, 20590Sstevel@tonic-gate md_error_t *ep 20600Sstevel@tonic-gate ) 20610Sstevel@tonic-gate { 20620Sstevel@tonic-gate /* get names */ 20630Sstevel@tonic-gate if (np->rname) 20640Sstevel@tonic-gate Free(np->rname); 20650Sstevel@tonic-gate np->rname = Strdup(rname); 20660Sstevel@tonic-gate if (getbname(np, ep) != 0) 20670Sstevel@tonic-gate return (-1); 20680Sstevel@tonic-gate getcname(sp, np); 20690Sstevel@tonic-gate if (meta_getdev(sp, np, ep) != 0) 20700Sstevel@tonic-gate return (-1); 20710Sstevel@tonic-gate 20720Sstevel@tonic-gate /* return success */ 20730Sstevel@tonic-gate return (0); 20740Sstevel@tonic-gate } 20750Sstevel@tonic-gate 20760Sstevel@tonic-gate /* 20770Sstevel@tonic-gate * fake up names for a slice 20780Sstevel@tonic-gate */ 20790Sstevel@tonic-gate static void 20800Sstevel@tonic-gate getfakenames( 20810Sstevel@tonic-gate mdsetname_t *sp, 20820Sstevel@tonic-gate mdname_t *np, 20830Sstevel@tonic-gate char *rname 20840Sstevel@tonic-gate ) 20850Sstevel@tonic-gate { 20860Sstevel@tonic-gate char *p; 20870Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1]; 20880Sstevel@tonic-gate uint_t d = 0; 20890Sstevel@tonic-gate int l = 0; 20900Sstevel@tonic-gate 20910Sstevel@tonic-gate /* fake names */ 20920Sstevel@tonic-gate if (np->rname != NULL) 20930Sstevel@tonic-gate Free(np->rname); 20940Sstevel@tonic-gate np->rname = Strdup(rname); 20950Sstevel@tonic-gate 20960Sstevel@tonic-gate if (np->bname != NULL) 20970Sstevel@tonic-gate Free(np->bname); 20980Sstevel@tonic-gate np->bname = Strdup(rname); 20990Sstevel@tonic-gate 21000Sstevel@tonic-gate /* 21010Sstevel@tonic-gate * Fixup old style names 21020Sstevel@tonic-gate */ 21030Sstevel@tonic-gate if (sscanf(rname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 21040Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 21050Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(rname)) 21060Sstevel@tonic-gate (void) snprintf(np->bname, l, "/dev/%s%u%s", onmb, d, snm); 21070Sstevel@tonic-gate 21080Sstevel@tonic-gate /* 21090Sstevel@tonic-gate * Fixup new style names 21100Sstevel@tonic-gate */ 21110Sstevel@tonic-gate if ((p = strstr(np->bname, "/rdsk/")) != NULL) { 21120Sstevel@tonic-gate for (++p; (*(p + 1) != '\0'); ++p) 21130Sstevel@tonic-gate *p = *(p + 1); 21140Sstevel@tonic-gate *p = '\0'; 21150Sstevel@tonic-gate } 21160Sstevel@tonic-gate 21170Sstevel@tonic-gate if (np->cname != NULL) 21180Sstevel@tonic-gate Free(np->cname); 21190Sstevel@tonic-gate getcname(sp, np); 21200Sstevel@tonic-gate } 21210Sstevel@tonic-gate 21220Sstevel@tonic-gate static mdname_t * 21230Sstevel@tonic-gate setup_slice( 2124*1623Stw21770 mdsetname_t *sp, 2125*1623Stw21770 meta_device_type_t uname_type, 2126*1623Stw21770 mddrivename_t *dnp, 2127*1623Stw21770 char *uname, 2128*1623Stw21770 char *rname, 2129*1623Stw21770 char *dname, 2130*1623Stw21770 uint_t partno, 2131*1623Stw21770 md_error_t *ep 21320Sstevel@tonic-gate ) 21330Sstevel@tonic-gate { 2134*1623Stw21770 char *srname = NULL; 2135*1623Stw21770 mdname_t *np; 21360Sstevel@tonic-gate 21370Sstevel@tonic-gate /* must have a set */ 21380Sstevel@tonic-gate assert(sp != NULL); 21390Sstevel@tonic-gate assert(partno < dnp->parts.parts_len); 21400Sstevel@tonic-gate assert(dname != NULL); 21410Sstevel@tonic-gate 21420Sstevel@tonic-gate np = &dnp->parts.parts_val[partno]; 21430Sstevel@tonic-gate 21440Sstevel@tonic-gate if (rname) 21450Sstevel@tonic-gate srname = rname; 2146*1623Stw21770 else if (uname_type == META_DEVICE) 21470Sstevel@tonic-gate srname = dname; 21480Sstevel@tonic-gate else { 21490Sstevel@tonic-gate char onmb[BUFSIZ+1]; 21500Sstevel@tonic-gate uint_t d = 0; 21510Sstevel@tonic-gate int l = 0, cl = strlen(dname); 21520Sstevel@tonic-gate size_t len; 21530Sstevel@tonic-gate 21540Sstevel@tonic-gate len = cl + 20 + 1; 21550Sstevel@tonic-gate srname = Malloc(len); 21560Sstevel@tonic-gate 21570Sstevel@tonic-gate /* 21580Sstevel@tonic-gate * Handle /dev/rXXNN. 21590Sstevel@tonic-gate */ 21600Sstevel@tonic-gate if (sscanf(dname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%n", 21610Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 21620Sstevel@tonic-gate (void) snprintf(srname, len, "/dev/r%s%u%c", onmb, d, 21630Sstevel@tonic-gate 'a' + partno); 21640Sstevel@tonic-gate } else if (sscanf(dname, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%n", 21650Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 21660Sstevel@tonic-gate (void) snprintf(srname, len, "/dev/%s%u%c", onmb, d, 21670Sstevel@tonic-gate 'a' + partno); 21680Sstevel@tonic-gate } else { 21690Sstevel@tonic-gate /* build the slice that is wanted */ 21700Sstevel@tonic-gate (void) snprintf(srname, len, "%ss%u", dname, partno); 21710Sstevel@tonic-gate } 21720Sstevel@tonic-gate } 21730Sstevel@tonic-gate 21740Sstevel@tonic-gate if (getnames(sp, np, srname, ep) != 0) { 21750Sstevel@tonic-gate if (dnp->type == MDT_UNKNOWN) { 21760Sstevel@tonic-gate mdclrerror(ep); 21770Sstevel@tonic-gate getfakenames(sp, np, srname); 21780Sstevel@tonic-gate } else if (dnp->type == MDT_COMP && mdissyserror(ep, ENOENT)) { 21790Sstevel@tonic-gate dnp->type = MDT_UNKNOWN; 21800Sstevel@tonic-gate if (mdanysyserror(ep)) { 21810Sstevel@tonic-gate dnp->errnum = 21820Sstevel@tonic-gate ep->info.md_error_info_t_u.sys_error.errnum; 21830Sstevel@tonic-gate } else { 21840Sstevel@tonic-gate dnp->errnum = ENOENT; 21850Sstevel@tonic-gate } 21860Sstevel@tonic-gate mdclrerror(ep); 21870Sstevel@tonic-gate getfakenames(sp, np, srname); 21880Sstevel@tonic-gate } else { 21890Sstevel@tonic-gate mdclrerror(ep); 21900Sstevel@tonic-gate if (getnames(sp, np, dname, ep) != 0) { 21910Sstevel@tonic-gate np = NULL; 21920Sstevel@tonic-gate goto fixup; 21930Sstevel@tonic-gate } 21940Sstevel@tonic-gate } 21950Sstevel@tonic-gate } 21960Sstevel@tonic-gate 21970Sstevel@tonic-gate out: 21980Sstevel@tonic-gate if ((srname != rname) && (srname != dname)) 21990Sstevel@tonic-gate Free(srname); 22000Sstevel@tonic-gate 22010Sstevel@tonic-gate /* return name */ 22020Sstevel@tonic-gate return (np); 22030Sstevel@tonic-gate 22040Sstevel@tonic-gate fixup: 22050Sstevel@tonic-gate if (mdanysyserror(ep)) { 22060Sstevel@tonic-gate char *p; 22070Sstevel@tonic-gate int errnum = ep->info.md_error_info_t_u.sys_error.errnum; 22080Sstevel@tonic-gate 22090Sstevel@tonic-gate mdclrerror(ep); 22100Sstevel@tonic-gate if (uname && *uname) { 22110Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL) 22120Sstevel@tonic-gate (void) mdsyserror(ep, errnum, ++p); 22130Sstevel@tonic-gate else 22140Sstevel@tonic-gate (void) mdsyserror(ep, errnum, uname); 22150Sstevel@tonic-gate } else { 22160Sstevel@tonic-gate if ((p = strrchr(srname, '/')) != NULL) 22170Sstevel@tonic-gate (void) mdsyserror(ep, errnum, ++p); 22180Sstevel@tonic-gate else 22190Sstevel@tonic-gate (void) mdsyserror(ep, errnum, srname); 22200Sstevel@tonic-gate } 22210Sstevel@tonic-gate } 22220Sstevel@tonic-gate goto out; 22230Sstevel@tonic-gate } 22240Sstevel@tonic-gate 22250Sstevel@tonic-gate /* 22260Sstevel@tonic-gate * flush the fast name cache 22270Sstevel@tonic-gate */ 22280Sstevel@tonic-gate static void 22290Sstevel@tonic-gate metafreefastnm(mdname_t **np) 22300Sstevel@tonic-gate { 22310Sstevel@tonic-gate mddrivename_t *dnp; 22320Sstevel@tonic-gate 22330Sstevel@tonic-gate assert(np != NULL && *np != NULL); 22340Sstevel@tonic-gate 22350Sstevel@tonic-gate if ((dnp = (*np)->drivenamep) != NULL) { 22360Sstevel@tonic-gate if (dnp->cname != NULL) 22370Sstevel@tonic-gate Free(dnp->cname); 22380Sstevel@tonic-gate if (dnp->rname != NULL) 22390Sstevel@tonic-gate Free(dnp->rname); 22400Sstevel@tonic-gate if (dnp->miscname != NULL) 22410Sstevel@tonic-gate Free(dnp->miscname); 22420Sstevel@tonic-gate meta_free_unit(dnp); 22430Sstevel@tonic-gate Free(dnp); 22440Sstevel@tonic-gate } 22450Sstevel@tonic-gate if ((*np)->cname != NULL) 22460Sstevel@tonic-gate Free((*np)->cname); 22470Sstevel@tonic-gate if ((*np)->bname != NULL) 22480Sstevel@tonic-gate Free((*np)->bname); 22490Sstevel@tonic-gate if ((*np)->rname != NULL) 22500Sstevel@tonic-gate Free((*np)->rname); 22510Sstevel@tonic-gate if ((*np)->devicesname != NULL) 22520Sstevel@tonic-gate Free((*np)->devicesname); 22530Sstevel@tonic-gate Free(*np); 22540Sstevel@tonic-gate *np = NULL; 22550Sstevel@tonic-gate } 22560Sstevel@tonic-gate 22570Sstevel@tonic-gate /* 22580Sstevel@tonic-gate * flush the fast name cache 22590Sstevel@tonic-gate */ 22600Sstevel@tonic-gate static void 22610Sstevel@tonic-gate metaflushfastnames() 22620Sstevel@tonic-gate { 22630Sstevel@tonic-gate mdnamelist_t *p, *n; 22640Sstevel@tonic-gate 22650Sstevel@tonic-gate for (p = fastnmlp, n = NULL; (p != NULL); p = n) { 22660Sstevel@tonic-gate n = p->next; 22670Sstevel@tonic-gate metafreefastnm(&p->namep); 22680Sstevel@tonic-gate Free(p); 22690Sstevel@tonic-gate } 22700Sstevel@tonic-gate fastnmlp = NULL; 22710Sstevel@tonic-gate } 22720Sstevel@tonic-gate static char * 2273*1623Stw21770 getrname_fast(char *unm, meta_device_type_t uname_type, md_error_t *ep) 22740Sstevel@tonic-gate { 22750Sstevel@tonic-gate uint_t d = 0; 22760Sstevel@tonic-gate int l = 0; 22770Sstevel@tonic-gate int cl = strlen(unm); 22780Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1], cnmb[BUFSIZ]; 22790Sstevel@tonic-gate char *rnm; 22800Sstevel@tonic-gate char *p; 22810Sstevel@tonic-gate size_t len; 22820Sstevel@tonic-gate 2283*1623Stw21770 if (uname_type == META_DEVICE) { 2284*1623Stw21770 /* fully qualified - local set */ 2285*1623Stw21770 if (((sscanf(unm, "/dev/md/dsk/%" VAL2STR(BUFSIZ) "s%n", 2286*1623Stw21770 onmb, &len) == 1) && (cl == len)) || 2287*1623Stw21770 ((sscanf(unm, "/dev/md/rdsk/%" VAL2STR(BUFSIZ) "s%n", 2288*1623Stw21770 onmb, &len) == 1) && (cl == len))) { 2289*1623Stw21770 len = strlen("/dev/md/rdsk/") + strlen(onmb) + 1; 2290*1623Stw21770 rnm = Zalloc(len); 2291*1623Stw21770 (void) snprintf(rnm, len, "/dev/md/rdsk/%s", onmb); 2292*1623Stw21770 return (rnm); 2293*1623Stw21770 } 2294*1623Stw21770 2295*1623Stw21770 /* fully qualified - setname specified */ 2296*1623Stw21770 if (((sscanf(unm, "/dev/md/%[^/]/dsk/%" 2297*1623Stw21770 VAL2STR(BUFSIZ) "s%n", 2298*1623Stw21770 snm, onmb, &len) == 2) && (cl == len)) || 2299*1623Stw21770 ((sscanf(unm, "/dev/md/%[^/]/rdsk/%" 2300*1623Stw21770 VAL2STR(BUFSIZ) "s%n", 2301*1623Stw21770 snm, onmb, &len) == 2) && (cl == len))) { 2302*1623Stw21770 2303*1623Stw21770 len = strlen("/dev/md//rdsk/") + strlen(snm) + 2304*1623Stw21770 strlen(onmb) + 1; 2305*1623Stw21770 rnm = Zalloc(len); 2306*1623Stw21770 (void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s", 2307*1623Stw21770 snm, onmb); 23080Sstevel@tonic-gate return (rnm); 23090Sstevel@tonic-gate } 23100Sstevel@tonic-gate 2311*1623Stw21770 /* Fully qualified path - error */ 2312*1623Stw21770 if (unm[0] == '/') { 2313*1623Stw21770 (void) mdsyserror(ep, EINVAL, unm); 2314*1623Stw21770 return (NULL); 2315*1623Stw21770 } 2316*1623Stw21770 2317*1623Stw21770 /* setname specified <setname>/<metadev> */ 2318*1623Stw21770 if (((sscanf(unm, "%[^/]/%" VAL2STR(BUFSIZ) "s%n", 2319*1623Stw21770 snm, onmb, &len) == 2) && (cl == len))) { 2320*1623Stw21770 /* Not <setname>/<metadev> - error */ 2321*1623Stw21770 if (strchr(onmb, '/') != NULL) { 2322*1623Stw21770 (void) mdsyserror(ep, EINVAL, unm); 2323*1623Stw21770 return (NULL); 2324*1623Stw21770 } 2325*1623Stw21770 2326*1623Stw21770 len = strlen("/dev/md//rdsk/") + strlen(snm) + 2327*1623Stw21770 strlen(onmb) + 1; 2328*1623Stw21770 rnm = Zalloc(len); 2329*1623Stw21770 (void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s", 2330*1623Stw21770 snm, onmb); 23310Sstevel@tonic-gate return (rnm); 23320Sstevel@tonic-gate } 23330Sstevel@tonic-gate 2334*1623Stw21770 /* Must be simple metaname/hsp pool name */ 2335*1623Stw21770 len = strlen("/dev/md/rdsk/") + strlen(unm) + 1; 2336*1623Stw21770 rnm = Zalloc(len); 2337*1623Stw21770 (void) snprintf(rnm, len, "/dev/md/rdsk/%s", unm); 2338*1623Stw21770 return (rnm); 23390Sstevel@tonic-gate } 23400Sstevel@tonic-gate 23410Sstevel@tonic-gate /* NOT Fully qualified path, done */ 23420Sstevel@tonic-gate if (unm[0] != '/') { 23430Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, unm); 23440Sstevel@tonic-gate return (NULL); 23450Sstevel@tonic-gate } 23460Sstevel@tonic-gate 23470Sstevel@tonic-gate /* 23480Sstevel@tonic-gate * Get slice information from old style names of the form 23490Sstevel@tonic-gate * /dev/rXXNN[a-h] or /dev/XXNN[a-h], must be done before regular 23500Sstevel@tonic-gate * devices, but after metadevices. 23510Sstevel@tonic-gate */ 23520Sstevel@tonic-gate if ((sscanf(unm, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 23530Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 23540Sstevel@tonic-gate onmb, &d, snm, &l) == 3 || 23550Sstevel@tonic-gate sscanf(unm, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u" 23560Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 23570Sstevel@tonic-gate onmb, &d, snm, &l) == 3) && l == cl) { 23580Sstevel@tonic-gate if ((p = strchr("abcdefgh", snm[0])) != NULL) { 23590Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u%s", 23600Sstevel@tonic-gate onmb, d, snm); 23610Sstevel@tonic-gate return (Strdup(cnmb)); 23620Sstevel@tonic-gate } 23630Sstevel@tonic-gate } 23640Sstevel@tonic-gate 23650Sstevel@tonic-gate if ((p = strstr(unm, "/dsk/")) != NULL) { /* /.../dsk/... */ 23660Sstevel@tonic-gate ++p; 23670Sstevel@tonic-gate rnm = Zalloc(strlen(unm) + 1 + 1); 23680Sstevel@tonic-gate (void) strncpy(rnm, unm, (p - unm)); 23690Sstevel@tonic-gate rnm[(p - unm)] = 'r'; 23700Sstevel@tonic-gate (void) strcpy(&rnm[(p - unm) + 1], p); 23710Sstevel@tonic-gate return (rnm); 23720Sstevel@tonic-gate } else if (strstr(unm, "/rdsk/") != NULL) { /* /.../rdsk/... */ 23730Sstevel@tonic-gate return (Strdup(unm)); 23740Sstevel@tonic-gate } 23750Sstevel@tonic-gate 23760Sstevel@tonic-gate /* 23770Sstevel@tonic-gate * Shouldn't get here but if we do then we have an unrecognized 23780Sstevel@tonic-gate * fully qualified path - error 23790Sstevel@tonic-gate */ 23800Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, unm); 23810Sstevel@tonic-gate return (NULL); 23820Sstevel@tonic-gate } 23830Sstevel@tonic-gate 23840Sstevel@tonic-gate static mdname_t * 23850Sstevel@tonic-gate metainitfastname( 2386*1623Stw21770 mdsetname_t *sp, 2387*1623Stw21770 char *uname, 2388*1623Stw21770 meta_device_type_t uname_type, 2389*1623Stw21770 md_error_t *ep 23900Sstevel@tonic-gate ) 23910Sstevel@tonic-gate { 23920Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0, s = 0; 23930Sstevel@tonic-gate int l = 0; 23940Sstevel@tonic-gate mddrivename_t *dnp; 23950Sstevel@tonic-gate mdname_t *np; 23960Sstevel@tonic-gate mdnamelist_t **fnlpp; 2397*1623Stw21770 char *cname; 23980Sstevel@tonic-gate 23990Sstevel@tonic-gate for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) { 24000Sstevel@tonic-gate np = (*fnlpp)->namep; 24010Sstevel@tonic-gate 24020Sstevel@tonic-gate if (strcmp(np->bname, uname) == 0) 24030Sstevel@tonic-gate return (np); 24040Sstevel@tonic-gate } 24050Sstevel@tonic-gate 24060Sstevel@tonic-gate *fnlpp = Zalloc(sizeof (**fnlpp)); 24070Sstevel@tonic-gate np = (*fnlpp)->namep = Zalloc(sizeof (mdname_t)); 24080Sstevel@tonic-gate metainitname(np); 24090Sstevel@tonic-gate dnp = np->drivenamep = Zalloc(sizeof (mddrivename_t)); 24100Sstevel@tonic-gate metainitdrivename(dnp); 24110Sstevel@tonic-gate 24120Sstevel@tonic-gate 24130Sstevel@tonic-gate /* Metadevices */ 2414*1623Stw21770 if (uname_type == META_DEVICE && 2415*1623Stw21770 (cname = meta_canonicalize(sp, uname)) != NULL) { 2416*1623Stw21770 2417*1623Stw21770 np->cname = cname; 24180Sstevel@tonic-gate dnp->type = MDT_FAST_META; 24190Sstevel@tonic-gate goto done; 24200Sstevel@tonic-gate } 24210Sstevel@tonic-gate 24220Sstevel@tonic-gate /* Others */ 24230Sstevel@tonic-gate dnp->type = MDT_FAST_COMP; 24240Sstevel@tonic-gate 24250Sstevel@tonic-gate if (((sscanf(uname, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d, 24260Sstevel@tonic-gate &s, &l) == 4 || 24270Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d, 24280Sstevel@tonic-gate &s, &l) == 4 || 24290Sstevel@tonic-gate sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c, &t, &d, 24300Sstevel@tonic-gate &s, &l) == 4 || 24310Sstevel@tonic-gate sscanf(uname, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c, &t, &d, 24320Sstevel@tonic-gate &s, &l) == 4 || 24330Sstevel@tonic-gate sscanf(uname, "/dev/did/rdsk/d%us%u%n", &t, &s, &l) == 2 || 24340Sstevel@tonic-gate sscanf(uname, "/dev/did/dsk/d%us%u%n", &t, &s, &l) == 2|| 24350Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 || 24360Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 || 24370Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 || 24380Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 || 24390Sstevel@tonic-gate sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 || 24400Sstevel@tonic-gate sscanf(uname, "/dev/ap/dsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 || 24410Sstevel@tonic-gate sscanf(uname, "/dev/did/rdsk/d%u%n", &t, &l) == 1 || 24420Sstevel@tonic-gate sscanf(uname, "/dev/did/dsk/d%u%n", &t, &l) == 1 || 24430Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ud%u%n", &c, &d, &l) == 2 || 24440Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2) && 24450Sstevel@tonic-gate l == strlen(uname))) { 24460Sstevel@tonic-gate if ((np->cname = strrchr(uname, '/')) == NULL) 24470Sstevel@tonic-gate np->cname = Strdup(uname); 24480Sstevel@tonic-gate else 24490Sstevel@tonic-gate np->cname = Strdup(++np->cname); 24500Sstevel@tonic-gate } else { 24510Sstevel@tonic-gate np->cname = Strdup(uname); 24520Sstevel@tonic-gate } 24530Sstevel@tonic-gate 24540Sstevel@tonic-gate done: 24550Sstevel@tonic-gate /* Driver always gives us block names */ 24560Sstevel@tonic-gate np->bname = Strdup(uname); 24570Sstevel@tonic-gate 24580Sstevel@tonic-gate /* canonical disk name */ 24590Sstevel@tonic-gate if ((dnp->cname = metadiskname(np->cname)) == NULL) 24600Sstevel@tonic-gate dnp->cname = Strdup(np->cname); 24610Sstevel@tonic-gate 2462*1623Stw21770 if ((np->rname = getrname_fast(uname, uname_type, ep)) != NULL) { 24630Sstevel@tonic-gate if ((dnp->rname = metadiskname(np->rname)) == NULL) 24640Sstevel@tonic-gate dnp->rname = Strdup(np->rname); 24650Sstevel@tonic-gate } else { 24660Sstevel@tonic-gate metafreefastnm(&(*fnlpp)->namep); 24670Sstevel@tonic-gate Free(*fnlpp); 24680Sstevel@tonic-gate *fnlpp = NULL; 24690Sstevel@tonic-gate return (NULL); 24700Sstevel@tonic-gate } 24710Sstevel@tonic-gate 24720Sstevel@tonic-gate /* cleanup, return success */ 24730Sstevel@tonic-gate return (np); 24740Sstevel@tonic-gate } 24750Sstevel@tonic-gate 24760Sstevel@tonic-gate /* 24770Sstevel@tonic-gate * set up names for a device 24780Sstevel@tonic-gate */ 24790Sstevel@tonic-gate static mdname_t * 24800Sstevel@tonic-gate metaname_common( 24810Sstevel@tonic-gate mdsetname_t **spp, 24820Sstevel@tonic-gate char *uname, 24830Sstevel@tonic-gate int fast, 2484*1623Stw21770 meta_device_type_t uname_type, 24850Sstevel@tonic-gate md_error_t *ep 24860Sstevel@tonic-gate ) 24870Sstevel@tonic-gate { 24880Sstevel@tonic-gate mddrivenamelist_t **tail; 24890Sstevel@tonic-gate mddrivename_t *dnp; 24900Sstevel@tonic-gate uint_t slice; 24910Sstevel@tonic-gate mdname_t *np; 24920Sstevel@tonic-gate char *rname = NULL; 24930Sstevel@tonic-gate char *dname = NULL; 24940Sstevel@tonic-gate char *cname = NULL; 24950Sstevel@tonic-gate uint_t nparts, partno; 24960Sstevel@tonic-gate 24970Sstevel@tonic-gate assert(uname != NULL); 24980Sstevel@tonic-gate 24990Sstevel@tonic-gate /* check setname */ 2500*1623Stw21770 if ((cname = meta_name_getname(spp, uname, uname_type, ep)) == NULL) 25010Sstevel@tonic-gate return (NULL); 25020Sstevel@tonic-gate 25030Sstevel@tonic-gate assert(*spp != NULL); 25040Sstevel@tonic-gate Free(cname); 25050Sstevel@tonic-gate 25060Sstevel@tonic-gate /* get raw name (rname) of the slice and drive (dname) we have */ 2507*1623Stw21770 if ((rname = getrawnames(spp, uname, 2508*1623Stw21770 &dname, &uname_type, ep)) == NULL) { 25090Sstevel@tonic-gate return (NULL); 25100Sstevel@tonic-gate } 25110Sstevel@tonic-gate 2512*1623Stw21770 assert(uname_type != UNKNOWN); 2513*1623Stw21770 25140Sstevel@tonic-gate /* look in cache first */ 25150Sstevel@tonic-gate for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 25160Sstevel@tonic-gate dnp = (*tail)->drivenamep; 25170Sstevel@tonic-gate 25180Sstevel@tonic-gate /* check to see if the drive name is already in the cache */ 25190Sstevel@tonic-gate if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) { 25200Sstevel@tonic-gate 25210Sstevel@tonic-gate Free(rname); 25220Sstevel@tonic-gate if (dname != NULL) 25230Sstevel@tonic-gate Free(dname); 25240Sstevel@tonic-gate 2525*1623Stw21770 if (uname2sliceno(uname, uname_type, &partno, ep) < 0) 25260Sstevel@tonic-gate return (NULL); 25270Sstevel@tonic-gate 25280Sstevel@tonic-gate return (metaslicename(dnp, partno, ep)); 25290Sstevel@tonic-gate } 25300Sstevel@tonic-gate } 25310Sstevel@tonic-gate 25320Sstevel@tonic-gate /* 25330Sstevel@tonic-gate * If a fast names is OK, then get one, and be done. 25340Sstevel@tonic-gate */ 25350Sstevel@tonic-gate if (fast) { 25360Sstevel@tonic-gate Free(rname); 25370Sstevel@tonic-gate if (dname != NULL) 25380Sstevel@tonic-gate Free(dname); 25390Sstevel@tonic-gate 2540*1623Stw21770 return (metainitfastname(*spp, uname, uname_type, ep)); 25410Sstevel@tonic-gate } 25420Sstevel@tonic-gate 25430Sstevel@tonic-gate /* allocate new list element and drive */ 25440Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 25450Sstevel@tonic-gate dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp)); 25460Sstevel@tonic-gate 25470Sstevel@tonic-gate metainitdrivename(dnp); 25480Sstevel@tonic-gate 25490Sstevel@tonic-gate /* get parts info */ 2550*1623Stw21770 if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0) 25510Sstevel@tonic-gate goto out; 25520Sstevel@tonic-gate 25530Sstevel@tonic-gate /* 25540Sstevel@tonic-gate * libmeta needs at least V_NUMPAR partitions. 25550Sstevel@tonic-gate * If we have an EFI partition with less than V_NUMPAR slices, 25560Sstevel@tonic-gate * we nevertheless reserve space for V_NUMPAR 25570Sstevel@tonic-gate */ 25580Sstevel@tonic-gate if (nparts < V_NUMPAR) { 25590Sstevel@tonic-gate nparts = V_NUMPAR; 25600Sstevel@tonic-gate } 25610Sstevel@tonic-gate 25620Sstevel@tonic-gate /* allocate and link in parts */ 25630Sstevel@tonic-gate dnp->parts.parts_len = nparts; 25640Sstevel@tonic-gate dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) * 25650Sstevel@tonic-gate dnp->parts.parts_len); 25660Sstevel@tonic-gate for (slice = 0; (slice < nparts); ++slice) { 25670Sstevel@tonic-gate np = &dnp->parts.parts_val[slice]; 25680Sstevel@tonic-gate metainitname(np); 25690Sstevel@tonic-gate np->drivenamep = dnp; 25700Sstevel@tonic-gate } 25710Sstevel@tonic-gate 25720Sstevel@tonic-gate /* setup name_t (or slice) wanted */ 2573*1623Stw21770 if ((np = setup_slice(*spp, uname_type, dnp, uname, rname, 2574*1623Stw21770 dname, partno, ep)) == NULL) 25750Sstevel@tonic-gate goto out; 25760Sstevel@tonic-gate 25770Sstevel@tonic-gate /* canonical disk name */ 25780Sstevel@tonic-gate if ((dnp->cname = metadiskname(np->cname)) == NULL) 25790Sstevel@tonic-gate dnp->cname = Strdup(np->cname); 25800Sstevel@tonic-gate if ((dnp->rname = metadiskname(np->rname)) == NULL) 25810Sstevel@tonic-gate dnp->rname = Strdup(np->rname); 25820Sstevel@tonic-gate 25830Sstevel@tonic-gate /* cleanup, return success */ 25840Sstevel@tonic-gate if (dname != NULL) 25850Sstevel@tonic-gate Free(dname); 25860Sstevel@tonic-gate Free(rname); 25870Sstevel@tonic-gate return (np); 25880Sstevel@tonic-gate 25890Sstevel@tonic-gate /* cleanup, return error */ 25900Sstevel@tonic-gate out: 25910Sstevel@tonic-gate if (dname != NULL) 25920Sstevel@tonic-gate Free(dname); 25930Sstevel@tonic-gate if (rname != NULL) 25940Sstevel@tonic-gate Free(rname); 25950Sstevel@tonic-gate 25960Sstevel@tonic-gate metafreedrivename(dnp); 25970Sstevel@tonic-gate Free(dnp); 25980Sstevel@tonic-gate Free(*tail); 25990Sstevel@tonic-gate *tail = NULL; 26000Sstevel@tonic-gate return (NULL); 26010Sstevel@tonic-gate } 26020Sstevel@tonic-gate 26030Sstevel@tonic-gate mdname_t * 26040Sstevel@tonic-gate metaname( 26050Sstevel@tonic-gate mdsetname_t **spp, 26060Sstevel@tonic-gate char *uname, 2607*1623Stw21770 meta_device_type_t uname_type, 26080Sstevel@tonic-gate md_error_t *ep 26090Sstevel@tonic-gate ) 26100Sstevel@tonic-gate { 2611*1623Stw21770 return (metaname_common(spp, uname, 0, uname_type, ep)); 26120Sstevel@tonic-gate } 26130Sstevel@tonic-gate 26140Sstevel@tonic-gate mdname_t * 26150Sstevel@tonic-gate metaname_fast( 26160Sstevel@tonic-gate mdsetname_t **spp, 26170Sstevel@tonic-gate char *uname, 2618*1623Stw21770 meta_device_type_t uname_type, 26190Sstevel@tonic-gate md_error_t *ep 26200Sstevel@tonic-gate ) 26210Sstevel@tonic-gate { 2622*1623Stw21770 return (metaname_common(spp, uname, 1, uname_type, ep)); 26230Sstevel@tonic-gate } 26240Sstevel@tonic-gate 26250Sstevel@tonic-gate /* 26260Sstevel@tonic-gate * set up names for a drive 26270Sstevel@tonic-gate */ 26280Sstevel@tonic-gate mddrivename_t * 26290Sstevel@tonic-gate metadrivename( 2630*1623Stw21770 mdsetname_t **spp, 2631*1623Stw21770 char *uname, 2632*1623Stw21770 md_error_t *ep 26330Sstevel@tonic-gate ) 26340Sstevel@tonic-gate { 26350Sstevel@tonic-gate char *slicename; 26360Sstevel@tonic-gate mdname_t *np; 26370Sstevel@tonic-gate 26380Sstevel@tonic-gate mddrivenamelist_t **tail; 26390Sstevel@tonic-gate mddrivename_t *dnp; 26400Sstevel@tonic-gate char *dname; 26410Sstevel@tonic-gate int i; 26420Sstevel@tonic-gate int mplen; 26430Sstevel@tonic-gate size_t len; 26440Sstevel@tonic-gate 26450Sstevel@tonic-gate assert(uname != NULL); 2646*1623Stw21770 2647*1623Stw21770 if ((dname = metadiskname(uname)) == NULL) { 26480Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 26490Sstevel@tonic-gate return (NULL); 26500Sstevel@tonic-gate } 26510Sstevel@tonic-gate 26520Sstevel@tonic-gate /* look in cache first */ 26530Sstevel@tonic-gate for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 26540Sstevel@tonic-gate dnp = (*tail)->drivenamep; 26550Sstevel@tonic-gate if ((dnp->cname != NULL && 26560Sstevel@tonic-gate (strcmp(dnp->cname, dname) == 0)) || 26570Sstevel@tonic-gate (dnp->rname != NULL && 26580Sstevel@tonic-gate (strcmp(dnp->rname, dname) == 0))) { 26590Sstevel@tonic-gate Free(dname); 26600Sstevel@tonic-gate return (dnp); 26610Sstevel@tonic-gate } 26620Sstevel@tonic-gate } 2663*1623Stw21770 Free(dname); 26640Sstevel@tonic-gate 26650Sstevel@tonic-gate /* Check each possible slice name based on MD_MAX_PARTS. */ 26660Sstevel@tonic-gate 26670Sstevel@tonic-gate /* 26680Sstevel@tonic-gate * Figure out how much string space to reserve to fit 26690Sstevel@tonic-gate * (MD_MAX_PARTS - 1) into the name string; the loop will 26700Sstevel@tonic-gate * increment the mplen counter once for each decimal digit in 26710Sstevel@tonic-gate * (MD_MAX_PARTS - 1). 26720Sstevel@tonic-gate */ 26730Sstevel@tonic-gate for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen); 26740Sstevel@tonic-gate len = strlen(uname) + mplen + 2; 26750Sstevel@tonic-gate slicename = Malloc(len); 26760Sstevel@tonic-gate 26770Sstevel@tonic-gate /* Check for each slice in turn until we find one */ 26780Sstevel@tonic-gate for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) { 26790Sstevel@tonic-gate (void) snprintf(slicename, len, "%ss%d", uname, i); 2680*1623Stw21770 np = metaname(spp, slicename, LOGICAL_DEVICE, ep); 26810Sstevel@tonic-gate } 26820Sstevel@tonic-gate Free(slicename); 26830Sstevel@tonic-gate 26840Sstevel@tonic-gate if (np == NULL) { 2685*1623Stw21770 if ((mdiserror(ep, MDE_UNIT_NOT_FOUND)) && 26860Sstevel@tonic-gate ((dname = metadiskname(uname)) != NULL)) { 26870Sstevel@tonic-gate Free(dname); 26880Sstevel@tonic-gate (void) mderror(ep, MDE_NOT_DRIVENAME, uname); 26890Sstevel@tonic-gate } 26900Sstevel@tonic-gate return (NULL); 26910Sstevel@tonic-gate } 26920Sstevel@tonic-gate return (np->drivenamep); 26930Sstevel@tonic-gate } 26940Sstevel@tonic-gate 26950Sstevel@tonic-gate /* 2696*1623Stw21770 * FUNCTION: metaslicename_type() 2697*1623Stw21770 * INPUT: dnp - the drivename structure 2698*1623Stw21770 * sliceno - the slice on the drive to return 2699*1623Stw21770 * type - LOGICAL_DEVICE or META_DEVICE 2700*1623Stw21770 * OUTPUT: ep - return error pointer 2701*1623Stw21770 * RETURNS: mdname_t- pointer the the slice name structure 2702*1623Stw21770 * PURPOSE: interface to the parts struct in the drive name struct 2703*1623Stw21770 * Since there is no guarantee that the slice name 2704*1623Stw21770 * structures are populated users should call this 2705*1623Stw21770 * function rather than accessing the structure directly 2706*1623Stw21770 * since it will populate the structure values if they 2707*1623Stw21770 * haven't already been populated before returning. 2708*1623Stw21770 */ 2709*1623Stw21770 mdname_t * 2710*1623Stw21770 metaslicename_type( 2711*1623Stw21770 mddrivename_t *dnp, 2712*1623Stw21770 uint_t sliceno, 2713*1623Stw21770 meta_device_type_t uname_type, 2714*1623Stw21770 md_error_t *ep 2715*1623Stw21770 ) 2716*1623Stw21770 { 2717*1623Stw21770 mdsetname_t *sp = NULL; 2718*1623Stw21770 char *namep = NULL; 2719*1623Stw21770 mdname_t *np; 2720*1623Stw21770 2721*1623Stw21770 assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 2722*1623Stw21770 2723*1623Stw21770 if (sliceno >= dnp->parts.parts_len) { 2724*1623Stw21770 (void) mderror(ep, MDE_NOSLICE, dnp->cname); 2725*1623Stw21770 return (NULL); 2726*1623Stw21770 } 2727*1623Stw21770 2728*1623Stw21770 np = &dnp->parts.parts_val[sliceno]; 2729*1623Stw21770 2730*1623Stw21770 /* check to see if the struct is already populated */ 2731*1623Stw21770 if (np->cname) { 2732*1623Stw21770 return (np); 2733*1623Stw21770 } 2734*1623Stw21770 2735*1623Stw21770 if ((namep = meta_name_getname(&sp, dnp->cname, 2736*1623Stw21770 uname_type, ep)) == NULL) 2737*1623Stw21770 return (NULL); 2738*1623Stw21770 2739*1623Stw21770 np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname, 2740*1623Stw21770 sliceno, ep); 2741*1623Stw21770 2742*1623Stw21770 Free(namep); 2743*1623Stw21770 2744*1623Stw21770 return (np); 2745*1623Stw21770 } 2746*1623Stw21770 2747*1623Stw21770 /* 27480Sstevel@tonic-gate * FUNCTION: metaslicename() 27490Sstevel@tonic-gate * INPUT: dnp - the drivename structure 27500Sstevel@tonic-gate * sliceno - the slice on the drive to return 27510Sstevel@tonic-gate * OUTPUT: ep - return error pointer 27520Sstevel@tonic-gate * RETURNS: mdname_t- pointer the the slice name structure 27530Sstevel@tonic-gate * PURPOSE: interface to the parts struct in the drive name struct 27540Sstevel@tonic-gate * Since there is no guarantee that the slice name 27550Sstevel@tonic-gate * structures are populated users should call this 27560Sstevel@tonic-gate * function rather than accessing the structure directly 27570Sstevel@tonic-gate * since it will populate the structure values if they 27580Sstevel@tonic-gate * haven't already been populated before returning. 27590Sstevel@tonic-gate */ 27600Sstevel@tonic-gate mdname_t * 27610Sstevel@tonic-gate metaslicename( 27620Sstevel@tonic-gate mddrivename_t *dnp, 27630Sstevel@tonic-gate uint_t sliceno, 27640Sstevel@tonic-gate md_error_t *ep 27650Sstevel@tonic-gate ) 27660Sstevel@tonic-gate { 2767*1623Stw21770 return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep)); 27680Sstevel@tonic-gate } 27690Sstevel@tonic-gate 27700Sstevel@tonic-gate /* 27710Sstevel@tonic-gate * set up metadevice name from id 27720Sstevel@tonic-gate */ 27730Sstevel@tonic-gate mdname_t * 27740Sstevel@tonic-gate metamnumname( 27750Sstevel@tonic-gate mdsetname_t **spp, 27760Sstevel@tonic-gate minor_t mnum, 27770Sstevel@tonic-gate int fast, 27780Sstevel@tonic-gate md_error_t *ep 27790Sstevel@tonic-gate ) 27800Sstevel@tonic-gate { 27810Sstevel@tonic-gate set_t setno = MD_MIN2SET(mnum); 27820Sstevel@tonic-gate mdsetname_t *sp = NULL; 27830Sstevel@tonic-gate char *uname; 27840Sstevel@tonic-gate mdname_t *np; 2785*1623Stw21770 md_dev64_t dev; 2786*1623Stw21770 mdkey_t key; 27870Sstevel@tonic-gate 27880Sstevel@tonic-gate /* check set first */ 27890Sstevel@tonic-gate if (spp == NULL) 27900Sstevel@tonic-gate spp = &sp; 27910Sstevel@tonic-gate if (chksetno(spp, setno, ep) != 0) 27920Sstevel@tonic-gate return (NULL); 27930Sstevel@tonic-gate assert(*spp != NULL); 27940Sstevel@tonic-gate sp = *spp; 27950Sstevel@tonic-gate 2796*1623Stw21770 /* get corresponding device name */ 2797*1623Stw21770 dev = metamakedev(mnum); 2798*1623Stw21770 if ((uname = meta_getnmentbydev(sp->setno, MD_SIDEWILD, dev, 2799*1623Stw21770 NULL, NULL, &key, ep)) == NULL) 2800*1623Stw21770 return (NULL); 28010Sstevel@tonic-gate 28020Sstevel@tonic-gate /* setup name */ 28030Sstevel@tonic-gate if (fast) { 2804*1623Stw21770 np = metaname_fast(spp, uname, META_DEVICE, ep); 2805*1623Stw21770 if (np) { 2806*1623Stw21770 np->dev = dev; 2807*1623Stw21770 np->key = key; 2808*1623Stw21770 } 28090Sstevel@tonic-gate } else 2810*1623Stw21770 np = metaname(spp, uname, META_DEVICE, ep); 28110Sstevel@tonic-gate 28120Sstevel@tonic-gate Free(uname); 28130Sstevel@tonic-gate return (np); 28140Sstevel@tonic-gate } 28150Sstevel@tonic-gate 28160Sstevel@tonic-gate /* 28170Sstevel@tonic-gate * return metadevice name 28180Sstevel@tonic-gate */ 28190Sstevel@tonic-gate char * 28200Sstevel@tonic-gate get_mdname( 2821*1623Stw21770 mdsetname_t *sp, 28220Sstevel@tonic-gate minor_t mnum 28230Sstevel@tonic-gate ) 28240Sstevel@tonic-gate { 28250Sstevel@tonic-gate mdname_t *np; 28260Sstevel@tonic-gate md_error_t status = mdnullerror; 2827*1623Stw21770 mdsetname_t **spp = NULL; 2828*1623Stw21770 2829*1623Stw21770 if (sp != NULL) 2830*1623Stw21770 spp = &sp; 28310Sstevel@tonic-gate 28320Sstevel@tonic-gate /* get name */ 2833*1623Stw21770 if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) { 28340Sstevel@tonic-gate return (NULL); 28350Sstevel@tonic-gate } 28360Sstevel@tonic-gate assert(meta_getminor(np->dev) == mnum); 28370Sstevel@tonic-gate 28380Sstevel@tonic-gate /* return name */ 28390Sstevel@tonic-gate return (np->cname); 28400Sstevel@tonic-gate } 28410Sstevel@tonic-gate 28420Sstevel@tonic-gate /* 28430Sstevel@tonic-gate * check for device type 28440Sstevel@tonic-gate */ 28450Sstevel@tonic-gate int 28460Sstevel@tonic-gate metaismeta( 28470Sstevel@tonic-gate mdname_t *np 28480Sstevel@tonic-gate ) 28490Sstevel@tonic-gate { 28500Sstevel@tonic-gate return (np->drivenamep->type == MDT_META || 28510Sstevel@tonic-gate np->drivenamep->type == MDT_FAST_META); 28520Sstevel@tonic-gate } 28530Sstevel@tonic-gate 28540Sstevel@tonic-gate int 28550Sstevel@tonic-gate metachkmeta( 28560Sstevel@tonic-gate mdname_t *np, 28570Sstevel@tonic-gate md_error_t *ep 28580Sstevel@tonic-gate ) 28590Sstevel@tonic-gate { 28600Sstevel@tonic-gate if (! metaismeta(np)) { 28610Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_META, np->dev, 28620Sstevel@tonic-gate np->cname)); 28630Sstevel@tonic-gate } 28640Sstevel@tonic-gate return (0); 28650Sstevel@tonic-gate } 28660Sstevel@tonic-gate 28670Sstevel@tonic-gate int 28680Sstevel@tonic-gate metachkdisk( 28690Sstevel@tonic-gate mdname_t *np, 28700Sstevel@tonic-gate md_error_t *ep 28710Sstevel@tonic-gate ) 28720Sstevel@tonic-gate { 28730Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep; 28740Sstevel@tonic-gate 28750Sstevel@tonic-gate assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 28760Sstevel@tonic-gate 28770Sstevel@tonic-gate if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) { 28780Sstevel@tonic-gate switch (dnp->type) { 28790Sstevel@tonic-gate case MDT_ACCES: 28800Sstevel@tonic-gate case MDT_UNKNOWN: 28810Sstevel@tonic-gate return (mdsyserror(ep, dnp->errnum, np->bname)); 28820Sstevel@tonic-gate default: 28830Sstevel@tonic-gate assert(0); 28840Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, np->dev, 28850Sstevel@tonic-gate np->cname)); 28860Sstevel@tonic-gate } 28870Sstevel@tonic-gate } 28880Sstevel@tonic-gate return (0); 28890Sstevel@tonic-gate } 28900Sstevel@tonic-gate 28910Sstevel@tonic-gate int 28920Sstevel@tonic-gate metachkcomp( 28930Sstevel@tonic-gate mdname_t *np, 28940Sstevel@tonic-gate md_error_t *ep 28950Sstevel@tonic-gate ) 28960Sstevel@tonic-gate { 28970Sstevel@tonic-gate if (metaismeta(np)) { 28980Sstevel@tonic-gate return (mddeverror(ep, MDE_IS_META, np->dev, 28990Sstevel@tonic-gate np->cname)); 29000Sstevel@tonic-gate } 29010Sstevel@tonic-gate return (metachkdisk(np, ep)); 29020Sstevel@tonic-gate } 29030Sstevel@tonic-gate 29040Sstevel@tonic-gate /* 29050Sstevel@tonic-gate * free list of names 29060Sstevel@tonic-gate */ 29070Sstevel@tonic-gate void 29080Sstevel@tonic-gate metafreenamelist( 29090Sstevel@tonic-gate mdnamelist_t *nlp 29100Sstevel@tonic-gate ) 29110Sstevel@tonic-gate { 29120Sstevel@tonic-gate mdnamelist_t *next = NULL; 29130Sstevel@tonic-gate 29140Sstevel@tonic-gate for (/* void */; (nlp != NULL); nlp = next) { 29150Sstevel@tonic-gate next = nlp->next; 29160Sstevel@tonic-gate Free(nlp); 29170Sstevel@tonic-gate } 29180Sstevel@tonic-gate } 29190Sstevel@tonic-gate 29200Sstevel@tonic-gate /* 29210Sstevel@tonic-gate * build list of names 29220Sstevel@tonic-gate */ 29230Sstevel@tonic-gate int 29240Sstevel@tonic-gate metanamelist( 29250Sstevel@tonic-gate mdsetname_t **spp, 29260Sstevel@tonic-gate mdnamelist_t **nlpp, 29270Sstevel@tonic-gate int argc, 29280Sstevel@tonic-gate char *argv[], 2929*1623Stw21770 meta_device_type_t type, 29300Sstevel@tonic-gate md_error_t *ep 29310Sstevel@tonic-gate ) 29320Sstevel@tonic-gate { 29330Sstevel@tonic-gate mdnamelist_t **tailpp = nlpp; 29340Sstevel@tonic-gate int count = 0; 29350Sstevel@tonic-gate 29360Sstevel@tonic-gate for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 29370Sstevel@tonic-gate mdnamelist_t *nlp = Zalloc(sizeof (*nlp)); 29380Sstevel@tonic-gate 2939*1623Stw21770 if ((nlp->namep = metaname(spp, argv[0], 2940*1623Stw21770 type, ep)) == NULL) { 29410Sstevel@tonic-gate metafreenamelist(*nlpp); 29420Sstevel@tonic-gate *nlpp = NULL; 29430Sstevel@tonic-gate return (-1); 29440Sstevel@tonic-gate } 29450Sstevel@tonic-gate *tailpp = nlp; 29460Sstevel@tonic-gate tailpp = &nlp->next; 29470Sstevel@tonic-gate } 29480Sstevel@tonic-gate return (count); 29490Sstevel@tonic-gate } 29500Sstevel@tonic-gate 29510Sstevel@tonic-gate /* 29520Sstevel@tonic-gate * append to end of name list 29530Sstevel@tonic-gate */ 29540Sstevel@tonic-gate mdname_t * 29550Sstevel@tonic-gate metanamelist_append( 29560Sstevel@tonic-gate mdnamelist_t **nlpp, 29570Sstevel@tonic-gate mdname_t *np 29580Sstevel@tonic-gate ) 29590Sstevel@tonic-gate { 29600Sstevel@tonic-gate mdnamelist_t *nlp; 29610Sstevel@tonic-gate 29620Sstevel@tonic-gate /* run to end of list */ 29630Sstevel@tonic-gate for (; (*nlpp != NULL); nlpp = &(*nlpp)->next) 29640Sstevel@tonic-gate ; 29650Sstevel@tonic-gate 29660Sstevel@tonic-gate /* allocate new list element */ 29670Sstevel@tonic-gate nlp = *nlpp = Zalloc(sizeof (*nlp)); 29680Sstevel@tonic-gate 29690Sstevel@tonic-gate /* append name */ 29700Sstevel@tonic-gate nlp->namep = np; 29710Sstevel@tonic-gate return (np); 29720Sstevel@tonic-gate } 29730Sstevel@tonic-gate 29740Sstevel@tonic-gate /* 29750Sstevel@tonic-gate * FUNCTION: meta_namelist_append_wrapper() 29760Sstevel@tonic-gate * INPUT: tailpp - pointer to the list tail pointer 29770Sstevel@tonic-gate * np - name node to be appended to list 29780Sstevel@tonic-gate * OUTPUT: none 29790Sstevel@tonic-gate * RETURNS: mdnamelist_t * - new tail of the list. 29800Sstevel@tonic-gate * PURPOSE: wrapper to meta_namelist_append for performance. 29810Sstevel@tonic-gate * metanamelist_append finds the tail each time which slows 29820Sstevel@tonic-gate * down long lists. By keeping track of the tail ourselves 29830Sstevel@tonic-gate * we can change metanamelist_append into a constant time 29840Sstevel@tonic-gate * operation. 29850Sstevel@tonic-gate */ 29860Sstevel@tonic-gate mdnamelist_t ** 29870Sstevel@tonic-gate meta_namelist_append_wrapper( 29880Sstevel@tonic-gate mdnamelist_t **tailpp, 29890Sstevel@tonic-gate mdname_t *np 29900Sstevel@tonic-gate ) 29910Sstevel@tonic-gate { 29920Sstevel@tonic-gate (void) metanamelist_append(tailpp, np); 29930Sstevel@tonic-gate 29940Sstevel@tonic-gate /* If it's the first item in the list, return it instead of the next */ 29950Sstevel@tonic-gate if ((*tailpp)->next == NULL) 29960Sstevel@tonic-gate return (tailpp); 29970Sstevel@tonic-gate 29980Sstevel@tonic-gate return (&(*tailpp)->next); 29990Sstevel@tonic-gate } 30000Sstevel@tonic-gate 30010Sstevel@tonic-gate 30020Sstevel@tonic-gate /* 30030Sstevel@tonic-gate * mdhspname_t stuff 30040Sstevel@tonic-gate */ 30050Sstevel@tonic-gate 30060Sstevel@tonic-gate /* 30070Sstevel@tonic-gate * initialize hspname 30080Sstevel@tonic-gate */ 30090Sstevel@tonic-gate static void 30100Sstevel@tonic-gate metainithspname( 30110Sstevel@tonic-gate mdhspname_t *hspnamep 30120Sstevel@tonic-gate ) 30130Sstevel@tonic-gate { 30140Sstevel@tonic-gate (void) memset(hspnamep, '\0', sizeof (*hspnamep)); 30150Sstevel@tonic-gate hspnamep->hsp = MD_HSP_NONE; 30160Sstevel@tonic-gate } 30170Sstevel@tonic-gate 30180Sstevel@tonic-gate /* 30190Sstevel@tonic-gate * free allocated hspname 30200Sstevel@tonic-gate */ 30210Sstevel@tonic-gate static void 30220Sstevel@tonic-gate metafreehspname( 30230Sstevel@tonic-gate mdhspname_t *hspnamep 30240Sstevel@tonic-gate ) 30250Sstevel@tonic-gate { 30260Sstevel@tonic-gate if (hspnamep->hspname != NULL) 30270Sstevel@tonic-gate Free(hspnamep->hspname); 30280Sstevel@tonic-gate if (hspnamep->unitp != NULL) 30290Sstevel@tonic-gate meta_invalidate_hsp(hspnamep); 30300Sstevel@tonic-gate metainithspname(hspnamep); 30310Sstevel@tonic-gate } 30320Sstevel@tonic-gate 30330Sstevel@tonic-gate /* 30340Sstevel@tonic-gate * clear the hspname cache 30350Sstevel@tonic-gate */ 30360Sstevel@tonic-gate static void 30370Sstevel@tonic-gate metaflushhspnames() 30380Sstevel@tonic-gate { 30390Sstevel@tonic-gate mdhspnamelist_t *p, *n; 30400Sstevel@tonic-gate 30410Sstevel@tonic-gate for (p = hsplistp, n = NULL; (p != NULL); p = n) { 30420Sstevel@tonic-gate n = p->next; 30430Sstevel@tonic-gate metafreehspname(p->hspnamep); 30440Sstevel@tonic-gate Free(p->hspnamep); 30450Sstevel@tonic-gate Free(p); 30460Sstevel@tonic-gate } 30470Sstevel@tonic-gate hsplistp = NULL; 30480Sstevel@tonic-gate } 30490Sstevel@tonic-gate 30500Sstevel@tonic-gate /* 30510Sstevel@tonic-gate * check set and get comparison name 30520Sstevel@tonic-gate */ 30530Sstevel@tonic-gate static char * 30540Sstevel@tonic-gate gethspname( 30550Sstevel@tonic-gate mdsetname_t **spp, 30560Sstevel@tonic-gate char *uname, 30570Sstevel@tonic-gate md_error_t *ep 30580Sstevel@tonic-gate ) 30590Sstevel@tonic-gate { 3060*1623Stw21770 char *cname = NULL; 3061*1623Stw21770 3062*1623Stw21770 cname = meta_canonicalize(*spp, uname); 3063*1623Stw21770 /* if it is not a meta/hsp name then flag an error */ 3064*1623Stw21770 if (cname == NULL) { 3065*1623Stw21770 (void) mdsyserror(ep, ENOENT, uname); 3066*1623Stw21770 return (NULL); 3067*1623Stw21770 } 3068*1623Stw21770 return (cname); 3069*1623Stw21770 } 3070*1623Stw21770 3071*1623Stw21770 /* 3072*1623Stw21770 * set up a hotspare pool name structure using both the name 3073*1623Stw21770 * and the self id 3074*1623Stw21770 */ 3075*1623Stw21770 static mdhspname_t * 3076*1623Stw21770 metahspname_hsp( 3077*1623Stw21770 mdsetname_t **spp, 3078*1623Stw21770 char *uname, 3079*1623Stw21770 hsp_t hsp, 3080*1623Stw21770 md_error_t *ep 3081*1623Stw21770 ) 3082*1623Stw21770 { 3083*1623Stw21770 char *cname; 3084*1623Stw21770 mdhspnamelist_t **tail; 3085*1623Stw21770 mdhspname_t *hspnp; 30860Sstevel@tonic-gate 30870Sstevel@tonic-gate /* check setname */ 30880Sstevel@tonic-gate assert(uname != NULL); 3089*1623Stw21770 if ((cname = gethspname(spp, uname, ep)) == NULL) 30900Sstevel@tonic-gate return (NULL); 3091*1623Stw21770 assert(*spp != NULL); 3092*1623Stw21770 3093*1623Stw21770 /* look in cache first */ 3094*1623Stw21770 for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) { 3095*1623Stw21770 hspnp = (*tail)->hspnamep; 3096*1623Stw21770 if (strcmp(hspnp->hspname, cname) == 0) { 3097*1623Stw21770 Free(cname); 3098*1623Stw21770 /* if the hsp value has not been set then set it now */ 3099*1623Stw21770 if (hspnp->hsp == MD_HSP_NONE) 3100*1623Stw21770 hspnp->hsp = hsp; 3101*1623Stw21770 return (hspnp); 3102*1623Stw21770 } 31030Sstevel@tonic-gate } 3104*1623Stw21770 3105*1623Stw21770 /* if the hsp number isn't specified then attempt to get it */ 3106*1623Stw21770 if (hsp == MD_HSP_NONE && (hsp = meta_gethspnmentbyname((*spp)->setno, 3107*1623Stw21770 MD_SIDEWILD, cname, ep)) == MD_HSP_NONE) { 3108*1623Stw21770 if (! mdisok(ep)) { 3109*1623Stw21770 /* 3110*1623Stw21770 * If the error is ENOENT, then we will continue on, 3111*1623Stw21770 * because the device does not yet exist. 3112*1623Stw21770 * For other types of errors, however, we'll bail out. 3113*1623Stw21770 */ 3114*1623Stw21770 if (! mdissyserror(ep, ENOENT)) { 3115*1623Stw21770 Free(cname); 3116*1623Stw21770 return (NULL); 3117*1623Stw21770 } 3118*1623Stw21770 mdclrerror(ep); 3119*1623Stw21770 } 31200Sstevel@tonic-gate } 3121*1623Stw21770 3122*1623Stw21770 /* allocate new list element and hspname */ 3123*1623Stw21770 *tail = Zalloc(sizeof (**tail)); 3124*1623Stw21770 hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp)); 3125*1623Stw21770 metainithspname(hspnp); 3126*1623Stw21770 3127*1623Stw21770 /* save hspname and number */ 3128*1623Stw21770 hspnp->hspname = cname; 3129*1623Stw21770 hspnp->hsp = hsp; 3130*1623Stw21770 3131*1623Stw21770 /* success */ 3132*1623Stw21770 return (hspnp); 31330Sstevel@tonic-gate } 31340Sstevel@tonic-gate 31350Sstevel@tonic-gate /* 31360Sstevel@tonic-gate * set up names for a hotspare pool 31370Sstevel@tonic-gate */ 31380Sstevel@tonic-gate mdhspname_t * 31390Sstevel@tonic-gate metahspname( 31400Sstevel@tonic-gate mdsetname_t **spp, 31410Sstevel@tonic-gate char *uname, 31420Sstevel@tonic-gate md_error_t *ep 31430Sstevel@tonic-gate ) 31440Sstevel@tonic-gate { 3145*1623Stw21770 return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep)); 31460Sstevel@tonic-gate } 31470Sstevel@tonic-gate 31480Sstevel@tonic-gate /* 3149*1623Stw21770 * set up hotspare pool name from key 31500Sstevel@tonic-gate */ 31510Sstevel@tonic-gate mdhspname_t * 31520Sstevel@tonic-gate metahsphspname( 31530Sstevel@tonic-gate mdsetname_t **spp, 31540Sstevel@tonic-gate hsp_t hsp, 31550Sstevel@tonic-gate md_error_t *ep 31560Sstevel@tonic-gate ) 31570Sstevel@tonic-gate { 31580Sstevel@tonic-gate set_t setno = HSP_SET(hsp); 31590Sstevel@tonic-gate mdsetname_t *sp = NULL; 31600Sstevel@tonic-gate char *uname; 31610Sstevel@tonic-gate mdhspname_t *hspnp; 31620Sstevel@tonic-gate 31630Sstevel@tonic-gate /* check set first */ 31640Sstevel@tonic-gate if (spp == NULL) 31650Sstevel@tonic-gate spp = &sp; 31660Sstevel@tonic-gate if (chksetno(spp, setno, ep) != 0) 31670Sstevel@tonic-gate return (NULL); 31680Sstevel@tonic-gate assert(*spp != NULL); 31690Sstevel@tonic-gate sp = *spp; 31700Sstevel@tonic-gate 3171*1623Stw21770 /* get corresponding hotspare pool name */ 3172*1623Stw21770 if ((uname = meta_gethspnmentbyid(sp->setno, 3173*1623Stw21770 MD_SIDEWILD, hsp, ep)) == NULL) 3174*1623Stw21770 return (NULL); 31750Sstevel@tonic-gate 31760Sstevel@tonic-gate /* setup name */ 3177*1623Stw21770 hspnp = metahspname_hsp(spp, uname, hsp, ep); 31780Sstevel@tonic-gate Free(uname); 31790Sstevel@tonic-gate return (hspnp); 31800Sstevel@tonic-gate } 31810Sstevel@tonic-gate 31820Sstevel@tonic-gate /* 31830Sstevel@tonic-gate * return hotspare pool name 31840Sstevel@tonic-gate */ 31850Sstevel@tonic-gate char * 3186*1623Stw21770 get_hspname(mdsetname_t *sp, hsp_t hsp) 31870Sstevel@tonic-gate { 31880Sstevel@tonic-gate mdhspname_t *hspnp; 31890Sstevel@tonic-gate md_error_t status = mdnullerror; 3190*1623Stw21770 mdsetname_t **spp = NULL; 3191*1623Stw21770 3192*1623Stw21770 if (sp != NULL) 3193*1623Stw21770 spp = &sp; 31940Sstevel@tonic-gate 31950Sstevel@tonic-gate /* get name */ 3196*1623Stw21770 if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) { 31970Sstevel@tonic-gate mdclrerror(&status); 31980Sstevel@tonic-gate return (NULL); 31990Sstevel@tonic-gate } 32000Sstevel@tonic-gate 32010Sstevel@tonic-gate /* return name */ 32020Sstevel@tonic-gate return (hspnp->hspname); 32030Sstevel@tonic-gate } 32040Sstevel@tonic-gate 32050Sstevel@tonic-gate /* 32060Sstevel@tonic-gate * free hotspare pool list 32070Sstevel@tonic-gate */ 32080Sstevel@tonic-gate void 32090Sstevel@tonic-gate metafreehspnamelist(mdhspnamelist_t *hspnlp) 32100Sstevel@tonic-gate { 32110Sstevel@tonic-gate mdhspnamelist_t *next = NULL; 32120Sstevel@tonic-gate 32130Sstevel@tonic-gate for (/* void */; (hspnlp != NULL); hspnlp = next) { 32140Sstevel@tonic-gate next = hspnlp->next; 32150Sstevel@tonic-gate Free(hspnlp); 32160Sstevel@tonic-gate } 32170Sstevel@tonic-gate } 32180Sstevel@tonic-gate 32190Sstevel@tonic-gate /* 32200Sstevel@tonic-gate * build list of hotspare pool names 32210Sstevel@tonic-gate */ 32220Sstevel@tonic-gate int 32230Sstevel@tonic-gate metahspnamelist( 32240Sstevel@tonic-gate mdsetname_t **spp, 32250Sstevel@tonic-gate mdhspnamelist_t **hspnlpp, 32260Sstevel@tonic-gate int argc, 32270Sstevel@tonic-gate char *argv[], 32280Sstevel@tonic-gate md_error_t *ep 32290Sstevel@tonic-gate ) 32300Sstevel@tonic-gate { 32310Sstevel@tonic-gate mdhspnamelist_t **tailpp = hspnlpp; 32320Sstevel@tonic-gate int count = 0; 32330Sstevel@tonic-gate 32340Sstevel@tonic-gate for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 32350Sstevel@tonic-gate mdhspnamelist_t *hspnlp = Zalloc(sizeof (*hspnlp)); 32360Sstevel@tonic-gate 32370Sstevel@tonic-gate if ((hspnlp->hspnamep = metahspname(spp, argv[0], 32380Sstevel@tonic-gate ep)) == NULL) { 32390Sstevel@tonic-gate metafreehspnamelist(*hspnlpp); 32400Sstevel@tonic-gate *hspnlpp = NULL; 32410Sstevel@tonic-gate return (-1); 32420Sstevel@tonic-gate } 32430Sstevel@tonic-gate *tailpp = hspnlp; 32440Sstevel@tonic-gate tailpp = &hspnlp->next; 32450Sstevel@tonic-gate } 32460Sstevel@tonic-gate return (count); 32470Sstevel@tonic-gate } 32480Sstevel@tonic-gate 32490Sstevel@tonic-gate /* 32500Sstevel@tonic-gate * append to end of hotspare pool list 32510Sstevel@tonic-gate */ 32520Sstevel@tonic-gate mdhspname_t * 32530Sstevel@tonic-gate metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp) 32540Sstevel@tonic-gate { 32550Sstevel@tonic-gate mdhspnamelist_t *hspnlp; 32560Sstevel@tonic-gate 32570Sstevel@tonic-gate /* run to end of list */ 32580Sstevel@tonic-gate for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next) 32590Sstevel@tonic-gate ; 32600Sstevel@tonic-gate 32610Sstevel@tonic-gate /* allocate new list element */ 32620Sstevel@tonic-gate hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp)); 32630Sstevel@tonic-gate 32640Sstevel@tonic-gate /* append hotspare pool name */ 32650Sstevel@tonic-gate hspnlp->hspnamep = hspnp; 32660Sstevel@tonic-gate return (hspnp); 32670Sstevel@tonic-gate } 32680Sstevel@tonic-gate 32690Sstevel@tonic-gate /* 32700Sstevel@tonic-gate * get name from dev 32710Sstevel@tonic-gate */ 32720Sstevel@tonic-gate mdname_t * 32730Sstevel@tonic-gate metadevname( 32740Sstevel@tonic-gate mdsetname_t **spp, 32750Sstevel@tonic-gate md_dev64_t dev, 32760Sstevel@tonic-gate md_error_t *ep) 32770Sstevel@tonic-gate { 32780Sstevel@tonic-gate char *device_name; 32790Sstevel@tonic-gate mdname_t *namep; 32800Sstevel@tonic-gate mdkey_t key; 32810Sstevel@tonic-gate 32820Sstevel@tonic-gate /* short circuit metadevices */ 32830Sstevel@tonic-gate assert(dev != NODEV64); 32840Sstevel@tonic-gate if (meta_dev_ismeta(dev)) 32850Sstevel@tonic-gate return (metamnumname(spp, meta_getminor(dev), 0, ep)); 32860Sstevel@tonic-gate 32870Sstevel@tonic-gate /* create local set, if necessary */ 32880Sstevel@tonic-gate if (*spp == NULL) { 32890Sstevel@tonic-gate if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 32900Sstevel@tonic-gate return (NULL); 32910Sstevel@tonic-gate } 32920Sstevel@tonic-gate 32930Sstevel@tonic-gate /* get name from namespace */ 32940Sstevel@tonic-gate if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD, 32950Sstevel@tonic-gate dev, NULL, NULL, &key, ep)) == NULL) { 32960Sstevel@tonic-gate return (NULL); 32970Sstevel@tonic-gate } 3298*1623Stw21770 namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep); 32990Sstevel@tonic-gate if (namep != NULL) 33000Sstevel@tonic-gate namep->key = key; 33010Sstevel@tonic-gate 33020Sstevel@tonic-gate Free(device_name); 33030Sstevel@tonic-gate return (namep); 33040Sstevel@tonic-gate } 33050Sstevel@tonic-gate 33060Sstevel@tonic-gate /* 33070Sstevel@tonic-gate * return cached name from md_dev64_t 33080Sstevel@tonic-gate */ 33090Sstevel@tonic-gate static char * 33100Sstevel@tonic-gate metadevtocachename(md_dev64_t dev) 33110Sstevel@tonic-gate { 33120Sstevel@tonic-gate mddrivenamelist_t *dnlp; 33130Sstevel@tonic-gate 33140Sstevel@tonic-gate /* look in cache */ 33150Sstevel@tonic-gate for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) { 33160Sstevel@tonic-gate mddrivename_t *dnp = dnlp->drivenamep; 33170Sstevel@tonic-gate uint_t i; 33180Sstevel@tonic-gate 33190Sstevel@tonic-gate for (i = 0; (i < dnp->parts.parts_len); ++i) { 33200Sstevel@tonic-gate mdname_t *np = &dnp->parts.parts_val[i]; 33210Sstevel@tonic-gate 33220Sstevel@tonic-gate if (np->dev == dev) 33230Sstevel@tonic-gate return (np->cname); 33240Sstevel@tonic-gate } 33250Sstevel@tonic-gate } 33260Sstevel@tonic-gate 33270Sstevel@tonic-gate /* not found */ 33280Sstevel@tonic-gate return (NULL); 33290Sstevel@tonic-gate } 33300Sstevel@tonic-gate 33310Sstevel@tonic-gate /* 33320Sstevel@tonic-gate * Ask the driver for the name, which has been stored in the 33330Sstevel@tonic-gate * metadevice state database (on behalf of the utilities). 33340Sstevel@tonic-gate * (by devno) 33350Sstevel@tonic-gate */ 33360Sstevel@tonic-gate char * 33370Sstevel@tonic-gate get_devname( 33380Sstevel@tonic-gate set_t setno, 33390Sstevel@tonic-gate md_dev64_t dev) 33400Sstevel@tonic-gate { 33410Sstevel@tonic-gate mdsetname_t *sp; 33420Sstevel@tonic-gate mdname_t *np; 33430Sstevel@tonic-gate md_error_t status = mdnullerror; 33440Sstevel@tonic-gate 33450Sstevel@tonic-gate /* get name */ 33460Sstevel@tonic-gate if ((setno == MD_SET_BAD) || 33470Sstevel@tonic-gate ((sp = metasetnosetname(setno, &status)) == NULL) || 33480Sstevel@tonic-gate ((np = metadevname(&sp, dev, &status)) == NULL)) { 33490Sstevel@tonic-gate mdclrerror(&status); 33500Sstevel@tonic-gate return (metadevtocachename(dev)); 33510Sstevel@tonic-gate } 33520Sstevel@tonic-gate 33530Sstevel@tonic-gate /* return name */ 33540Sstevel@tonic-gate return (np->cname); 33550Sstevel@tonic-gate } 33560Sstevel@tonic-gate 33570Sstevel@tonic-gate /* 33580Sstevel@tonic-gate * get name from key 33590Sstevel@tonic-gate */ 33600Sstevel@tonic-gate mdname_t * 33610Sstevel@tonic-gate metakeyname( 33620Sstevel@tonic-gate mdsetname_t **spp, 33630Sstevel@tonic-gate mdkey_t key, 33640Sstevel@tonic-gate int fast, 33650Sstevel@tonic-gate md_error_t *ep 33660Sstevel@tonic-gate ) 33670Sstevel@tonic-gate { 33680Sstevel@tonic-gate char *device_name; 33690Sstevel@tonic-gate md_dev64_t dev = NODEV64; 33700Sstevel@tonic-gate mdname_t *namep; 33710Sstevel@tonic-gate 33720Sstevel@tonic-gate /* create local set, if necessary */ 33730Sstevel@tonic-gate if (*spp == NULL) { 33740Sstevel@tonic-gate if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 33750Sstevel@tonic-gate return (NULL); 33760Sstevel@tonic-gate } 33770Sstevel@tonic-gate 33780Sstevel@tonic-gate /* get name from namespace */ 33790Sstevel@tonic-gate if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD, 33800Sstevel@tonic-gate key, NULL, NULL, &dev, ep)) == NULL) { 33810Sstevel@tonic-gate return (NULL); 33820Sstevel@tonic-gate } 33830Sstevel@tonic-gate if (fast) 3384*1623Stw21770 namep = metaname_fast(spp, device_name, UNKNOWN, ep); 33850Sstevel@tonic-gate else 3386*1623Stw21770 namep = metaname(spp, device_name, UNKNOWN, ep); 33870Sstevel@tonic-gate 33880Sstevel@tonic-gate assert(dev != NODEV64); 33890Sstevel@tonic-gate if (namep) 33900Sstevel@tonic-gate namep->dev = dev; 33910Sstevel@tonic-gate Free(device_name); 33920Sstevel@tonic-gate return (namep); 33930Sstevel@tonic-gate } 33940Sstevel@tonic-gate 33950Sstevel@tonic-gate /* 3396*1623Stw21770 * completely flush metadev/hsp caches 3397*1623Stw21770 */ 3398*1623Stw21770 void 3399*1623Stw21770 metaflushmetanames() 3400*1623Stw21770 { 3401*1623Stw21770 metaflushhspnames(); 3402*1623Stw21770 metaflushdrivenames(); 3403*1623Stw21770 metaflushfastnames(); 3404*1623Stw21770 metaflushstatcache(); 3405*1623Stw21770 } 3406*1623Stw21770 3407*1623Stw21770 /* 34080Sstevel@tonic-gate * completely flush the caches 34090Sstevel@tonic-gate */ 34100Sstevel@tonic-gate void 34110Sstevel@tonic-gate metaflushnames(int flush_sr_cache) 34120Sstevel@tonic-gate { 34130Sstevel@tonic-gate metaflushhspnames(); 34140Sstevel@tonic-gate metaflushdrivenames(); 34150Sstevel@tonic-gate metaflushsetnames(); 34160Sstevel@tonic-gate metaflushctlrcache(); 34170Sstevel@tonic-gate metaflushfastnames(); 34180Sstevel@tonic-gate metaflushstatcache(); 34190Sstevel@tonic-gate if (flush_sr_cache) 34200Sstevel@tonic-gate sr_cache_flush(0); 34210Sstevel@tonic-gate } 34220Sstevel@tonic-gate 34230Sstevel@tonic-gate /* 34240Sstevel@tonic-gate * meta_get_hotspare_names 34250Sstevel@tonic-gate * returns an mdnamelist_t of hot spare names 34260Sstevel@tonic-gate */ 34270Sstevel@tonic-gate 34280Sstevel@tonic-gate int 34290Sstevel@tonic-gate meta_get_hotspare_names( 34300Sstevel@tonic-gate mdsetname_t *sp, 34310Sstevel@tonic-gate mdnamelist_t **nlpp, 34320Sstevel@tonic-gate int options, 34330Sstevel@tonic-gate md_error_t *ep 34340Sstevel@tonic-gate ) 34350Sstevel@tonic-gate { 34360Sstevel@tonic-gate mdhspnamelist_t *hspnlp = NULL; 34370Sstevel@tonic-gate mdhspnamelist_t *hspp; 34380Sstevel@tonic-gate int cnt = 0; 34390Sstevel@tonic-gate 34400Sstevel@tonic-gate assert(nlpp != NULL); 34410Sstevel@tonic-gate 34420Sstevel@tonic-gate /* get hotspare names */ 34430Sstevel@tonic-gate if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) { 34440Sstevel@tonic-gate cnt = -1; 34450Sstevel@tonic-gate goto out; 34460Sstevel@tonic-gate } 34470Sstevel@tonic-gate 34480Sstevel@tonic-gate /* build name list */ 34490Sstevel@tonic-gate for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) { 34500Sstevel@tonic-gate md_hsp_t *hsp; 34510Sstevel@tonic-gate int i; 34520Sstevel@tonic-gate 34530Sstevel@tonic-gate if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) { 34540Sstevel@tonic-gate cnt = -1; 34550Sstevel@tonic-gate goto out; 34560Sstevel@tonic-gate } 34570Sstevel@tonic-gate for (i = 0; (i < hsp->hotspares.hotspares_len); i++) { 34580Sstevel@tonic-gate md_hs_t *hs = &hsp->hotspares.hotspares_val[i]; 34590Sstevel@tonic-gate 34600Sstevel@tonic-gate (void) metanamelist_append(nlpp, hs->hsnamep); 34610Sstevel@tonic-gate ++cnt; 34620Sstevel@tonic-gate } 34630Sstevel@tonic-gate } 34640Sstevel@tonic-gate 34650Sstevel@tonic-gate /* cleanup and return count or error */ 34660Sstevel@tonic-gate out: 34670Sstevel@tonic-gate metafreehspnamelist(hspnlp); 34680Sstevel@tonic-gate if ((cnt == -1) && mdisok(ep)) { 34690Sstevel@tonic-gate /* 34700Sstevel@tonic-gate * At least try to give some sort of meaningful error 34710Sstevel@tonic-gate */ 34720Sstevel@tonic-gate (void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error"); 34730Sstevel@tonic-gate } 34740Sstevel@tonic-gate 34750Sstevel@tonic-gate return (cnt); 34760Sstevel@tonic-gate } 34770Sstevel@tonic-gate /* 34780Sstevel@tonic-gate * meta_create_non_dup_list 34790Sstevel@tonic-gate * INPUT: mdnp mdname_t pointer to add to the list if a new name 34800Sstevel@tonic-gate * ldevidp list of non-duplicate names. 34810Sstevel@tonic-gate * OUTPUT: ldevidp list of non-duplicate names. 34820Sstevel@tonic-gate * meta_create_non_dup_list will take a mdname_t pointer and if the device 34830Sstevel@tonic-gate * is not in the list (ldevidp) will add it to the list. 34840Sstevel@tonic-gate * User needs to free allocated memory. 34850Sstevel@tonic-gate */ 34860Sstevel@tonic-gate void 34870Sstevel@tonic-gate meta_create_non_dup_list( 34880Sstevel@tonic-gate mdname_t *mdnp, 34890Sstevel@tonic-gate mddevid_t **ldevidpp 34900Sstevel@tonic-gate ) 34910Sstevel@tonic-gate { 34920Sstevel@tonic-gate char *lcname; 34930Sstevel@tonic-gate mddevid_t *tmp; 34940Sstevel@tonic-gate mddevid_t *lastdevidp; 34950Sstevel@tonic-gate mddevid_t *lldevidp; 34960Sstevel@tonic-gate char *ctd, *slice; 34970Sstevel@tonic-gate mddevid_t *ldevidp; 34980Sstevel@tonic-gate 34990Sstevel@tonic-gate if (mdnp == NULL) 35000Sstevel@tonic-gate return; 35010Sstevel@tonic-gate 35020Sstevel@tonic-gate ldevidp = *ldevidpp; 35030Sstevel@tonic-gate /* 35040Sstevel@tonic-gate * Grab the name of the device and strip off slice information 35050Sstevel@tonic-gate */ 35060Sstevel@tonic-gate lcname = Strdup(mdnp->cname); 35070Sstevel@tonic-gate if (lcname == NULL) { 35080Sstevel@tonic-gate return; 35090Sstevel@tonic-gate } 35100Sstevel@tonic-gate ctd = strrchr(lcname, '/'); 35110Sstevel@tonic-gate if (ctd != NULL) 35120Sstevel@tonic-gate slice = strrchr(ctd, 's'); 35130Sstevel@tonic-gate else 35140Sstevel@tonic-gate slice = strrchr(lcname, 's'); 35150Sstevel@tonic-gate 35160Sstevel@tonic-gate if (slice != NULL) 35170Sstevel@tonic-gate *slice = '\0'; 35180Sstevel@tonic-gate 35190Sstevel@tonic-gate if (ldevidp == NULL) { 35200Sstevel@tonic-gate /* first item in list */ 35210Sstevel@tonic-gate ldevidp = Zalloc(sizeof (mddevid_t)); 35220Sstevel@tonic-gate ldevidp->ctdname = lcname; 35230Sstevel@tonic-gate ldevidp->key = mdnp->key; 35240Sstevel@tonic-gate *ldevidpp = ldevidp; 35250Sstevel@tonic-gate } else { 35260Sstevel@tonic-gate for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) { 35270Sstevel@tonic-gate if (strcmp(tmp->ctdname, lcname) == 0) { 35280Sstevel@tonic-gate /* already there so just return */ 35290Sstevel@tonic-gate Free(lcname); 35300Sstevel@tonic-gate return; 35310Sstevel@tonic-gate } 35320Sstevel@tonic-gate lastdevidp = tmp; 35330Sstevel@tonic-gate } 35340Sstevel@tonic-gate lldevidp = Zalloc(sizeof (mddevid_t)); 35350Sstevel@tonic-gate lldevidp->ctdname = lcname; 35360Sstevel@tonic-gate lldevidp->key = mdnp->key; 35370Sstevel@tonic-gate lastdevidp->next = lldevidp; 35380Sstevel@tonic-gate } 35390Sstevel@tonic-gate } 3540