1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <meta.h> 30*0Sstevel@tonic-gate #include <metad.h> 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate #include <ctype.h> 33*0Sstevel@tonic-gate #include <string.h> 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate /* 36*0Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that 37*0Sstevel@tonic-gate * TEXT_DOMAIN gets set to something. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 40*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 41*0Sstevel@tonic-gate #endif 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate /* 44*0Sstevel@tonic-gate * Macros to produce a quoted string containing the value of a 45*0Sstevel@tonic-gate * preprocessor macro. For example, if SIZE is defined to be 256, 46*0Sstevel@tonic-gate * VAL2STR(SIZE) is "256". This is used to construct format 47*0Sstevel@tonic-gate * strings for scanf-family functions below. 48*0Sstevel@tonic-gate */ 49*0Sstevel@tonic-gate #define QUOTE(x) #x 50*0Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x) 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate extern char *getfullblkname(); 53*0Sstevel@tonic-gate extern char *getfullrawname(); 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate /* 56*0Sstevel@tonic-gate * caches 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate static mdsetnamelist_t *setlistp = NULL; 59*0Sstevel@tonic-gate static mddrivenamelist_t *drivelistp = NULL; 60*0Sstevel@tonic-gate static mdnamelist_t *fastnmlp = NULL; 61*0Sstevel@tonic-gate static mdhspnamelist_t *hsplistp = NULL; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate /* 64*0Sstevel@tonic-gate * leak proof name conversion 65*0Sstevel@tonic-gate */ 66*0Sstevel@tonic-gate static char * 67*0Sstevel@tonic-gate rawname( 68*0Sstevel@tonic-gate char *uname 69*0Sstevel@tonic-gate ) 70*0Sstevel@tonic-gate { 71*0Sstevel@tonic-gate char *p; 72*0Sstevel@tonic-gate struct stat sbuf1, sbuf2; 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate if ((p = getfullrawname(uname)) == NULL) { 75*0Sstevel@tonic-gate return (NULL); 76*0Sstevel@tonic-gate } else if (*p == '\0') { 77*0Sstevel@tonic-gate Free(p); 78*0Sstevel@tonic-gate return (NULL); 79*0Sstevel@tonic-gate } else { 80*0Sstevel@tonic-gate if (stat(uname, &sbuf1) != 0) { 81*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 82*0Sstevel@tonic-gate "device to mount in /etc/vfstab is " 83*0Sstevel@tonic-gate "invalid for device %s\n"), uname); 84*0Sstevel@tonic-gate exit(1); 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate if (stat(p, &sbuf2) != 0) { 87*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 88*0Sstevel@tonic-gate "device to fsck in /etc/vfstab is " 89*0Sstevel@tonic-gate "invalid for raw device %s\n"), p); 90*0Sstevel@tonic-gate exit(1); 91*0Sstevel@tonic-gate } 92*0Sstevel@tonic-gate if (sbuf1.st_rdev != sbuf2.st_rdev) { 93*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 94*0Sstevel@tonic-gate "/etc/vfstab entries inconsistent on " 95*0Sstevel@tonic-gate "line containing device %s\n"), uname); 96*0Sstevel@tonic-gate exit(1); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate if ((sbuf1.st_mode & S_IFBLK) == 0) { 99*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 100*0Sstevel@tonic-gate "/etc/vfstab device to mount is not a " 101*0Sstevel@tonic-gate "block device for device %s\n"), uname); 102*0Sstevel@tonic-gate exit(1); 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate if ((sbuf2.st_mode & S_IFCHR) == 0) { 105*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 106*0Sstevel@tonic-gate "/etc/vfstab device to fsck is not a " 107*0Sstevel@tonic-gate "raw device for device %s\n"), p); 108*0Sstevel@tonic-gate exit(1); 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate return (p); 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate char * 115*0Sstevel@tonic-gate blkname( 116*0Sstevel@tonic-gate char *uname 117*0Sstevel@tonic-gate ) 118*0Sstevel@tonic-gate { 119*0Sstevel@tonic-gate char *p; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate if ((p = getfullblkname(uname)) == NULL) { 122*0Sstevel@tonic-gate return (NULL); 123*0Sstevel@tonic-gate } else if (*p == '\0') { 124*0Sstevel@tonic-gate Free(p); 125*0Sstevel@tonic-gate return (NULL); 126*0Sstevel@tonic-gate } else { 127*0Sstevel@tonic-gate return (p); 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate /* 132*0Sstevel@tonic-gate * parse up metadevice name 133*0Sstevel@tonic-gate */ 134*0Sstevel@tonic-gate static int 135*0Sstevel@tonic-gate parse_metadevice( 136*0Sstevel@tonic-gate char *uname, 137*0Sstevel@tonic-gate char **snamep, 138*0Sstevel@tonic-gate unit_t *unitp 139*0Sstevel@tonic-gate ) 140*0Sstevel@tonic-gate { 141*0Sstevel@tonic-gate char *sname = Malloc(strlen(uname) + 1); 142*0Sstevel@tonic-gate char *tname = Malloc(strlen(uname) + 1); 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate unit_t unit; 145*0Sstevel@tonic-gate int len; 146*0Sstevel@tonic-gate char *up; 147*0Sstevel@tonic-gate char *tp; 148*0Sstevel@tonic-gate int lcws; /* last character was slash */ 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate /* handle dont cares */ 151*0Sstevel@tonic-gate if (unitp == NULL) 152*0Sstevel@tonic-gate unitp = &unit; 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* Now copy uname to tname by throwing away any duplicate '/' */ 155*0Sstevel@tonic-gate for (lcws = 0, tp = tname, up = uname; *up; up++) { 156*0Sstevel@tonic-gate if (lcws) { 157*0Sstevel@tonic-gate if (*up == '/') { 158*0Sstevel@tonic-gate continue; 159*0Sstevel@tonic-gate } else { 160*0Sstevel@tonic-gate lcws = 0; 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate if (*up == '/') { 164*0Sstevel@tonic-gate lcws = 1; 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate *tp++ = *up; /* ++ is done by for loop */ 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate *tp = '\0'; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate /* without set */ 171*0Sstevel@tonic-gate if ((sscanf(tname, "d%lu%n", unitp, &len) == 1) && 172*0Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0)) { 173*0Sstevel@tonic-gate if (snamep != NULL) 174*0Sstevel@tonic-gate *snamep = NULL; 175*0Sstevel@tonic-gate Free(sname); 176*0Sstevel@tonic-gate Free(tname); 177*0Sstevel@tonic-gate return (0); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* fully-qualified without set */ 181*0Sstevel@tonic-gate if (((sscanf(tname, "/dev/md/dsk/d%lu%n", unitp, &len) == 1) && 182*0Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0)) || 183*0Sstevel@tonic-gate ((sscanf(tname, "/dev/md/rdsk/d%lu%n", unitp, &len) == 1) && 184*0Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0))) { 185*0Sstevel@tonic-gate if (snamep != NULL) 186*0Sstevel@tonic-gate *snamep = Strdup(MD_LOCAL_NAME); 187*0Sstevel@tonic-gate Free(sname); 188*0Sstevel@tonic-gate Free(tname); 189*0Sstevel@tonic-gate return (0); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate /* with set */ 193*0Sstevel@tonic-gate if (((sscanf(tname, "%[^/]/d%lu%n", sname, unitp, &len) == 2) && 194*0Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0)) || 195*0Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/dsk/d%lu%n", sname, 196*0Sstevel@tonic-gate unitp, &len) == 2) && 197*0Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0)) || 198*0Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/rdsk/d%lu%n", sname, 199*0Sstevel@tonic-gate unitp, &len) == 2) && 200*0Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0))) { 201*0Sstevel@tonic-gate if (snamep != NULL) { 202*0Sstevel@tonic-gate *snamep = sname; 203*0Sstevel@tonic-gate } else { 204*0Sstevel@tonic-gate Free(sname); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate Free(tname); 207*0Sstevel@tonic-gate return (0); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate /* no match */ 211*0Sstevel@tonic-gate if (snamep != NULL) 212*0Sstevel@tonic-gate *snamep = NULL; 213*0Sstevel@tonic-gate Free(sname); 214*0Sstevel@tonic-gate Free(tname); 215*0Sstevel@tonic-gate return (-1); 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate /* 219*0Sstevel@tonic-gate * FUNCTION: parse_device() 220*0Sstevel@tonic-gate * INPUT: sp - pointer to setname struct 221*0Sstevel@tonic-gate * uname - Name of either a hotspare pool or metadevice 222*0Sstevel@tonic-gate * This can either be a fully qualified path or 223*0Sstevel@tonic-gate * in the form [set name/]device 224*0Sstevel@tonic-gate * OUTPUT: setnamep - name of the set that uname is in 225*0Sstevel@tonic-gate * uname - name of the hotspare pools or metadevice 226*0Sstevel@tonic-gate * only contains the name of the device with all 227*0Sstevel@tonic-gate * other path information stripped off. 228*0Sstevel@tonic-gate * PURPOSE: Parse uname and sp into the set name and device name strings. 229*0Sstevel@tonic-gate * If the set name is specified as part of uname then use that 230*0Sstevel@tonic-gate * otherwise attempt to get the set name from sp. 231*0Sstevel@tonic-gate */ 232*0Sstevel@tonic-gate static void 233*0Sstevel@tonic-gate parse_device( 234*0Sstevel@tonic-gate mdsetname_t *sp, 235*0Sstevel@tonic-gate char *uname, 236*0Sstevel@tonic-gate char **setnamep /* dynamically alloced - caller must free */ 237*0Sstevel@tonic-gate ) 238*0Sstevel@tonic-gate { 239*0Sstevel@tonic-gate char setname[FILENAME_MAX+1]; 240*0Sstevel@tonic-gate char *tname = Malloc(strlen(uname) + 1); 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate int len; 243*0Sstevel@tonic-gate char *up; 244*0Sstevel@tonic-gate char *tp; 245*0Sstevel@tonic-gate int lcws; /* last character was slash */ 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate /* Now copy uname to tname by throwing away any duplicate '/' */ 248*0Sstevel@tonic-gate for (lcws = 0, tp = tname, up = uname; *up; up++) { 249*0Sstevel@tonic-gate if (lcws) { 250*0Sstevel@tonic-gate if (*up == '/') { 251*0Sstevel@tonic-gate continue; 252*0Sstevel@tonic-gate } else { 253*0Sstevel@tonic-gate lcws = 0; 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate if (*up == '/') { 257*0Sstevel@tonic-gate lcws = 1; 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate *tp++ = *up; /* ++ is done by for loop */ 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate *tp = '\0'; 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate /* fully-qualified - local set */ 264*0Sstevel@tonic-gate if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n", 265*0Sstevel@tonic-gate uname, &len) == 1) && (strlen(tname) == len)) || 266*0Sstevel@tonic-gate ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", 267*0Sstevel@tonic-gate uname, &len) == 1) && (strlen(tname) == len))) { 268*0Sstevel@tonic-gate if (setnamep != NULL) 269*0Sstevel@tonic-gate *setnamep = NULL; 270*0Sstevel@tonic-gate Free(tname); 271*0Sstevel@tonic-gate return; 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate /* with setname specified - either fully qualified and relative spec */ 275*0Sstevel@tonic-gate if (((sscanf(tname, "%" VAL2STR(FILENAME_MAX) "s/%" 276*0Sstevel@tonic-gate VAL2STR(FILENAME_MAX) "s%n", setname, uname, &len) == 2) && 277*0Sstevel@tonic-gate (strlen(tname) == len)) || 278*0Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n", 279*0Sstevel@tonic-gate setname, uname, &len) == 2) && (strlen(tname) == len)) || 280*0Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", 281*0Sstevel@tonic-gate setname, uname, &len) == 2) && (strlen(tname) == len))) { 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate if (setnamep != NULL) { 284*0Sstevel@tonic-gate *setnamep = Strdup(setname); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate Free(tname); 287*0Sstevel@tonic-gate return; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate /* without setname specified */ 291*0Sstevel@tonic-gate (void) strcpy(uname, tname); 292*0Sstevel@tonic-gate if (setnamep != NULL) { 293*0Sstevel@tonic-gate if (sp != NULL && !metaislocalset(sp)) 294*0Sstevel@tonic-gate *setnamep = Strdup(sp->setname); 295*0Sstevel@tonic-gate else 296*0Sstevel@tonic-gate *setnamep = NULL; 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate Free(tname); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate /* 302*0Sstevel@tonic-gate * parse up hotspare pool name 303*0Sstevel@tonic-gate */ 304*0Sstevel@tonic-gate static int 305*0Sstevel@tonic-gate parse_hsp( 306*0Sstevel@tonic-gate char *uname, 307*0Sstevel@tonic-gate char **snamep, 308*0Sstevel@tonic-gate hsp_t *hspp 309*0Sstevel@tonic-gate ) 310*0Sstevel@tonic-gate { 311*0Sstevel@tonic-gate char *sname = Malloc(strlen(uname) + 1); 312*0Sstevel@tonic-gate hsp_t hsp; 313*0Sstevel@tonic-gate int len; 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate /* handle dont cares */ 316*0Sstevel@tonic-gate if (hspp == NULL) 317*0Sstevel@tonic-gate hspp = &hsp; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate /* without set */ 320*0Sstevel@tonic-gate if ((sscanf(uname, "hsp%03u%n", hspp, &len) == 1) && 321*0Sstevel@tonic-gate (strlen(uname) == len) && ((long)*hspp >= 0)) { 322*0Sstevel@tonic-gate if (snamep != NULL) 323*0Sstevel@tonic-gate *snamep = NULL; 324*0Sstevel@tonic-gate Free(sname); 325*0Sstevel@tonic-gate return (0); 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate /* with set */ 329*0Sstevel@tonic-gate if ((sscanf(uname, "%[^/]/hsp%03u%n", sname, 330*0Sstevel@tonic-gate hspp, &len) == 2) && 331*0Sstevel@tonic-gate (strlen(uname) == len) && ((long)*hspp >= 0)) { 332*0Sstevel@tonic-gate if (snamep != NULL) { 333*0Sstevel@tonic-gate *snamep = sname; 334*0Sstevel@tonic-gate } else { 335*0Sstevel@tonic-gate Free(sname); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate return (0); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate /* no match */ 341*0Sstevel@tonic-gate Free(sname); 342*0Sstevel@tonic-gate return (-1); 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate /* 346*0Sstevel@tonic-gate * canonicalize metadevice name 347*0Sstevel@tonic-gate */ 348*0Sstevel@tonic-gate static char * 349*0Sstevel@tonic-gate canon_metadevice( 350*0Sstevel@tonic-gate char *sname, 351*0Sstevel@tonic-gate unit_t unit 352*0Sstevel@tonic-gate ) 353*0Sstevel@tonic-gate { 354*0Sstevel@tonic-gate char *cname; 355*0Sstevel@tonic-gate size_t len; 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 358*0Sstevel@tonic-gate len = strlen("d") + 20 + 1; 359*0Sstevel@tonic-gate cname = Malloc(len); 360*0Sstevel@tonic-gate (void) snprintf(cname, len, "d%lu", unit); 361*0Sstevel@tonic-gate } else { 362*0Sstevel@tonic-gate len = strlen(sname) + strlen("/d") + 20 + 1; 363*0Sstevel@tonic-gate cname = Malloc(len); 364*0Sstevel@tonic-gate (void) snprintf(cname, len, "%s/d%lu", sname, unit); 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate return (cname); 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate /* 371*0Sstevel@tonic-gate * canonicalize hotspare pool name 372*0Sstevel@tonic-gate */ 373*0Sstevel@tonic-gate static char * 374*0Sstevel@tonic-gate canon_hsp( 375*0Sstevel@tonic-gate char *sname, 376*0Sstevel@tonic-gate hsp_t hsp 377*0Sstevel@tonic-gate ) 378*0Sstevel@tonic-gate { 379*0Sstevel@tonic-gate char *cname; 380*0Sstevel@tonic-gate size_t len; 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 383*0Sstevel@tonic-gate cname = Malloc(strlen("hsp000") + 1); 384*0Sstevel@tonic-gate (void) sprintf(cname, "hsp%03u", hsp); 385*0Sstevel@tonic-gate } else { 386*0Sstevel@tonic-gate len = strlen(sname) + strlen("/hsp000") + 1; 387*0Sstevel@tonic-gate cname = Malloc(len); 388*0Sstevel@tonic-gate (void) snprintf(cname, len, "%s/hsp%03lu", sname, hsp); 389*0Sstevel@tonic-gate } 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate return (cname); 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate /* 395*0Sstevel@tonic-gate * canonicalize name, return type 396*0Sstevel@tonic-gate * 397*0Sstevel@tonic-gate * NOTE: this is really only for use by meta_tab* 398*0Sstevel@tonic-gate */ 399*0Sstevel@tonic-gate char * 400*0Sstevel@tonic-gate meta_canonicalize( 401*0Sstevel@tonic-gate mdsetname_t *sp, 402*0Sstevel@tonic-gate char *uname 403*0Sstevel@tonic-gate ) 404*0Sstevel@tonic-gate { 405*0Sstevel@tonic-gate char *sname = NULL; 406*0Sstevel@tonic-gate char *cname; 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate /* return the set name and dev name */ 409*0Sstevel@tonic-gate parse_device(sp, uname, &sname); 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate if (sname == NULL) 412*0Sstevel@tonic-gate cname = Strdup(uname); 413*0Sstevel@tonic-gate else { 414*0Sstevel@tonic-gate size_t cname_len; 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate cname_len = strlen(uname) + strlen(sname) + 2; 417*0Sstevel@tonic-gate cname = Malloc(cname_len); 418*0Sstevel@tonic-gate (void) snprintf( 419*0Sstevel@tonic-gate cname, cname_len, "%s/%s", sname, uname); 420*0Sstevel@tonic-gate Free(sname); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate return (cname); 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* 426*0Sstevel@tonic-gate * check that name is a metadevice 427*0Sstevel@tonic-gate */ 428*0Sstevel@tonic-gate int 429*0Sstevel@tonic-gate is_metaname( 430*0Sstevel@tonic-gate char *uname 431*0Sstevel@tonic-gate ) 432*0Sstevel@tonic-gate { 433*0Sstevel@tonic-gate if (parse_metadevice(uname, NULL, NULL) == 0) 434*0Sstevel@tonic-gate return (1); 435*0Sstevel@tonic-gate else 436*0Sstevel@tonic-gate return (0); 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate /* 440*0Sstevel@tonic-gate * check that name is a hotspare pool 441*0Sstevel@tonic-gate */ 442*0Sstevel@tonic-gate int 443*0Sstevel@tonic-gate is_hspname( 444*0Sstevel@tonic-gate char *uname 445*0Sstevel@tonic-gate ) 446*0Sstevel@tonic-gate { 447*0Sstevel@tonic-gate if (parse_hsp(uname, NULL, NULL) == 0) 448*0Sstevel@tonic-gate return (1); 449*0Sstevel@tonic-gate else 450*0Sstevel@tonic-gate return (0); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate /* 454*0Sstevel@tonic-gate * mdsetname_t stuff 455*0Sstevel@tonic-gate */ 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate /* 458*0Sstevel@tonic-gate * initialize setname 459*0Sstevel@tonic-gate */ 460*0Sstevel@tonic-gate static void 461*0Sstevel@tonic-gate metainitsetname( 462*0Sstevel@tonic-gate mdsetname_t *sp 463*0Sstevel@tonic-gate ) 464*0Sstevel@tonic-gate { 465*0Sstevel@tonic-gate (void) memset(sp, '\0', sizeof (*sp)); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate static void 469*0Sstevel@tonic-gate metafreesetdesc(md_set_desc *sd) 470*0Sstevel@tonic-gate { 471*0Sstevel@tonic-gate md_mnnode_desc *nd; 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) { 474*0Sstevel@tonic-gate nd = sd->sd_nodelist; 475*0Sstevel@tonic-gate while (nd) { 476*0Sstevel@tonic-gate sd->sd_nodelist = nd->nd_next; 477*0Sstevel@tonic-gate Free(nd); 478*0Sstevel@tonic-gate nd = sd->sd_nodelist; 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate metafreedrivedesc(&sd->sd_drvs); 482*0Sstevel@tonic-gate Free(sd); 483*0Sstevel@tonic-gate } 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate /* 486*0Sstevel@tonic-gate * free allocated setname 487*0Sstevel@tonic-gate */ 488*0Sstevel@tonic-gate static void 489*0Sstevel@tonic-gate metafreesetname( 490*0Sstevel@tonic-gate mdsetname_t *sp 491*0Sstevel@tonic-gate ) 492*0Sstevel@tonic-gate { 493*0Sstevel@tonic-gate if (sp->setname != NULL) 494*0Sstevel@tonic-gate Free(sp->setname); 495*0Sstevel@tonic-gate if (sp->setdesc != NULL) 496*0Sstevel@tonic-gate metafreesetdesc(sp->setdesc); 497*0Sstevel@tonic-gate metainitsetname(sp); 498*0Sstevel@tonic-gate } 499*0Sstevel@tonic-gate 500*0Sstevel@tonic-gate /* 501*0Sstevel@tonic-gate * flush the setname cache 502*0Sstevel@tonic-gate */ 503*0Sstevel@tonic-gate static void 504*0Sstevel@tonic-gate metaflushsetnames() 505*0Sstevel@tonic-gate { 506*0Sstevel@tonic-gate mdsetnamelist_t *p, *n; 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate for (p = setlistp, n = NULL; (p != NULL); p = n) { 509*0Sstevel@tonic-gate n = p->next; 510*0Sstevel@tonic-gate metafreesetname(p->sp); 511*0Sstevel@tonic-gate Free(p->sp); 512*0Sstevel@tonic-gate Free(p); 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate setlistp = NULL; 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* 518*0Sstevel@tonic-gate * get set number 519*0Sstevel@tonic-gate */ 520*0Sstevel@tonic-gate static int 521*0Sstevel@tonic-gate getsetno( 522*0Sstevel@tonic-gate char *sname, 523*0Sstevel@tonic-gate set_t *setnop, 524*0Sstevel@tonic-gate md_error_t *ep 525*0Sstevel@tonic-gate ) 526*0Sstevel@tonic-gate { 527*0Sstevel@tonic-gate md_set_record *sr; 528*0Sstevel@tonic-gate size_t len; 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate /* local set */ 531*0Sstevel@tonic-gate if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 532*0Sstevel@tonic-gate *setnop = 0; 533*0Sstevel@tonic-gate return (0); 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate /* shared set */ 537*0Sstevel@tonic-gate if ((sr = getsetbyname(sname, ep)) == NULL) { 538*0Sstevel@tonic-gate if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) { 539*0Sstevel@tonic-gate char *p; 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate len = strlen(sname) + 30; 542*0Sstevel@tonic-gate p = Malloc(len); 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate (void) snprintf(p, len, "setname \"%s\"", sname); 545*0Sstevel@tonic-gate (void) mderror(ep, MDE_NO_SET, p); 546*0Sstevel@tonic-gate Free(p); 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate return (-1); 549*0Sstevel@tonic-gate } 550*0Sstevel@tonic-gate *setnop = sr->sr_setno; 551*0Sstevel@tonic-gate free_sr(sr); 552*0Sstevel@tonic-gate return (0); 553*0Sstevel@tonic-gate } 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate /* 556*0Sstevel@tonic-gate * find setname from name 557*0Sstevel@tonic-gate */ 558*0Sstevel@tonic-gate mdsetname_t * 559*0Sstevel@tonic-gate metasetname( 560*0Sstevel@tonic-gate char *sname, 561*0Sstevel@tonic-gate md_error_t *ep 562*0Sstevel@tonic-gate ) 563*0Sstevel@tonic-gate { 564*0Sstevel@tonic-gate mdsetnamelist_t **tail; 565*0Sstevel@tonic-gate set_t setno; 566*0Sstevel@tonic-gate mdsetname_t *sp; 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate /* look for cached value first */ 569*0Sstevel@tonic-gate assert(sname != NULL); 570*0Sstevel@tonic-gate for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) { 571*0Sstevel@tonic-gate sp = (*tail)->sp; 572*0Sstevel@tonic-gate if (strcmp(sp->setname, sname) == 0) { 573*0Sstevel@tonic-gate return (sp); 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate /* setup set */ 578*0Sstevel@tonic-gate if (getsetno(sname, &setno, ep) != 0) 579*0Sstevel@tonic-gate return (NULL); 580*0Sstevel@tonic-gate 581*0Sstevel@tonic-gate /* allocate new list element and setname */ 582*0Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 583*0Sstevel@tonic-gate sp = (*tail)->sp = Zalloc(sizeof (*sp)); 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate sp->setname = Strdup(sname); 586*0Sstevel@tonic-gate sp->setno = setno; 587*0Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK; 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate return (sp); 590*0Sstevel@tonic-gate } 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate /* 593*0Sstevel@tonic-gate * find setname from setno 594*0Sstevel@tonic-gate */ 595*0Sstevel@tonic-gate mdsetname_t * 596*0Sstevel@tonic-gate metasetnosetname( 597*0Sstevel@tonic-gate set_t setno, 598*0Sstevel@tonic-gate md_error_t *ep 599*0Sstevel@tonic-gate ) 600*0Sstevel@tonic-gate { 601*0Sstevel@tonic-gate mdsetnamelist_t *slp; 602*0Sstevel@tonic-gate mdsetname_t *sp; 603*0Sstevel@tonic-gate md_set_record *sr; 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate /* look for cached value first */ 606*0Sstevel@tonic-gate for (slp = setlistp; (slp != NULL); slp = slp->next) { 607*0Sstevel@tonic-gate sp = slp->sp; 608*0Sstevel@tonic-gate if (sp->setno == setno) 609*0Sstevel@tonic-gate return (sp); 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate /* local set */ 613*0Sstevel@tonic-gate if (setno == MD_LOCAL_SET) 614*0Sstevel@tonic-gate return (metasetname(MD_LOCAL_NAME, ep)); 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate /* shared set */ 617*0Sstevel@tonic-gate if ((sr = getsetbynum(setno, ep)) == NULL) 618*0Sstevel@tonic-gate return (NULL); 619*0Sstevel@tonic-gate sp = metasetname(sr->sr_setname, ep); 620*0Sstevel@tonic-gate free_sr(sr); 621*0Sstevel@tonic-gate return (sp); 622*0Sstevel@tonic-gate } 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate mdsetname_t * 625*0Sstevel@tonic-gate metafakesetname( 626*0Sstevel@tonic-gate set_t setno, 627*0Sstevel@tonic-gate char *sname 628*0Sstevel@tonic-gate ) 629*0Sstevel@tonic-gate { 630*0Sstevel@tonic-gate mdsetnamelist_t **tail; 631*0Sstevel@tonic-gate mdsetname_t *sp; 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate /* look for cached value first */ 634*0Sstevel@tonic-gate for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) { 635*0Sstevel@tonic-gate sp = (*tail)->sp; 636*0Sstevel@tonic-gate if (sp->setno == setno) { 637*0Sstevel@tonic-gate if ((sp->setname == NULL) && (sname != NULL)) 638*0Sstevel@tonic-gate sp->setname = Strdup(sname); 639*0Sstevel@tonic-gate return (sp); 640*0Sstevel@tonic-gate } 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate /* allocate new list element and setname */ 644*0Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 645*0Sstevel@tonic-gate sp = (*tail)->sp = Zalloc(sizeof (*sp)); 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate if (sname != NULL) 648*0Sstevel@tonic-gate sp->setname = Strdup(sname); 649*0Sstevel@tonic-gate sp->setno = setno; 650*0Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK; 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate return (sp); 653*0Sstevel@tonic-gate } 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * setup set record (sr) and cache it in the mdsetname_t struct 658*0Sstevel@tonic-gate */ 659*0Sstevel@tonic-gate md_set_desc * 660*0Sstevel@tonic-gate sr2setdesc( 661*0Sstevel@tonic-gate md_set_record *sr 662*0Sstevel@tonic-gate ) 663*0Sstevel@tonic-gate { 664*0Sstevel@tonic-gate md_set_desc *sd; 665*0Sstevel@tonic-gate int i; 666*0Sstevel@tonic-gate md_mnset_record *mnsr; 667*0Sstevel@tonic-gate md_mnnode_desc *nd, *nd_prev = 0; 668*0Sstevel@tonic-gate md_mnnode_record *nr; 669*0Sstevel@tonic-gate md_error_t status = mdnullerror; 670*0Sstevel@tonic-gate md_error_t *ep = &status; 671*0Sstevel@tonic-gate int nodecnt, nrcnt; 672*0Sstevel@tonic-gate mndiskset_membershiplist_t *nl, *nl2; 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate sd = Zalloc(sizeof (*sd)); 675*0Sstevel@tonic-gate sd->sd_ctime = sr->sr_ctime; 676*0Sstevel@tonic-gate sd->sd_genid = sr->sr_genid; 677*0Sstevel@tonic-gate sd->sd_setno = sr->sr_setno; 678*0Sstevel@tonic-gate sd->sd_flags = sr->sr_flags; 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) { 681*0Sstevel@tonic-gate mnsr = (md_mnset_record *)sr; 682*0Sstevel@tonic-gate (void) strlcpy(sd->sd_mn_master_nodenm, 683*0Sstevel@tonic-gate mnsr->sr_master_nodenm, sizeof (sd->sd_mn_master_nodenm)); 684*0Sstevel@tonic-gate sd->sd_mn_master_nodeid = mnsr->sr_master_nodeid; 685*0Sstevel@tonic-gate if (strcmp(mnsr->sr_master_nodenm, mynode()) == 0) { 686*0Sstevel@tonic-gate sd->sd_mn_am_i_master = 1; 687*0Sstevel@tonic-gate } 688*0Sstevel@tonic-gate 689*0Sstevel@tonic-gate /* 690*0Sstevel@tonic-gate * Get membershiplist from API routine. If there's 691*0Sstevel@tonic-gate * an error, just use a NULL nodelist. 692*0Sstevel@tonic-gate */ 693*0Sstevel@tonic-gate if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) { 694*0Sstevel@tonic-gate nodecnt = 0; /* no nodes are alive */ 695*0Sstevel@tonic-gate nl = NULL; 696*0Sstevel@tonic-gate } 697*0Sstevel@tonic-gate nr = mnsr->sr_nodechain; 698*0Sstevel@tonic-gate nrcnt = 0; 699*0Sstevel@tonic-gate /* 700*0Sstevel@tonic-gate * Node descriptor node list must be built in 701*0Sstevel@tonic-gate * ascending order of nodeid. The nodechain 702*0Sstevel@tonic-gate * in the mnset record is in ascending order, 703*0Sstevel@tonic-gate * so just make them the same. 704*0Sstevel@tonic-gate */ 705*0Sstevel@tonic-gate while (nr) { 706*0Sstevel@tonic-gate nd = Zalloc(sizeof (*nd)); 707*0Sstevel@tonic-gate if (nd_prev) { 708*0Sstevel@tonic-gate nd_prev->nd_next = nd; 709*0Sstevel@tonic-gate } else { 710*0Sstevel@tonic-gate sd->sd_nodelist = nd; 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate nd->nd_ctime = nr->nr_ctime; 713*0Sstevel@tonic-gate nd->nd_genid = nr->nr_genid; 714*0Sstevel@tonic-gate nd->nd_flags = nr->nr_flags; 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate (void) strlcpy(nd->nd_nodename, nr->nr_nodename, 717*0Sstevel@tonic-gate sizeof (nd->nd_nodename)); 718*0Sstevel@tonic-gate nd->nd_nodeid = nr->nr_nodeid; 719*0Sstevel@tonic-gate if (strcmp(nd->nd_nodename, mynode()) == 0) { 720*0Sstevel@tonic-gate sd->sd_mn_mynode = nd; 721*0Sstevel@tonic-gate } 722*0Sstevel@tonic-gate if (nd->nd_nodeid == sd->sd_mn_master_nodeid) { 723*0Sstevel@tonic-gate sd->sd_mn_masternode = nd; 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate /* 727*0Sstevel@tonic-gate * If node is marked ALIVE, then set priv_ic 728*0Sstevel@tonic-gate * from membership list. During the early part 729*0Sstevel@tonic-gate * of a reconfig cycle, the membership list may 730*0Sstevel@tonic-gate * have been changed, (a node entering or leaving 731*0Sstevel@tonic-gate * the cluster), but rpc.metad hasn't flushed 732*0Sstevel@tonic-gate * its data yet. So, if node is marked alive, but 733*0Sstevel@tonic-gate * is no longer in the membership list (node has 734*0Sstevel@tonic-gate * left the cluster) then just leave priv_ic to NULL. 735*0Sstevel@tonic-gate */ 736*0Sstevel@tonic-gate if (nd->nd_flags & MD_MN_NODE_ALIVE) { 737*0Sstevel@tonic-gate nl2 = nl; 738*0Sstevel@tonic-gate while (nl2) { 739*0Sstevel@tonic-gate if (nl2->msl_node_id == nd->nd_nodeid) { 740*0Sstevel@tonic-gate (void) strlcpy(nd->nd_priv_ic, 741*0Sstevel@tonic-gate nl2->msl_node_addr, 742*0Sstevel@tonic-gate sizeof (nd->nd_priv_ic)); 743*0Sstevel@tonic-gate break; 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate nl2 = nl2->next; 746*0Sstevel@tonic-gate } 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate nr = nr->nr_next; 750*0Sstevel@tonic-gate nrcnt++; 751*0Sstevel@tonic-gate nd_prev = nd; 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate sd->sd_mn_numnodes = nrcnt; 754*0Sstevel@tonic-gate if (nodecnt) 755*0Sstevel@tonic-gate meta_free_nodelist(nl); 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate /* Just copying to keep consistent view between sr & sd */ 758*0Sstevel@tonic-gate (void) strlcpy(sd->sd_nodes[0], mnsr->sr_nodes_bw_compat[0], 759*0Sstevel@tonic-gate sizeof (sd->sd_nodes[0])); 760*0Sstevel@tonic-gate } else { 761*0Sstevel@tonic-gate for (i = 0; i < MD_MAXSIDES; i++) 762*0Sstevel@tonic-gate (void) strlcpy(sd->sd_nodes[i], sr->sr_nodes[i], 763*0Sstevel@tonic-gate sizeof (sd->sd_nodes[i])); 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate sd->sd_med = sr->sr_med; /* structure assignment */ 767*0Sstevel@tonic-gate 768*0Sstevel@tonic-gate return (sd); 769*0Sstevel@tonic-gate } 770*0Sstevel@tonic-gate 771*0Sstevel@tonic-gate md_set_desc * 772*0Sstevel@tonic-gate metaget_setdesc( 773*0Sstevel@tonic-gate mdsetname_t *sp, 774*0Sstevel@tonic-gate md_error_t *ep 775*0Sstevel@tonic-gate ) 776*0Sstevel@tonic-gate { 777*0Sstevel@tonic-gate md_set_record *sr; 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate if (sp->setdesc != NULL) 780*0Sstevel@tonic-gate return (sp->setdesc); 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate if (sp->setname != NULL) { 783*0Sstevel@tonic-gate if ((sr = getsetbyname(sp->setname, ep)) != NULL) { 784*0Sstevel@tonic-gate sp->setdesc = sr2setdesc(sr); 785*0Sstevel@tonic-gate free_sr(sr); 786*0Sstevel@tonic-gate return (sp->setdesc); 787*0Sstevel@tonic-gate } 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate if (sp->setno > 0) { 791*0Sstevel@tonic-gate if ((sr = getsetbynum(sp->setno, ep)) != NULL) { 792*0Sstevel@tonic-gate sp->setdesc = sr2setdesc(sr); 793*0Sstevel@tonic-gate free_sr(sr); 794*0Sstevel@tonic-gate return (sp->setdesc); 795*0Sstevel@tonic-gate } 796*0Sstevel@tonic-gate } 797*0Sstevel@tonic-gate 798*0Sstevel@tonic-gate return (NULL); 799*0Sstevel@tonic-gate } 800*0Sstevel@tonic-gate 801*0Sstevel@tonic-gate void 802*0Sstevel@tonic-gate metaflushsetname(mdsetname_t *sp) 803*0Sstevel@tonic-gate { 804*0Sstevel@tonic-gate if (sp == NULL) 805*0Sstevel@tonic-gate return; 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate if (sp->setdesc == NULL) 808*0Sstevel@tonic-gate return; 809*0Sstevel@tonic-gate 810*0Sstevel@tonic-gate metafreesetdesc(sp->setdesc); 811*0Sstevel@tonic-gate sp->setdesc = NULL; 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate /* 815*0Sstevel@tonic-gate * check for local set 816*0Sstevel@tonic-gate */ 817*0Sstevel@tonic-gate int 818*0Sstevel@tonic-gate metaislocalset( 819*0Sstevel@tonic-gate mdsetname_t *sp 820*0Sstevel@tonic-gate ) 821*0Sstevel@tonic-gate { 822*0Sstevel@tonic-gate assert(sp->setname != NULL); 823*0Sstevel@tonic-gate if (strcmp(sp->setname, MD_LOCAL_NAME) == 0) { 824*0Sstevel@tonic-gate assert(sp->setno == MD_LOCAL_SET); 825*0Sstevel@tonic-gate return (1); 826*0Sstevel@tonic-gate } else { 827*0Sstevel@tonic-gate assert(sp->setno != MD_LOCAL_SET); 828*0Sstevel@tonic-gate return (0); 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate } 831*0Sstevel@tonic-gate 832*0Sstevel@tonic-gate /* 833*0Sstevel@tonic-gate * check for same set 834*0Sstevel@tonic-gate */ 835*0Sstevel@tonic-gate int 836*0Sstevel@tonic-gate metaissameset( 837*0Sstevel@tonic-gate mdsetname_t *sp1, 838*0Sstevel@tonic-gate mdsetname_t *sp2 839*0Sstevel@tonic-gate ) 840*0Sstevel@tonic-gate { 841*0Sstevel@tonic-gate if (strcmp(sp1->setname, sp2->setname) == 0) { 842*0Sstevel@tonic-gate assert(sp1->setno == sp2->setno); 843*0Sstevel@tonic-gate return (1); 844*0Sstevel@tonic-gate } else { 845*0Sstevel@tonic-gate assert(sp1->setno != sp2->setno); 846*0Sstevel@tonic-gate return (0); 847*0Sstevel@tonic-gate } 848*0Sstevel@tonic-gate } 849*0Sstevel@tonic-gate 850*0Sstevel@tonic-gate /* 851*0Sstevel@tonic-gate * check to see if set changed 852*0Sstevel@tonic-gate */ 853*0Sstevel@tonic-gate static int 854*0Sstevel@tonic-gate chkset( 855*0Sstevel@tonic-gate mdsetname_t **spp, 856*0Sstevel@tonic-gate char *sname, 857*0Sstevel@tonic-gate md_error_t *ep 858*0Sstevel@tonic-gate ) 859*0Sstevel@tonic-gate { 860*0Sstevel@tonic-gate /* if we already have a set, make sure it's the same */ 861*0Sstevel@tonic-gate if (*spp != NULL) { 862*0Sstevel@tonic-gate if ((*spp)->setname != sname && 863*0Sstevel@tonic-gate strcmp((*spp)->setname, sname) != 0) { 864*0Sstevel@tonic-gate return (mderror(ep, MDE_SET_DIFF, sname)); 865*0Sstevel@tonic-gate } 866*0Sstevel@tonic-gate return (0); 867*0Sstevel@tonic-gate } 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate /* otherwise store new set name and number */ 870*0Sstevel@tonic-gate if ((*spp = metasetname(sname, ep)) == NULL) { 871*0Sstevel@tonic-gate return (-1); 872*0Sstevel@tonic-gate } 873*0Sstevel@tonic-gate 874*0Sstevel@tonic-gate /* return success */ 875*0Sstevel@tonic-gate return (0); 876*0Sstevel@tonic-gate } 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate /* 879*0Sstevel@tonic-gate * check to see if set changed from default 880*0Sstevel@tonic-gate */ 881*0Sstevel@tonic-gate static int 882*0Sstevel@tonic-gate chksetname( 883*0Sstevel@tonic-gate mdsetname_t **spp, 884*0Sstevel@tonic-gate char *sname, 885*0Sstevel@tonic-gate md_error_t *ep 886*0Sstevel@tonic-gate ) 887*0Sstevel@tonic-gate { 888*0Sstevel@tonic-gate /* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */ 889*0Sstevel@tonic-gate if (sname == NULL) { 890*0Sstevel@tonic-gate if (*spp) { 891*0Sstevel@tonic-gate sname = (*spp)->setname; 892*0Sstevel@tonic-gate } else { 893*0Sstevel@tonic-gate sname = MD_LOCAL_NAME; 894*0Sstevel@tonic-gate } 895*0Sstevel@tonic-gate } 896*0Sstevel@tonic-gate 897*0Sstevel@tonic-gate /* see if changed */ 898*0Sstevel@tonic-gate return (chkset(spp, sname, ep)); 899*0Sstevel@tonic-gate } 900*0Sstevel@tonic-gate 901*0Sstevel@tonic-gate /* 902*0Sstevel@tonic-gate * check setname from setno 903*0Sstevel@tonic-gate */ 904*0Sstevel@tonic-gate static int 905*0Sstevel@tonic-gate chksetno( 906*0Sstevel@tonic-gate mdsetname_t **spp, 907*0Sstevel@tonic-gate set_t setno, 908*0Sstevel@tonic-gate md_error_t *ep 909*0Sstevel@tonic-gate ) 910*0Sstevel@tonic-gate { 911*0Sstevel@tonic-gate md_set_record *sr; 912*0Sstevel@tonic-gate int rval; 913*0Sstevel@tonic-gate 914*0Sstevel@tonic-gate /* local set */ 915*0Sstevel@tonic-gate if (setno == 0) 916*0Sstevel@tonic-gate return (chkset(spp, MD_LOCAL_NAME, ep)); 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate /* shared set */ 919*0Sstevel@tonic-gate if ((sr = getsetbynum(setno, ep)) == NULL) 920*0Sstevel@tonic-gate return (-1); 921*0Sstevel@tonic-gate rval = chkset(spp, sr->sr_setname, ep); 922*0Sstevel@tonic-gate free_sr(sr); 923*0Sstevel@tonic-gate return (rval); 924*0Sstevel@tonic-gate } 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate /* 927*0Sstevel@tonic-gate * mddrivename_t stuff 928*0Sstevel@tonic-gate */ 929*0Sstevel@tonic-gate 930*0Sstevel@tonic-gate /* 931*0Sstevel@tonic-gate * initialize name 932*0Sstevel@tonic-gate */ 933*0Sstevel@tonic-gate static void 934*0Sstevel@tonic-gate metainitname( 935*0Sstevel@tonic-gate mdname_t *np 936*0Sstevel@tonic-gate ) 937*0Sstevel@tonic-gate { 938*0Sstevel@tonic-gate (void) memset(np, 0, sizeof (*np)); 939*0Sstevel@tonic-gate np->dev = NODEV64; 940*0Sstevel@tonic-gate np->key = MD_KEYBAD; 941*0Sstevel@tonic-gate np->end_blk = -1; 942*0Sstevel@tonic-gate np->start_blk = -1; 943*0Sstevel@tonic-gate } 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate /* 946*0Sstevel@tonic-gate * free allocated name 947*0Sstevel@tonic-gate */ 948*0Sstevel@tonic-gate static void 949*0Sstevel@tonic-gate metafreename( 950*0Sstevel@tonic-gate mdname_t *np 951*0Sstevel@tonic-gate ) 952*0Sstevel@tonic-gate { 953*0Sstevel@tonic-gate if (np->cname != NULL) 954*0Sstevel@tonic-gate Free(np->cname); 955*0Sstevel@tonic-gate if (np->bname != NULL) 956*0Sstevel@tonic-gate Free(np->bname); 957*0Sstevel@tonic-gate if (np->rname != NULL) 958*0Sstevel@tonic-gate Free(np->rname); 959*0Sstevel@tonic-gate if (np->devicesname != NULL) 960*0Sstevel@tonic-gate Free(np->devicesname); 961*0Sstevel@tonic-gate metainitname(np); 962*0Sstevel@tonic-gate } 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate /* 965*0Sstevel@tonic-gate * initialize drive name 966*0Sstevel@tonic-gate */ 967*0Sstevel@tonic-gate static void 968*0Sstevel@tonic-gate metainitdrivename( 969*0Sstevel@tonic-gate mddrivename_t *dnp 970*0Sstevel@tonic-gate ) 971*0Sstevel@tonic-gate { 972*0Sstevel@tonic-gate (void) memset(dnp, 0, sizeof (*dnp)); 973*0Sstevel@tonic-gate dnp->side_names_key = MD_KEYBAD; 974*0Sstevel@tonic-gate } 975*0Sstevel@tonic-gate 976*0Sstevel@tonic-gate /* 977*0Sstevel@tonic-gate * flush side names 978*0Sstevel@tonic-gate */ 979*0Sstevel@tonic-gate void 980*0Sstevel@tonic-gate metaflushsidenames( 981*0Sstevel@tonic-gate mddrivename_t *dnp 982*0Sstevel@tonic-gate ) 983*0Sstevel@tonic-gate { 984*0Sstevel@tonic-gate mdsidenames_t *p, *n; 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate for (p = dnp->side_names, n = NULL; (p != NULL); p = n) { 987*0Sstevel@tonic-gate n = p->next; 988*0Sstevel@tonic-gate if (p->dname != NULL) 989*0Sstevel@tonic-gate Free(p->dname); 990*0Sstevel@tonic-gate if (p->cname != NULL) 991*0Sstevel@tonic-gate Free(p->cname); 992*0Sstevel@tonic-gate Free(p); 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate dnp->side_names = NULL; 995*0Sstevel@tonic-gate } 996*0Sstevel@tonic-gate 997*0Sstevel@tonic-gate /* 998*0Sstevel@tonic-gate * free drive name 999*0Sstevel@tonic-gate */ 1000*0Sstevel@tonic-gate void 1001*0Sstevel@tonic-gate metafreedrivename( 1002*0Sstevel@tonic-gate mddrivename_t *dnp 1003*0Sstevel@tonic-gate ) 1004*0Sstevel@tonic-gate { 1005*0Sstevel@tonic-gate uint_t slice; 1006*0Sstevel@tonic-gate 1007*0Sstevel@tonic-gate if (dnp->cname != NULL) 1008*0Sstevel@tonic-gate Free(dnp->cname); 1009*0Sstevel@tonic-gate if (dnp->rname != NULL) 1010*0Sstevel@tonic-gate Free(dnp->rname); 1011*0Sstevel@tonic-gate metafreevtoc(&dnp->vtoc); 1012*0Sstevel@tonic-gate for (slice = 0; (slice < dnp->parts.parts_len); ++slice) 1013*0Sstevel@tonic-gate metafreename(&dnp->parts.parts_val[slice]); 1014*0Sstevel@tonic-gate if (dnp->parts.parts_val != NULL) 1015*0Sstevel@tonic-gate Free(dnp->parts.parts_val); 1016*0Sstevel@tonic-gate metaflushsidenames(dnp); 1017*0Sstevel@tonic-gate if (dnp->miscname != NULL) 1018*0Sstevel@tonic-gate Free(dnp->miscname); 1019*0Sstevel@tonic-gate meta_free_unit(dnp); 1020*0Sstevel@tonic-gate metainitdrivename(dnp); 1021*0Sstevel@tonic-gate } 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate /* 1024*0Sstevel@tonic-gate * flush the drive name cache 1025*0Sstevel@tonic-gate */ 1026*0Sstevel@tonic-gate static void 1027*0Sstevel@tonic-gate metaflushdrivenames() 1028*0Sstevel@tonic-gate { 1029*0Sstevel@tonic-gate mddrivenamelist_t *p, *n; 1030*0Sstevel@tonic-gate 1031*0Sstevel@tonic-gate for (p = drivelistp, n = NULL; (p != NULL); p = n) { 1032*0Sstevel@tonic-gate n = p->next; 1033*0Sstevel@tonic-gate metafreedrivename(p->drivenamep); 1034*0Sstevel@tonic-gate Free(p->drivenamep); 1035*0Sstevel@tonic-gate Free(p); 1036*0Sstevel@tonic-gate } 1037*0Sstevel@tonic-gate drivelistp = NULL; 1038*0Sstevel@tonic-gate } 1039*0Sstevel@tonic-gate 1040*0Sstevel@tonic-gate /* 1041*0Sstevel@tonic-gate * peel off s%u from name 1042*0Sstevel@tonic-gate */ 1043*0Sstevel@tonic-gate char * 1044*0Sstevel@tonic-gate metadiskname( 1045*0Sstevel@tonic-gate char *name 1046*0Sstevel@tonic-gate ) 1047*0Sstevel@tonic-gate { 1048*0Sstevel@tonic-gate char *p, *e; 1049*0Sstevel@tonic-gate char onmb[BUFSIZ+1], cnmb[BUFSIZ]; 1050*0Sstevel@tonic-gate uint_t d = 0; 1051*0Sstevel@tonic-gate int l = 0; 1052*0Sstevel@tonic-gate int cl = strlen(name); 1053*0Sstevel@tonic-gate 1054*0Sstevel@tonic-gate if (is_metaname(name)) 1055*0Sstevel@tonic-gate return (Strdup(name)); 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate /* 1058*0Sstevel@tonic-gate * Handle old style names, which are of the form /dev/rXXNN[a-h]. 1059*0Sstevel@tonic-gate */ 1060*0Sstevel@tonic-gate if (sscanf(name, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n", 1061*0Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 1062*0Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u", onmb, d); 1063*0Sstevel@tonic-gate return (Strdup(cnmb)); 1064*0Sstevel@tonic-gate } 1065*0Sstevel@tonic-gate 1066*0Sstevel@tonic-gate /* 1067*0Sstevel@tonic-gate * Handle old style names, which are of the form /dev/XXNN[a-h]. 1068*0Sstevel@tonic-gate */ 1069*0Sstevel@tonic-gate if (sscanf(name, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n", 1070*0Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 1071*0Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/%s%u", onmb, d); 1072*0Sstevel@tonic-gate return (Strdup(cnmb)); 1073*0Sstevel@tonic-gate } 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate /* gobble number and 's' */ 1076*0Sstevel@tonic-gate p = e = name + strlen(name) - 1; 1077*0Sstevel@tonic-gate for (; (p > name); --p) { 1078*0Sstevel@tonic-gate if (!isdigit(*p)) 1079*0Sstevel@tonic-gate break; 1080*0Sstevel@tonic-gate } 1081*0Sstevel@tonic-gate if ((p == e) || (p <= name)) 1082*0Sstevel@tonic-gate return (Strdup(name)); 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gate if (*p != 's' && strchr("dt", *p) == NULL) 1085*0Sstevel@tonic-gate return (Strdup(name)); 1086*0Sstevel@tonic-gate else if (strchr("dt", *p) != NULL) 1087*0Sstevel@tonic-gate return (Strdup(name)); 1088*0Sstevel@tonic-gate p--; 1089*0Sstevel@tonic-gate 1090*0Sstevel@tonic-gate if ((p <= name) || (!isdigit(*p))) 1091*0Sstevel@tonic-gate return (Strdup(name)); 1092*0Sstevel@tonic-gate 1093*0Sstevel@tonic-gate *(++p) = '\0'; 1094*0Sstevel@tonic-gate e = Strdup(name); 1095*0Sstevel@tonic-gate *p = 's'; 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate return (e); 1098*0Sstevel@tonic-gate } 1099*0Sstevel@tonic-gate 1100*0Sstevel@tonic-gate /* 1101*0Sstevel@tonic-gate * free list of drivenames 1102*0Sstevel@tonic-gate */ 1103*0Sstevel@tonic-gate void 1104*0Sstevel@tonic-gate metafreedrivenamelist( 1105*0Sstevel@tonic-gate mddrivenamelist_t *dnlp 1106*0Sstevel@tonic-gate ) 1107*0Sstevel@tonic-gate { 1108*0Sstevel@tonic-gate mddrivenamelist_t *next = NULL; 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate for (/* void */; (dnlp != NULL); dnlp = next) { 1111*0Sstevel@tonic-gate next = dnlp->next; 1112*0Sstevel@tonic-gate Free(dnlp); 1113*0Sstevel@tonic-gate } 1114*0Sstevel@tonic-gate } 1115*0Sstevel@tonic-gate 1116*0Sstevel@tonic-gate /* 1117*0Sstevel@tonic-gate * build list of drivenames 1118*0Sstevel@tonic-gate */ 1119*0Sstevel@tonic-gate int 1120*0Sstevel@tonic-gate metadrivenamelist( 1121*0Sstevel@tonic-gate mdsetname_t **spp, 1122*0Sstevel@tonic-gate mddrivenamelist_t **dnlpp, 1123*0Sstevel@tonic-gate int argc, 1124*0Sstevel@tonic-gate char *argv[], 1125*0Sstevel@tonic-gate md_error_t *ep 1126*0Sstevel@tonic-gate ) 1127*0Sstevel@tonic-gate { 1128*0Sstevel@tonic-gate mddrivenamelist_t **tailpp = dnlpp; 1129*0Sstevel@tonic-gate int count = 0; 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 1132*0Sstevel@tonic-gate mddrivenamelist_t *dnlp = Zalloc(sizeof (*dnlp)); 1133*0Sstevel@tonic-gate 1134*0Sstevel@tonic-gate if ((dnlp->drivenamep = metadrivename(spp, argv[0], 1135*0Sstevel@tonic-gate ep)) == NULL) { 1136*0Sstevel@tonic-gate metafreedrivenamelist(*dnlpp); 1137*0Sstevel@tonic-gate *dnlpp = NULL; 1138*0Sstevel@tonic-gate return (-1); 1139*0Sstevel@tonic-gate } 1140*0Sstevel@tonic-gate *tailpp = dnlp; 1141*0Sstevel@tonic-gate tailpp = &dnlp->next; 1142*0Sstevel@tonic-gate } 1143*0Sstevel@tonic-gate return (count); 1144*0Sstevel@tonic-gate } 1145*0Sstevel@tonic-gate 1146*0Sstevel@tonic-gate /* 1147*0Sstevel@tonic-gate * append to end of drivename list 1148*0Sstevel@tonic-gate */ 1149*0Sstevel@tonic-gate mddrivename_t * 1150*0Sstevel@tonic-gate metadrivenamelist_append( 1151*0Sstevel@tonic-gate mddrivenamelist_t **dnlpp, 1152*0Sstevel@tonic-gate mddrivename_t *dnp 1153*0Sstevel@tonic-gate ) 1154*0Sstevel@tonic-gate { 1155*0Sstevel@tonic-gate mddrivenamelist_t *dnlp; 1156*0Sstevel@tonic-gate 1157*0Sstevel@tonic-gate /* run to end of list */ 1158*0Sstevel@tonic-gate for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next) 1159*0Sstevel@tonic-gate ; 1160*0Sstevel@tonic-gate 1161*0Sstevel@tonic-gate /* allocate new list element */ 1162*0Sstevel@tonic-gate dnlp = *dnlpp = Zalloc(sizeof (*dnlp)); 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate /* append drivename */ 1165*0Sstevel@tonic-gate dnlp->drivenamep = dnp; 1166*0Sstevel@tonic-gate return (dnp); 1167*0Sstevel@tonic-gate } 1168*0Sstevel@tonic-gate 1169*0Sstevel@tonic-gate /* 1170*0Sstevel@tonic-gate * FUNCTION: meta_drivenamelist_append_wrapper() 1171*0Sstevel@tonic-gate * INPUT: tailpp - pointer to the list tail pointer 1172*0Sstevel@tonic-gate * dnp - name node to be appended to list 1173*0Sstevel@tonic-gate * OUTPUT: none 1174*0Sstevel@tonic-gate * RETURNS: mddrivenamelist_t * - new tail of the list. 1175*0Sstevel@tonic-gate * PURPOSE: wrapper to meta_namelist_append for performance. 1176*0Sstevel@tonic-gate * metanamelist_append finds the tail each time which slows 1177*0Sstevel@tonic-gate * down long lists. By keeping track of the tail ourselves 1178*0Sstevel@tonic-gate * we can change metadrivenamelist_append into a 1179*0Sstevel@tonic-gate * constant time operation. 1180*0Sstevel@tonic-gate */ 1181*0Sstevel@tonic-gate mddrivenamelist_t ** 1182*0Sstevel@tonic-gate meta_drivenamelist_append_wrapper( 1183*0Sstevel@tonic-gate mddrivenamelist_t **tailpp, 1184*0Sstevel@tonic-gate mddrivename_t *dnp 1185*0Sstevel@tonic-gate ) 1186*0Sstevel@tonic-gate { 1187*0Sstevel@tonic-gate (void) metadrivenamelist_append(tailpp, dnp); 1188*0Sstevel@tonic-gate 1189*0Sstevel@tonic-gate /* If it's the first item in the list, return it instead of the next */ 1190*0Sstevel@tonic-gate if ((*tailpp)->next == NULL) 1191*0Sstevel@tonic-gate return (tailpp); 1192*0Sstevel@tonic-gate 1193*0Sstevel@tonic-gate return (&(*tailpp)->next); 1194*0Sstevel@tonic-gate } 1195*0Sstevel@tonic-gate 1196*0Sstevel@tonic-gate 1197*0Sstevel@tonic-gate /* 1198*0Sstevel@tonic-gate * mdname_t stuff 1199*0Sstevel@tonic-gate */ 1200*0Sstevel@tonic-gate 1201*0Sstevel@tonic-gate /* 1202*0Sstevel@tonic-gate * check set and get comparison name 1203*0Sstevel@tonic-gate */ 1204*0Sstevel@tonic-gate char * 1205*0Sstevel@tonic-gate meta_name_getname( 1206*0Sstevel@tonic-gate mdsetname_t **spp, 1207*0Sstevel@tonic-gate char *uname, 1208*0Sstevel@tonic-gate md_error_t *ep 1209*0Sstevel@tonic-gate ) 1210*0Sstevel@tonic-gate { 1211*0Sstevel@tonic-gate char *sname = NULL; 1212*0Sstevel@tonic-gate int ismeta = 0; 1213*0Sstevel@tonic-gate unit_t unit; 1214*0Sstevel@tonic-gate 1215*0Sstevel@tonic-gate /* check set name */ 1216*0Sstevel@tonic-gate if (parse_metadevice(uname, &sname, &unit) == 0) 1217*0Sstevel@tonic-gate ismeta = 1; 1218*0Sstevel@tonic-gate if (chksetname(spp, sname, ep) != 0) { 1219*0Sstevel@tonic-gate if (sname != NULL) 1220*0Sstevel@tonic-gate Free(sname); 1221*0Sstevel@tonic-gate return (NULL); 1222*0Sstevel@tonic-gate } 1223*0Sstevel@tonic-gate if (sname != NULL) 1224*0Sstevel@tonic-gate Free(sname); 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate /* return comparison name */ 1227*0Sstevel@tonic-gate if (ismeta) 1228*0Sstevel@tonic-gate return (canon_metadevice((*spp)->setname, unit)); 1229*0Sstevel@tonic-gate else 1230*0Sstevel@tonic-gate return (Strdup(uname)); 1231*0Sstevel@tonic-gate } 1232*0Sstevel@tonic-gate 1233*0Sstevel@tonic-gate /* 1234*0Sstevel@tonic-gate * FUNCTION: getrname() 1235*0Sstevel@tonic-gate * INPUT: spp - the setname struct 1236*0Sstevel@tonic-gate * uname - the possibly unqualified device name 1237*0Sstevel@tonic-gate * OUTPUT: ep - return error pointer 1238*0Sstevel@tonic-gate * RETURNS: char* - character string containing the fully 1239*0Sstevel@tonic-gate * qualified raw device name 1240*0Sstevel@tonic-gate * PURPOSE: Create the fully qualified raw name for the possibly 1241*0Sstevel@tonic-gate * unqualified device name. If uname is an absolute 1242*0Sstevel@tonic-gate * path the raw name is derived from the input string. 1243*0Sstevel@tonic-gate * Otherwise, an attempt is made to get the rawname by 1244*0Sstevel@tonic-gate * catting "/dev/md/rdsk" and "/dev/rdsk". 1245*0Sstevel@tonic-gate */ 1246*0Sstevel@tonic-gate static char * 1247*0Sstevel@tonic-gate getrname(mdsetname_t **spp, char *uname, md_error_t *ep) 1248*0Sstevel@tonic-gate { 1249*0Sstevel@tonic-gate char *rname, 1250*0Sstevel@tonic-gate *fname; 1251*0Sstevel@tonic-gate int constructed = 0; 1252*0Sstevel@tonic-gate 1253*0Sstevel@tonic-gate assert(uname != NULL); 1254*0Sstevel@tonic-gate /* if it is an absolute name then just call rawname on the input */ 1255*0Sstevel@tonic-gate if (uname[0] == '/') { 1256*0Sstevel@tonic-gate if ((rname = rawname(uname)) != NULL) 1257*0Sstevel@tonic-gate return (rname); 1258*0Sstevel@tonic-gate 1259*0Sstevel@tonic-gate /* out of luck */ 1260*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 1261*0Sstevel@tonic-gate return (NULL); 1262*0Sstevel@tonic-gate } 1263*0Sstevel@tonic-gate 1264*0Sstevel@tonic-gate /* 1265*0Sstevel@tonic-gate * Check for metadevice before physical device. 1266*0Sstevel@tonic-gate * With the introduction of softpartitions it is more 1267*0Sstevel@tonic-gate * likely to be a metadevice. 1268*0Sstevel@tonic-gate */ 1269*0Sstevel@tonic-gate 1270*0Sstevel@tonic-gate /* metadevice short form */ 1271*0Sstevel@tonic-gate if (metaislocalset(*spp)) { 1272*0Sstevel@tonic-gate fname = Malloc(strlen(uname) + strlen("/dev/md/rdsk/") + 1); 1273*0Sstevel@tonic-gate (void) strcpy(fname, "/dev/md/rdsk/"); 1274*0Sstevel@tonic-gate (void) strcat(fname, uname); 1275*0Sstevel@tonic-gate if (*uname == 'd') 1276*0Sstevel@tonic-gate constructed = 1; 1277*0Sstevel@tonic-gate } else { 1278*0Sstevel@tonic-gate char *p; 1279*0Sstevel@tonic-gate size_t len; 1280*0Sstevel@tonic-gate 1281*0Sstevel@tonic-gate if ((p = strchr(uname, '/')) != NULL) { 1282*0Sstevel@tonic-gate ++p; 1283*0Sstevel@tonic-gate } else { 1284*0Sstevel@tonic-gate p = uname; 1285*0Sstevel@tonic-gate } 1286*0Sstevel@tonic-gate len = strlen((*spp)->setname) + strlen(p) + 1287*0Sstevel@tonic-gate strlen("/dev/md//rdsk/") + 1; 1288*0Sstevel@tonic-gate fname = Malloc(len); 1289*0Sstevel@tonic-gate (void) snprintf(fname, len, "/dev/md/%s/rdsk/%s", 1290*0Sstevel@tonic-gate (*spp)->setname, p); 1291*0Sstevel@tonic-gate if (*p == 'd') 1292*0Sstevel@tonic-gate constructed = 1; 1293*0Sstevel@tonic-gate } 1294*0Sstevel@tonic-gate rname = rawname(fname); 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate /* 1297*0Sstevel@tonic-gate * Handle the case where we have a new metadevice that does not yet 1298*0Sstevel@tonic-gate * exist in the name-space. In this case we return the constructed 1299*0Sstevel@tonic-gate * metadevice name as that will exist after the metainit call has 1300*0Sstevel@tonic-gate * created it. 1301*0Sstevel@tonic-gate */ 1302*0Sstevel@tonic-gate if ((rname == NULL) && constructed) { 1303*0Sstevel@tonic-gate rname = Strdup(fname); 1304*0Sstevel@tonic-gate } 1305*0Sstevel@tonic-gate Free(fname); 1306*0Sstevel@tonic-gate if (rname != NULL) 1307*0Sstevel@tonic-gate return (rname); 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1); 1310*0Sstevel@tonic-gate (void) strcpy(fname, "/dev/rdsk/"); 1311*0Sstevel@tonic-gate (void) strcat(fname, uname); 1312*0Sstevel@tonic-gate rname = rawname(fname); 1313*0Sstevel@tonic-gate Free(fname); 1314*0Sstevel@tonic-gate if (rname != NULL) 1315*0Sstevel@tonic-gate return (rname); 1316*0Sstevel@tonic-gate 1317*0Sstevel@tonic-gate /* 1318*0Sstevel@tonic-gate * If all else fails try the straight uname. 1319*0Sstevel@tonic-gate * NOTE: This check was at the beginning of getrname instead 1320*0Sstevel@tonic-gate * of here. It was moved to avoid a conflict with SC3.0. If 1321*0Sstevel@tonic-gate * a diskset was mounted with the same name it would hang 1322*0Sstevel@tonic-gate * the cluster in a loop. Example: 1323*0Sstevel@tonic-gate * 1324*0Sstevel@tonic-gate * fubar/d10 -m fubar/d0 fubar/d1 1325*0Sstevel@tonic-gate * mount /dev/md/fubar/dsk/d10 /fubar 1326*0Sstevel@tonic-gate * 1327*0Sstevel@tonic-gate * When the system was booted DiskSuite would try to take ownership 1328*0Sstevel@tonic-gate * of diskset fubar. This would cause rawname("fubar/d10") to be 1329*0Sstevel@tonic-gate * called. rawname() stats the string which caused the cluster 1330*0Sstevel@tonic-gate * reservation code to try and take ownership which it was already 1331*0Sstevel@tonic-gate * doing and a deadlock would occur. By moving this final attempt 1332*0Sstevel@tonic-gate * at resolving the rawname to the end we avoid this deadlock. 1333*0Sstevel@tonic-gate */ 1334*0Sstevel@tonic-gate if (rname = rawname(uname)) 1335*0Sstevel@tonic-gate return (rname); 1336*0Sstevel@tonic-gate 1337*0Sstevel@tonic-gate /* out of luck */ 1338*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 1339*0Sstevel@tonic-gate return (NULL); 1340*0Sstevel@tonic-gate } 1341*0Sstevel@tonic-gate 1342*0Sstevel@tonic-gate /* 1343*0Sstevel@tonic-gate * get raw slice and drive names 1344*0Sstevel@tonic-gate */ 1345*0Sstevel@tonic-gate static char * 1346*0Sstevel@tonic-gate getrawnames( 1347*0Sstevel@tonic-gate mdsetname_t **spp, 1348*0Sstevel@tonic-gate char *uname, 1349*0Sstevel@tonic-gate char **dnamep, 1350*0Sstevel@tonic-gate md_error_t *ep 1351*0Sstevel@tonic-gate ) 1352*0Sstevel@tonic-gate { 1353*0Sstevel@tonic-gate char *rname; 1354*0Sstevel@tonic-gate size_t len; 1355*0Sstevel@tonic-gate 1356*0Sstevel@tonic-gate /* initialize */ 1357*0Sstevel@tonic-gate *dnamep = NULL; 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate /* get slice name */ 1360*0Sstevel@tonic-gate if ((rname = getrname(spp, uname, ep)) != NULL) { 1361*0Sstevel@tonic-gate *dnamep = metadiskname(rname); 1362*0Sstevel@tonic-gate return (rname); 1363*0Sstevel@tonic-gate } 1364*0Sstevel@tonic-gate 1365*0Sstevel@tonic-gate /* 1366*0Sstevel@tonic-gate * If name cannot be found, if may be because is is not accessible. 1367*0Sstevel@tonic-gate * If it is an absolute name, try all possible disk name formats and 1368*0Sstevel@tonic-gate * if it is device name, assume it is /dev/rdsk/... 1369*0Sstevel@tonic-gate */ 1370*0Sstevel@tonic-gate if (mdissyserror(ep, ENOENT)) { 1371*0Sstevel@tonic-gate if (uname[0] == '/') { 1372*0Sstevel@tonic-gate /* Absolute name */ 1373*0Sstevel@tonic-gate char *p; 1374*0Sstevel@tonic-gate uint_t d = 0; 1375*0Sstevel@tonic-gate int l = 0; 1376*0Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1]; 1377*0Sstevel@tonic-gate 1378*0Sstevel@tonic-gate /* 1379*0Sstevel@tonic-gate * Handle old style raw names 1380*0Sstevel@tonic-gate */ 1381*0Sstevel@tonic-gate if (sscanf(uname, 1382*0Sstevel@tonic-gate "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 1383*0Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 1384*0Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(uname)) { 1385*0Sstevel@tonic-gate mdclrerror(ep); 1386*0Sstevel@tonic-gate rname = Strdup(uname); 1387*0Sstevel@tonic-gate *dnamep = metadiskname(rname); 1388*0Sstevel@tonic-gate return (rname); 1389*0Sstevel@tonic-gate } 1390*0Sstevel@tonic-gate 1391*0Sstevel@tonic-gate /* 1392*0Sstevel@tonic-gate * Handle old style block names 1393*0Sstevel@tonic-gate */ 1394*0Sstevel@tonic-gate if (sscanf(uname, 1395*0Sstevel@tonic-gate "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u" 1396*0Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 1397*0Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(uname)) { 1398*0Sstevel@tonic-gate len = strlen(uname) + 1 + 1; 1399*0Sstevel@tonic-gate rname = Malloc(len); 1400*0Sstevel@tonic-gate (void) snprintf(rname, len, "/dev/r%s%u%s", 1401*0Sstevel@tonic-gate onmb, d, snm); 1402*0Sstevel@tonic-gate *dnamep = metadiskname(rname); 1403*0Sstevel@tonic-gate return (rname); 1404*0Sstevel@tonic-gate } 1405*0Sstevel@tonic-gate 1406*0Sstevel@tonic-gate /* /.../dsk/... */ 1407*0Sstevel@tonic-gate if ((p = strstr(uname, "/dsk/")) != NULL) { 1408*0Sstevel@tonic-gate mdclrerror(ep); 1409*0Sstevel@tonic-gate ++p; 1410*0Sstevel@tonic-gate rname = Malloc(strlen(uname) + 1 + 1); 1411*0Sstevel@tonic-gate (void) strncpy(rname, uname, (p - uname)); 1412*0Sstevel@tonic-gate rname[(p - uname)] = 'r'; 1413*0Sstevel@tonic-gate (void) strcpy(&rname[(p - uname) + 1], p); 1414*0Sstevel@tonic-gate *dnamep = metadiskname(rname); 1415*0Sstevel@tonic-gate return (rname); 1416*0Sstevel@tonic-gate } 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate /* /.../rdsk/... */ 1419*0Sstevel@tonic-gate else if (strstr(uname, "/rdsk/") != NULL) { 1420*0Sstevel@tonic-gate mdclrerror(ep); 1421*0Sstevel@tonic-gate rname = Strdup(uname); 1422*0Sstevel@tonic-gate *dnamep = metadiskname(rname); 1423*0Sstevel@tonic-gate return (rname); 1424*0Sstevel@tonic-gate } 1425*0Sstevel@tonic-gate } else { 1426*0Sstevel@tonic-gate /* 1427*0Sstevel@tonic-gate * If it's not an absolute name but is a valid ctd name, 1428*0Sstevel@tonic-gate * guess at /dev/rdsk/... 1429*0Sstevel@tonic-gate */ 1430*0Sstevel@tonic-gate uint_t s; 1431*0Sstevel@tonic-gate if (parse_ctd(uname, &s) == 0) { 1432*0Sstevel@tonic-gate len = strlen(uname) + strlen("/dev/rdsk/") + 1; 1433*0Sstevel@tonic-gate rname = Malloc(len); 1434*0Sstevel@tonic-gate (void) snprintf(rname, len, "/dev/rdsk/%s", 1435*0Sstevel@tonic-gate uname); 1436*0Sstevel@tonic-gate *dnamep = metadiskname(rname); 1437*0Sstevel@tonic-gate return (rname); 1438*0Sstevel@tonic-gate } 1439*0Sstevel@tonic-gate } 1440*0Sstevel@tonic-gate } 1441*0Sstevel@tonic-gate 1442*0Sstevel@tonic-gate /* out of luck */ 1443*0Sstevel@tonic-gate return (NULL); 1444*0Sstevel@tonic-gate } 1445*0Sstevel@tonic-gate 1446*0Sstevel@tonic-gate /* 1447*0Sstevel@tonic-gate * get number of slices for name 1448*0Sstevel@tonic-gate */ 1449*0Sstevel@tonic-gate static int 1450*0Sstevel@tonic-gate getnslice( 1451*0Sstevel@tonic-gate char *rname, 1452*0Sstevel@tonic-gate char *dname, 1453*0Sstevel@tonic-gate uint_t *slicep 1454*0Sstevel@tonic-gate ) 1455*0Sstevel@tonic-gate { 1456*0Sstevel@tonic-gate char *srname; 1457*0Sstevel@tonic-gate uint_t nslice; 1458*0Sstevel@tonic-gate size_t dl = strlen(dname); 1459*0Sstevel@tonic-gate size_t rl = strlen(rname); 1460*0Sstevel@tonic-gate size_t l = 0; 1461*0Sstevel@tonic-gate size_t len; 1462*0Sstevel@tonic-gate 1463*0Sstevel@tonic-gate /* 1464*0Sstevel@tonic-gate * get our slice number - works only with names that end in s%u - 1465*0Sstevel@tonic-gate * all others return -1. 1466*0Sstevel@tonic-gate */ 1467*0Sstevel@tonic-gate if (dl >= rl || 1468*0Sstevel@tonic-gate sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl || 1469*0Sstevel@tonic-gate (int)*slicep < 0) { 1470*0Sstevel@tonic-gate return (-1); 1471*0Sstevel@tonic-gate } 1472*0Sstevel@tonic-gate 1473*0Sstevel@tonic-gate /* 1474*0Sstevel@tonic-gate * go find how many slices there really are 1475*0Sstevel@tonic-gate */ 1476*0Sstevel@tonic-gate len = strlen(dname) + 20 + 1; 1477*0Sstevel@tonic-gate srname = Malloc(len); 1478*0Sstevel@tonic-gate for (nslice = 0; /* void */; ++nslice) { 1479*0Sstevel@tonic-gate struct stat statbuf; 1480*0Sstevel@tonic-gate 1481*0Sstevel@tonic-gate /* build slice name */ 1482*0Sstevel@tonic-gate (void) snprintf(srname, len, "%ss%u", dname, nslice); 1483*0Sstevel@tonic-gate 1484*0Sstevel@tonic-gate /* see if it's there */ 1485*0Sstevel@tonic-gate if ((meta_stat(srname, &statbuf) != 0) || 1486*0Sstevel@tonic-gate (! S_ISCHR(statbuf.st_mode))) { 1487*0Sstevel@tonic-gate break; 1488*0Sstevel@tonic-gate } 1489*0Sstevel@tonic-gate } 1490*0Sstevel@tonic-gate Free(srname); 1491*0Sstevel@tonic-gate 1492*0Sstevel@tonic-gate /* Need to make sure that we at least have V_NUMPAR */ 1493*0Sstevel@tonic-gate nslice = max(nslice, V_NUMPAR); 1494*0Sstevel@tonic-gate 1495*0Sstevel@tonic-gate /* make sure we have at least our slice */ 1496*0Sstevel@tonic-gate if (nslice < *slicep) 1497*0Sstevel@tonic-gate return (-1); 1498*0Sstevel@tonic-gate 1499*0Sstevel@tonic-gate /* return number of slices */ 1500*0Sstevel@tonic-gate return (nslice); 1501*0Sstevel@tonic-gate } 1502*0Sstevel@tonic-gate 1503*0Sstevel@tonic-gate /* 1504*0Sstevel@tonic-gate * Attempt to parse the input string as a c[t]ds specifier 1505*0Sstevel@tonic-gate * The target can either be a SCSI target id or if the device 1506*0Sstevel@tonic-gate * is in a fabric configuration in a fibre channel setup then 1507*0Sstevel@tonic-gate * the target is a standard WWN (world wide name). 1508*0Sstevel@tonic-gate * 1509*0Sstevel@tonic-gate * if successful return 0 1510*0Sstevel@tonic-gate * if c[t]dp name return 1 1511*0Sstevel@tonic-gate * otherwise return -1 1512*0Sstevel@tonic-gate */ 1513*0Sstevel@tonic-gate int 1514*0Sstevel@tonic-gate parse_ctd( 1515*0Sstevel@tonic-gate char *uname, 1516*0Sstevel@tonic-gate uint_t *slice) 1517*0Sstevel@tonic-gate { 1518*0Sstevel@tonic-gate uint_t channel; 1519*0Sstevel@tonic-gate uint_t target; 1520*0Sstevel@tonic-gate uint_t device; 1521*0Sstevel@tonic-gate int has_target = 1; 1522*0Sstevel@tonic-gate uint_t cl; 1523*0Sstevel@tonic-gate uint_t target_str_len; 1524*0Sstevel@tonic-gate char *partial_ctd_str; 1525*0Sstevel@tonic-gate char *target_str; 1526*0Sstevel@tonic-gate char *device_start_pos; 1527*0Sstevel@tonic-gate int l = -1; 1528*0Sstevel@tonic-gate 1529*0Sstevel@tonic-gate /* pull off the channel spec and the 't' for the target */ 1530*0Sstevel@tonic-gate if (sscanf(uname, "c%ut%n", &channel, &l) != 1 || l == -1) { 1531*0Sstevel@tonic-gate /* check for cds style name */ 1532*0Sstevel@tonic-gate if (sscanf(uname, "c%ud%n", &channel, &l) != 1 || l == -1) { 1533*0Sstevel@tonic-gate return (-1); 1534*0Sstevel@tonic-gate } else { 1535*0Sstevel@tonic-gate l--; /* we want to be on the 'd' */ 1536*0Sstevel@tonic-gate has_target = 0; 1537*0Sstevel@tonic-gate } 1538*0Sstevel@tonic-gate } 1539*0Sstevel@tonic-gate partial_ctd_str = uname + l; 1540*0Sstevel@tonic-gate 1541*0Sstevel@tonic-gate /* find the beginning of the device specifier */ 1542*0Sstevel@tonic-gate device_start_pos = strrchr(partial_ctd_str, 'd'); 1543*0Sstevel@tonic-gate if (device_start_pos == NULL) { 1544*0Sstevel@tonic-gate return (-1); 1545*0Sstevel@tonic-gate } 1546*0Sstevel@tonic-gate 1547*0Sstevel@tonic-gate /* check to see if it is a ctd with a WWN or SCSI target */ 1548*0Sstevel@tonic-gate if (has_target) { 1549*0Sstevel@tonic-gate /* pull off the target and see if it is a WWN */ 1550*0Sstevel@tonic-gate target_str_len = device_start_pos - partial_ctd_str + 2; 1551*0Sstevel@tonic-gate target_str = (char *)Malloc(target_str_len+1); 1552*0Sstevel@tonic-gate (void) strcpy(target_str, "0X"); 1553*0Sstevel@tonic-gate (void) strncpy(target_str+2, partial_ctd_str, 1554*0Sstevel@tonic-gate target_str_len - 2); 1555*0Sstevel@tonic-gate target_str[target_str_len] = '\0'; 1556*0Sstevel@tonic-gate if (sscanf(target_str, "%x%n", &target, &l) != 1 || 1557*0Sstevel@tonic-gate l != target_str_len) { 1558*0Sstevel@tonic-gate Free(target_str); 1559*0Sstevel@tonic-gate return (-1); 1560*0Sstevel@tonic-gate } 1561*0Sstevel@tonic-gate Free(target_str); 1562*0Sstevel@tonic-gate } 1563*0Sstevel@tonic-gate 1564*0Sstevel@tonic-gate /* check the device and slice */ 1565*0Sstevel@tonic-gate cl = strlen(device_start_pos); 1566*0Sstevel@tonic-gate if (sscanf(device_start_pos, "d%us%u%n", &device, slice, &l) != 2 || 1567*0Sstevel@tonic-gate l != cl) { 1568*0Sstevel@tonic-gate /* check the device and partition */ 1569*0Sstevel@tonic-gate if (sscanf(device_start_pos, "d%up%u%n", &device, slice, &l) 1570*0Sstevel@tonic-gate == 2 && l == cl) { 1571*0Sstevel@tonic-gate return (1); 1572*0Sstevel@tonic-gate } 1573*0Sstevel@tonic-gate return (-1); 1574*0Sstevel@tonic-gate } 1575*0Sstevel@tonic-gate 1576*0Sstevel@tonic-gate return (0); 1577*0Sstevel@tonic-gate } 1578*0Sstevel@tonic-gate 1579*0Sstevel@tonic-gate 1580*0Sstevel@tonic-gate /* 1581*0Sstevel@tonic-gate * get number of slices for name 1582*0Sstevel@tonic-gate */ 1583*0Sstevel@tonic-gate static int 1584*0Sstevel@tonic-gate uname2sliceno( 1585*0Sstevel@tonic-gate char *uname, 1586*0Sstevel@tonic-gate uint_t *slicep, 1587*0Sstevel@tonic-gate md_error_t *ep 1588*0Sstevel@tonic-gate ) 1589*0Sstevel@tonic-gate { 1590*0Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0; 1591*0Sstevel@tonic-gate int l = 0, cl = 0; 1592*0Sstevel@tonic-gate int fd; 1593*0Sstevel@tonic-gate struct dk_cinfo cinfo; 1594*0Sstevel@tonic-gate char *p; 1595*0Sstevel@tonic-gate char *rname = NULL; 1596*0Sstevel@tonic-gate 1597*0Sstevel@tonic-gate if (is_metaname(uname)) 1598*0Sstevel@tonic-gate return (*slicep = 0); 1599*0Sstevel@tonic-gate 1600*0Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL) 1601*0Sstevel@tonic-gate p++; 1602*0Sstevel@tonic-gate else 1603*0Sstevel@tonic-gate p = uname; 1604*0Sstevel@tonic-gate 1605*0Sstevel@tonic-gate cl = strlen(p); 1606*0Sstevel@tonic-gate 1607*0Sstevel@tonic-gate if (parse_ctd(p, slicep) == 0) 1608*0Sstevel@tonic-gate return (*slicep); 1609*0Sstevel@tonic-gate else if (sscanf(p, "mc%ut%ud%us%u%n", &c, &t, &d, slicep, &l) == 4 && 1610*0Sstevel@tonic-gate l == cl) 1611*0Sstevel@tonic-gate return (*slicep); 1612*0Sstevel@tonic-gate else if (sscanf(p, "d%us%u%n", &d, slicep, &l) == 2 && l == cl) 1613*0Sstevel@tonic-gate return (*slicep); 1614*0Sstevel@tonic-gate 1615*0Sstevel@tonic-gate /* 1616*0Sstevel@tonic-gate * If we can't get the slice from the name, then we have to do it the 1617*0Sstevel@tonic-gate * hard and expensive way. 1618*0Sstevel@tonic-gate */ 1619*0Sstevel@tonic-gate if ((rname = rawname(uname)) == NULL) 1620*0Sstevel@tonic-gate return (-1); 1621*0Sstevel@tonic-gate 1622*0Sstevel@tonic-gate /* get controller info */ 1623*0Sstevel@tonic-gate if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) { 1624*0Sstevel@tonic-gate Free(rname); 1625*0Sstevel@tonic-gate return (-1); 1626*0Sstevel@tonic-gate } 1627*0Sstevel@tonic-gate 1628*0Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &cinfo) != 0) { 1629*0Sstevel@tonic-gate int save = errno; 1630*0Sstevel@tonic-gate 1631*0Sstevel@tonic-gate if (save == ENOTTY) 1632*0Sstevel@tonic-gate (void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname); 1633*0Sstevel@tonic-gate else 1634*0Sstevel@tonic-gate (void) mdsyserror(ep, save, rname); 1635*0Sstevel@tonic-gate 1636*0Sstevel@tonic-gate Free(rname); 1637*0Sstevel@tonic-gate (void) close(fd); 1638*0Sstevel@tonic-gate return (-1); 1639*0Sstevel@tonic-gate } 1640*0Sstevel@tonic-gate (void) close(fd); /* sd/ssd bug */ 1641*0Sstevel@tonic-gate 1642*0Sstevel@tonic-gate if (cinfo.dki_partition < V_NUMPAR) { 1643*0Sstevel@tonic-gate Free(rname); 1644*0Sstevel@tonic-gate return (*slicep = cinfo.dki_partition); 1645*0Sstevel@tonic-gate } 1646*0Sstevel@tonic-gate 1647*0Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname)); 1648*0Sstevel@tonic-gate } 1649*0Sstevel@tonic-gate 1650*0Sstevel@tonic-gate /* 1651*0Sstevel@tonic-gate * get partition info 1652*0Sstevel@tonic-gate */ 1653*0Sstevel@tonic-gate static int 1654*0Sstevel@tonic-gate getparts( 1655*0Sstevel@tonic-gate mddrivename_t *dnp, 1656*0Sstevel@tonic-gate char *rname, 1657*0Sstevel@tonic-gate char *dname, 1658*0Sstevel@tonic-gate uint_t *npartsp, 1659*0Sstevel@tonic-gate uint_t *partnop, 1660*0Sstevel@tonic-gate md_error_t *ep 1661*0Sstevel@tonic-gate ) 1662*0Sstevel@tonic-gate { 1663*0Sstevel@tonic-gate int nparts; 1664*0Sstevel@tonic-gate uint_t partno; 1665*0Sstevel@tonic-gate mdname_t name; 1666*0Sstevel@tonic-gate mdvtoc_t *vtocp; 1667*0Sstevel@tonic-gate 1668*0Sstevel@tonic-gate /* metadevice */ 1669*0Sstevel@tonic-gate if (is_metaname(rname)) { 1670*0Sstevel@tonic-gate dnp->type = MDT_META; 1671*0Sstevel@tonic-gate nparts = 1; 1672*0Sstevel@tonic-gate partno = 0; 1673*0Sstevel@tonic-gate goto gotit; 1674*0Sstevel@tonic-gate } 1675*0Sstevel@tonic-gate 1676*0Sstevel@tonic-gate /* see how many partitions in drive, this is really tricky */ 1677*0Sstevel@tonic-gate metainitname(&name); 1678*0Sstevel@tonic-gate name.rname = rname; 1679*0Sstevel@tonic-gate name.drivenamep = dnp; 1680*0Sstevel@tonic-gate if ((vtocp = metagetvtoc(&name, TRUE, &partno, ep)) != NULL) { 1681*0Sstevel@tonic-gate dnp->type = MDT_COMP; 1682*0Sstevel@tonic-gate nparts = vtocp->nparts; 1683*0Sstevel@tonic-gate /* partno already setup */ 1684*0Sstevel@tonic-gate /* dname already setup */ 1685*0Sstevel@tonic-gate goto gotit; 1686*0Sstevel@tonic-gate } 1687*0Sstevel@tonic-gate 1688*0Sstevel@tonic-gate if ((ep->info.errclass == MDEC_DEV) && 1689*0Sstevel@tonic-gate (ep->info.md_error_info_t_u.dev_error.errnum == MDE_TOO_MANY_PARTS)) 1690*0Sstevel@tonic-gate return (-1); 1691*0Sstevel@tonic-gate 1692*0Sstevel@tonic-gate /* fallback and try and guess (used to check for just EACCES here) */ 1693*0Sstevel@tonic-gate if ((dname != NULL) && 1694*0Sstevel@tonic-gate ((nparts = getnslice(rname, dname, &partno)) > 0)) { 1695*0Sstevel@tonic-gate dnp->type = MDT_ACCES; 1696*0Sstevel@tonic-gate if (mdanysyserror(ep)) { 1697*0Sstevel@tonic-gate dnp->errnum = 1698*0Sstevel@tonic-gate ep->info.md_error_info_t_u.sys_error.errnum; 1699*0Sstevel@tonic-gate } else { 1700*0Sstevel@tonic-gate dnp->errnum = ENOENT; 1701*0Sstevel@tonic-gate } 1702*0Sstevel@tonic-gate mdclrerror(ep); 1703*0Sstevel@tonic-gate /* nparts already setup */ 1704*0Sstevel@tonic-gate /* partno already setup */ 1705*0Sstevel@tonic-gate /* dname already setup */ 1706*0Sstevel@tonic-gate nparts = roundup(nparts, V_NUMPAR); 1707*0Sstevel@tonic-gate goto gotit; 1708*0Sstevel@tonic-gate } 1709*0Sstevel@tonic-gate 1710*0Sstevel@tonic-gate /* nothing worked */ 1711*0Sstevel@tonic-gate dnp->type = MDT_UNKNOWN; 1712*0Sstevel@tonic-gate if (mdissyserror(ep, EACCES)) 1713*0Sstevel@tonic-gate dnp->type = MDT_ACCES; 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate if (mdanysyserror(ep)) { 1716*0Sstevel@tonic-gate dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum; 1717*0Sstevel@tonic-gate } else { 1718*0Sstevel@tonic-gate dnp->errnum = ENOENT; 1719*0Sstevel@tonic-gate } 1720*0Sstevel@tonic-gate 1721*0Sstevel@tonic-gate mdclrerror(ep); 1722*0Sstevel@tonic-gate nparts = V_NUMPAR; 1723*0Sstevel@tonic-gate if (uname2sliceno(rname, &partno, ep) < 0) { 1724*0Sstevel@tonic-gate mdclrerror(ep); 1725*0Sstevel@tonic-gate partno = 0; 1726*0Sstevel@tonic-gate } 1727*0Sstevel@tonic-gate 1728*0Sstevel@tonic-gate /* return success */ 1729*0Sstevel@tonic-gate gotit: 1730*0Sstevel@tonic-gate assert(nparts > 0); 1731*0Sstevel@tonic-gate 1732*0Sstevel@tonic-gate if (partno >= nparts) 1733*0Sstevel@tonic-gate return (mdsyserror(ep, ENOENT, rname)); 1734*0Sstevel@tonic-gate 1735*0Sstevel@tonic-gate *npartsp = nparts; 1736*0Sstevel@tonic-gate *partnop = partno; 1737*0Sstevel@tonic-gate return (0); 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate 1740*0Sstevel@tonic-gate /* 1741*0Sstevel@tonic-gate * get block name 1742*0Sstevel@tonic-gate */ 1743*0Sstevel@tonic-gate static int 1744*0Sstevel@tonic-gate getbname( 1745*0Sstevel@tonic-gate mdname_t *np, 1746*0Sstevel@tonic-gate md_error_t *ep 1747*0Sstevel@tonic-gate ) 1748*0Sstevel@tonic-gate { 1749*0Sstevel@tonic-gate char *rname = np->rname; 1750*0Sstevel@tonic-gate char *bname; 1751*0Sstevel@tonic-gate 1752*0Sstevel@tonic-gate /* fully qualified */ 1753*0Sstevel@tonic-gate assert(rname != NULL); 1754*0Sstevel@tonic-gate if ((bname = blkname(rname)) != NULL) { 1755*0Sstevel@tonic-gate if (np->bname) 1756*0Sstevel@tonic-gate Free(np->bname); 1757*0Sstevel@tonic-gate np->bname = bname; 1758*0Sstevel@tonic-gate return (0); 1759*0Sstevel@tonic-gate } 1760*0Sstevel@tonic-gate 1761*0Sstevel@tonic-gate /* out of luck */ 1762*0Sstevel@tonic-gate return (mdsyserror(ep, ENOENT, rname)); 1763*0Sstevel@tonic-gate } 1764*0Sstevel@tonic-gate 1765*0Sstevel@tonic-gate static void 1766*0Sstevel@tonic-gate getcname( 1767*0Sstevel@tonic-gate mdsetname_t *sp, 1768*0Sstevel@tonic-gate mdname_t *np 1769*0Sstevel@tonic-gate ) 1770*0Sstevel@tonic-gate { 1771*0Sstevel@tonic-gate char *sname = sp->setname; 1772*0Sstevel@tonic-gate char *bname = np->bname; 1773*0Sstevel@tonic-gate char *p; 1774*0Sstevel@tonic-gate size_t len; 1775*0Sstevel@tonic-gate 1776*0Sstevel@tonic-gate assert(sname != NULL); 1777*0Sstevel@tonic-gate assert(bname != NULL); 1778*0Sstevel@tonic-gate assert(np->drivenamep->type != MDT_FAST_COMP && 1779*0Sstevel@tonic-gate np->drivenamep->type != MDT_FAST_META); 1780*0Sstevel@tonic-gate 1781*0Sstevel@tonic-gate /* regular device */ 1782*0Sstevel@tonic-gate if ((strncmp(bname, "/dev/dsk/", strlen("/dev/dsk/")) == 0) && 1783*0Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/dsk/")), '/') == NULL)) { 1784*0Sstevel@tonic-gate if (np->cname) 1785*0Sstevel@tonic-gate Free(np->cname); 1786*0Sstevel@tonic-gate np->cname = Strdup(p); 1787*0Sstevel@tonic-gate return; 1788*0Sstevel@tonic-gate } 1789*0Sstevel@tonic-gate 1790*0Sstevel@tonic-gate if ((strncmp(bname, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) && 1791*0Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/ap/dsk/")), '/') == NULL)) { 1792*0Sstevel@tonic-gate if (np->cname) 1793*0Sstevel@tonic-gate Free(np->cname); 1794*0Sstevel@tonic-gate np->cname = Strdup(p); 1795*0Sstevel@tonic-gate return; 1796*0Sstevel@tonic-gate } 1797*0Sstevel@tonic-gate 1798*0Sstevel@tonic-gate if ((strncmp(bname, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) && 1799*0Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/did/dsk/")), '/') == NULL)) { 1800*0Sstevel@tonic-gate if (np->cname) 1801*0Sstevel@tonic-gate Free(np->cname); 1802*0Sstevel@tonic-gate np->cname = Strdup(p); 1803*0Sstevel@tonic-gate return; 1804*0Sstevel@tonic-gate } 1805*0Sstevel@tonic-gate 1806*0Sstevel@tonic-gate /* anything else but metadevice */ 1807*0Sstevel@tonic-gate if (np->drivenamep->type != MDT_META) { 1808*0Sstevel@tonic-gate if (np->cname) 1809*0Sstevel@tonic-gate Free(np->cname); 1810*0Sstevel@tonic-gate np->cname = Strdup(bname); 1811*0Sstevel@tonic-gate return; 1812*0Sstevel@tonic-gate } 1813*0Sstevel@tonic-gate 1814*0Sstevel@tonic-gate /* metadevice */ 1815*0Sstevel@tonic-gate p = strrchr(bname, '/'); 1816*0Sstevel@tonic-gate assert(p != NULL); 1817*0Sstevel@tonic-gate ++p; 1818*0Sstevel@tonic-gate if (metaislocalset(sp)) { 1819*0Sstevel@tonic-gate if (np->cname) 1820*0Sstevel@tonic-gate Free(np->cname); 1821*0Sstevel@tonic-gate np->cname = Strdup(p); 1822*0Sstevel@tonic-gate } else { 1823*0Sstevel@tonic-gate assert(sname[0] != '\0'); 1824*0Sstevel@tonic-gate if (np->cname) 1825*0Sstevel@tonic-gate Free(np->cname); 1826*0Sstevel@tonic-gate len = strlen(sname) + 1 + strlen(p) + 1; 1827*0Sstevel@tonic-gate np->cname = Malloc(len); 1828*0Sstevel@tonic-gate (void) snprintf(np->cname, len, "%s/%s", sname, p); 1829*0Sstevel@tonic-gate } 1830*0Sstevel@tonic-gate } 1831*0Sstevel@tonic-gate 1832*0Sstevel@tonic-gate /* 1833*0Sstevel@tonic-gate * get dev 1834*0Sstevel@tonic-gate */ 1835*0Sstevel@tonic-gate int 1836*0Sstevel@tonic-gate meta_getdev( 1837*0Sstevel@tonic-gate mdsetname_t *sp, 1838*0Sstevel@tonic-gate mdname_t *np, 1839*0Sstevel@tonic-gate md_error_t *ep 1840*0Sstevel@tonic-gate ) 1841*0Sstevel@tonic-gate { 1842*0Sstevel@tonic-gate struct stat statbuf; 1843*0Sstevel@tonic-gate 1844*0Sstevel@tonic-gate /* get dev */ 1845*0Sstevel@tonic-gate if (meta_stat(np->rname, &statbuf) != 0) 1846*0Sstevel@tonic-gate return (mdsyserror(ep, errno, np->rname)); 1847*0Sstevel@tonic-gate else if (! S_ISCHR(statbuf.st_mode)) 1848*0Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, NODEV64, np->rname)); 1849*0Sstevel@tonic-gate np->dev = meta_expldev(statbuf.st_rdev); 1850*0Sstevel@tonic-gate 1851*0Sstevel@tonic-gate assert(np->drivenamep->type != MDT_FAST_META && 1852*0Sstevel@tonic-gate np->drivenamep->type != MDT_FAST_COMP); 1853*0Sstevel@tonic-gate 1854*0Sstevel@tonic-gate /* check set */ 1855*0Sstevel@tonic-gate assert((np->drivenamep->type == MDT_META) ? 1856*0Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1); 1857*0Sstevel@tonic-gate 1858*0Sstevel@tonic-gate /* return sucess */ 1859*0Sstevel@tonic-gate return (0); 1860*0Sstevel@tonic-gate } 1861*0Sstevel@tonic-gate 1862*0Sstevel@tonic-gate /* 1863*0Sstevel@tonic-gate * set up names for a slice 1864*0Sstevel@tonic-gate */ 1865*0Sstevel@tonic-gate static int 1866*0Sstevel@tonic-gate getnames( 1867*0Sstevel@tonic-gate mdsetname_t *sp, 1868*0Sstevel@tonic-gate mdname_t *np, 1869*0Sstevel@tonic-gate char *rname, 1870*0Sstevel@tonic-gate md_error_t *ep 1871*0Sstevel@tonic-gate ) 1872*0Sstevel@tonic-gate { 1873*0Sstevel@tonic-gate /* get names */ 1874*0Sstevel@tonic-gate if (np->rname) 1875*0Sstevel@tonic-gate Free(np->rname); 1876*0Sstevel@tonic-gate np->rname = Strdup(rname); 1877*0Sstevel@tonic-gate if (getbname(np, ep) != 0) 1878*0Sstevel@tonic-gate return (-1); 1879*0Sstevel@tonic-gate getcname(sp, np); 1880*0Sstevel@tonic-gate if (meta_getdev(sp, np, ep) != 0) 1881*0Sstevel@tonic-gate return (-1); 1882*0Sstevel@tonic-gate 1883*0Sstevel@tonic-gate /* return success */ 1884*0Sstevel@tonic-gate return (0); 1885*0Sstevel@tonic-gate } 1886*0Sstevel@tonic-gate 1887*0Sstevel@tonic-gate /* 1888*0Sstevel@tonic-gate * fake up names for a slice 1889*0Sstevel@tonic-gate */ 1890*0Sstevel@tonic-gate static void 1891*0Sstevel@tonic-gate getfakenames( 1892*0Sstevel@tonic-gate mdsetname_t *sp, 1893*0Sstevel@tonic-gate mdname_t *np, 1894*0Sstevel@tonic-gate char *rname 1895*0Sstevel@tonic-gate ) 1896*0Sstevel@tonic-gate { 1897*0Sstevel@tonic-gate char *p; 1898*0Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1]; 1899*0Sstevel@tonic-gate uint_t d = 0; 1900*0Sstevel@tonic-gate int l = 0; 1901*0Sstevel@tonic-gate 1902*0Sstevel@tonic-gate /* fake names */ 1903*0Sstevel@tonic-gate if (np->rname != NULL) 1904*0Sstevel@tonic-gate Free(np->rname); 1905*0Sstevel@tonic-gate np->rname = Strdup(rname); 1906*0Sstevel@tonic-gate 1907*0Sstevel@tonic-gate if (np->bname != NULL) 1908*0Sstevel@tonic-gate Free(np->bname); 1909*0Sstevel@tonic-gate np->bname = Strdup(rname); 1910*0Sstevel@tonic-gate 1911*0Sstevel@tonic-gate /* 1912*0Sstevel@tonic-gate * Fixup old style names 1913*0Sstevel@tonic-gate */ 1914*0Sstevel@tonic-gate if (sscanf(rname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 1915*0Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 1916*0Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(rname)) 1917*0Sstevel@tonic-gate (void) snprintf(np->bname, l, "/dev/%s%u%s", onmb, d, snm); 1918*0Sstevel@tonic-gate 1919*0Sstevel@tonic-gate /* 1920*0Sstevel@tonic-gate * Fixup new style names 1921*0Sstevel@tonic-gate */ 1922*0Sstevel@tonic-gate if ((p = strstr(np->bname, "/rdsk/")) != NULL) { 1923*0Sstevel@tonic-gate for (++p; (*(p + 1) != '\0'); ++p) 1924*0Sstevel@tonic-gate *p = *(p + 1); 1925*0Sstevel@tonic-gate *p = '\0'; 1926*0Sstevel@tonic-gate } 1927*0Sstevel@tonic-gate 1928*0Sstevel@tonic-gate if (np->cname != NULL) 1929*0Sstevel@tonic-gate Free(np->cname); 1930*0Sstevel@tonic-gate getcname(sp, np); 1931*0Sstevel@tonic-gate } 1932*0Sstevel@tonic-gate 1933*0Sstevel@tonic-gate static mdname_t * 1934*0Sstevel@tonic-gate setup_slice( 1935*0Sstevel@tonic-gate mdsetname_t *sp, 1936*0Sstevel@tonic-gate mddrivename_t *dnp, 1937*0Sstevel@tonic-gate char *uname, 1938*0Sstevel@tonic-gate char *rname, 1939*0Sstevel@tonic-gate char *dname, 1940*0Sstevel@tonic-gate uint_t partno, 1941*0Sstevel@tonic-gate md_error_t *ep 1942*0Sstevel@tonic-gate ) 1943*0Sstevel@tonic-gate { 1944*0Sstevel@tonic-gate char *srname = NULL; 1945*0Sstevel@tonic-gate mdname_t *np; 1946*0Sstevel@tonic-gate 1947*0Sstevel@tonic-gate /* must have a set */ 1948*0Sstevel@tonic-gate assert(sp != NULL); 1949*0Sstevel@tonic-gate assert(partno < dnp->parts.parts_len); 1950*0Sstevel@tonic-gate assert(dname != NULL); 1951*0Sstevel@tonic-gate 1952*0Sstevel@tonic-gate np = &dnp->parts.parts_val[partno]; 1953*0Sstevel@tonic-gate 1954*0Sstevel@tonic-gate if (rname) 1955*0Sstevel@tonic-gate srname = rname; 1956*0Sstevel@tonic-gate else if (is_metaname(dname)) 1957*0Sstevel@tonic-gate srname = dname; 1958*0Sstevel@tonic-gate else { 1959*0Sstevel@tonic-gate char onmb[BUFSIZ+1]; 1960*0Sstevel@tonic-gate uint_t d = 0; 1961*0Sstevel@tonic-gate int l = 0, cl = strlen(dname); 1962*0Sstevel@tonic-gate size_t len; 1963*0Sstevel@tonic-gate 1964*0Sstevel@tonic-gate len = cl + 20 + 1; 1965*0Sstevel@tonic-gate srname = Malloc(len); 1966*0Sstevel@tonic-gate 1967*0Sstevel@tonic-gate /* 1968*0Sstevel@tonic-gate * Handle /dev/rXXNN. 1969*0Sstevel@tonic-gate */ 1970*0Sstevel@tonic-gate if (sscanf(dname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%n", 1971*0Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 1972*0Sstevel@tonic-gate (void) snprintf(srname, len, "/dev/r%s%u%c", onmb, d, 1973*0Sstevel@tonic-gate 'a' + partno); 1974*0Sstevel@tonic-gate } else if (sscanf(dname, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%n", 1975*0Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 1976*0Sstevel@tonic-gate (void) snprintf(srname, len, "/dev/%s%u%c", onmb, d, 1977*0Sstevel@tonic-gate 'a' + partno); 1978*0Sstevel@tonic-gate } else { 1979*0Sstevel@tonic-gate /* build the slice that is wanted */ 1980*0Sstevel@tonic-gate (void) snprintf(srname, len, "%ss%u", dname, partno); 1981*0Sstevel@tonic-gate } 1982*0Sstevel@tonic-gate } 1983*0Sstevel@tonic-gate 1984*0Sstevel@tonic-gate if (getnames(sp, np, srname, ep) != 0) { 1985*0Sstevel@tonic-gate if (dnp->type == MDT_UNKNOWN) { 1986*0Sstevel@tonic-gate mdclrerror(ep); 1987*0Sstevel@tonic-gate getfakenames(sp, np, srname); 1988*0Sstevel@tonic-gate } else if (dnp->type == MDT_COMP && mdissyserror(ep, ENOENT)) { 1989*0Sstevel@tonic-gate dnp->type = MDT_UNKNOWN; 1990*0Sstevel@tonic-gate if (mdanysyserror(ep)) { 1991*0Sstevel@tonic-gate dnp->errnum = 1992*0Sstevel@tonic-gate ep->info.md_error_info_t_u.sys_error.errnum; 1993*0Sstevel@tonic-gate } else { 1994*0Sstevel@tonic-gate dnp->errnum = ENOENT; 1995*0Sstevel@tonic-gate } 1996*0Sstevel@tonic-gate mdclrerror(ep); 1997*0Sstevel@tonic-gate getfakenames(sp, np, srname); 1998*0Sstevel@tonic-gate } else { 1999*0Sstevel@tonic-gate mdclrerror(ep); 2000*0Sstevel@tonic-gate if (getnames(sp, np, dname, ep) != 0) { 2001*0Sstevel@tonic-gate np = NULL; 2002*0Sstevel@tonic-gate goto fixup; 2003*0Sstevel@tonic-gate } 2004*0Sstevel@tonic-gate } 2005*0Sstevel@tonic-gate } 2006*0Sstevel@tonic-gate 2007*0Sstevel@tonic-gate out: 2008*0Sstevel@tonic-gate if ((srname != rname) && (srname != dname)) 2009*0Sstevel@tonic-gate Free(srname); 2010*0Sstevel@tonic-gate 2011*0Sstevel@tonic-gate /* return name */ 2012*0Sstevel@tonic-gate return (np); 2013*0Sstevel@tonic-gate 2014*0Sstevel@tonic-gate fixup: 2015*0Sstevel@tonic-gate if (mdanysyserror(ep)) { 2016*0Sstevel@tonic-gate char *p; 2017*0Sstevel@tonic-gate int errnum = ep->info.md_error_info_t_u.sys_error.errnum; 2018*0Sstevel@tonic-gate 2019*0Sstevel@tonic-gate mdclrerror(ep); 2020*0Sstevel@tonic-gate if (uname && *uname) { 2021*0Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL) 2022*0Sstevel@tonic-gate (void) mdsyserror(ep, errnum, ++p); 2023*0Sstevel@tonic-gate else 2024*0Sstevel@tonic-gate (void) mdsyserror(ep, errnum, uname); 2025*0Sstevel@tonic-gate } else { 2026*0Sstevel@tonic-gate if ((p = strrchr(srname, '/')) != NULL) 2027*0Sstevel@tonic-gate (void) mdsyserror(ep, errnum, ++p); 2028*0Sstevel@tonic-gate else 2029*0Sstevel@tonic-gate (void) mdsyserror(ep, errnum, srname); 2030*0Sstevel@tonic-gate } 2031*0Sstevel@tonic-gate } 2032*0Sstevel@tonic-gate goto out; 2033*0Sstevel@tonic-gate } 2034*0Sstevel@tonic-gate 2035*0Sstevel@tonic-gate /* 2036*0Sstevel@tonic-gate * flush the fast name cache 2037*0Sstevel@tonic-gate */ 2038*0Sstevel@tonic-gate static void 2039*0Sstevel@tonic-gate metafreefastnm(mdname_t **np) 2040*0Sstevel@tonic-gate { 2041*0Sstevel@tonic-gate mddrivename_t *dnp; 2042*0Sstevel@tonic-gate 2043*0Sstevel@tonic-gate assert(np != NULL && *np != NULL); 2044*0Sstevel@tonic-gate 2045*0Sstevel@tonic-gate if ((dnp = (*np)->drivenamep) != NULL) { 2046*0Sstevel@tonic-gate if (dnp->cname != NULL) 2047*0Sstevel@tonic-gate Free(dnp->cname); 2048*0Sstevel@tonic-gate if (dnp->rname != NULL) 2049*0Sstevel@tonic-gate Free(dnp->rname); 2050*0Sstevel@tonic-gate if (dnp->miscname != NULL) 2051*0Sstevel@tonic-gate Free(dnp->miscname); 2052*0Sstevel@tonic-gate meta_free_unit(dnp); 2053*0Sstevel@tonic-gate Free(dnp); 2054*0Sstevel@tonic-gate } 2055*0Sstevel@tonic-gate if ((*np)->cname != NULL) 2056*0Sstevel@tonic-gate Free((*np)->cname); 2057*0Sstevel@tonic-gate if ((*np)->bname != NULL) 2058*0Sstevel@tonic-gate Free((*np)->bname); 2059*0Sstevel@tonic-gate if ((*np)->rname != NULL) 2060*0Sstevel@tonic-gate Free((*np)->rname); 2061*0Sstevel@tonic-gate if ((*np)->devicesname != NULL) 2062*0Sstevel@tonic-gate Free((*np)->devicesname); 2063*0Sstevel@tonic-gate Free(*np); 2064*0Sstevel@tonic-gate *np = NULL; 2065*0Sstevel@tonic-gate } 2066*0Sstevel@tonic-gate 2067*0Sstevel@tonic-gate /* 2068*0Sstevel@tonic-gate * flush the fast name cache 2069*0Sstevel@tonic-gate */ 2070*0Sstevel@tonic-gate static void 2071*0Sstevel@tonic-gate metaflushfastnames() 2072*0Sstevel@tonic-gate { 2073*0Sstevel@tonic-gate mdnamelist_t *p, *n; 2074*0Sstevel@tonic-gate 2075*0Sstevel@tonic-gate for (p = fastnmlp, n = NULL; (p != NULL); p = n) { 2076*0Sstevel@tonic-gate n = p->next; 2077*0Sstevel@tonic-gate metafreefastnm(&p->namep); 2078*0Sstevel@tonic-gate Free(p); 2079*0Sstevel@tonic-gate } 2080*0Sstevel@tonic-gate fastnmlp = NULL; 2081*0Sstevel@tonic-gate } 2082*0Sstevel@tonic-gate 2083*0Sstevel@tonic-gate static char * 2084*0Sstevel@tonic-gate getrname_fast(char *unm, md_error_t *ep) 2085*0Sstevel@tonic-gate { 2086*0Sstevel@tonic-gate uint_t d = 0; 2087*0Sstevel@tonic-gate int l = 0; 2088*0Sstevel@tonic-gate int cl = strlen(unm); 2089*0Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1], cnmb[BUFSIZ]; 2090*0Sstevel@tonic-gate char *rnm; 2091*0Sstevel@tonic-gate char *p; 2092*0Sstevel@tonic-gate size_t len; 2093*0Sstevel@tonic-gate 2094*0Sstevel@tonic-gate if (is_metaname(unm)) { 2095*0Sstevel@tonic-gate /* without set */ 2096*0Sstevel@tonic-gate if (sscanf(unm, "d%u%n", &d, &l) == 1 && cl == l) { 2097*0Sstevel@tonic-gate rnm = Zalloc(14 + cl + 1); 2098*0Sstevel@tonic-gate (void) sprintf(rnm, "/dev/md/rdsk/d%u", d); 2099*0Sstevel@tonic-gate return (rnm); 2100*0Sstevel@tonic-gate } 2101*0Sstevel@tonic-gate 2102*0Sstevel@tonic-gate /* fully-qualified without set */ 2103*0Sstevel@tonic-gate if ((sscanf(unm, "/dev/md/dsk/d%u%n", &d, &l) == 1 || 2104*0Sstevel@tonic-gate sscanf(unm, "/dev/md/rdsk/d%u%n", &d, &l) == 1) && 2105*0Sstevel@tonic-gate cl == l) { 2106*0Sstevel@tonic-gate rnm = Zalloc(14 + cl + 1); 2107*0Sstevel@tonic-gate (void) sprintf(rnm, "/dev/md/rdsk/d%u", d); 2108*0Sstevel@tonic-gate return (rnm); 2109*0Sstevel@tonic-gate } 2110*0Sstevel@tonic-gate 2111*0Sstevel@tonic-gate /* with set */ 2112*0Sstevel@tonic-gate if ((sscanf(unm, 2113*0Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[^/]/d%u%n", snm, &d, &l) == 2 || 2114*0Sstevel@tonic-gate sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/d%u%n", 2115*0Sstevel@tonic-gate snm, &d, &l) == 2 || 2116*0Sstevel@tonic-gate sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/rdsk/d%u%n", 2117*0Sstevel@tonic-gate snm, &d, &l) == 2) && cl == l) { 2118*0Sstevel@tonic-gate len = 14 + cl + strlen(snm) + 1; 2119*0Sstevel@tonic-gate rnm = Zalloc(len); 2120*0Sstevel@tonic-gate (void) snprintf(rnm, len, "/dev/md/%s/rdsk/d%u", 2121*0Sstevel@tonic-gate snm, d); 2122*0Sstevel@tonic-gate return (rnm); 2123*0Sstevel@tonic-gate } 2124*0Sstevel@tonic-gate } 2125*0Sstevel@tonic-gate 2126*0Sstevel@tonic-gate /* NOT Fully qualified path, done */ 2127*0Sstevel@tonic-gate if (unm[0] != '/') { 2128*0Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, unm); 2129*0Sstevel@tonic-gate return (NULL); 2130*0Sstevel@tonic-gate } 2131*0Sstevel@tonic-gate 2132*0Sstevel@tonic-gate /* 2133*0Sstevel@tonic-gate * Get slice information from old style names of the form 2134*0Sstevel@tonic-gate * /dev/rXXNN[a-h] or /dev/XXNN[a-h], must be done before regular 2135*0Sstevel@tonic-gate * devices, but after metadevices. 2136*0Sstevel@tonic-gate */ 2137*0Sstevel@tonic-gate if ((sscanf(unm, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 2138*0Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 2139*0Sstevel@tonic-gate onmb, &d, snm, &l) == 3 || 2140*0Sstevel@tonic-gate sscanf(unm, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u" 2141*0Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 2142*0Sstevel@tonic-gate onmb, &d, snm, &l) == 3) && l == cl) { 2143*0Sstevel@tonic-gate if ((p = strchr("abcdefgh", snm[0])) != NULL) { 2144*0Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u%s", 2145*0Sstevel@tonic-gate onmb, d, snm); 2146*0Sstevel@tonic-gate return (Strdup(cnmb)); 2147*0Sstevel@tonic-gate } 2148*0Sstevel@tonic-gate } 2149*0Sstevel@tonic-gate 2150*0Sstevel@tonic-gate if ((p = strstr(unm, "/dsk/")) != NULL) { /* /.../dsk/... */ 2151*0Sstevel@tonic-gate ++p; 2152*0Sstevel@tonic-gate rnm = Zalloc(strlen(unm) + 1 + 1); 2153*0Sstevel@tonic-gate (void) strncpy(rnm, unm, (p - unm)); 2154*0Sstevel@tonic-gate rnm[(p - unm)] = 'r'; 2155*0Sstevel@tonic-gate (void) strcpy(&rnm[(p - unm) + 1], p); 2156*0Sstevel@tonic-gate return (rnm); 2157*0Sstevel@tonic-gate } else if (strstr(unm, "/rdsk/") != NULL) { /* /.../rdsk/... */ 2158*0Sstevel@tonic-gate return (Strdup(unm)); 2159*0Sstevel@tonic-gate } 2160*0Sstevel@tonic-gate 2161*0Sstevel@tonic-gate /* 2162*0Sstevel@tonic-gate * Shouldn't get here but if we do then we have an unrecognized 2163*0Sstevel@tonic-gate * fully qualified path - error 2164*0Sstevel@tonic-gate */ 2165*0Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, unm); 2166*0Sstevel@tonic-gate return (NULL); 2167*0Sstevel@tonic-gate } 2168*0Sstevel@tonic-gate 2169*0Sstevel@tonic-gate static mdname_t * 2170*0Sstevel@tonic-gate metainitfastname( 2171*0Sstevel@tonic-gate mdsetname_t *sp, 2172*0Sstevel@tonic-gate char *uname, 2173*0Sstevel@tonic-gate md_error_t *ep 2174*0Sstevel@tonic-gate ) 2175*0Sstevel@tonic-gate { 2176*0Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0, s = 0; 2177*0Sstevel@tonic-gate int l = 0; 2178*0Sstevel@tonic-gate mddrivename_t *dnp; 2179*0Sstevel@tonic-gate mdname_t *np; 2180*0Sstevel@tonic-gate mdnamelist_t **fnlpp; 2181*0Sstevel@tonic-gate 2182*0Sstevel@tonic-gate for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) { 2183*0Sstevel@tonic-gate np = (*fnlpp)->namep; 2184*0Sstevel@tonic-gate 2185*0Sstevel@tonic-gate if (strcmp(np->bname, uname) == 0) 2186*0Sstevel@tonic-gate return (np); 2187*0Sstevel@tonic-gate } 2188*0Sstevel@tonic-gate 2189*0Sstevel@tonic-gate *fnlpp = Zalloc(sizeof (**fnlpp)); 2190*0Sstevel@tonic-gate np = (*fnlpp)->namep = Zalloc(sizeof (mdname_t)); 2191*0Sstevel@tonic-gate metainitname(np); 2192*0Sstevel@tonic-gate dnp = np->drivenamep = Zalloc(sizeof (mddrivename_t)); 2193*0Sstevel@tonic-gate metainitdrivename(dnp); 2194*0Sstevel@tonic-gate 2195*0Sstevel@tonic-gate 2196*0Sstevel@tonic-gate /* Metadevices */ 2197*0Sstevel@tonic-gate if (is_metaname(uname)) { 2198*0Sstevel@tonic-gate char *p; 2199*0Sstevel@tonic-gate size_t len; 2200*0Sstevel@tonic-gate 2201*0Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL) 2202*0Sstevel@tonic-gate ++p; 2203*0Sstevel@tonic-gate else 2204*0Sstevel@tonic-gate p = uname; 2205*0Sstevel@tonic-gate 2206*0Sstevel@tonic-gate if (metaislocalset(sp)) { 2207*0Sstevel@tonic-gate if (np->cname) 2208*0Sstevel@tonic-gate Free(np->cname); 2209*0Sstevel@tonic-gate np->cname = Strdup(p); 2210*0Sstevel@tonic-gate } else { 2211*0Sstevel@tonic-gate if (np->cname) 2212*0Sstevel@tonic-gate Free(np->cname); 2213*0Sstevel@tonic-gate len = strlen(sp->setname) + 1 + strlen(p) + 1; 2214*0Sstevel@tonic-gate np->cname = Zalloc(len); 2215*0Sstevel@tonic-gate (void) snprintf(np->cname, len, "%s/%s", 2216*0Sstevel@tonic-gate sp->setname, p); 2217*0Sstevel@tonic-gate } 2218*0Sstevel@tonic-gate dnp->type = MDT_FAST_META; 2219*0Sstevel@tonic-gate goto done; 2220*0Sstevel@tonic-gate } 2221*0Sstevel@tonic-gate 2222*0Sstevel@tonic-gate /* Others */ 2223*0Sstevel@tonic-gate dnp->type = MDT_FAST_COMP; 2224*0Sstevel@tonic-gate 2225*0Sstevel@tonic-gate if (((sscanf(uname, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d, 2226*0Sstevel@tonic-gate &s, &l) == 4 || 2227*0Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d, 2228*0Sstevel@tonic-gate &s, &l) == 4 || 2229*0Sstevel@tonic-gate sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c, &t, &d, 2230*0Sstevel@tonic-gate &s, &l) == 4 || 2231*0Sstevel@tonic-gate sscanf(uname, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c, &t, &d, 2232*0Sstevel@tonic-gate &s, &l) == 4 || 2233*0Sstevel@tonic-gate sscanf(uname, "/dev/did/rdsk/d%us%u%n", &t, &s, &l) == 2 || 2234*0Sstevel@tonic-gate sscanf(uname, "/dev/did/dsk/d%us%u%n", &t, &s, &l) == 2|| 2235*0Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 || 2236*0Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 || 2237*0Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 || 2238*0Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 || 2239*0Sstevel@tonic-gate sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 || 2240*0Sstevel@tonic-gate sscanf(uname, "/dev/ap/dsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 || 2241*0Sstevel@tonic-gate sscanf(uname, "/dev/did/rdsk/d%u%n", &t, &l) == 1 || 2242*0Sstevel@tonic-gate sscanf(uname, "/dev/did/dsk/d%u%n", &t, &l) == 1 || 2243*0Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ud%u%n", &c, &d, &l) == 2 || 2244*0Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2) && 2245*0Sstevel@tonic-gate l == strlen(uname))) { 2246*0Sstevel@tonic-gate if ((np->cname = strrchr(uname, '/')) == NULL) 2247*0Sstevel@tonic-gate np->cname = Strdup(uname); 2248*0Sstevel@tonic-gate else 2249*0Sstevel@tonic-gate np->cname = Strdup(++np->cname); 2250*0Sstevel@tonic-gate } else { 2251*0Sstevel@tonic-gate np->cname = Strdup(uname); 2252*0Sstevel@tonic-gate } 2253*0Sstevel@tonic-gate 2254*0Sstevel@tonic-gate done: 2255*0Sstevel@tonic-gate /* Driver always gives us block names */ 2256*0Sstevel@tonic-gate np->bname = Strdup(uname); 2257*0Sstevel@tonic-gate 2258*0Sstevel@tonic-gate /* canonical disk name */ 2259*0Sstevel@tonic-gate if ((dnp->cname = metadiskname(np->cname)) == NULL) 2260*0Sstevel@tonic-gate dnp->cname = Strdup(np->cname); 2261*0Sstevel@tonic-gate 2262*0Sstevel@tonic-gate if ((np->rname = getrname_fast(uname, ep)) != NULL) { 2263*0Sstevel@tonic-gate if ((dnp->rname = metadiskname(np->rname)) == NULL) 2264*0Sstevel@tonic-gate dnp->rname = Strdup(np->rname); 2265*0Sstevel@tonic-gate } else { 2266*0Sstevel@tonic-gate metafreefastnm(&(*fnlpp)->namep); 2267*0Sstevel@tonic-gate Free(*fnlpp); 2268*0Sstevel@tonic-gate *fnlpp = NULL; 2269*0Sstevel@tonic-gate return (NULL); 2270*0Sstevel@tonic-gate } 2271*0Sstevel@tonic-gate 2272*0Sstevel@tonic-gate /* cleanup, return success */ 2273*0Sstevel@tonic-gate return (np); 2274*0Sstevel@tonic-gate } 2275*0Sstevel@tonic-gate 2276*0Sstevel@tonic-gate /* 2277*0Sstevel@tonic-gate * set up names for a device 2278*0Sstevel@tonic-gate */ 2279*0Sstevel@tonic-gate static mdname_t * 2280*0Sstevel@tonic-gate metaname_common( 2281*0Sstevel@tonic-gate mdsetname_t **spp, 2282*0Sstevel@tonic-gate char *uname, 2283*0Sstevel@tonic-gate int fast, 2284*0Sstevel@tonic-gate md_error_t *ep 2285*0Sstevel@tonic-gate ) 2286*0Sstevel@tonic-gate { 2287*0Sstevel@tonic-gate mddrivenamelist_t **tail; 2288*0Sstevel@tonic-gate mddrivename_t *dnp; 2289*0Sstevel@tonic-gate uint_t slice; 2290*0Sstevel@tonic-gate mdname_t *np; 2291*0Sstevel@tonic-gate char *rname = NULL; 2292*0Sstevel@tonic-gate char *dname = NULL; 2293*0Sstevel@tonic-gate char *cname = NULL; 2294*0Sstevel@tonic-gate uint_t nparts, partno; 2295*0Sstevel@tonic-gate 2296*0Sstevel@tonic-gate assert(uname != NULL); 2297*0Sstevel@tonic-gate 2298*0Sstevel@tonic-gate /* check setname */ 2299*0Sstevel@tonic-gate if ((cname = meta_name_getname(spp, uname, ep)) == NULL) 2300*0Sstevel@tonic-gate return (NULL); 2301*0Sstevel@tonic-gate 2302*0Sstevel@tonic-gate assert(*spp != NULL); 2303*0Sstevel@tonic-gate Free(cname); 2304*0Sstevel@tonic-gate 2305*0Sstevel@tonic-gate /* get raw name (rname) of the slice and drive (dname) we have */ 2306*0Sstevel@tonic-gate if ((rname = getrawnames(spp, uname, &dname, ep)) == NULL) { 2307*0Sstevel@tonic-gate return (NULL); 2308*0Sstevel@tonic-gate } 2309*0Sstevel@tonic-gate 2310*0Sstevel@tonic-gate /* look in cache first */ 2311*0Sstevel@tonic-gate for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 2312*0Sstevel@tonic-gate dnp = (*tail)->drivenamep; 2313*0Sstevel@tonic-gate 2314*0Sstevel@tonic-gate /* check to see if the drive name is already in the cache */ 2315*0Sstevel@tonic-gate if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) { 2316*0Sstevel@tonic-gate 2317*0Sstevel@tonic-gate Free(rname); 2318*0Sstevel@tonic-gate if (dname != NULL) 2319*0Sstevel@tonic-gate Free(dname); 2320*0Sstevel@tonic-gate 2321*0Sstevel@tonic-gate if (uname2sliceno(uname, &partno, ep) < 0) 2322*0Sstevel@tonic-gate return (NULL); 2323*0Sstevel@tonic-gate 2324*0Sstevel@tonic-gate return (metaslicename(dnp, partno, ep)); 2325*0Sstevel@tonic-gate } 2326*0Sstevel@tonic-gate } 2327*0Sstevel@tonic-gate 2328*0Sstevel@tonic-gate /* 2329*0Sstevel@tonic-gate * If a fast names is OK, then get one, and be done. 2330*0Sstevel@tonic-gate */ 2331*0Sstevel@tonic-gate if (fast) { 2332*0Sstevel@tonic-gate Free(rname); 2333*0Sstevel@tonic-gate if (dname != NULL) 2334*0Sstevel@tonic-gate Free(dname); 2335*0Sstevel@tonic-gate 2336*0Sstevel@tonic-gate return (metainitfastname(*spp, uname, ep)); 2337*0Sstevel@tonic-gate } 2338*0Sstevel@tonic-gate 2339*0Sstevel@tonic-gate /* allocate new list element and drive */ 2340*0Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 2341*0Sstevel@tonic-gate dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp)); 2342*0Sstevel@tonic-gate 2343*0Sstevel@tonic-gate metainitdrivename(dnp); 2344*0Sstevel@tonic-gate 2345*0Sstevel@tonic-gate /* get parts info */ 2346*0Sstevel@tonic-gate if (getparts(dnp, rname, dname, &nparts, &partno, ep) != 0) 2347*0Sstevel@tonic-gate goto out; 2348*0Sstevel@tonic-gate 2349*0Sstevel@tonic-gate /* 2350*0Sstevel@tonic-gate * libmeta needs at least V_NUMPAR partitions. 2351*0Sstevel@tonic-gate * If we have an EFI partition with less than V_NUMPAR slices, 2352*0Sstevel@tonic-gate * we nevertheless reserve space for V_NUMPAR 2353*0Sstevel@tonic-gate */ 2354*0Sstevel@tonic-gate if (nparts < V_NUMPAR) { 2355*0Sstevel@tonic-gate nparts = V_NUMPAR; 2356*0Sstevel@tonic-gate } 2357*0Sstevel@tonic-gate 2358*0Sstevel@tonic-gate /* allocate and link in parts */ 2359*0Sstevel@tonic-gate dnp->parts.parts_len = nparts; 2360*0Sstevel@tonic-gate dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) * 2361*0Sstevel@tonic-gate dnp->parts.parts_len); 2362*0Sstevel@tonic-gate for (slice = 0; (slice < nparts); ++slice) { 2363*0Sstevel@tonic-gate np = &dnp->parts.parts_val[slice]; 2364*0Sstevel@tonic-gate metainitname(np); 2365*0Sstevel@tonic-gate np->drivenamep = dnp; 2366*0Sstevel@tonic-gate } 2367*0Sstevel@tonic-gate 2368*0Sstevel@tonic-gate /* setup name_t (or slice) wanted */ 2369*0Sstevel@tonic-gate if ((np = setup_slice(*spp, dnp, uname, rname, dname, partno, ep)) 2370*0Sstevel@tonic-gate == NULL) 2371*0Sstevel@tonic-gate goto out; 2372*0Sstevel@tonic-gate 2373*0Sstevel@tonic-gate /* canonical disk name */ 2374*0Sstevel@tonic-gate if ((dnp->cname = metadiskname(np->cname)) == NULL) 2375*0Sstevel@tonic-gate dnp->cname = Strdup(np->cname); 2376*0Sstevel@tonic-gate if ((dnp->rname = metadiskname(np->rname)) == NULL) 2377*0Sstevel@tonic-gate dnp->rname = Strdup(np->rname); 2378*0Sstevel@tonic-gate 2379*0Sstevel@tonic-gate /* cleanup, return success */ 2380*0Sstevel@tonic-gate if (dname != NULL) 2381*0Sstevel@tonic-gate Free(dname); 2382*0Sstevel@tonic-gate Free(rname); 2383*0Sstevel@tonic-gate return (np); 2384*0Sstevel@tonic-gate 2385*0Sstevel@tonic-gate /* cleanup, return error */ 2386*0Sstevel@tonic-gate out: 2387*0Sstevel@tonic-gate if (dname != NULL) 2388*0Sstevel@tonic-gate Free(dname); 2389*0Sstevel@tonic-gate if (rname != NULL) 2390*0Sstevel@tonic-gate Free(rname); 2391*0Sstevel@tonic-gate 2392*0Sstevel@tonic-gate metafreedrivename(dnp); 2393*0Sstevel@tonic-gate Free(dnp); 2394*0Sstevel@tonic-gate Free(*tail); 2395*0Sstevel@tonic-gate *tail = NULL; 2396*0Sstevel@tonic-gate return (NULL); 2397*0Sstevel@tonic-gate } 2398*0Sstevel@tonic-gate 2399*0Sstevel@tonic-gate mdname_t * 2400*0Sstevel@tonic-gate metaname( 2401*0Sstevel@tonic-gate mdsetname_t **spp, 2402*0Sstevel@tonic-gate char *uname, 2403*0Sstevel@tonic-gate md_error_t *ep 2404*0Sstevel@tonic-gate ) 2405*0Sstevel@tonic-gate { 2406*0Sstevel@tonic-gate return (metaname_common(spp, uname, 0, ep)); 2407*0Sstevel@tonic-gate } 2408*0Sstevel@tonic-gate 2409*0Sstevel@tonic-gate mdname_t * 2410*0Sstevel@tonic-gate metaname_fast( 2411*0Sstevel@tonic-gate mdsetname_t **spp, 2412*0Sstevel@tonic-gate char *uname, 2413*0Sstevel@tonic-gate md_error_t *ep 2414*0Sstevel@tonic-gate ) 2415*0Sstevel@tonic-gate { 2416*0Sstevel@tonic-gate return (metaname_common(spp, uname, 1, ep)); 2417*0Sstevel@tonic-gate } 2418*0Sstevel@tonic-gate 2419*0Sstevel@tonic-gate /* 2420*0Sstevel@tonic-gate * set up names for a drive 2421*0Sstevel@tonic-gate */ 2422*0Sstevel@tonic-gate mddrivename_t * 2423*0Sstevel@tonic-gate metadrivename( 2424*0Sstevel@tonic-gate mdsetname_t **spp, 2425*0Sstevel@tonic-gate char *uname, 2426*0Sstevel@tonic-gate md_error_t *ep 2427*0Sstevel@tonic-gate ) 2428*0Sstevel@tonic-gate { 2429*0Sstevel@tonic-gate char *slicename; 2430*0Sstevel@tonic-gate mdname_t *np; 2431*0Sstevel@tonic-gate 2432*0Sstevel@tonic-gate char *cname; 2433*0Sstevel@tonic-gate mddrivenamelist_t **tail; 2434*0Sstevel@tonic-gate mddrivename_t *dnp; 2435*0Sstevel@tonic-gate char *dname; 2436*0Sstevel@tonic-gate int i; 2437*0Sstevel@tonic-gate int mplen; 2438*0Sstevel@tonic-gate size_t len; 2439*0Sstevel@tonic-gate 2440*0Sstevel@tonic-gate /* check setname, get comparison name */ 2441*0Sstevel@tonic-gate assert(uname != NULL); 2442*0Sstevel@tonic-gate if ((cname = meta_name_getname(spp, uname, ep)) == NULL) { 2443*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 2444*0Sstevel@tonic-gate return (NULL); 2445*0Sstevel@tonic-gate } 2446*0Sstevel@tonic-gate 2447*0Sstevel@tonic-gate assert(*spp != NULL); 2448*0Sstevel@tonic-gate 2449*0Sstevel@tonic-gate if ((dname = metadiskname(cname)) == NULL) { 2450*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, cname); 2451*0Sstevel@tonic-gate Free(cname); 2452*0Sstevel@tonic-gate return (NULL); 2453*0Sstevel@tonic-gate } 2454*0Sstevel@tonic-gate 2455*0Sstevel@tonic-gate /* look in cache first */ 2456*0Sstevel@tonic-gate for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 2457*0Sstevel@tonic-gate dnp = (*tail)->drivenamep; 2458*0Sstevel@tonic-gate if ((dnp->cname != NULL && 2459*0Sstevel@tonic-gate (strcmp(dnp->cname, dname) == 0)) || 2460*0Sstevel@tonic-gate (dnp->rname != NULL && 2461*0Sstevel@tonic-gate (strcmp(dnp->rname, dname) == 0))) { 2462*0Sstevel@tonic-gate Free(cname); 2463*0Sstevel@tonic-gate Free(dname); 2464*0Sstevel@tonic-gate return (dnp); 2465*0Sstevel@tonic-gate } 2466*0Sstevel@tonic-gate } 2467*0Sstevel@tonic-gate 2468*0Sstevel@tonic-gate /* Check each possible slice name based on MD_MAX_PARTS. */ 2469*0Sstevel@tonic-gate 2470*0Sstevel@tonic-gate /* 2471*0Sstevel@tonic-gate * Figure out how much string space to reserve to fit 2472*0Sstevel@tonic-gate * (MD_MAX_PARTS - 1) into the name string; the loop will 2473*0Sstevel@tonic-gate * increment the mplen counter once for each decimal digit in 2474*0Sstevel@tonic-gate * (MD_MAX_PARTS - 1). 2475*0Sstevel@tonic-gate */ 2476*0Sstevel@tonic-gate for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen); 2477*0Sstevel@tonic-gate len = strlen(uname) + mplen + 2; 2478*0Sstevel@tonic-gate slicename = Malloc(len); 2479*0Sstevel@tonic-gate 2480*0Sstevel@tonic-gate /* Check for each slice in turn until we find one */ 2481*0Sstevel@tonic-gate for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) { 2482*0Sstevel@tonic-gate (void) snprintf(slicename, len, "%ss%d", uname, i); 2483*0Sstevel@tonic-gate np = metaname(spp, slicename, ep); 2484*0Sstevel@tonic-gate } 2485*0Sstevel@tonic-gate Free(slicename); 2486*0Sstevel@tonic-gate 2487*0Sstevel@tonic-gate if (np == NULL) { 2488*0Sstevel@tonic-gate char *dname; 2489*0Sstevel@tonic-gate 2490*0Sstevel@tonic-gate if ((mdissyserror(ep, ENOENT)) && 2491*0Sstevel@tonic-gate ((dname = metadiskname(uname)) != NULL)) { 2492*0Sstevel@tonic-gate Free(dname); 2493*0Sstevel@tonic-gate (void) mderror(ep, MDE_NOT_DRIVENAME, uname); 2494*0Sstevel@tonic-gate } 2495*0Sstevel@tonic-gate return (NULL); 2496*0Sstevel@tonic-gate } 2497*0Sstevel@tonic-gate return (np->drivenamep); 2498*0Sstevel@tonic-gate } 2499*0Sstevel@tonic-gate 2500*0Sstevel@tonic-gate /* 2501*0Sstevel@tonic-gate * FUNCTION: metaslicename() 2502*0Sstevel@tonic-gate * INPUT: dnp - the drivename structure 2503*0Sstevel@tonic-gate * sliceno - the slice on the drive to return 2504*0Sstevel@tonic-gate * OUTPUT: ep - return error pointer 2505*0Sstevel@tonic-gate * RETURNS: mdname_t- pointer the the slice name structure 2506*0Sstevel@tonic-gate * PURPOSE: interface to the parts struct in the drive name struct 2507*0Sstevel@tonic-gate * Since there is no guarantee that the slice name 2508*0Sstevel@tonic-gate * structures are populated users should call this 2509*0Sstevel@tonic-gate * function rather than accessing the structure directly 2510*0Sstevel@tonic-gate * since it will populate the structure values if they 2511*0Sstevel@tonic-gate * haven't already been populated before returning. 2512*0Sstevel@tonic-gate */ 2513*0Sstevel@tonic-gate mdname_t * 2514*0Sstevel@tonic-gate metaslicename( 2515*0Sstevel@tonic-gate mddrivename_t *dnp, 2516*0Sstevel@tonic-gate uint_t sliceno, 2517*0Sstevel@tonic-gate md_error_t *ep 2518*0Sstevel@tonic-gate ) 2519*0Sstevel@tonic-gate { 2520*0Sstevel@tonic-gate mdsetname_t *sp = NULL; 2521*0Sstevel@tonic-gate char *namep = NULL; 2522*0Sstevel@tonic-gate mdname_t *np; 2523*0Sstevel@tonic-gate 2524*0Sstevel@tonic-gate assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 2525*0Sstevel@tonic-gate 2526*0Sstevel@tonic-gate if (sliceno >= dnp->parts.parts_len) { 2527*0Sstevel@tonic-gate (void) mderror(ep, MDE_NOSLICE, dnp->cname); 2528*0Sstevel@tonic-gate return (NULL); 2529*0Sstevel@tonic-gate } 2530*0Sstevel@tonic-gate 2531*0Sstevel@tonic-gate np = &dnp->parts.parts_val[sliceno]; 2532*0Sstevel@tonic-gate 2533*0Sstevel@tonic-gate /* check to see if the struct is already populated */ 2534*0Sstevel@tonic-gate if (np->cname) { 2535*0Sstevel@tonic-gate return (np); 2536*0Sstevel@tonic-gate } 2537*0Sstevel@tonic-gate 2538*0Sstevel@tonic-gate if ((namep = meta_name_getname(&sp, dnp->cname, ep)) == NULL) 2539*0Sstevel@tonic-gate return (NULL); 2540*0Sstevel@tonic-gate 2541*0Sstevel@tonic-gate np = setup_slice(sp, dnp, NULL, NULL, dnp->rname, sliceno, ep); 2542*0Sstevel@tonic-gate 2543*0Sstevel@tonic-gate Free(namep); 2544*0Sstevel@tonic-gate 2545*0Sstevel@tonic-gate return (np); 2546*0Sstevel@tonic-gate } 2547*0Sstevel@tonic-gate 2548*0Sstevel@tonic-gate /* 2549*0Sstevel@tonic-gate * set up metadevice name from id 2550*0Sstevel@tonic-gate */ 2551*0Sstevel@tonic-gate mdname_t * 2552*0Sstevel@tonic-gate metamnumname( 2553*0Sstevel@tonic-gate mdsetname_t **spp, 2554*0Sstevel@tonic-gate minor_t mnum, 2555*0Sstevel@tonic-gate int fast, 2556*0Sstevel@tonic-gate md_error_t *ep 2557*0Sstevel@tonic-gate ) 2558*0Sstevel@tonic-gate { 2559*0Sstevel@tonic-gate set_t setno = MD_MIN2SET(mnum); 2560*0Sstevel@tonic-gate mdsetname_t *sp = NULL; 2561*0Sstevel@tonic-gate char *uname; 2562*0Sstevel@tonic-gate mdname_t *np; 2563*0Sstevel@tonic-gate size_t len; 2564*0Sstevel@tonic-gate 2565*0Sstevel@tonic-gate /* check set first */ 2566*0Sstevel@tonic-gate if (spp == NULL) 2567*0Sstevel@tonic-gate spp = &sp; 2568*0Sstevel@tonic-gate if (chksetno(spp, setno, ep) != 0) 2569*0Sstevel@tonic-gate return (NULL); 2570*0Sstevel@tonic-gate assert(*spp != NULL); 2571*0Sstevel@tonic-gate sp = *spp; 2572*0Sstevel@tonic-gate 2573*0Sstevel@tonic-gate /* build corresponding device name */ 2574*0Sstevel@tonic-gate if (metaislocalset(sp)) { 2575*0Sstevel@tonic-gate uname = Malloc(20); 2576*0Sstevel@tonic-gate (void) sprintf(uname, "d%lu", MD_MIN2UNIT(mnum)); 2577*0Sstevel@tonic-gate } else { 2578*0Sstevel@tonic-gate len = strlen(sp->setname) + 1 + 20; 2579*0Sstevel@tonic-gate uname = Malloc(len); 2580*0Sstevel@tonic-gate (void) snprintf(uname, len, "%s/d%lu", sp->setname, 2581*0Sstevel@tonic-gate MD_MIN2UNIT(mnum)); 2582*0Sstevel@tonic-gate } 2583*0Sstevel@tonic-gate 2584*0Sstevel@tonic-gate /* setup name */ 2585*0Sstevel@tonic-gate if (fast) { 2586*0Sstevel@tonic-gate np = metaname_fast(spp, uname, ep); 2587*0Sstevel@tonic-gate np->dev = metamakedev(mnum); 2588*0Sstevel@tonic-gate } else 2589*0Sstevel@tonic-gate np = metaname(spp, uname, ep); 2590*0Sstevel@tonic-gate 2591*0Sstevel@tonic-gate Free(uname); 2592*0Sstevel@tonic-gate return (np); 2593*0Sstevel@tonic-gate } 2594*0Sstevel@tonic-gate 2595*0Sstevel@tonic-gate /* 2596*0Sstevel@tonic-gate * return metadevice name 2597*0Sstevel@tonic-gate */ 2598*0Sstevel@tonic-gate char * 2599*0Sstevel@tonic-gate get_mdname( 2600*0Sstevel@tonic-gate minor_t mnum 2601*0Sstevel@tonic-gate ) 2602*0Sstevel@tonic-gate { 2603*0Sstevel@tonic-gate mdname_t *np; 2604*0Sstevel@tonic-gate md_error_t status = mdnullerror; 2605*0Sstevel@tonic-gate 2606*0Sstevel@tonic-gate /* get name */ 2607*0Sstevel@tonic-gate if ((np = metamnumname(NULL, mnum, 0, &status)) == NULL) { 2608*0Sstevel@tonic-gate mdclrerror(&status); 2609*0Sstevel@tonic-gate return (NULL); 2610*0Sstevel@tonic-gate } 2611*0Sstevel@tonic-gate assert(meta_getminor(np->dev) == mnum); 2612*0Sstevel@tonic-gate 2613*0Sstevel@tonic-gate /* return name */ 2614*0Sstevel@tonic-gate return (np->cname); 2615*0Sstevel@tonic-gate } 2616*0Sstevel@tonic-gate 2617*0Sstevel@tonic-gate /* 2618*0Sstevel@tonic-gate * check for device type 2619*0Sstevel@tonic-gate */ 2620*0Sstevel@tonic-gate int 2621*0Sstevel@tonic-gate metaismeta( 2622*0Sstevel@tonic-gate mdname_t *np 2623*0Sstevel@tonic-gate ) 2624*0Sstevel@tonic-gate { 2625*0Sstevel@tonic-gate return (np->drivenamep->type == MDT_META || 2626*0Sstevel@tonic-gate np->drivenamep->type == MDT_FAST_META); 2627*0Sstevel@tonic-gate } 2628*0Sstevel@tonic-gate 2629*0Sstevel@tonic-gate int 2630*0Sstevel@tonic-gate metachkmeta( 2631*0Sstevel@tonic-gate mdname_t *np, 2632*0Sstevel@tonic-gate md_error_t *ep 2633*0Sstevel@tonic-gate ) 2634*0Sstevel@tonic-gate { 2635*0Sstevel@tonic-gate if (! metaismeta(np)) { 2636*0Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_META, np->dev, 2637*0Sstevel@tonic-gate np->cname)); 2638*0Sstevel@tonic-gate } 2639*0Sstevel@tonic-gate return (0); 2640*0Sstevel@tonic-gate } 2641*0Sstevel@tonic-gate 2642*0Sstevel@tonic-gate int 2643*0Sstevel@tonic-gate metachkdisk( 2644*0Sstevel@tonic-gate mdname_t *np, 2645*0Sstevel@tonic-gate md_error_t *ep 2646*0Sstevel@tonic-gate ) 2647*0Sstevel@tonic-gate { 2648*0Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep; 2649*0Sstevel@tonic-gate 2650*0Sstevel@tonic-gate assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 2651*0Sstevel@tonic-gate 2652*0Sstevel@tonic-gate if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) { 2653*0Sstevel@tonic-gate switch (dnp->type) { 2654*0Sstevel@tonic-gate case MDT_ACCES: 2655*0Sstevel@tonic-gate case MDT_UNKNOWN: 2656*0Sstevel@tonic-gate return (mdsyserror(ep, dnp->errnum, np->bname)); 2657*0Sstevel@tonic-gate default: 2658*0Sstevel@tonic-gate assert(0); 2659*0Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, np->dev, 2660*0Sstevel@tonic-gate np->cname)); 2661*0Sstevel@tonic-gate } 2662*0Sstevel@tonic-gate } 2663*0Sstevel@tonic-gate return (0); 2664*0Sstevel@tonic-gate } 2665*0Sstevel@tonic-gate 2666*0Sstevel@tonic-gate int 2667*0Sstevel@tonic-gate metachkcomp( 2668*0Sstevel@tonic-gate mdname_t *np, 2669*0Sstevel@tonic-gate md_error_t *ep 2670*0Sstevel@tonic-gate ) 2671*0Sstevel@tonic-gate { 2672*0Sstevel@tonic-gate if (metaismeta(np)) { 2673*0Sstevel@tonic-gate return (mddeverror(ep, MDE_IS_META, np->dev, 2674*0Sstevel@tonic-gate np->cname)); 2675*0Sstevel@tonic-gate } 2676*0Sstevel@tonic-gate return (metachkdisk(np, ep)); 2677*0Sstevel@tonic-gate } 2678*0Sstevel@tonic-gate 2679*0Sstevel@tonic-gate /* 2680*0Sstevel@tonic-gate * free list of names 2681*0Sstevel@tonic-gate */ 2682*0Sstevel@tonic-gate void 2683*0Sstevel@tonic-gate metafreenamelist( 2684*0Sstevel@tonic-gate mdnamelist_t *nlp 2685*0Sstevel@tonic-gate ) 2686*0Sstevel@tonic-gate { 2687*0Sstevel@tonic-gate mdnamelist_t *next = NULL; 2688*0Sstevel@tonic-gate 2689*0Sstevel@tonic-gate for (/* void */; (nlp != NULL); nlp = next) { 2690*0Sstevel@tonic-gate next = nlp->next; 2691*0Sstevel@tonic-gate Free(nlp); 2692*0Sstevel@tonic-gate } 2693*0Sstevel@tonic-gate } 2694*0Sstevel@tonic-gate 2695*0Sstevel@tonic-gate /* 2696*0Sstevel@tonic-gate * build list of names 2697*0Sstevel@tonic-gate */ 2698*0Sstevel@tonic-gate int 2699*0Sstevel@tonic-gate metanamelist( 2700*0Sstevel@tonic-gate mdsetname_t **spp, 2701*0Sstevel@tonic-gate mdnamelist_t **nlpp, 2702*0Sstevel@tonic-gate int argc, 2703*0Sstevel@tonic-gate char *argv[], 2704*0Sstevel@tonic-gate md_error_t *ep 2705*0Sstevel@tonic-gate ) 2706*0Sstevel@tonic-gate { 2707*0Sstevel@tonic-gate mdnamelist_t **tailpp = nlpp; 2708*0Sstevel@tonic-gate int count = 0; 2709*0Sstevel@tonic-gate 2710*0Sstevel@tonic-gate for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 2711*0Sstevel@tonic-gate mdnamelist_t *nlp = Zalloc(sizeof (*nlp)); 2712*0Sstevel@tonic-gate 2713*0Sstevel@tonic-gate if ((nlp->namep = metaname(spp, argv[0], ep)) == NULL) { 2714*0Sstevel@tonic-gate metafreenamelist(*nlpp); 2715*0Sstevel@tonic-gate *nlpp = NULL; 2716*0Sstevel@tonic-gate return (-1); 2717*0Sstevel@tonic-gate } 2718*0Sstevel@tonic-gate *tailpp = nlp; 2719*0Sstevel@tonic-gate tailpp = &nlp->next; 2720*0Sstevel@tonic-gate } 2721*0Sstevel@tonic-gate return (count); 2722*0Sstevel@tonic-gate } 2723*0Sstevel@tonic-gate 2724*0Sstevel@tonic-gate /* 2725*0Sstevel@tonic-gate * append to end of name list 2726*0Sstevel@tonic-gate */ 2727*0Sstevel@tonic-gate mdname_t * 2728*0Sstevel@tonic-gate metanamelist_append( 2729*0Sstevel@tonic-gate mdnamelist_t **nlpp, 2730*0Sstevel@tonic-gate mdname_t *np 2731*0Sstevel@tonic-gate ) 2732*0Sstevel@tonic-gate { 2733*0Sstevel@tonic-gate mdnamelist_t *nlp; 2734*0Sstevel@tonic-gate 2735*0Sstevel@tonic-gate /* run to end of list */ 2736*0Sstevel@tonic-gate for (; (*nlpp != NULL); nlpp = &(*nlpp)->next) 2737*0Sstevel@tonic-gate ; 2738*0Sstevel@tonic-gate 2739*0Sstevel@tonic-gate /* allocate new list element */ 2740*0Sstevel@tonic-gate nlp = *nlpp = Zalloc(sizeof (*nlp)); 2741*0Sstevel@tonic-gate 2742*0Sstevel@tonic-gate /* append name */ 2743*0Sstevel@tonic-gate nlp->namep = np; 2744*0Sstevel@tonic-gate return (np); 2745*0Sstevel@tonic-gate } 2746*0Sstevel@tonic-gate 2747*0Sstevel@tonic-gate /* 2748*0Sstevel@tonic-gate * FUNCTION: meta_namelist_append_wrapper() 2749*0Sstevel@tonic-gate * INPUT: tailpp - pointer to the list tail pointer 2750*0Sstevel@tonic-gate * np - name node to be appended to list 2751*0Sstevel@tonic-gate * OUTPUT: none 2752*0Sstevel@tonic-gate * RETURNS: mdnamelist_t * - new tail of the list. 2753*0Sstevel@tonic-gate * PURPOSE: wrapper to meta_namelist_append for performance. 2754*0Sstevel@tonic-gate * metanamelist_append finds the tail each time which slows 2755*0Sstevel@tonic-gate * down long lists. By keeping track of the tail ourselves 2756*0Sstevel@tonic-gate * we can change metanamelist_append into a constant time 2757*0Sstevel@tonic-gate * operation. 2758*0Sstevel@tonic-gate */ 2759*0Sstevel@tonic-gate mdnamelist_t ** 2760*0Sstevel@tonic-gate meta_namelist_append_wrapper( 2761*0Sstevel@tonic-gate mdnamelist_t **tailpp, 2762*0Sstevel@tonic-gate mdname_t *np 2763*0Sstevel@tonic-gate ) 2764*0Sstevel@tonic-gate { 2765*0Sstevel@tonic-gate (void) metanamelist_append(tailpp, np); 2766*0Sstevel@tonic-gate 2767*0Sstevel@tonic-gate /* If it's the first item in the list, return it instead of the next */ 2768*0Sstevel@tonic-gate if ((*tailpp)->next == NULL) 2769*0Sstevel@tonic-gate return (tailpp); 2770*0Sstevel@tonic-gate 2771*0Sstevel@tonic-gate return (&(*tailpp)->next); 2772*0Sstevel@tonic-gate } 2773*0Sstevel@tonic-gate 2774*0Sstevel@tonic-gate 2775*0Sstevel@tonic-gate /* 2776*0Sstevel@tonic-gate * mdhspname_t stuff 2777*0Sstevel@tonic-gate */ 2778*0Sstevel@tonic-gate 2779*0Sstevel@tonic-gate /* 2780*0Sstevel@tonic-gate * initialize hspname 2781*0Sstevel@tonic-gate */ 2782*0Sstevel@tonic-gate static void 2783*0Sstevel@tonic-gate metainithspname( 2784*0Sstevel@tonic-gate mdhspname_t *hspnamep 2785*0Sstevel@tonic-gate ) 2786*0Sstevel@tonic-gate { 2787*0Sstevel@tonic-gate (void) memset(hspnamep, '\0', sizeof (*hspnamep)); 2788*0Sstevel@tonic-gate hspnamep->hsp = MD_HSP_NONE; 2789*0Sstevel@tonic-gate } 2790*0Sstevel@tonic-gate 2791*0Sstevel@tonic-gate /* 2792*0Sstevel@tonic-gate * free allocated hspname 2793*0Sstevel@tonic-gate */ 2794*0Sstevel@tonic-gate static void 2795*0Sstevel@tonic-gate metafreehspname( 2796*0Sstevel@tonic-gate mdhspname_t *hspnamep 2797*0Sstevel@tonic-gate ) 2798*0Sstevel@tonic-gate { 2799*0Sstevel@tonic-gate if (hspnamep->hspname != NULL) 2800*0Sstevel@tonic-gate Free(hspnamep->hspname); 2801*0Sstevel@tonic-gate if (hspnamep->unitp != NULL) 2802*0Sstevel@tonic-gate meta_invalidate_hsp(hspnamep); 2803*0Sstevel@tonic-gate metainithspname(hspnamep); 2804*0Sstevel@tonic-gate } 2805*0Sstevel@tonic-gate 2806*0Sstevel@tonic-gate /* 2807*0Sstevel@tonic-gate * clear the hspname cache 2808*0Sstevel@tonic-gate */ 2809*0Sstevel@tonic-gate static void 2810*0Sstevel@tonic-gate metaflushhspnames() 2811*0Sstevel@tonic-gate { 2812*0Sstevel@tonic-gate mdhspnamelist_t *p, *n; 2813*0Sstevel@tonic-gate 2814*0Sstevel@tonic-gate for (p = hsplistp, n = NULL; (p != NULL); p = n) { 2815*0Sstevel@tonic-gate n = p->next; 2816*0Sstevel@tonic-gate metafreehspname(p->hspnamep); 2817*0Sstevel@tonic-gate Free(p->hspnamep); 2818*0Sstevel@tonic-gate Free(p); 2819*0Sstevel@tonic-gate } 2820*0Sstevel@tonic-gate hsplistp = NULL; 2821*0Sstevel@tonic-gate } 2822*0Sstevel@tonic-gate 2823*0Sstevel@tonic-gate /* 2824*0Sstevel@tonic-gate * check set and get comparison name 2825*0Sstevel@tonic-gate */ 2826*0Sstevel@tonic-gate static char * 2827*0Sstevel@tonic-gate gethspname( 2828*0Sstevel@tonic-gate mdsetname_t **spp, 2829*0Sstevel@tonic-gate char *uname, 2830*0Sstevel@tonic-gate hsp_t *hspp, 2831*0Sstevel@tonic-gate md_error_t *ep 2832*0Sstevel@tonic-gate ) 2833*0Sstevel@tonic-gate { 2834*0Sstevel@tonic-gate char *sname = NULL; 2835*0Sstevel@tonic-gate 2836*0Sstevel@tonic-gate /* check setname */ 2837*0Sstevel@tonic-gate assert(uname != NULL); 2838*0Sstevel@tonic-gate if (parse_hsp(uname, &sname, hspp) != 0) { 2839*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 2840*0Sstevel@tonic-gate return (NULL); 2841*0Sstevel@tonic-gate } 2842*0Sstevel@tonic-gate if (chksetname(spp, sname, ep) != 0) { 2843*0Sstevel@tonic-gate if (sname != NULL) 2844*0Sstevel@tonic-gate Free(sname); 2845*0Sstevel@tonic-gate return (NULL); 2846*0Sstevel@tonic-gate } 2847*0Sstevel@tonic-gate if (sname != NULL) 2848*0Sstevel@tonic-gate Free(sname); 2849*0Sstevel@tonic-gate 2850*0Sstevel@tonic-gate /* return comparison name */ 2851*0Sstevel@tonic-gate return (canon_hsp((*spp)->setname, *hspp)); 2852*0Sstevel@tonic-gate } 2853*0Sstevel@tonic-gate 2854*0Sstevel@tonic-gate /* 2855*0Sstevel@tonic-gate * set up names for a hotspare pool 2856*0Sstevel@tonic-gate */ 2857*0Sstevel@tonic-gate mdhspname_t * 2858*0Sstevel@tonic-gate metahspname( 2859*0Sstevel@tonic-gate mdsetname_t **spp, 2860*0Sstevel@tonic-gate char *uname, 2861*0Sstevel@tonic-gate md_error_t *ep 2862*0Sstevel@tonic-gate ) 2863*0Sstevel@tonic-gate { 2864*0Sstevel@tonic-gate char *cname; 2865*0Sstevel@tonic-gate hsp_t hsp; 2866*0Sstevel@tonic-gate mdhspnamelist_t **tail; 2867*0Sstevel@tonic-gate mdhspname_t *hspnp; 2868*0Sstevel@tonic-gate 2869*0Sstevel@tonic-gate /* check setname */ 2870*0Sstevel@tonic-gate assert(uname != NULL); 2871*0Sstevel@tonic-gate if ((cname = gethspname(spp, uname, &hsp, ep)) == NULL) 2872*0Sstevel@tonic-gate return (NULL); 2873*0Sstevel@tonic-gate assert(*spp != NULL); 2874*0Sstevel@tonic-gate 2875*0Sstevel@tonic-gate /* look in cache first */ 2876*0Sstevel@tonic-gate for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) { 2877*0Sstevel@tonic-gate hspnp = (*tail)->hspnamep; 2878*0Sstevel@tonic-gate if (strcmp(hspnp->hspname, cname) == 0) { 2879*0Sstevel@tonic-gate Free(cname); 2880*0Sstevel@tonic-gate return (hspnp); 2881*0Sstevel@tonic-gate } 2882*0Sstevel@tonic-gate } 2883*0Sstevel@tonic-gate 2884*0Sstevel@tonic-gate /* allocate new list element and hspname */ 2885*0Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 2886*0Sstevel@tonic-gate hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp)); 2887*0Sstevel@tonic-gate metainithspname(hspnp); 2888*0Sstevel@tonic-gate 2889*0Sstevel@tonic-gate /* save hspname and number */ 2890*0Sstevel@tonic-gate hspnp->hspname = cname; 2891*0Sstevel@tonic-gate hspnp->hsp = MAKE_HSP_ID((*spp)->setno, hsp); 2892*0Sstevel@tonic-gate 2893*0Sstevel@tonic-gate /* success */ 2894*0Sstevel@tonic-gate return (hspnp); 2895*0Sstevel@tonic-gate 2896*0Sstevel@tonic-gate /* cleanup, return error */ 2897*0Sstevel@tonic-gate out: 2898*0Sstevel@tonic-gate metafreehspname(hspnp); 2899*0Sstevel@tonic-gate Free(hspnp); 2900*0Sstevel@tonic-gate Free(*tail); 2901*0Sstevel@tonic-gate *tail = NULL; 2902*0Sstevel@tonic-gate return (NULL); 2903*0Sstevel@tonic-gate 2904*0Sstevel@tonic-gate 2905*0Sstevel@tonic-gate } 2906*0Sstevel@tonic-gate 2907*0Sstevel@tonic-gate /* 2908*0Sstevel@tonic-gate * set up hotspare pool name from id 2909*0Sstevel@tonic-gate */ 2910*0Sstevel@tonic-gate mdhspname_t * 2911*0Sstevel@tonic-gate metahsphspname( 2912*0Sstevel@tonic-gate mdsetname_t **spp, 2913*0Sstevel@tonic-gate hsp_t hsp, 2914*0Sstevel@tonic-gate md_error_t *ep 2915*0Sstevel@tonic-gate ) 2916*0Sstevel@tonic-gate { 2917*0Sstevel@tonic-gate set_t setno = HSP_SET(hsp); 2918*0Sstevel@tonic-gate mdsetname_t *sp = NULL; 2919*0Sstevel@tonic-gate char *uname; 2920*0Sstevel@tonic-gate mdhspname_t *hspnp; 2921*0Sstevel@tonic-gate size_t len; 2922*0Sstevel@tonic-gate 2923*0Sstevel@tonic-gate /* check set first */ 2924*0Sstevel@tonic-gate if (spp == NULL) 2925*0Sstevel@tonic-gate spp = &sp; 2926*0Sstevel@tonic-gate if (chksetno(spp, setno, ep) != 0) 2927*0Sstevel@tonic-gate return (NULL); 2928*0Sstevel@tonic-gate assert(*spp != NULL); 2929*0Sstevel@tonic-gate sp = *spp; 2930*0Sstevel@tonic-gate 2931*0Sstevel@tonic-gate /* build corresponding hotspare pool name */ 2932*0Sstevel@tonic-gate if (metaislocalset(sp)) { 2933*0Sstevel@tonic-gate uname = Malloc(20); 2934*0Sstevel@tonic-gate (void) sprintf(uname, "hsp%03u", HSP_ID(hsp)); 2935*0Sstevel@tonic-gate } else { 2936*0Sstevel@tonic-gate len = strlen(sp->setname) + 1 + 20; 2937*0Sstevel@tonic-gate uname = Malloc(len); 2938*0Sstevel@tonic-gate (void) snprintf(uname, len, "%s/hsp%03lu", sp->setname, 2939*0Sstevel@tonic-gate HSP_ID(hsp)); 2940*0Sstevel@tonic-gate } 2941*0Sstevel@tonic-gate 2942*0Sstevel@tonic-gate /* setup name */ 2943*0Sstevel@tonic-gate hspnp = metahspname(spp, uname, ep); 2944*0Sstevel@tonic-gate Free(uname); 2945*0Sstevel@tonic-gate return (hspnp); 2946*0Sstevel@tonic-gate } 2947*0Sstevel@tonic-gate 2948*0Sstevel@tonic-gate /* 2949*0Sstevel@tonic-gate * return hotspare pool name 2950*0Sstevel@tonic-gate */ 2951*0Sstevel@tonic-gate char * 2952*0Sstevel@tonic-gate get_hspname(hsp_t hsp) 2953*0Sstevel@tonic-gate { 2954*0Sstevel@tonic-gate mdhspname_t *hspnp; 2955*0Sstevel@tonic-gate md_error_t status = mdnullerror; 2956*0Sstevel@tonic-gate 2957*0Sstevel@tonic-gate /* get name */ 2958*0Sstevel@tonic-gate if ((hspnp = metahsphspname(NULL, hsp, &status)) == NULL) { 2959*0Sstevel@tonic-gate mdclrerror(&status); 2960*0Sstevel@tonic-gate return (NULL); 2961*0Sstevel@tonic-gate } 2962*0Sstevel@tonic-gate 2963*0Sstevel@tonic-gate /* return name */ 2964*0Sstevel@tonic-gate return (hspnp->hspname); 2965*0Sstevel@tonic-gate } 2966*0Sstevel@tonic-gate 2967*0Sstevel@tonic-gate /* 2968*0Sstevel@tonic-gate * free hotspare pool list 2969*0Sstevel@tonic-gate */ 2970*0Sstevel@tonic-gate void 2971*0Sstevel@tonic-gate metafreehspnamelist(mdhspnamelist_t *hspnlp) 2972*0Sstevel@tonic-gate { 2973*0Sstevel@tonic-gate mdhspnamelist_t *next = NULL; 2974*0Sstevel@tonic-gate 2975*0Sstevel@tonic-gate for (/* void */; (hspnlp != NULL); hspnlp = next) { 2976*0Sstevel@tonic-gate next = hspnlp->next; 2977*0Sstevel@tonic-gate Free(hspnlp); 2978*0Sstevel@tonic-gate } 2979*0Sstevel@tonic-gate } 2980*0Sstevel@tonic-gate 2981*0Sstevel@tonic-gate /* 2982*0Sstevel@tonic-gate * build list of hotspare pool names 2983*0Sstevel@tonic-gate */ 2984*0Sstevel@tonic-gate int 2985*0Sstevel@tonic-gate metahspnamelist( 2986*0Sstevel@tonic-gate mdsetname_t **spp, 2987*0Sstevel@tonic-gate mdhspnamelist_t **hspnlpp, 2988*0Sstevel@tonic-gate int argc, 2989*0Sstevel@tonic-gate char *argv[], 2990*0Sstevel@tonic-gate md_error_t *ep 2991*0Sstevel@tonic-gate ) 2992*0Sstevel@tonic-gate { 2993*0Sstevel@tonic-gate mdhspnamelist_t **tailpp = hspnlpp; 2994*0Sstevel@tonic-gate int count = 0; 2995*0Sstevel@tonic-gate 2996*0Sstevel@tonic-gate for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 2997*0Sstevel@tonic-gate mdhspnamelist_t *hspnlp = Zalloc(sizeof (*hspnlp)); 2998*0Sstevel@tonic-gate 2999*0Sstevel@tonic-gate if ((hspnlp->hspnamep = metahspname(spp, argv[0], 3000*0Sstevel@tonic-gate ep)) == NULL) { 3001*0Sstevel@tonic-gate metafreehspnamelist(*hspnlpp); 3002*0Sstevel@tonic-gate *hspnlpp = NULL; 3003*0Sstevel@tonic-gate return (-1); 3004*0Sstevel@tonic-gate } 3005*0Sstevel@tonic-gate *tailpp = hspnlp; 3006*0Sstevel@tonic-gate tailpp = &hspnlp->next; 3007*0Sstevel@tonic-gate } 3008*0Sstevel@tonic-gate return (count); 3009*0Sstevel@tonic-gate } 3010*0Sstevel@tonic-gate 3011*0Sstevel@tonic-gate /* 3012*0Sstevel@tonic-gate * append to end of hotspare pool list 3013*0Sstevel@tonic-gate */ 3014*0Sstevel@tonic-gate mdhspname_t * 3015*0Sstevel@tonic-gate metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp) 3016*0Sstevel@tonic-gate { 3017*0Sstevel@tonic-gate mdhspnamelist_t *hspnlp; 3018*0Sstevel@tonic-gate 3019*0Sstevel@tonic-gate /* run to end of list */ 3020*0Sstevel@tonic-gate for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next) 3021*0Sstevel@tonic-gate ; 3022*0Sstevel@tonic-gate 3023*0Sstevel@tonic-gate /* allocate new list element */ 3024*0Sstevel@tonic-gate hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp)); 3025*0Sstevel@tonic-gate 3026*0Sstevel@tonic-gate /* append hotspare pool name */ 3027*0Sstevel@tonic-gate hspnlp->hspnamep = hspnp; 3028*0Sstevel@tonic-gate return (hspnp); 3029*0Sstevel@tonic-gate } 3030*0Sstevel@tonic-gate 3031*0Sstevel@tonic-gate /* 3032*0Sstevel@tonic-gate * get name from dev 3033*0Sstevel@tonic-gate */ 3034*0Sstevel@tonic-gate mdname_t * 3035*0Sstevel@tonic-gate metadevname( 3036*0Sstevel@tonic-gate mdsetname_t **spp, 3037*0Sstevel@tonic-gate md_dev64_t dev, 3038*0Sstevel@tonic-gate md_error_t *ep) 3039*0Sstevel@tonic-gate { 3040*0Sstevel@tonic-gate char *device_name; 3041*0Sstevel@tonic-gate mdname_t *namep; 3042*0Sstevel@tonic-gate mdkey_t key; 3043*0Sstevel@tonic-gate 3044*0Sstevel@tonic-gate /* short circuit metadevices */ 3045*0Sstevel@tonic-gate assert(dev != NODEV64); 3046*0Sstevel@tonic-gate if (meta_dev_ismeta(dev)) 3047*0Sstevel@tonic-gate return (metamnumname(spp, meta_getminor(dev), 0, ep)); 3048*0Sstevel@tonic-gate 3049*0Sstevel@tonic-gate /* create local set, if necessary */ 3050*0Sstevel@tonic-gate if (*spp == NULL) { 3051*0Sstevel@tonic-gate if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 3052*0Sstevel@tonic-gate return (NULL); 3053*0Sstevel@tonic-gate } 3054*0Sstevel@tonic-gate 3055*0Sstevel@tonic-gate /* get name from namespace */ 3056*0Sstevel@tonic-gate if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD, 3057*0Sstevel@tonic-gate dev, NULL, NULL, &key, ep)) == NULL) { 3058*0Sstevel@tonic-gate return (NULL); 3059*0Sstevel@tonic-gate } 3060*0Sstevel@tonic-gate namep = metaname_fast(spp, device_name, ep); 3061*0Sstevel@tonic-gate if (namep != NULL) 3062*0Sstevel@tonic-gate namep->key = key; 3063*0Sstevel@tonic-gate 3064*0Sstevel@tonic-gate Free(device_name); 3065*0Sstevel@tonic-gate return (namep); 3066*0Sstevel@tonic-gate } 3067*0Sstevel@tonic-gate 3068*0Sstevel@tonic-gate /* 3069*0Sstevel@tonic-gate * return cached name from md_dev64_t 3070*0Sstevel@tonic-gate */ 3071*0Sstevel@tonic-gate static char * 3072*0Sstevel@tonic-gate metadevtocachename(md_dev64_t dev) 3073*0Sstevel@tonic-gate { 3074*0Sstevel@tonic-gate mddrivenamelist_t *dnlp; 3075*0Sstevel@tonic-gate 3076*0Sstevel@tonic-gate /* look in cache */ 3077*0Sstevel@tonic-gate for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) { 3078*0Sstevel@tonic-gate mddrivename_t *dnp = dnlp->drivenamep; 3079*0Sstevel@tonic-gate uint_t i; 3080*0Sstevel@tonic-gate 3081*0Sstevel@tonic-gate for (i = 0; (i < dnp->parts.parts_len); ++i) { 3082*0Sstevel@tonic-gate mdname_t *np = &dnp->parts.parts_val[i]; 3083*0Sstevel@tonic-gate 3084*0Sstevel@tonic-gate if (np->dev == dev) 3085*0Sstevel@tonic-gate return (np->cname); 3086*0Sstevel@tonic-gate } 3087*0Sstevel@tonic-gate } 3088*0Sstevel@tonic-gate 3089*0Sstevel@tonic-gate /* not found */ 3090*0Sstevel@tonic-gate return (NULL); 3091*0Sstevel@tonic-gate } 3092*0Sstevel@tonic-gate 3093*0Sstevel@tonic-gate /* 3094*0Sstevel@tonic-gate * Ask the driver for the name, which has been stored in the 3095*0Sstevel@tonic-gate * metadevice state database (on behalf of the utilities). 3096*0Sstevel@tonic-gate * (by devno) 3097*0Sstevel@tonic-gate */ 3098*0Sstevel@tonic-gate char * 3099*0Sstevel@tonic-gate get_devname( 3100*0Sstevel@tonic-gate set_t setno, 3101*0Sstevel@tonic-gate md_dev64_t dev) 3102*0Sstevel@tonic-gate { 3103*0Sstevel@tonic-gate mdsetname_t *sp; 3104*0Sstevel@tonic-gate mdname_t *np; 3105*0Sstevel@tonic-gate md_error_t status = mdnullerror; 3106*0Sstevel@tonic-gate 3107*0Sstevel@tonic-gate /* get name */ 3108*0Sstevel@tonic-gate if ((setno == MD_SET_BAD) || 3109*0Sstevel@tonic-gate ((sp = metasetnosetname(setno, &status)) == NULL) || 3110*0Sstevel@tonic-gate ((np = metadevname(&sp, dev, &status)) == NULL)) { 3111*0Sstevel@tonic-gate mdclrerror(&status); 3112*0Sstevel@tonic-gate return (metadevtocachename(dev)); 3113*0Sstevel@tonic-gate } 3114*0Sstevel@tonic-gate 3115*0Sstevel@tonic-gate /* return name */ 3116*0Sstevel@tonic-gate return (np->cname); 3117*0Sstevel@tonic-gate } 3118*0Sstevel@tonic-gate 3119*0Sstevel@tonic-gate /* 3120*0Sstevel@tonic-gate * get name from key 3121*0Sstevel@tonic-gate */ 3122*0Sstevel@tonic-gate mdname_t * 3123*0Sstevel@tonic-gate metakeyname( 3124*0Sstevel@tonic-gate mdsetname_t **spp, 3125*0Sstevel@tonic-gate mdkey_t key, 3126*0Sstevel@tonic-gate int fast, 3127*0Sstevel@tonic-gate md_error_t *ep 3128*0Sstevel@tonic-gate ) 3129*0Sstevel@tonic-gate { 3130*0Sstevel@tonic-gate char *device_name; 3131*0Sstevel@tonic-gate md_dev64_t dev = NODEV64; 3132*0Sstevel@tonic-gate mdname_t *namep; 3133*0Sstevel@tonic-gate 3134*0Sstevel@tonic-gate /* create local set, if necessary */ 3135*0Sstevel@tonic-gate if (*spp == NULL) { 3136*0Sstevel@tonic-gate if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 3137*0Sstevel@tonic-gate return (NULL); 3138*0Sstevel@tonic-gate } 3139*0Sstevel@tonic-gate 3140*0Sstevel@tonic-gate /* get name from namespace */ 3141*0Sstevel@tonic-gate if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD, 3142*0Sstevel@tonic-gate key, NULL, NULL, &dev, ep)) == NULL) { 3143*0Sstevel@tonic-gate return (NULL); 3144*0Sstevel@tonic-gate } 3145*0Sstevel@tonic-gate if (fast) 3146*0Sstevel@tonic-gate namep = metaname_fast(spp, device_name, ep); 3147*0Sstevel@tonic-gate else 3148*0Sstevel@tonic-gate namep = metaname(spp, device_name, ep); 3149*0Sstevel@tonic-gate 3150*0Sstevel@tonic-gate assert(dev != NODEV64); 3151*0Sstevel@tonic-gate if (namep) 3152*0Sstevel@tonic-gate namep->dev = dev; 3153*0Sstevel@tonic-gate Free(device_name); 3154*0Sstevel@tonic-gate return (namep); 3155*0Sstevel@tonic-gate } 3156*0Sstevel@tonic-gate 3157*0Sstevel@tonic-gate /* 3158*0Sstevel@tonic-gate * completely flush the caches 3159*0Sstevel@tonic-gate */ 3160*0Sstevel@tonic-gate void 3161*0Sstevel@tonic-gate metaflushnames(int flush_sr_cache) 3162*0Sstevel@tonic-gate { 3163*0Sstevel@tonic-gate metaflushhspnames(); 3164*0Sstevel@tonic-gate metaflushdrivenames(); 3165*0Sstevel@tonic-gate metaflushsetnames(); 3166*0Sstevel@tonic-gate metaflushctlrcache(); 3167*0Sstevel@tonic-gate metaflushfastnames(); 3168*0Sstevel@tonic-gate metaflushstatcache(); 3169*0Sstevel@tonic-gate if (flush_sr_cache) 3170*0Sstevel@tonic-gate sr_cache_flush(0); 3171*0Sstevel@tonic-gate } 3172*0Sstevel@tonic-gate 3173*0Sstevel@tonic-gate /* 3174*0Sstevel@tonic-gate * meta_get_hotspare_names 3175*0Sstevel@tonic-gate * returns an mdnamelist_t of hot spare names 3176*0Sstevel@tonic-gate */ 3177*0Sstevel@tonic-gate 3178*0Sstevel@tonic-gate int 3179*0Sstevel@tonic-gate meta_get_hotspare_names( 3180*0Sstevel@tonic-gate mdsetname_t *sp, 3181*0Sstevel@tonic-gate mdnamelist_t **nlpp, 3182*0Sstevel@tonic-gate int options, 3183*0Sstevel@tonic-gate md_error_t *ep 3184*0Sstevel@tonic-gate ) 3185*0Sstevel@tonic-gate { 3186*0Sstevel@tonic-gate mdhspnamelist_t *hspnlp = NULL; 3187*0Sstevel@tonic-gate mdhspnamelist_t *hspp; 3188*0Sstevel@tonic-gate int cnt = 0; 3189*0Sstevel@tonic-gate 3190*0Sstevel@tonic-gate assert(nlpp != NULL); 3191*0Sstevel@tonic-gate 3192*0Sstevel@tonic-gate /* get hotspare names */ 3193*0Sstevel@tonic-gate if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) { 3194*0Sstevel@tonic-gate cnt = -1; 3195*0Sstevel@tonic-gate goto out; 3196*0Sstevel@tonic-gate } 3197*0Sstevel@tonic-gate 3198*0Sstevel@tonic-gate /* build name list */ 3199*0Sstevel@tonic-gate for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) { 3200*0Sstevel@tonic-gate md_hsp_t *hsp; 3201*0Sstevel@tonic-gate int i; 3202*0Sstevel@tonic-gate 3203*0Sstevel@tonic-gate if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) { 3204*0Sstevel@tonic-gate cnt = -1; 3205*0Sstevel@tonic-gate goto out; 3206*0Sstevel@tonic-gate } 3207*0Sstevel@tonic-gate for (i = 0; (i < hsp->hotspares.hotspares_len); i++) { 3208*0Sstevel@tonic-gate md_hs_t *hs = &hsp->hotspares.hotspares_val[i]; 3209*0Sstevel@tonic-gate 3210*0Sstevel@tonic-gate (void) metanamelist_append(nlpp, hs->hsnamep); 3211*0Sstevel@tonic-gate ++cnt; 3212*0Sstevel@tonic-gate } 3213*0Sstevel@tonic-gate } 3214*0Sstevel@tonic-gate 3215*0Sstevel@tonic-gate /* cleanup and return count or error */ 3216*0Sstevel@tonic-gate out: 3217*0Sstevel@tonic-gate metafreehspnamelist(hspnlp); 3218*0Sstevel@tonic-gate if ((cnt == -1) && mdisok(ep)) { 3219*0Sstevel@tonic-gate /* 3220*0Sstevel@tonic-gate * At least try to give some sort of meaningful error 3221*0Sstevel@tonic-gate */ 3222*0Sstevel@tonic-gate (void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error"); 3223*0Sstevel@tonic-gate } 3224*0Sstevel@tonic-gate 3225*0Sstevel@tonic-gate return (cnt); 3226*0Sstevel@tonic-gate } 3227*0Sstevel@tonic-gate /* 3228*0Sstevel@tonic-gate * meta_create_non_dup_list 3229*0Sstevel@tonic-gate * INPUT: mdnp mdname_t pointer to add to the list if a new name 3230*0Sstevel@tonic-gate * ldevidp list of non-duplicate names. 3231*0Sstevel@tonic-gate * OUTPUT: ldevidp list of non-duplicate names. 3232*0Sstevel@tonic-gate * meta_create_non_dup_list will take a mdname_t pointer and if the device 3233*0Sstevel@tonic-gate * is not in the list (ldevidp) will add it to the list. 3234*0Sstevel@tonic-gate * User needs to free allocated memory. 3235*0Sstevel@tonic-gate */ 3236*0Sstevel@tonic-gate void 3237*0Sstevel@tonic-gate meta_create_non_dup_list( 3238*0Sstevel@tonic-gate mdname_t *mdnp, 3239*0Sstevel@tonic-gate mddevid_t **ldevidpp 3240*0Sstevel@tonic-gate ) 3241*0Sstevel@tonic-gate { 3242*0Sstevel@tonic-gate char *lcname; 3243*0Sstevel@tonic-gate mddevid_t *tmp; 3244*0Sstevel@tonic-gate mddevid_t *lastdevidp; 3245*0Sstevel@tonic-gate mddevid_t *lldevidp; 3246*0Sstevel@tonic-gate char *ctd, *slice; 3247*0Sstevel@tonic-gate mddevid_t *ldevidp; 3248*0Sstevel@tonic-gate 3249*0Sstevel@tonic-gate if (mdnp == NULL) 3250*0Sstevel@tonic-gate return; 3251*0Sstevel@tonic-gate 3252*0Sstevel@tonic-gate ldevidp = *ldevidpp; 3253*0Sstevel@tonic-gate /* 3254*0Sstevel@tonic-gate * Grab the name of the device and strip off slice information 3255*0Sstevel@tonic-gate */ 3256*0Sstevel@tonic-gate lcname = Strdup(mdnp->cname); 3257*0Sstevel@tonic-gate if (lcname == NULL) { 3258*0Sstevel@tonic-gate return; 3259*0Sstevel@tonic-gate } 3260*0Sstevel@tonic-gate ctd = strrchr(lcname, '/'); 3261*0Sstevel@tonic-gate if (ctd != NULL) 3262*0Sstevel@tonic-gate slice = strrchr(ctd, 's'); 3263*0Sstevel@tonic-gate else 3264*0Sstevel@tonic-gate slice = strrchr(lcname, 's'); 3265*0Sstevel@tonic-gate 3266*0Sstevel@tonic-gate if (slice != NULL) 3267*0Sstevel@tonic-gate *slice = '\0'; 3268*0Sstevel@tonic-gate 3269*0Sstevel@tonic-gate if (ldevidp == NULL) { 3270*0Sstevel@tonic-gate /* first item in list */ 3271*0Sstevel@tonic-gate ldevidp = Zalloc(sizeof (mddevid_t)); 3272*0Sstevel@tonic-gate ldevidp->ctdname = lcname; 3273*0Sstevel@tonic-gate ldevidp->key = mdnp->key; 3274*0Sstevel@tonic-gate *ldevidpp = ldevidp; 3275*0Sstevel@tonic-gate } else { 3276*0Sstevel@tonic-gate for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) { 3277*0Sstevel@tonic-gate if (strcmp(tmp->ctdname, lcname) == 0) { 3278*0Sstevel@tonic-gate /* already there so just return */ 3279*0Sstevel@tonic-gate Free(lcname); 3280*0Sstevel@tonic-gate return; 3281*0Sstevel@tonic-gate } 3282*0Sstevel@tonic-gate lastdevidp = tmp; 3283*0Sstevel@tonic-gate } 3284*0Sstevel@tonic-gate lldevidp = Zalloc(sizeof (mddevid_t)); 3285*0Sstevel@tonic-gate lldevidp->ctdname = lcname; 3286*0Sstevel@tonic-gate lldevidp->key = mdnp->key; 3287*0Sstevel@tonic-gate lastdevidp->next = lldevidp; 3288*0Sstevel@tonic-gate } 3289*0Sstevel@tonic-gate } 3290