10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <meta.h> 300Sstevel@tonic-gate #include <metad.h> 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <ctype.h> 330Sstevel@tonic-gate #include <string.h> 340Sstevel@tonic-gate 350Sstevel@tonic-gate /* 360Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that 370Sstevel@tonic-gate * TEXT_DOMAIN gets set to something. 380Sstevel@tonic-gate */ 390Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 400Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 410Sstevel@tonic-gate #endif 420Sstevel@tonic-gate 430Sstevel@tonic-gate /* 440Sstevel@tonic-gate * Macros to produce a quoted string containing the value of a 450Sstevel@tonic-gate * preprocessor macro. For example, if SIZE is defined to be 256, 460Sstevel@tonic-gate * VAL2STR(SIZE) is "256". This is used to construct format 470Sstevel@tonic-gate * strings for scanf-family functions below. 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate #define QUOTE(x) #x 500Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x) 510Sstevel@tonic-gate 520Sstevel@tonic-gate extern char *getfullblkname(); 530Sstevel@tonic-gate extern char *getfullrawname(); 540Sstevel@tonic-gate 550Sstevel@tonic-gate /* 560Sstevel@tonic-gate * caches 570Sstevel@tonic-gate */ 580Sstevel@tonic-gate static mdsetnamelist_t *setlistp = NULL; 590Sstevel@tonic-gate static mddrivenamelist_t *drivelistp = NULL; 600Sstevel@tonic-gate static mdnamelist_t *fastnmlp = NULL; 610Sstevel@tonic-gate static mdhspnamelist_t *hsplistp = NULL; 620Sstevel@tonic-gate 630Sstevel@tonic-gate /* 640Sstevel@tonic-gate * leak proof name conversion 650Sstevel@tonic-gate */ 660Sstevel@tonic-gate static char * 670Sstevel@tonic-gate rawname( 680Sstevel@tonic-gate char *uname 690Sstevel@tonic-gate ) 700Sstevel@tonic-gate { 710Sstevel@tonic-gate char *p; 720Sstevel@tonic-gate struct stat sbuf1, sbuf2; 730Sstevel@tonic-gate 740Sstevel@tonic-gate if ((p = getfullrawname(uname)) == NULL) { 750Sstevel@tonic-gate return (NULL); 760Sstevel@tonic-gate } else if (*p == '\0') { 770Sstevel@tonic-gate Free(p); 780Sstevel@tonic-gate return (NULL); 790Sstevel@tonic-gate } else { 800Sstevel@tonic-gate if (stat(uname, &sbuf1) != 0) { 810Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 820Sstevel@tonic-gate "device to mount in /etc/vfstab is " 830Sstevel@tonic-gate "invalid for device %s\n"), uname); 840Sstevel@tonic-gate exit(1); 850Sstevel@tonic-gate } 860Sstevel@tonic-gate if (stat(p, &sbuf2) != 0) { 870Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 880Sstevel@tonic-gate "device to fsck in /etc/vfstab is " 890Sstevel@tonic-gate "invalid for raw device %s\n"), p); 900Sstevel@tonic-gate exit(1); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate if (sbuf1.st_rdev != sbuf2.st_rdev) { 930Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 940Sstevel@tonic-gate "/etc/vfstab entries inconsistent on " 950Sstevel@tonic-gate "line containing device %s\n"), uname); 960Sstevel@tonic-gate exit(1); 970Sstevel@tonic-gate } 98*871Scasper if (!S_ISBLK(sbuf1.st_mode)) { 990Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1000Sstevel@tonic-gate "/etc/vfstab device to mount is not a " 1010Sstevel@tonic-gate "block device for device %s\n"), uname); 1020Sstevel@tonic-gate exit(1); 1030Sstevel@tonic-gate } 104*871Scasper if (!S_ISCHR(sbuf2.st_mode)) { 1050Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1060Sstevel@tonic-gate "/etc/vfstab device to fsck is not a " 1070Sstevel@tonic-gate "raw device for device %s\n"), p); 1080Sstevel@tonic-gate exit(1); 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate return (p); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate char * 1150Sstevel@tonic-gate blkname( 1160Sstevel@tonic-gate char *uname 1170Sstevel@tonic-gate ) 1180Sstevel@tonic-gate { 1190Sstevel@tonic-gate char *p; 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate if ((p = getfullblkname(uname)) == NULL) { 1220Sstevel@tonic-gate return (NULL); 1230Sstevel@tonic-gate } else if (*p == '\0') { 1240Sstevel@tonic-gate Free(p); 1250Sstevel@tonic-gate return (NULL); 1260Sstevel@tonic-gate } else { 1270Sstevel@tonic-gate return (p); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* 1320Sstevel@tonic-gate * parse up metadevice name 1330Sstevel@tonic-gate */ 1340Sstevel@tonic-gate static int 1350Sstevel@tonic-gate parse_metadevice( 1360Sstevel@tonic-gate char *uname, 1370Sstevel@tonic-gate char **snamep, 1380Sstevel@tonic-gate unit_t *unitp 1390Sstevel@tonic-gate ) 1400Sstevel@tonic-gate { 1410Sstevel@tonic-gate char *sname = Malloc(strlen(uname) + 1); 1420Sstevel@tonic-gate char *tname = Malloc(strlen(uname) + 1); 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate unit_t unit; 1450Sstevel@tonic-gate int len; 1460Sstevel@tonic-gate char *up; 1470Sstevel@tonic-gate char *tp; 1480Sstevel@tonic-gate int lcws; /* last character was slash */ 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate /* handle dont cares */ 1510Sstevel@tonic-gate if (unitp == NULL) 1520Sstevel@tonic-gate unitp = &unit; 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate /* Now copy uname to tname by throwing away any duplicate '/' */ 1550Sstevel@tonic-gate for (lcws = 0, tp = tname, up = uname; *up; up++) { 1560Sstevel@tonic-gate if (lcws) { 1570Sstevel@tonic-gate if (*up == '/') { 1580Sstevel@tonic-gate continue; 1590Sstevel@tonic-gate } else { 1600Sstevel@tonic-gate lcws = 0; 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate if (*up == '/') { 1640Sstevel@tonic-gate lcws = 1; 1650Sstevel@tonic-gate } 1660Sstevel@tonic-gate *tp++ = *up; /* ++ is done by for loop */ 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate *tp = '\0'; 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate /* without set */ 1710Sstevel@tonic-gate if ((sscanf(tname, "d%lu%n", unitp, &len) == 1) && 1720Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0)) { 1730Sstevel@tonic-gate if (snamep != NULL) 1740Sstevel@tonic-gate *snamep = NULL; 1750Sstevel@tonic-gate Free(sname); 1760Sstevel@tonic-gate Free(tname); 1770Sstevel@tonic-gate return (0); 1780Sstevel@tonic-gate } 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate /* fully-qualified without set */ 1810Sstevel@tonic-gate if (((sscanf(tname, "/dev/md/dsk/d%lu%n", unitp, &len) == 1) && 1820Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0)) || 1830Sstevel@tonic-gate ((sscanf(tname, "/dev/md/rdsk/d%lu%n", unitp, &len) == 1) && 1840Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0))) { 1850Sstevel@tonic-gate if (snamep != NULL) 1860Sstevel@tonic-gate *snamep = Strdup(MD_LOCAL_NAME); 1870Sstevel@tonic-gate Free(sname); 1880Sstevel@tonic-gate Free(tname); 1890Sstevel@tonic-gate return (0); 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* with set */ 1930Sstevel@tonic-gate if (((sscanf(tname, "%[^/]/d%lu%n", sname, unitp, &len) == 2) && 1940Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0)) || 1950Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/dsk/d%lu%n", sname, 1960Sstevel@tonic-gate unitp, &len) == 2) && 1970Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0)) || 1980Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/rdsk/d%lu%n", sname, 1990Sstevel@tonic-gate unitp, &len) == 2) && 2000Sstevel@tonic-gate (strlen(tname) == len) && ((long)*unitp >= 0))) { 2010Sstevel@tonic-gate if (snamep != NULL) { 2020Sstevel@tonic-gate *snamep = sname; 2030Sstevel@tonic-gate } else { 2040Sstevel@tonic-gate Free(sname); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate Free(tname); 2070Sstevel@tonic-gate return (0); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate /* no match */ 2110Sstevel@tonic-gate if (snamep != NULL) 2120Sstevel@tonic-gate *snamep = NULL; 2130Sstevel@tonic-gate Free(sname); 2140Sstevel@tonic-gate Free(tname); 2150Sstevel@tonic-gate return (-1); 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /* 2190Sstevel@tonic-gate * FUNCTION: parse_device() 2200Sstevel@tonic-gate * INPUT: sp - pointer to setname struct 2210Sstevel@tonic-gate * uname - Name of either a hotspare pool or metadevice 2220Sstevel@tonic-gate * This can either be a fully qualified path or 2230Sstevel@tonic-gate * in the form [set name/]device 2240Sstevel@tonic-gate * OUTPUT: setnamep - name of the set that uname is in 2250Sstevel@tonic-gate * uname - name of the hotspare pools or metadevice 2260Sstevel@tonic-gate * only contains the name of the device with all 2270Sstevel@tonic-gate * other path information stripped off. 2280Sstevel@tonic-gate * PURPOSE: Parse uname and sp into the set name and device name strings. 2290Sstevel@tonic-gate * If the set name is specified as part of uname then use that 2300Sstevel@tonic-gate * otherwise attempt to get the set name from sp. 2310Sstevel@tonic-gate */ 2320Sstevel@tonic-gate static void 2330Sstevel@tonic-gate parse_device( 2340Sstevel@tonic-gate mdsetname_t *sp, 2350Sstevel@tonic-gate char *uname, 2360Sstevel@tonic-gate char **setnamep /* dynamically alloced - caller must free */ 2370Sstevel@tonic-gate ) 2380Sstevel@tonic-gate { 2390Sstevel@tonic-gate char setname[FILENAME_MAX+1]; 2400Sstevel@tonic-gate char *tname = Malloc(strlen(uname) + 1); 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate int len; 2430Sstevel@tonic-gate char *up; 2440Sstevel@tonic-gate char *tp; 2450Sstevel@tonic-gate int lcws; /* last character was slash */ 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate /* Now copy uname to tname by throwing away any duplicate '/' */ 2480Sstevel@tonic-gate for (lcws = 0, tp = tname, up = uname; *up; up++) { 2490Sstevel@tonic-gate if (lcws) { 2500Sstevel@tonic-gate if (*up == '/') { 2510Sstevel@tonic-gate continue; 2520Sstevel@tonic-gate } else { 2530Sstevel@tonic-gate lcws = 0; 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate if (*up == '/') { 2570Sstevel@tonic-gate lcws = 1; 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate *tp++ = *up; /* ++ is done by for loop */ 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate *tp = '\0'; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate /* fully-qualified - local set */ 2640Sstevel@tonic-gate if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n", 2650Sstevel@tonic-gate uname, &len) == 1) && (strlen(tname) == len)) || 2660Sstevel@tonic-gate ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", 2670Sstevel@tonic-gate uname, &len) == 1) && (strlen(tname) == len))) { 2680Sstevel@tonic-gate if (setnamep != NULL) 2690Sstevel@tonic-gate *setnamep = NULL; 2700Sstevel@tonic-gate Free(tname); 2710Sstevel@tonic-gate return; 2720Sstevel@tonic-gate } 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate /* with setname specified - either fully qualified and relative spec */ 2750Sstevel@tonic-gate if (((sscanf(tname, "%" VAL2STR(FILENAME_MAX) "s/%" 2760Sstevel@tonic-gate VAL2STR(FILENAME_MAX) "s%n", setname, uname, &len) == 2) && 2770Sstevel@tonic-gate (strlen(tname) == len)) || 2780Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n", 2790Sstevel@tonic-gate setname, uname, &len) == 2) && (strlen(tname) == len)) || 2800Sstevel@tonic-gate ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", 2810Sstevel@tonic-gate setname, uname, &len) == 2) && (strlen(tname) == len))) { 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate if (setnamep != NULL) { 2840Sstevel@tonic-gate *setnamep = Strdup(setname); 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate Free(tname); 2870Sstevel@tonic-gate return; 2880Sstevel@tonic-gate } 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate /* without setname specified */ 2910Sstevel@tonic-gate (void) strcpy(uname, tname); 2920Sstevel@tonic-gate if (setnamep != NULL) { 2930Sstevel@tonic-gate if (sp != NULL && !metaislocalset(sp)) 2940Sstevel@tonic-gate *setnamep = Strdup(sp->setname); 2950Sstevel@tonic-gate else 2960Sstevel@tonic-gate *setnamep = NULL; 2970Sstevel@tonic-gate } 2980Sstevel@tonic-gate Free(tname); 2990Sstevel@tonic-gate } 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate /* 3020Sstevel@tonic-gate * parse up hotspare pool name 3030Sstevel@tonic-gate */ 3040Sstevel@tonic-gate static int 3050Sstevel@tonic-gate parse_hsp( 3060Sstevel@tonic-gate char *uname, 3070Sstevel@tonic-gate char **snamep, 3080Sstevel@tonic-gate hsp_t *hspp 3090Sstevel@tonic-gate ) 3100Sstevel@tonic-gate { 3110Sstevel@tonic-gate char *sname = Malloc(strlen(uname) + 1); 3120Sstevel@tonic-gate hsp_t hsp; 3130Sstevel@tonic-gate int len; 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate /* handle dont cares */ 3160Sstevel@tonic-gate if (hspp == NULL) 3170Sstevel@tonic-gate hspp = &hsp; 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* without set */ 3200Sstevel@tonic-gate if ((sscanf(uname, "hsp%03u%n", hspp, &len) == 1) && 3210Sstevel@tonic-gate (strlen(uname) == len) && ((long)*hspp >= 0)) { 3220Sstevel@tonic-gate if (snamep != NULL) 3230Sstevel@tonic-gate *snamep = NULL; 3240Sstevel@tonic-gate Free(sname); 3250Sstevel@tonic-gate return (0); 3260Sstevel@tonic-gate } 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate /* with set */ 3290Sstevel@tonic-gate if ((sscanf(uname, "%[^/]/hsp%03u%n", sname, 3300Sstevel@tonic-gate hspp, &len) == 2) && 3310Sstevel@tonic-gate (strlen(uname) == len) && ((long)*hspp >= 0)) { 3320Sstevel@tonic-gate if (snamep != NULL) { 3330Sstevel@tonic-gate *snamep = sname; 3340Sstevel@tonic-gate } else { 3350Sstevel@tonic-gate Free(sname); 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate return (0); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* no match */ 3410Sstevel@tonic-gate Free(sname); 3420Sstevel@tonic-gate return (-1); 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * canonicalize metadevice name 3470Sstevel@tonic-gate */ 3480Sstevel@tonic-gate static char * 3490Sstevel@tonic-gate canon_metadevice( 3500Sstevel@tonic-gate char *sname, 3510Sstevel@tonic-gate unit_t unit 3520Sstevel@tonic-gate ) 3530Sstevel@tonic-gate { 3540Sstevel@tonic-gate char *cname; 3550Sstevel@tonic-gate size_t len; 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 3580Sstevel@tonic-gate len = strlen("d") + 20 + 1; 3590Sstevel@tonic-gate cname = Malloc(len); 3600Sstevel@tonic-gate (void) snprintf(cname, len, "d%lu", unit); 3610Sstevel@tonic-gate } else { 3620Sstevel@tonic-gate len = strlen(sname) + strlen("/d") + 20 + 1; 3630Sstevel@tonic-gate cname = Malloc(len); 3640Sstevel@tonic-gate (void) snprintf(cname, len, "%s/d%lu", sname, unit); 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate return (cname); 3680Sstevel@tonic-gate } 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate /* 3710Sstevel@tonic-gate * canonicalize hotspare pool name 3720Sstevel@tonic-gate */ 3730Sstevel@tonic-gate static char * 3740Sstevel@tonic-gate canon_hsp( 3750Sstevel@tonic-gate char *sname, 3760Sstevel@tonic-gate hsp_t hsp 3770Sstevel@tonic-gate ) 3780Sstevel@tonic-gate { 3790Sstevel@tonic-gate char *cname; 3800Sstevel@tonic-gate size_t len; 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 3830Sstevel@tonic-gate cname = Malloc(strlen("hsp000") + 1); 3840Sstevel@tonic-gate (void) sprintf(cname, "hsp%03u", hsp); 3850Sstevel@tonic-gate } else { 3860Sstevel@tonic-gate len = strlen(sname) + strlen("/hsp000") + 1; 3870Sstevel@tonic-gate cname = Malloc(len); 3880Sstevel@tonic-gate (void) snprintf(cname, len, "%s/hsp%03lu", sname, hsp); 3890Sstevel@tonic-gate } 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate return (cname); 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate /* 3950Sstevel@tonic-gate * canonicalize name, return type 3960Sstevel@tonic-gate * 3970Sstevel@tonic-gate * NOTE: this is really only for use by meta_tab* 3980Sstevel@tonic-gate */ 3990Sstevel@tonic-gate char * 4000Sstevel@tonic-gate meta_canonicalize( 4010Sstevel@tonic-gate mdsetname_t *sp, 4020Sstevel@tonic-gate char *uname 4030Sstevel@tonic-gate ) 4040Sstevel@tonic-gate { 4050Sstevel@tonic-gate char *sname = NULL; 4060Sstevel@tonic-gate char *cname; 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate /* return the set name and dev name */ 4090Sstevel@tonic-gate parse_device(sp, uname, &sname); 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate if (sname == NULL) 4120Sstevel@tonic-gate cname = Strdup(uname); 4130Sstevel@tonic-gate else { 4140Sstevel@tonic-gate size_t cname_len; 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate cname_len = strlen(uname) + strlen(sname) + 2; 4170Sstevel@tonic-gate cname = Malloc(cname_len); 4180Sstevel@tonic-gate (void) snprintf( 4190Sstevel@tonic-gate cname, cname_len, "%s/%s", sname, uname); 4200Sstevel@tonic-gate Free(sname); 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate return (cname); 4230Sstevel@tonic-gate } 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate /* 4260Sstevel@tonic-gate * check that name is a metadevice 4270Sstevel@tonic-gate */ 4280Sstevel@tonic-gate int 4290Sstevel@tonic-gate is_metaname( 4300Sstevel@tonic-gate char *uname 4310Sstevel@tonic-gate ) 4320Sstevel@tonic-gate { 4330Sstevel@tonic-gate if (parse_metadevice(uname, NULL, NULL) == 0) 4340Sstevel@tonic-gate return (1); 4350Sstevel@tonic-gate else 4360Sstevel@tonic-gate return (0); 4370Sstevel@tonic-gate } 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate /* 4400Sstevel@tonic-gate * check that name is a hotspare pool 4410Sstevel@tonic-gate */ 4420Sstevel@tonic-gate int 4430Sstevel@tonic-gate is_hspname( 4440Sstevel@tonic-gate char *uname 4450Sstevel@tonic-gate ) 4460Sstevel@tonic-gate { 4470Sstevel@tonic-gate if (parse_hsp(uname, NULL, NULL) == 0) 4480Sstevel@tonic-gate return (1); 4490Sstevel@tonic-gate else 4500Sstevel@tonic-gate return (0); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate /* 4540Sstevel@tonic-gate * mdsetname_t stuff 4550Sstevel@tonic-gate */ 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate /* 4580Sstevel@tonic-gate * initialize setname 4590Sstevel@tonic-gate */ 4600Sstevel@tonic-gate static void 4610Sstevel@tonic-gate metainitsetname( 4620Sstevel@tonic-gate mdsetname_t *sp 4630Sstevel@tonic-gate ) 4640Sstevel@tonic-gate { 4650Sstevel@tonic-gate (void) memset(sp, '\0', sizeof (*sp)); 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate static void 4690Sstevel@tonic-gate metafreesetdesc(md_set_desc *sd) 4700Sstevel@tonic-gate { 4710Sstevel@tonic-gate md_mnnode_desc *nd; 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) { 4740Sstevel@tonic-gate nd = sd->sd_nodelist; 4750Sstevel@tonic-gate while (nd) { 4760Sstevel@tonic-gate sd->sd_nodelist = nd->nd_next; 4770Sstevel@tonic-gate Free(nd); 4780Sstevel@tonic-gate nd = sd->sd_nodelist; 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate } 4810Sstevel@tonic-gate metafreedrivedesc(&sd->sd_drvs); 4820Sstevel@tonic-gate Free(sd); 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate /* 4860Sstevel@tonic-gate * free allocated setname 4870Sstevel@tonic-gate */ 4880Sstevel@tonic-gate static void 4890Sstevel@tonic-gate metafreesetname( 4900Sstevel@tonic-gate mdsetname_t *sp 4910Sstevel@tonic-gate ) 4920Sstevel@tonic-gate { 4930Sstevel@tonic-gate if (sp->setname != NULL) 4940Sstevel@tonic-gate Free(sp->setname); 4950Sstevel@tonic-gate if (sp->setdesc != NULL) 4960Sstevel@tonic-gate metafreesetdesc(sp->setdesc); 4970Sstevel@tonic-gate metainitsetname(sp); 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate /* 5010Sstevel@tonic-gate * flush the setname cache 5020Sstevel@tonic-gate */ 5030Sstevel@tonic-gate static void 5040Sstevel@tonic-gate metaflushsetnames() 5050Sstevel@tonic-gate { 5060Sstevel@tonic-gate mdsetnamelist_t *p, *n; 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate for (p = setlistp, n = NULL; (p != NULL); p = n) { 5090Sstevel@tonic-gate n = p->next; 5100Sstevel@tonic-gate metafreesetname(p->sp); 5110Sstevel@tonic-gate Free(p->sp); 5120Sstevel@tonic-gate Free(p); 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate setlistp = NULL; 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate /* 5180Sstevel@tonic-gate * get set number 5190Sstevel@tonic-gate */ 5200Sstevel@tonic-gate static int 5210Sstevel@tonic-gate getsetno( 5220Sstevel@tonic-gate char *sname, 5230Sstevel@tonic-gate set_t *setnop, 5240Sstevel@tonic-gate md_error_t *ep 5250Sstevel@tonic-gate ) 5260Sstevel@tonic-gate { 5270Sstevel@tonic-gate md_set_record *sr; 5280Sstevel@tonic-gate size_t len; 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate /* local set */ 5310Sstevel@tonic-gate if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 5320Sstevel@tonic-gate *setnop = 0; 5330Sstevel@tonic-gate return (0); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate /* shared set */ 5370Sstevel@tonic-gate if ((sr = getsetbyname(sname, ep)) == NULL) { 5380Sstevel@tonic-gate if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) { 5390Sstevel@tonic-gate char *p; 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate len = strlen(sname) + 30; 5420Sstevel@tonic-gate p = Malloc(len); 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate (void) snprintf(p, len, "setname \"%s\"", sname); 5450Sstevel@tonic-gate (void) mderror(ep, MDE_NO_SET, p); 5460Sstevel@tonic-gate Free(p); 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate return (-1); 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate *setnop = sr->sr_setno; 5510Sstevel@tonic-gate free_sr(sr); 5520Sstevel@tonic-gate return (0); 5530Sstevel@tonic-gate } 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate /* 5560Sstevel@tonic-gate * find setname from name 5570Sstevel@tonic-gate */ 5580Sstevel@tonic-gate mdsetname_t * 5590Sstevel@tonic-gate metasetname( 5600Sstevel@tonic-gate char *sname, 5610Sstevel@tonic-gate md_error_t *ep 5620Sstevel@tonic-gate ) 5630Sstevel@tonic-gate { 5640Sstevel@tonic-gate mdsetnamelist_t **tail; 5650Sstevel@tonic-gate set_t setno; 5660Sstevel@tonic-gate mdsetname_t *sp; 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate /* look for cached value first */ 5690Sstevel@tonic-gate assert(sname != NULL); 5700Sstevel@tonic-gate for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) { 5710Sstevel@tonic-gate sp = (*tail)->sp; 5720Sstevel@tonic-gate if (strcmp(sp->setname, sname) == 0) { 5730Sstevel@tonic-gate return (sp); 5740Sstevel@tonic-gate } 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate /* setup set */ 5780Sstevel@tonic-gate if (getsetno(sname, &setno, ep) != 0) 5790Sstevel@tonic-gate return (NULL); 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate /* allocate new list element and setname */ 5820Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 5830Sstevel@tonic-gate sp = (*tail)->sp = Zalloc(sizeof (*sp)); 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate sp->setname = Strdup(sname); 5860Sstevel@tonic-gate sp->setno = setno; 5870Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK; 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate return (sp); 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate /* 5930Sstevel@tonic-gate * find setname from setno 5940Sstevel@tonic-gate */ 5950Sstevel@tonic-gate mdsetname_t * 5960Sstevel@tonic-gate metasetnosetname( 5970Sstevel@tonic-gate set_t setno, 5980Sstevel@tonic-gate md_error_t *ep 5990Sstevel@tonic-gate ) 6000Sstevel@tonic-gate { 6010Sstevel@tonic-gate mdsetnamelist_t *slp; 6020Sstevel@tonic-gate mdsetname_t *sp; 6030Sstevel@tonic-gate md_set_record *sr; 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate /* look for cached value first */ 6060Sstevel@tonic-gate for (slp = setlistp; (slp != NULL); slp = slp->next) { 6070Sstevel@tonic-gate sp = slp->sp; 6080Sstevel@tonic-gate if (sp->setno == setno) 6090Sstevel@tonic-gate return (sp); 6100Sstevel@tonic-gate } 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate /* local set */ 6130Sstevel@tonic-gate if (setno == MD_LOCAL_SET) 6140Sstevel@tonic-gate return (metasetname(MD_LOCAL_NAME, ep)); 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate /* shared set */ 6170Sstevel@tonic-gate if ((sr = getsetbynum(setno, ep)) == NULL) 6180Sstevel@tonic-gate return (NULL); 6190Sstevel@tonic-gate sp = metasetname(sr->sr_setname, ep); 6200Sstevel@tonic-gate free_sr(sr); 6210Sstevel@tonic-gate return (sp); 6220Sstevel@tonic-gate } 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate mdsetname_t * 6250Sstevel@tonic-gate metafakesetname( 6260Sstevel@tonic-gate set_t setno, 6270Sstevel@tonic-gate char *sname 6280Sstevel@tonic-gate ) 6290Sstevel@tonic-gate { 6300Sstevel@tonic-gate mdsetnamelist_t **tail; 6310Sstevel@tonic-gate mdsetname_t *sp; 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate /* look for cached value first */ 6340Sstevel@tonic-gate for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) { 6350Sstevel@tonic-gate sp = (*tail)->sp; 6360Sstevel@tonic-gate if (sp->setno == setno) { 6370Sstevel@tonic-gate if ((sp->setname == NULL) && (sname != NULL)) 6380Sstevel@tonic-gate sp->setname = Strdup(sname); 6390Sstevel@tonic-gate return (sp); 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate /* allocate new list element and setname */ 6440Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 6450Sstevel@tonic-gate sp = (*tail)->sp = Zalloc(sizeof (*sp)); 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate if (sname != NULL) 6480Sstevel@tonic-gate sp->setname = Strdup(sname); 6490Sstevel@tonic-gate sp->setno = setno; 6500Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK; 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate return (sp); 6530Sstevel@tonic-gate } 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate /* 6570Sstevel@tonic-gate * setup set record (sr) and cache it in the mdsetname_t struct 6580Sstevel@tonic-gate */ 6590Sstevel@tonic-gate md_set_desc * 6600Sstevel@tonic-gate sr2setdesc( 6610Sstevel@tonic-gate md_set_record *sr 6620Sstevel@tonic-gate ) 6630Sstevel@tonic-gate { 6640Sstevel@tonic-gate md_set_desc *sd; 6650Sstevel@tonic-gate int i; 6660Sstevel@tonic-gate md_mnset_record *mnsr; 6670Sstevel@tonic-gate md_mnnode_desc *nd, *nd_prev = 0; 6680Sstevel@tonic-gate md_mnnode_record *nr; 6690Sstevel@tonic-gate md_error_t status = mdnullerror; 6700Sstevel@tonic-gate md_error_t *ep = &status; 6710Sstevel@tonic-gate int nodecnt, nrcnt; 6720Sstevel@tonic-gate mndiskset_membershiplist_t *nl, *nl2; 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate sd = Zalloc(sizeof (*sd)); 6750Sstevel@tonic-gate sd->sd_ctime = sr->sr_ctime; 6760Sstevel@tonic-gate sd->sd_genid = sr->sr_genid; 6770Sstevel@tonic-gate sd->sd_setno = sr->sr_setno; 6780Sstevel@tonic-gate sd->sd_flags = sr->sr_flags; 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) { 6810Sstevel@tonic-gate mnsr = (md_mnset_record *)sr; 6820Sstevel@tonic-gate (void) strlcpy(sd->sd_mn_master_nodenm, 6830Sstevel@tonic-gate mnsr->sr_master_nodenm, sizeof (sd->sd_mn_master_nodenm)); 6840Sstevel@tonic-gate sd->sd_mn_master_nodeid = mnsr->sr_master_nodeid; 6850Sstevel@tonic-gate if (strcmp(mnsr->sr_master_nodenm, mynode()) == 0) { 6860Sstevel@tonic-gate sd->sd_mn_am_i_master = 1; 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate /* 6900Sstevel@tonic-gate * Get membershiplist from API routine. If there's 6910Sstevel@tonic-gate * an error, just use a NULL nodelist. 6920Sstevel@tonic-gate */ 6930Sstevel@tonic-gate if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) { 6940Sstevel@tonic-gate nodecnt = 0; /* no nodes are alive */ 6950Sstevel@tonic-gate nl = NULL; 6960Sstevel@tonic-gate } 6970Sstevel@tonic-gate nr = mnsr->sr_nodechain; 6980Sstevel@tonic-gate nrcnt = 0; 6990Sstevel@tonic-gate /* 7000Sstevel@tonic-gate * Node descriptor node list must be built in 7010Sstevel@tonic-gate * ascending order of nodeid. The nodechain 7020Sstevel@tonic-gate * in the mnset record is in ascending order, 7030Sstevel@tonic-gate * so just make them the same. 7040Sstevel@tonic-gate */ 7050Sstevel@tonic-gate while (nr) { 7060Sstevel@tonic-gate nd = Zalloc(sizeof (*nd)); 7070Sstevel@tonic-gate if (nd_prev) { 7080Sstevel@tonic-gate nd_prev->nd_next = nd; 7090Sstevel@tonic-gate } else { 7100Sstevel@tonic-gate sd->sd_nodelist = nd; 7110Sstevel@tonic-gate } 7120Sstevel@tonic-gate nd->nd_ctime = nr->nr_ctime; 7130Sstevel@tonic-gate nd->nd_genid = nr->nr_genid; 7140Sstevel@tonic-gate nd->nd_flags = nr->nr_flags; 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate (void) strlcpy(nd->nd_nodename, nr->nr_nodename, 7170Sstevel@tonic-gate sizeof (nd->nd_nodename)); 7180Sstevel@tonic-gate nd->nd_nodeid = nr->nr_nodeid; 7190Sstevel@tonic-gate if (strcmp(nd->nd_nodename, mynode()) == 0) { 7200Sstevel@tonic-gate sd->sd_mn_mynode = nd; 7210Sstevel@tonic-gate } 7220Sstevel@tonic-gate if (nd->nd_nodeid == sd->sd_mn_master_nodeid) { 7230Sstevel@tonic-gate sd->sd_mn_masternode = nd; 7240Sstevel@tonic-gate } 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate /* 7270Sstevel@tonic-gate * If node is marked ALIVE, then set priv_ic 7280Sstevel@tonic-gate * from membership list. During the early part 7290Sstevel@tonic-gate * of a reconfig cycle, the membership list may 7300Sstevel@tonic-gate * have been changed, (a node entering or leaving 7310Sstevel@tonic-gate * the cluster), but rpc.metad hasn't flushed 7320Sstevel@tonic-gate * its data yet. So, if node is marked alive, but 7330Sstevel@tonic-gate * is no longer in the membership list (node has 7340Sstevel@tonic-gate * left the cluster) then just leave priv_ic to NULL. 7350Sstevel@tonic-gate */ 7360Sstevel@tonic-gate if (nd->nd_flags & MD_MN_NODE_ALIVE) { 7370Sstevel@tonic-gate nl2 = nl; 7380Sstevel@tonic-gate while (nl2) { 7390Sstevel@tonic-gate if (nl2->msl_node_id == nd->nd_nodeid) { 7400Sstevel@tonic-gate (void) strlcpy(nd->nd_priv_ic, 7410Sstevel@tonic-gate nl2->msl_node_addr, 7420Sstevel@tonic-gate sizeof (nd->nd_priv_ic)); 7430Sstevel@tonic-gate break; 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate nl2 = nl2->next; 7460Sstevel@tonic-gate } 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate nr = nr->nr_next; 7500Sstevel@tonic-gate nrcnt++; 7510Sstevel@tonic-gate nd_prev = nd; 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate sd->sd_mn_numnodes = nrcnt; 7540Sstevel@tonic-gate if (nodecnt) 7550Sstevel@tonic-gate meta_free_nodelist(nl); 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate /* Just copying to keep consistent view between sr & sd */ 7580Sstevel@tonic-gate (void) strlcpy(sd->sd_nodes[0], mnsr->sr_nodes_bw_compat[0], 7590Sstevel@tonic-gate sizeof (sd->sd_nodes[0])); 7600Sstevel@tonic-gate } else { 7610Sstevel@tonic-gate for (i = 0; i < MD_MAXSIDES; i++) 7620Sstevel@tonic-gate (void) strlcpy(sd->sd_nodes[i], sr->sr_nodes[i], 7630Sstevel@tonic-gate sizeof (sd->sd_nodes[i])); 7640Sstevel@tonic-gate } 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate sd->sd_med = sr->sr_med; /* structure assignment */ 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate return (sd); 7690Sstevel@tonic-gate } 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate md_set_desc * 7720Sstevel@tonic-gate metaget_setdesc( 7730Sstevel@tonic-gate mdsetname_t *sp, 7740Sstevel@tonic-gate md_error_t *ep 7750Sstevel@tonic-gate ) 7760Sstevel@tonic-gate { 7770Sstevel@tonic-gate md_set_record *sr; 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate if (sp->setdesc != NULL) 7800Sstevel@tonic-gate return (sp->setdesc); 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate if (sp->setname != NULL) { 7830Sstevel@tonic-gate if ((sr = getsetbyname(sp->setname, ep)) != NULL) { 7840Sstevel@tonic-gate sp->setdesc = sr2setdesc(sr); 7850Sstevel@tonic-gate free_sr(sr); 7860Sstevel@tonic-gate return (sp->setdesc); 7870Sstevel@tonic-gate } 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate if (sp->setno > 0) { 7910Sstevel@tonic-gate if ((sr = getsetbynum(sp->setno, ep)) != NULL) { 7920Sstevel@tonic-gate sp->setdesc = sr2setdesc(sr); 7930Sstevel@tonic-gate free_sr(sr); 7940Sstevel@tonic-gate return (sp->setdesc); 7950Sstevel@tonic-gate } 7960Sstevel@tonic-gate } 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate return (NULL); 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate void 8020Sstevel@tonic-gate metaflushsetname(mdsetname_t *sp) 8030Sstevel@tonic-gate { 8040Sstevel@tonic-gate if (sp == NULL) 8050Sstevel@tonic-gate return; 8060Sstevel@tonic-gate 8070Sstevel@tonic-gate if (sp->setdesc == NULL) 8080Sstevel@tonic-gate return; 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate metafreesetdesc(sp->setdesc); 8110Sstevel@tonic-gate sp->setdesc = NULL; 8120Sstevel@tonic-gate } 8130Sstevel@tonic-gate 8140Sstevel@tonic-gate /* 8150Sstevel@tonic-gate * check for local set 8160Sstevel@tonic-gate */ 8170Sstevel@tonic-gate int 8180Sstevel@tonic-gate metaislocalset( 8190Sstevel@tonic-gate mdsetname_t *sp 8200Sstevel@tonic-gate ) 8210Sstevel@tonic-gate { 8220Sstevel@tonic-gate assert(sp->setname != NULL); 8230Sstevel@tonic-gate if (strcmp(sp->setname, MD_LOCAL_NAME) == 0) { 8240Sstevel@tonic-gate assert(sp->setno == MD_LOCAL_SET); 8250Sstevel@tonic-gate return (1); 8260Sstevel@tonic-gate } else { 8270Sstevel@tonic-gate assert(sp->setno != MD_LOCAL_SET); 8280Sstevel@tonic-gate return (0); 8290Sstevel@tonic-gate } 8300Sstevel@tonic-gate } 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate /* 8330Sstevel@tonic-gate * check for same set 8340Sstevel@tonic-gate */ 8350Sstevel@tonic-gate int 8360Sstevel@tonic-gate metaissameset( 8370Sstevel@tonic-gate mdsetname_t *sp1, 8380Sstevel@tonic-gate mdsetname_t *sp2 8390Sstevel@tonic-gate ) 8400Sstevel@tonic-gate { 8410Sstevel@tonic-gate if (strcmp(sp1->setname, sp2->setname) == 0) { 8420Sstevel@tonic-gate assert(sp1->setno == sp2->setno); 8430Sstevel@tonic-gate return (1); 8440Sstevel@tonic-gate } else { 8450Sstevel@tonic-gate assert(sp1->setno != sp2->setno); 8460Sstevel@tonic-gate return (0); 8470Sstevel@tonic-gate } 8480Sstevel@tonic-gate } 8490Sstevel@tonic-gate 8500Sstevel@tonic-gate /* 8510Sstevel@tonic-gate * check to see if set changed 8520Sstevel@tonic-gate */ 8530Sstevel@tonic-gate static int 8540Sstevel@tonic-gate chkset( 8550Sstevel@tonic-gate mdsetname_t **spp, 8560Sstevel@tonic-gate char *sname, 8570Sstevel@tonic-gate md_error_t *ep 8580Sstevel@tonic-gate ) 8590Sstevel@tonic-gate { 8600Sstevel@tonic-gate /* if we already have a set, make sure it's the same */ 8610Sstevel@tonic-gate if (*spp != NULL) { 8620Sstevel@tonic-gate if ((*spp)->setname != sname && 8630Sstevel@tonic-gate strcmp((*spp)->setname, sname) != 0) { 8640Sstevel@tonic-gate return (mderror(ep, MDE_SET_DIFF, sname)); 8650Sstevel@tonic-gate } 8660Sstevel@tonic-gate return (0); 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate /* otherwise store new set name and number */ 8700Sstevel@tonic-gate if ((*spp = metasetname(sname, ep)) == NULL) { 8710Sstevel@tonic-gate return (-1); 8720Sstevel@tonic-gate } 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate /* return success */ 8750Sstevel@tonic-gate return (0); 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate /* 8790Sstevel@tonic-gate * check to see if set changed from default 8800Sstevel@tonic-gate */ 8810Sstevel@tonic-gate static int 8820Sstevel@tonic-gate chksetname( 8830Sstevel@tonic-gate mdsetname_t **spp, 8840Sstevel@tonic-gate char *sname, 8850Sstevel@tonic-gate md_error_t *ep 8860Sstevel@tonic-gate ) 8870Sstevel@tonic-gate { 8880Sstevel@tonic-gate /* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */ 8890Sstevel@tonic-gate if (sname == NULL) { 8900Sstevel@tonic-gate if (*spp) { 8910Sstevel@tonic-gate sname = (*spp)->setname; 8920Sstevel@tonic-gate } else { 8930Sstevel@tonic-gate sname = MD_LOCAL_NAME; 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate /* see if changed */ 8980Sstevel@tonic-gate return (chkset(spp, sname, ep)); 8990Sstevel@tonic-gate } 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate /* 9020Sstevel@tonic-gate * check setname from setno 9030Sstevel@tonic-gate */ 9040Sstevel@tonic-gate static int 9050Sstevel@tonic-gate chksetno( 9060Sstevel@tonic-gate mdsetname_t **spp, 9070Sstevel@tonic-gate set_t setno, 9080Sstevel@tonic-gate md_error_t *ep 9090Sstevel@tonic-gate ) 9100Sstevel@tonic-gate { 9110Sstevel@tonic-gate md_set_record *sr; 9120Sstevel@tonic-gate int rval; 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate /* local set */ 9150Sstevel@tonic-gate if (setno == 0) 9160Sstevel@tonic-gate return (chkset(spp, MD_LOCAL_NAME, ep)); 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate /* shared set */ 9190Sstevel@tonic-gate if ((sr = getsetbynum(setno, ep)) == NULL) 9200Sstevel@tonic-gate return (-1); 9210Sstevel@tonic-gate rval = chkset(spp, sr->sr_setname, ep); 9220Sstevel@tonic-gate free_sr(sr); 9230Sstevel@tonic-gate return (rval); 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate /* 9270Sstevel@tonic-gate * mddrivename_t stuff 9280Sstevel@tonic-gate */ 9290Sstevel@tonic-gate 9300Sstevel@tonic-gate /* 9310Sstevel@tonic-gate * initialize name 9320Sstevel@tonic-gate */ 9330Sstevel@tonic-gate static void 9340Sstevel@tonic-gate metainitname( 9350Sstevel@tonic-gate mdname_t *np 9360Sstevel@tonic-gate ) 9370Sstevel@tonic-gate { 9380Sstevel@tonic-gate (void) memset(np, 0, sizeof (*np)); 9390Sstevel@tonic-gate np->dev = NODEV64; 9400Sstevel@tonic-gate np->key = MD_KEYBAD; 9410Sstevel@tonic-gate np->end_blk = -1; 9420Sstevel@tonic-gate np->start_blk = -1; 9430Sstevel@tonic-gate } 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate /* 9460Sstevel@tonic-gate * free allocated name 9470Sstevel@tonic-gate */ 9480Sstevel@tonic-gate static void 9490Sstevel@tonic-gate metafreename( 9500Sstevel@tonic-gate mdname_t *np 9510Sstevel@tonic-gate ) 9520Sstevel@tonic-gate { 9530Sstevel@tonic-gate if (np->cname != NULL) 9540Sstevel@tonic-gate Free(np->cname); 9550Sstevel@tonic-gate if (np->bname != NULL) 9560Sstevel@tonic-gate Free(np->bname); 9570Sstevel@tonic-gate if (np->rname != NULL) 9580Sstevel@tonic-gate Free(np->rname); 9590Sstevel@tonic-gate if (np->devicesname != NULL) 9600Sstevel@tonic-gate Free(np->devicesname); 9610Sstevel@tonic-gate metainitname(np); 9620Sstevel@tonic-gate } 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate /* 9650Sstevel@tonic-gate * initialize drive name 9660Sstevel@tonic-gate */ 9670Sstevel@tonic-gate static void 9680Sstevel@tonic-gate metainitdrivename( 9690Sstevel@tonic-gate mddrivename_t *dnp 9700Sstevel@tonic-gate ) 9710Sstevel@tonic-gate { 9720Sstevel@tonic-gate (void) memset(dnp, 0, sizeof (*dnp)); 9730Sstevel@tonic-gate dnp->side_names_key = MD_KEYBAD; 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate /* 9770Sstevel@tonic-gate * flush side names 9780Sstevel@tonic-gate */ 9790Sstevel@tonic-gate void 9800Sstevel@tonic-gate metaflushsidenames( 9810Sstevel@tonic-gate mddrivename_t *dnp 9820Sstevel@tonic-gate ) 9830Sstevel@tonic-gate { 9840Sstevel@tonic-gate mdsidenames_t *p, *n; 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate for (p = dnp->side_names, n = NULL; (p != NULL); p = n) { 9870Sstevel@tonic-gate n = p->next; 9880Sstevel@tonic-gate if (p->dname != NULL) 9890Sstevel@tonic-gate Free(p->dname); 9900Sstevel@tonic-gate if (p->cname != NULL) 9910Sstevel@tonic-gate Free(p->cname); 9920Sstevel@tonic-gate Free(p); 9930Sstevel@tonic-gate } 9940Sstevel@tonic-gate dnp->side_names = NULL; 9950Sstevel@tonic-gate } 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate /* 9980Sstevel@tonic-gate * free drive name 9990Sstevel@tonic-gate */ 10000Sstevel@tonic-gate void 10010Sstevel@tonic-gate metafreedrivename( 10020Sstevel@tonic-gate mddrivename_t *dnp 10030Sstevel@tonic-gate ) 10040Sstevel@tonic-gate { 10050Sstevel@tonic-gate uint_t slice; 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate if (dnp->cname != NULL) 10080Sstevel@tonic-gate Free(dnp->cname); 10090Sstevel@tonic-gate if (dnp->rname != NULL) 10100Sstevel@tonic-gate Free(dnp->rname); 10110Sstevel@tonic-gate metafreevtoc(&dnp->vtoc); 10120Sstevel@tonic-gate for (slice = 0; (slice < dnp->parts.parts_len); ++slice) 10130Sstevel@tonic-gate metafreename(&dnp->parts.parts_val[slice]); 10140Sstevel@tonic-gate if (dnp->parts.parts_val != NULL) 10150Sstevel@tonic-gate Free(dnp->parts.parts_val); 10160Sstevel@tonic-gate metaflushsidenames(dnp); 10170Sstevel@tonic-gate if (dnp->miscname != NULL) 10180Sstevel@tonic-gate Free(dnp->miscname); 10190Sstevel@tonic-gate meta_free_unit(dnp); 10200Sstevel@tonic-gate metainitdrivename(dnp); 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate 10230Sstevel@tonic-gate /* 10240Sstevel@tonic-gate * flush the drive name cache 10250Sstevel@tonic-gate */ 10260Sstevel@tonic-gate static void 10270Sstevel@tonic-gate metaflushdrivenames() 10280Sstevel@tonic-gate { 10290Sstevel@tonic-gate mddrivenamelist_t *p, *n; 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate for (p = drivelistp, n = NULL; (p != NULL); p = n) { 10320Sstevel@tonic-gate n = p->next; 10330Sstevel@tonic-gate metafreedrivename(p->drivenamep); 10340Sstevel@tonic-gate Free(p->drivenamep); 10350Sstevel@tonic-gate Free(p); 10360Sstevel@tonic-gate } 10370Sstevel@tonic-gate drivelistp = NULL; 10380Sstevel@tonic-gate } 10390Sstevel@tonic-gate 10400Sstevel@tonic-gate /* 10410Sstevel@tonic-gate * peel off s%u from name 10420Sstevel@tonic-gate */ 10430Sstevel@tonic-gate char * 10440Sstevel@tonic-gate metadiskname( 10450Sstevel@tonic-gate char *name 10460Sstevel@tonic-gate ) 10470Sstevel@tonic-gate { 10480Sstevel@tonic-gate char *p, *e; 10490Sstevel@tonic-gate char onmb[BUFSIZ+1], cnmb[BUFSIZ]; 10500Sstevel@tonic-gate uint_t d = 0; 10510Sstevel@tonic-gate int l = 0; 10520Sstevel@tonic-gate int cl = strlen(name); 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate if (is_metaname(name)) 10550Sstevel@tonic-gate return (Strdup(name)); 10560Sstevel@tonic-gate 10570Sstevel@tonic-gate /* 10580Sstevel@tonic-gate * Handle old style names, which are of the form /dev/rXXNN[a-h]. 10590Sstevel@tonic-gate */ 10600Sstevel@tonic-gate if (sscanf(name, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n", 10610Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 10620Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u", onmb, d); 10630Sstevel@tonic-gate return (Strdup(cnmb)); 10640Sstevel@tonic-gate } 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate /* 10670Sstevel@tonic-gate * Handle old style names, which are of the form /dev/XXNN[a-h]. 10680Sstevel@tonic-gate */ 10690Sstevel@tonic-gate if (sscanf(name, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n", 10700Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 10710Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/%s%u", onmb, d); 10720Sstevel@tonic-gate return (Strdup(cnmb)); 10730Sstevel@tonic-gate } 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate /* gobble number and 's' */ 10760Sstevel@tonic-gate p = e = name + strlen(name) - 1; 10770Sstevel@tonic-gate for (; (p > name); --p) { 10780Sstevel@tonic-gate if (!isdigit(*p)) 10790Sstevel@tonic-gate break; 10800Sstevel@tonic-gate } 10810Sstevel@tonic-gate if ((p == e) || (p <= name)) 10820Sstevel@tonic-gate return (Strdup(name)); 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate if (*p != 's' && strchr("dt", *p) == NULL) 10850Sstevel@tonic-gate return (Strdup(name)); 10860Sstevel@tonic-gate else if (strchr("dt", *p) != NULL) 10870Sstevel@tonic-gate return (Strdup(name)); 10880Sstevel@tonic-gate p--; 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate if ((p <= name) || (!isdigit(*p))) 10910Sstevel@tonic-gate return (Strdup(name)); 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate *(++p) = '\0'; 10940Sstevel@tonic-gate e = Strdup(name); 10950Sstevel@tonic-gate *p = 's'; 10960Sstevel@tonic-gate 10970Sstevel@tonic-gate return (e); 10980Sstevel@tonic-gate } 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate /* 11010Sstevel@tonic-gate * free list of drivenames 11020Sstevel@tonic-gate */ 11030Sstevel@tonic-gate void 11040Sstevel@tonic-gate metafreedrivenamelist( 11050Sstevel@tonic-gate mddrivenamelist_t *dnlp 11060Sstevel@tonic-gate ) 11070Sstevel@tonic-gate { 11080Sstevel@tonic-gate mddrivenamelist_t *next = NULL; 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate for (/* void */; (dnlp != NULL); dnlp = next) { 11110Sstevel@tonic-gate next = dnlp->next; 11120Sstevel@tonic-gate Free(dnlp); 11130Sstevel@tonic-gate } 11140Sstevel@tonic-gate } 11150Sstevel@tonic-gate 11160Sstevel@tonic-gate /* 11170Sstevel@tonic-gate * build list of drivenames 11180Sstevel@tonic-gate */ 11190Sstevel@tonic-gate int 11200Sstevel@tonic-gate metadrivenamelist( 11210Sstevel@tonic-gate mdsetname_t **spp, 11220Sstevel@tonic-gate mddrivenamelist_t **dnlpp, 11230Sstevel@tonic-gate int argc, 11240Sstevel@tonic-gate char *argv[], 11250Sstevel@tonic-gate md_error_t *ep 11260Sstevel@tonic-gate ) 11270Sstevel@tonic-gate { 11280Sstevel@tonic-gate mddrivenamelist_t **tailpp = dnlpp; 11290Sstevel@tonic-gate int count = 0; 11300Sstevel@tonic-gate 11310Sstevel@tonic-gate for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 11320Sstevel@tonic-gate mddrivenamelist_t *dnlp = Zalloc(sizeof (*dnlp)); 11330Sstevel@tonic-gate 11340Sstevel@tonic-gate if ((dnlp->drivenamep = metadrivename(spp, argv[0], 11350Sstevel@tonic-gate ep)) == NULL) { 11360Sstevel@tonic-gate metafreedrivenamelist(*dnlpp); 11370Sstevel@tonic-gate *dnlpp = NULL; 11380Sstevel@tonic-gate return (-1); 11390Sstevel@tonic-gate } 11400Sstevel@tonic-gate *tailpp = dnlp; 11410Sstevel@tonic-gate tailpp = &dnlp->next; 11420Sstevel@tonic-gate } 11430Sstevel@tonic-gate return (count); 11440Sstevel@tonic-gate } 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate /* 11470Sstevel@tonic-gate * append to end of drivename list 11480Sstevel@tonic-gate */ 11490Sstevel@tonic-gate mddrivename_t * 11500Sstevel@tonic-gate metadrivenamelist_append( 11510Sstevel@tonic-gate mddrivenamelist_t **dnlpp, 11520Sstevel@tonic-gate mddrivename_t *dnp 11530Sstevel@tonic-gate ) 11540Sstevel@tonic-gate { 11550Sstevel@tonic-gate mddrivenamelist_t *dnlp; 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate /* run to end of list */ 11580Sstevel@tonic-gate for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next) 11590Sstevel@tonic-gate ; 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate /* allocate new list element */ 11620Sstevel@tonic-gate dnlp = *dnlpp = Zalloc(sizeof (*dnlp)); 11630Sstevel@tonic-gate 11640Sstevel@tonic-gate /* append drivename */ 11650Sstevel@tonic-gate dnlp->drivenamep = dnp; 11660Sstevel@tonic-gate return (dnp); 11670Sstevel@tonic-gate } 11680Sstevel@tonic-gate 11690Sstevel@tonic-gate /* 11700Sstevel@tonic-gate * FUNCTION: meta_drivenamelist_append_wrapper() 11710Sstevel@tonic-gate * INPUT: tailpp - pointer to the list tail pointer 11720Sstevel@tonic-gate * dnp - name node to be appended to list 11730Sstevel@tonic-gate * OUTPUT: none 11740Sstevel@tonic-gate * RETURNS: mddrivenamelist_t * - new tail of the list. 11750Sstevel@tonic-gate * PURPOSE: wrapper to meta_namelist_append for performance. 11760Sstevel@tonic-gate * metanamelist_append finds the tail each time which slows 11770Sstevel@tonic-gate * down long lists. By keeping track of the tail ourselves 11780Sstevel@tonic-gate * we can change metadrivenamelist_append into a 11790Sstevel@tonic-gate * constant time operation. 11800Sstevel@tonic-gate */ 11810Sstevel@tonic-gate mddrivenamelist_t ** 11820Sstevel@tonic-gate meta_drivenamelist_append_wrapper( 11830Sstevel@tonic-gate mddrivenamelist_t **tailpp, 11840Sstevel@tonic-gate mddrivename_t *dnp 11850Sstevel@tonic-gate ) 11860Sstevel@tonic-gate { 11870Sstevel@tonic-gate (void) metadrivenamelist_append(tailpp, dnp); 11880Sstevel@tonic-gate 11890Sstevel@tonic-gate /* If it's the first item in the list, return it instead of the next */ 11900Sstevel@tonic-gate if ((*tailpp)->next == NULL) 11910Sstevel@tonic-gate return (tailpp); 11920Sstevel@tonic-gate 11930Sstevel@tonic-gate return (&(*tailpp)->next); 11940Sstevel@tonic-gate } 11950Sstevel@tonic-gate 11960Sstevel@tonic-gate 11970Sstevel@tonic-gate /* 11980Sstevel@tonic-gate * mdname_t stuff 11990Sstevel@tonic-gate */ 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate /* 12020Sstevel@tonic-gate * check set and get comparison name 12030Sstevel@tonic-gate */ 12040Sstevel@tonic-gate char * 12050Sstevel@tonic-gate meta_name_getname( 12060Sstevel@tonic-gate mdsetname_t **spp, 12070Sstevel@tonic-gate char *uname, 12080Sstevel@tonic-gate md_error_t *ep 12090Sstevel@tonic-gate ) 12100Sstevel@tonic-gate { 12110Sstevel@tonic-gate char *sname = NULL; 12120Sstevel@tonic-gate int ismeta = 0; 12130Sstevel@tonic-gate unit_t unit; 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate /* check set name */ 12160Sstevel@tonic-gate if (parse_metadevice(uname, &sname, &unit) == 0) 12170Sstevel@tonic-gate ismeta = 1; 12180Sstevel@tonic-gate if (chksetname(spp, sname, ep) != 0) { 12190Sstevel@tonic-gate if (sname != NULL) 12200Sstevel@tonic-gate Free(sname); 12210Sstevel@tonic-gate return (NULL); 12220Sstevel@tonic-gate } 12230Sstevel@tonic-gate if (sname != NULL) 12240Sstevel@tonic-gate Free(sname); 12250Sstevel@tonic-gate 12260Sstevel@tonic-gate /* return comparison name */ 12270Sstevel@tonic-gate if (ismeta) 12280Sstevel@tonic-gate return (canon_metadevice((*spp)->setname, unit)); 12290Sstevel@tonic-gate else 12300Sstevel@tonic-gate return (Strdup(uname)); 12310Sstevel@tonic-gate } 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate /* 12340Sstevel@tonic-gate * FUNCTION: getrname() 12350Sstevel@tonic-gate * INPUT: spp - the setname struct 12360Sstevel@tonic-gate * uname - the possibly unqualified device name 12370Sstevel@tonic-gate * OUTPUT: ep - return error pointer 12380Sstevel@tonic-gate * RETURNS: char* - character string containing the fully 12390Sstevel@tonic-gate * qualified raw device name 12400Sstevel@tonic-gate * PURPOSE: Create the fully qualified raw name for the possibly 12410Sstevel@tonic-gate * unqualified device name. If uname is an absolute 12420Sstevel@tonic-gate * path the raw name is derived from the input string. 12430Sstevel@tonic-gate * Otherwise, an attempt is made to get the rawname by 12440Sstevel@tonic-gate * catting "/dev/md/rdsk" and "/dev/rdsk". 12450Sstevel@tonic-gate */ 12460Sstevel@tonic-gate static char * 12470Sstevel@tonic-gate getrname(mdsetname_t **spp, char *uname, md_error_t *ep) 12480Sstevel@tonic-gate { 12490Sstevel@tonic-gate char *rname, 12500Sstevel@tonic-gate *fname; 12510Sstevel@tonic-gate int constructed = 0; 12520Sstevel@tonic-gate 12530Sstevel@tonic-gate assert(uname != NULL); 12540Sstevel@tonic-gate /* if it is an absolute name then just call rawname on the input */ 12550Sstevel@tonic-gate if (uname[0] == '/') { 12560Sstevel@tonic-gate if ((rname = rawname(uname)) != NULL) 12570Sstevel@tonic-gate return (rname); 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate /* out of luck */ 12600Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 12610Sstevel@tonic-gate return (NULL); 12620Sstevel@tonic-gate } 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate /* 12650Sstevel@tonic-gate * Check for metadevice before physical device. 12660Sstevel@tonic-gate * With the introduction of softpartitions it is more 12670Sstevel@tonic-gate * likely to be a metadevice. 12680Sstevel@tonic-gate */ 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate /* metadevice short form */ 12710Sstevel@tonic-gate if (metaislocalset(*spp)) { 12720Sstevel@tonic-gate fname = Malloc(strlen(uname) + strlen("/dev/md/rdsk/") + 1); 12730Sstevel@tonic-gate (void) strcpy(fname, "/dev/md/rdsk/"); 12740Sstevel@tonic-gate (void) strcat(fname, uname); 12750Sstevel@tonic-gate if (*uname == 'd') 12760Sstevel@tonic-gate constructed = 1; 12770Sstevel@tonic-gate } else { 12780Sstevel@tonic-gate char *p; 12790Sstevel@tonic-gate size_t len; 12800Sstevel@tonic-gate 12810Sstevel@tonic-gate if ((p = strchr(uname, '/')) != NULL) { 12820Sstevel@tonic-gate ++p; 12830Sstevel@tonic-gate } else { 12840Sstevel@tonic-gate p = uname; 12850Sstevel@tonic-gate } 12860Sstevel@tonic-gate len = strlen((*spp)->setname) + strlen(p) + 12870Sstevel@tonic-gate strlen("/dev/md//rdsk/") + 1; 12880Sstevel@tonic-gate fname = Malloc(len); 12890Sstevel@tonic-gate (void) snprintf(fname, len, "/dev/md/%s/rdsk/%s", 12900Sstevel@tonic-gate (*spp)->setname, p); 12910Sstevel@tonic-gate if (*p == 'd') 12920Sstevel@tonic-gate constructed = 1; 12930Sstevel@tonic-gate } 12940Sstevel@tonic-gate rname = rawname(fname); 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate /* 12970Sstevel@tonic-gate * Handle the case where we have a new metadevice that does not yet 12980Sstevel@tonic-gate * exist in the name-space. In this case we return the constructed 12990Sstevel@tonic-gate * metadevice name as that will exist after the metainit call has 13000Sstevel@tonic-gate * created it. 13010Sstevel@tonic-gate */ 13020Sstevel@tonic-gate if ((rname == NULL) && constructed) { 13030Sstevel@tonic-gate rname = Strdup(fname); 13040Sstevel@tonic-gate } 13050Sstevel@tonic-gate Free(fname); 13060Sstevel@tonic-gate if (rname != NULL) 13070Sstevel@tonic-gate return (rname); 13080Sstevel@tonic-gate 13090Sstevel@tonic-gate fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1); 13100Sstevel@tonic-gate (void) strcpy(fname, "/dev/rdsk/"); 13110Sstevel@tonic-gate (void) strcat(fname, uname); 13120Sstevel@tonic-gate rname = rawname(fname); 13130Sstevel@tonic-gate Free(fname); 13140Sstevel@tonic-gate if (rname != NULL) 13150Sstevel@tonic-gate return (rname); 13160Sstevel@tonic-gate 13170Sstevel@tonic-gate /* 13180Sstevel@tonic-gate * If all else fails try the straight uname. 13190Sstevel@tonic-gate * NOTE: This check was at the beginning of getrname instead 13200Sstevel@tonic-gate * of here. It was moved to avoid a conflict with SC3.0. If 13210Sstevel@tonic-gate * a diskset was mounted with the same name it would hang 13220Sstevel@tonic-gate * the cluster in a loop. Example: 13230Sstevel@tonic-gate * 13240Sstevel@tonic-gate * fubar/d10 -m fubar/d0 fubar/d1 13250Sstevel@tonic-gate * mount /dev/md/fubar/dsk/d10 /fubar 13260Sstevel@tonic-gate * 13270Sstevel@tonic-gate * When the system was booted DiskSuite would try to take ownership 13280Sstevel@tonic-gate * of diskset fubar. This would cause rawname("fubar/d10") to be 13290Sstevel@tonic-gate * called. rawname() stats the string which caused the cluster 13300Sstevel@tonic-gate * reservation code to try and take ownership which it was already 13310Sstevel@tonic-gate * doing and a deadlock would occur. By moving this final attempt 13320Sstevel@tonic-gate * at resolving the rawname to the end we avoid this deadlock. 13330Sstevel@tonic-gate */ 13340Sstevel@tonic-gate if (rname = rawname(uname)) 13350Sstevel@tonic-gate return (rname); 13360Sstevel@tonic-gate 13370Sstevel@tonic-gate /* out of luck */ 13380Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 13390Sstevel@tonic-gate return (NULL); 13400Sstevel@tonic-gate } 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate /* 13430Sstevel@tonic-gate * get raw slice and drive names 13440Sstevel@tonic-gate */ 13450Sstevel@tonic-gate static char * 13460Sstevel@tonic-gate getrawnames( 13470Sstevel@tonic-gate mdsetname_t **spp, 13480Sstevel@tonic-gate char *uname, 13490Sstevel@tonic-gate char **dnamep, 13500Sstevel@tonic-gate md_error_t *ep 13510Sstevel@tonic-gate ) 13520Sstevel@tonic-gate { 13530Sstevel@tonic-gate char *rname; 13540Sstevel@tonic-gate size_t len; 13550Sstevel@tonic-gate 13560Sstevel@tonic-gate /* initialize */ 13570Sstevel@tonic-gate *dnamep = NULL; 13580Sstevel@tonic-gate 13590Sstevel@tonic-gate /* get slice name */ 13600Sstevel@tonic-gate if ((rname = getrname(spp, uname, ep)) != NULL) { 13610Sstevel@tonic-gate *dnamep = metadiskname(rname); 13620Sstevel@tonic-gate return (rname); 13630Sstevel@tonic-gate } 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate /* 13660Sstevel@tonic-gate * If name cannot be found, if may be because is is not accessible. 13670Sstevel@tonic-gate * If it is an absolute name, try all possible disk name formats and 13680Sstevel@tonic-gate * if it is device name, assume it is /dev/rdsk/... 13690Sstevel@tonic-gate */ 13700Sstevel@tonic-gate if (mdissyserror(ep, ENOENT)) { 13710Sstevel@tonic-gate if (uname[0] == '/') { 13720Sstevel@tonic-gate /* Absolute name */ 13730Sstevel@tonic-gate char *p; 13740Sstevel@tonic-gate uint_t d = 0; 13750Sstevel@tonic-gate int l = 0; 13760Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1]; 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate /* 13790Sstevel@tonic-gate * Handle old style raw names 13800Sstevel@tonic-gate */ 13810Sstevel@tonic-gate if (sscanf(uname, 13820Sstevel@tonic-gate "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 13830Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 13840Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(uname)) { 13850Sstevel@tonic-gate mdclrerror(ep); 13860Sstevel@tonic-gate rname = Strdup(uname); 13870Sstevel@tonic-gate *dnamep = metadiskname(rname); 13880Sstevel@tonic-gate return (rname); 13890Sstevel@tonic-gate } 13900Sstevel@tonic-gate 13910Sstevel@tonic-gate /* 13920Sstevel@tonic-gate * Handle old style block names 13930Sstevel@tonic-gate */ 13940Sstevel@tonic-gate if (sscanf(uname, 13950Sstevel@tonic-gate "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u" 13960Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 13970Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(uname)) { 13980Sstevel@tonic-gate len = strlen(uname) + 1 + 1; 13990Sstevel@tonic-gate rname = Malloc(len); 14000Sstevel@tonic-gate (void) snprintf(rname, len, "/dev/r%s%u%s", 14010Sstevel@tonic-gate onmb, d, snm); 14020Sstevel@tonic-gate *dnamep = metadiskname(rname); 14030Sstevel@tonic-gate return (rname); 14040Sstevel@tonic-gate } 14050Sstevel@tonic-gate 14060Sstevel@tonic-gate /* /.../dsk/... */ 14070Sstevel@tonic-gate if ((p = strstr(uname, "/dsk/")) != NULL) { 14080Sstevel@tonic-gate mdclrerror(ep); 14090Sstevel@tonic-gate ++p; 14100Sstevel@tonic-gate rname = Malloc(strlen(uname) + 1 + 1); 14110Sstevel@tonic-gate (void) strncpy(rname, uname, (p - uname)); 14120Sstevel@tonic-gate rname[(p - uname)] = 'r'; 14130Sstevel@tonic-gate (void) strcpy(&rname[(p - uname) + 1], p); 14140Sstevel@tonic-gate *dnamep = metadiskname(rname); 14150Sstevel@tonic-gate return (rname); 14160Sstevel@tonic-gate } 14170Sstevel@tonic-gate 14180Sstevel@tonic-gate /* /.../rdsk/... */ 14190Sstevel@tonic-gate else if (strstr(uname, "/rdsk/") != NULL) { 14200Sstevel@tonic-gate mdclrerror(ep); 14210Sstevel@tonic-gate rname = Strdup(uname); 14220Sstevel@tonic-gate *dnamep = metadiskname(rname); 14230Sstevel@tonic-gate return (rname); 14240Sstevel@tonic-gate } 14250Sstevel@tonic-gate } else { 14260Sstevel@tonic-gate /* 14270Sstevel@tonic-gate * If it's not an absolute name but is a valid ctd name, 14280Sstevel@tonic-gate * guess at /dev/rdsk/... 14290Sstevel@tonic-gate */ 14300Sstevel@tonic-gate uint_t s; 14310Sstevel@tonic-gate if (parse_ctd(uname, &s) == 0) { 14320Sstevel@tonic-gate len = strlen(uname) + strlen("/dev/rdsk/") + 1; 14330Sstevel@tonic-gate rname = Malloc(len); 14340Sstevel@tonic-gate (void) snprintf(rname, len, "/dev/rdsk/%s", 14350Sstevel@tonic-gate uname); 14360Sstevel@tonic-gate *dnamep = metadiskname(rname); 14370Sstevel@tonic-gate return (rname); 14380Sstevel@tonic-gate } 14390Sstevel@tonic-gate } 14400Sstevel@tonic-gate } 14410Sstevel@tonic-gate 14420Sstevel@tonic-gate /* out of luck */ 14430Sstevel@tonic-gate return (NULL); 14440Sstevel@tonic-gate } 14450Sstevel@tonic-gate 14460Sstevel@tonic-gate /* 14470Sstevel@tonic-gate * get number of slices for name 14480Sstevel@tonic-gate */ 14490Sstevel@tonic-gate static int 14500Sstevel@tonic-gate getnslice( 14510Sstevel@tonic-gate char *rname, 14520Sstevel@tonic-gate char *dname, 14530Sstevel@tonic-gate uint_t *slicep 14540Sstevel@tonic-gate ) 14550Sstevel@tonic-gate { 14560Sstevel@tonic-gate char *srname; 14570Sstevel@tonic-gate uint_t nslice; 14580Sstevel@tonic-gate size_t dl = strlen(dname); 14590Sstevel@tonic-gate size_t rl = strlen(rname); 14600Sstevel@tonic-gate size_t l = 0; 14610Sstevel@tonic-gate size_t len; 14620Sstevel@tonic-gate 14630Sstevel@tonic-gate /* 14640Sstevel@tonic-gate * get our slice number - works only with names that end in s%u - 14650Sstevel@tonic-gate * all others return -1. 14660Sstevel@tonic-gate */ 14670Sstevel@tonic-gate if (dl >= rl || 14680Sstevel@tonic-gate sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl || 14690Sstevel@tonic-gate (int)*slicep < 0) { 14700Sstevel@tonic-gate return (-1); 14710Sstevel@tonic-gate } 14720Sstevel@tonic-gate 14730Sstevel@tonic-gate /* 14740Sstevel@tonic-gate * go find how many slices there really are 14750Sstevel@tonic-gate */ 14760Sstevel@tonic-gate len = strlen(dname) + 20 + 1; 14770Sstevel@tonic-gate srname = Malloc(len); 14780Sstevel@tonic-gate for (nslice = 0; /* void */; ++nslice) { 14790Sstevel@tonic-gate struct stat statbuf; 14800Sstevel@tonic-gate 14810Sstevel@tonic-gate /* build slice name */ 14820Sstevel@tonic-gate (void) snprintf(srname, len, "%ss%u", dname, nslice); 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate /* see if it's there */ 14850Sstevel@tonic-gate if ((meta_stat(srname, &statbuf) != 0) || 14860Sstevel@tonic-gate (! S_ISCHR(statbuf.st_mode))) { 14870Sstevel@tonic-gate break; 14880Sstevel@tonic-gate } 14890Sstevel@tonic-gate } 14900Sstevel@tonic-gate Free(srname); 14910Sstevel@tonic-gate 14920Sstevel@tonic-gate /* Need to make sure that we at least have V_NUMPAR */ 14930Sstevel@tonic-gate nslice = max(nslice, V_NUMPAR); 14940Sstevel@tonic-gate 14950Sstevel@tonic-gate /* make sure we have at least our slice */ 14960Sstevel@tonic-gate if (nslice < *slicep) 14970Sstevel@tonic-gate return (-1); 14980Sstevel@tonic-gate 14990Sstevel@tonic-gate /* return number of slices */ 15000Sstevel@tonic-gate return (nslice); 15010Sstevel@tonic-gate } 15020Sstevel@tonic-gate 15030Sstevel@tonic-gate /* 15040Sstevel@tonic-gate * Attempt to parse the input string as a c[t]ds specifier 15050Sstevel@tonic-gate * The target can either be a SCSI target id or if the device 15060Sstevel@tonic-gate * is in a fabric configuration in a fibre channel setup then 15070Sstevel@tonic-gate * the target is a standard WWN (world wide name). 15080Sstevel@tonic-gate * 15090Sstevel@tonic-gate * if successful return 0 15100Sstevel@tonic-gate * if c[t]dp name return 1 15110Sstevel@tonic-gate * otherwise return -1 15120Sstevel@tonic-gate */ 15130Sstevel@tonic-gate int 15140Sstevel@tonic-gate parse_ctd( 15150Sstevel@tonic-gate char *uname, 15160Sstevel@tonic-gate uint_t *slice) 15170Sstevel@tonic-gate { 15180Sstevel@tonic-gate uint_t channel; 15190Sstevel@tonic-gate uint_t target; 15200Sstevel@tonic-gate uint_t device; 15210Sstevel@tonic-gate int has_target = 1; 15220Sstevel@tonic-gate uint_t cl; 15230Sstevel@tonic-gate uint_t target_str_len; 15240Sstevel@tonic-gate char *partial_ctd_str; 15250Sstevel@tonic-gate char *target_str; 15260Sstevel@tonic-gate char *device_start_pos; 15270Sstevel@tonic-gate int l = -1; 15280Sstevel@tonic-gate 15290Sstevel@tonic-gate /* pull off the channel spec and the 't' for the target */ 15300Sstevel@tonic-gate if (sscanf(uname, "c%ut%n", &channel, &l) != 1 || l == -1) { 15310Sstevel@tonic-gate /* check for cds style name */ 15320Sstevel@tonic-gate if (sscanf(uname, "c%ud%n", &channel, &l) != 1 || l == -1) { 15330Sstevel@tonic-gate return (-1); 15340Sstevel@tonic-gate } else { 15350Sstevel@tonic-gate l--; /* we want to be on the 'd' */ 15360Sstevel@tonic-gate has_target = 0; 15370Sstevel@tonic-gate } 15380Sstevel@tonic-gate } 15390Sstevel@tonic-gate partial_ctd_str = uname + l; 15400Sstevel@tonic-gate 15410Sstevel@tonic-gate /* find the beginning of the device specifier */ 15420Sstevel@tonic-gate device_start_pos = strrchr(partial_ctd_str, 'd'); 15430Sstevel@tonic-gate if (device_start_pos == NULL) { 15440Sstevel@tonic-gate return (-1); 15450Sstevel@tonic-gate } 15460Sstevel@tonic-gate 15470Sstevel@tonic-gate /* check to see if it is a ctd with a WWN or SCSI target */ 15480Sstevel@tonic-gate if (has_target) { 15490Sstevel@tonic-gate /* pull off the target and see if it is a WWN */ 15500Sstevel@tonic-gate target_str_len = device_start_pos - partial_ctd_str + 2; 15510Sstevel@tonic-gate target_str = (char *)Malloc(target_str_len+1); 15520Sstevel@tonic-gate (void) strcpy(target_str, "0X"); 15530Sstevel@tonic-gate (void) strncpy(target_str+2, partial_ctd_str, 15540Sstevel@tonic-gate target_str_len - 2); 15550Sstevel@tonic-gate target_str[target_str_len] = '\0'; 15560Sstevel@tonic-gate if (sscanf(target_str, "%x%n", &target, &l) != 1 || 15570Sstevel@tonic-gate l != target_str_len) { 15580Sstevel@tonic-gate Free(target_str); 15590Sstevel@tonic-gate return (-1); 15600Sstevel@tonic-gate } 15610Sstevel@tonic-gate Free(target_str); 15620Sstevel@tonic-gate } 15630Sstevel@tonic-gate 15640Sstevel@tonic-gate /* check the device and slice */ 15650Sstevel@tonic-gate cl = strlen(device_start_pos); 15660Sstevel@tonic-gate if (sscanf(device_start_pos, "d%us%u%n", &device, slice, &l) != 2 || 15670Sstevel@tonic-gate l != cl) { 15680Sstevel@tonic-gate /* check the device and partition */ 15690Sstevel@tonic-gate if (sscanf(device_start_pos, "d%up%u%n", &device, slice, &l) 15700Sstevel@tonic-gate == 2 && l == cl) { 15710Sstevel@tonic-gate return (1); 15720Sstevel@tonic-gate } 15730Sstevel@tonic-gate return (-1); 15740Sstevel@tonic-gate } 15750Sstevel@tonic-gate 15760Sstevel@tonic-gate return (0); 15770Sstevel@tonic-gate } 15780Sstevel@tonic-gate 15790Sstevel@tonic-gate 15800Sstevel@tonic-gate /* 15810Sstevel@tonic-gate * get number of slices for name 15820Sstevel@tonic-gate */ 15830Sstevel@tonic-gate static int 15840Sstevel@tonic-gate uname2sliceno( 15850Sstevel@tonic-gate char *uname, 15860Sstevel@tonic-gate uint_t *slicep, 15870Sstevel@tonic-gate md_error_t *ep 15880Sstevel@tonic-gate ) 15890Sstevel@tonic-gate { 15900Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0; 15910Sstevel@tonic-gate int l = 0, cl = 0; 15920Sstevel@tonic-gate int fd; 15930Sstevel@tonic-gate struct dk_cinfo cinfo; 15940Sstevel@tonic-gate char *p; 15950Sstevel@tonic-gate char *rname = NULL; 15960Sstevel@tonic-gate 15970Sstevel@tonic-gate if (is_metaname(uname)) 15980Sstevel@tonic-gate return (*slicep = 0); 15990Sstevel@tonic-gate 16000Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL) 16010Sstevel@tonic-gate p++; 16020Sstevel@tonic-gate else 16030Sstevel@tonic-gate p = uname; 16040Sstevel@tonic-gate 16050Sstevel@tonic-gate cl = strlen(p); 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate if (parse_ctd(p, slicep) == 0) 16080Sstevel@tonic-gate return (*slicep); 16090Sstevel@tonic-gate else if (sscanf(p, "mc%ut%ud%us%u%n", &c, &t, &d, slicep, &l) == 4 && 16100Sstevel@tonic-gate l == cl) 16110Sstevel@tonic-gate return (*slicep); 16120Sstevel@tonic-gate else if (sscanf(p, "d%us%u%n", &d, slicep, &l) == 2 && l == cl) 16130Sstevel@tonic-gate return (*slicep); 16140Sstevel@tonic-gate 16150Sstevel@tonic-gate /* 16160Sstevel@tonic-gate * If we can't get the slice from the name, then we have to do it the 16170Sstevel@tonic-gate * hard and expensive way. 16180Sstevel@tonic-gate */ 16190Sstevel@tonic-gate if ((rname = rawname(uname)) == NULL) 16200Sstevel@tonic-gate return (-1); 16210Sstevel@tonic-gate 16220Sstevel@tonic-gate /* get controller info */ 16230Sstevel@tonic-gate if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) { 16240Sstevel@tonic-gate Free(rname); 16250Sstevel@tonic-gate return (-1); 16260Sstevel@tonic-gate } 16270Sstevel@tonic-gate 16280Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &cinfo) != 0) { 16290Sstevel@tonic-gate int save = errno; 16300Sstevel@tonic-gate 16310Sstevel@tonic-gate if (save == ENOTTY) 16320Sstevel@tonic-gate (void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname); 16330Sstevel@tonic-gate else 16340Sstevel@tonic-gate (void) mdsyserror(ep, save, rname); 16350Sstevel@tonic-gate 16360Sstevel@tonic-gate Free(rname); 16370Sstevel@tonic-gate (void) close(fd); 16380Sstevel@tonic-gate return (-1); 16390Sstevel@tonic-gate } 16400Sstevel@tonic-gate (void) close(fd); /* sd/ssd bug */ 16410Sstevel@tonic-gate 16420Sstevel@tonic-gate if (cinfo.dki_partition < V_NUMPAR) { 16430Sstevel@tonic-gate Free(rname); 16440Sstevel@tonic-gate return (*slicep = cinfo.dki_partition); 16450Sstevel@tonic-gate } 16460Sstevel@tonic-gate 16470Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname)); 16480Sstevel@tonic-gate } 16490Sstevel@tonic-gate 16500Sstevel@tonic-gate /* 16510Sstevel@tonic-gate * get partition info 16520Sstevel@tonic-gate */ 16530Sstevel@tonic-gate static int 16540Sstevel@tonic-gate getparts( 16550Sstevel@tonic-gate mddrivename_t *dnp, 16560Sstevel@tonic-gate char *rname, 16570Sstevel@tonic-gate char *dname, 16580Sstevel@tonic-gate uint_t *npartsp, 16590Sstevel@tonic-gate uint_t *partnop, 16600Sstevel@tonic-gate md_error_t *ep 16610Sstevel@tonic-gate ) 16620Sstevel@tonic-gate { 16630Sstevel@tonic-gate int nparts; 16640Sstevel@tonic-gate uint_t partno; 16650Sstevel@tonic-gate mdname_t name; 16660Sstevel@tonic-gate mdvtoc_t *vtocp; 16670Sstevel@tonic-gate 16680Sstevel@tonic-gate /* metadevice */ 16690Sstevel@tonic-gate if (is_metaname(rname)) { 16700Sstevel@tonic-gate dnp->type = MDT_META; 16710Sstevel@tonic-gate nparts = 1; 16720Sstevel@tonic-gate partno = 0; 16730Sstevel@tonic-gate goto gotit; 16740Sstevel@tonic-gate } 16750Sstevel@tonic-gate 16760Sstevel@tonic-gate /* see how many partitions in drive, this is really tricky */ 16770Sstevel@tonic-gate metainitname(&name); 16780Sstevel@tonic-gate name.rname = rname; 16790Sstevel@tonic-gate name.drivenamep = dnp; 16800Sstevel@tonic-gate if ((vtocp = metagetvtoc(&name, TRUE, &partno, ep)) != NULL) { 16810Sstevel@tonic-gate dnp->type = MDT_COMP; 16820Sstevel@tonic-gate nparts = vtocp->nparts; 16830Sstevel@tonic-gate /* partno already setup */ 16840Sstevel@tonic-gate /* dname already setup */ 16850Sstevel@tonic-gate goto gotit; 16860Sstevel@tonic-gate } 16870Sstevel@tonic-gate 16880Sstevel@tonic-gate if ((ep->info.errclass == MDEC_DEV) && 16890Sstevel@tonic-gate (ep->info.md_error_info_t_u.dev_error.errnum == MDE_TOO_MANY_PARTS)) 16900Sstevel@tonic-gate return (-1); 16910Sstevel@tonic-gate 16920Sstevel@tonic-gate /* fallback and try and guess (used to check for just EACCES here) */ 16930Sstevel@tonic-gate if ((dname != NULL) && 16940Sstevel@tonic-gate ((nparts = getnslice(rname, dname, &partno)) > 0)) { 16950Sstevel@tonic-gate dnp->type = MDT_ACCES; 16960Sstevel@tonic-gate if (mdanysyserror(ep)) { 16970Sstevel@tonic-gate dnp->errnum = 16980Sstevel@tonic-gate ep->info.md_error_info_t_u.sys_error.errnum; 16990Sstevel@tonic-gate } else { 17000Sstevel@tonic-gate dnp->errnum = ENOENT; 17010Sstevel@tonic-gate } 17020Sstevel@tonic-gate mdclrerror(ep); 17030Sstevel@tonic-gate /* nparts already setup */ 17040Sstevel@tonic-gate /* partno already setup */ 17050Sstevel@tonic-gate /* dname already setup */ 17060Sstevel@tonic-gate nparts = roundup(nparts, V_NUMPAR); 17070Sstevel@tonic-gate goto gotit; 17080Sstevel@tonic-gate } 17090Sstevel@tonic-gate 17100Sstevel@tonic-gate /* nothing worked */ 17110Sstevel@tonic-gate dnp->type = MDT_UNKNOWN; 17120Sstevel@tonic-gate if (mdissyserror(ep, EACCES)) 17130Sstevel@tonic-gate dnp->type = MDT_ACCES; 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate if (mdanysyserror(ep)) { 17160Sstevel@tonic-gate dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum; 17170Sstevel@tonic-gate } else { 17180Sstevel@tonic-gate dnp->errnum = ENOENT; 17190Sstevel@tonic-gate } 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate mdclrerror(ep); 17220Sstevel@tonic-gate nparts = V_NUMPAR; 17230Sstevel@tonic-gate if (uname2sliceno(rname, &partno, ep) < 0) { 17240Sstevel@tonic-gate mdclrerror(ep); 17250Sstevel@tonic-gate partno = 0; 17260Sstevel@tonic-gate } 17270Sstevel@tonic-gate 17280Sstevel@tonic-gate /* return success */ 17290Sstevel@tonic-gate gotit: 17300Sstevel@tonic-gate assert(nparts > 0); 17310Sstevel@tonic-gate 17320Sstevel@tonic-gate if (partno >= nparts) 17330Sstevel@tonic-gate return (mdsyserror(ep, ENOENT, rname)); 17340Sstevel@tonic-gate 17350Sstevel@tonic-gate *npartsp = nparts; 17360Sstevel@tonic-gate *partnop = partno; 17370Sstevel@tonic-gate return (0); 17380Sstevel@tonic-gate } 17390Sstevel@tonic-gate 17400Sstevel@tonic-gate /* 17410Sstevel@tonic-gate * get block name 17420Sstevel@tonic-gate */ 17430Sstevel@tonic-gate static int 17440Sstevel@tonic-gate getbname( 17450Sstevel@tonic-gate mdname_t *np, 17460Sstevel@tonic-gate md_error_t *ep 17470Sstevel@tonic-gate ) 17480Sstevel@tonic-gate { 17490Sstevel@tonic-gate char *rname = np->rname; 17500Sstevel@tonic-gate char *bname; 17510Sstevel@tonic-gate 17520Sstevel@tonic-gate /* fully qualified */ 17530Sstevel@tonic-gate assert(rname != NULL); 17540Sstevel@tonic-gate if ((bname = blkname(rname)) != NULL) { 17550Sstevel@tonic-gate if (np->bname) 17560Sstevel@tonic-gate Free(np->bname); 17570Sstevel@tonic-gate np->bname = bname; 17580Sstevel@tonic-gate return (0); 17590Sstevel@tonic-gate } 17600Sstevel@tonic-gate 17610Sstevel@tonic-gate /* out of luck */ 17620Sstevel@tonic-gate return (mdsyserror(ep, ENOENT, rname)); 17630Sstevel@tonic-gate } 17640Sstevel@tonic-gate 17650Sstevel@tonic-gate static void 17660Sstevel@tonic-gate getcname( 17670Sstevel@tonic-gate mdsetname_t *sp, 17680Sstevel@tonic-gate mdname_t *np 17690Sstevel@tonic-gate ) 17700Sstevel@tonic-gate { 17710Sstevel@tonic-gate char *sname = sp->setname; 17720Sstevel@tonic-gate char *bname = np->bname; 17730Sstevel@tonic-gate char *p; 17740Sstevel@tonic-gate size_t len; 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate assert(sname != NULL); 17770Sstevel@tonic-gate assert(bname != NULL); 17780Sstevel@tonic-gate assert(np->drivenamep->type != MDT_FAST_COMP && 17790Sstevel@tonic-gate np->drivenamep->type != MDT_FAST_META); 17800Sstevel@tonic-gate 17810Sstevel@tonic-gate /* regular device */ 17820Sstevel@tonic-gate if ((strncmp(bname, "/dev/dsk/", strlen("/dev/dsk/")) == 0) && 17830Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/dsk/")), '/') == NULL)) { 17840Sstevel@tonic-gate if (np->cname) 17850Sstevel@tonic-gate Free(np->cname); 17860Sstevel@tonic-gate np->cname = Strdup(p); 17870Sstevel@tonic-gate return; 17880Sstevel@tonic-gate } 17890Sstevel@tonic-gate 17900Sstevel@tonic-gate if ((strncmp(bname, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) && 17910Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/ap/dsk/")), '/') == NULL)) { 17920Sstevel@tonic-gate if (np->cname) 17930Sstevel@tonic-gate Free(np->cname); 17940Sstevel@tonic-gate np->cname = Strdup(p); 17950Sstevel@tonic-gate return; 17960Sstevel@tonic-gate } 17970Sstevel@tonic-gate 17980Sstevel@tonic-gate if ((strncmp(bname, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) && 17990Sstevel@tonic-gate (strchr((p = bname + strlen("/dev/did/dsk/")), '/') == NULL)) { 18000Sstevel@tonic-gate if (np->cname) 18010Sstevel@tonic-gate Free(np->cname); 18020Sstevel@tonic-gate np->cname = Strdup(p); 18030Sstevel@tonic-gate return; 18040Sstevel@tonic-gate } 18050Sstevel@tonic-gate 18060Sstevel@tonic-gate /* anything else but metadevice */ 18070Sstevel@tonic-gate if (np->drivenamep->type != MDT_META) { 18080Sstevel@tonic-gate if (np->cname) 18090Sstevel@tonic-gate Free(np->cname); 18100Sstevel@tonic-gate np->cname = Strdup(bname); 18110Sstevel@tonic-gate return; 18120Sstevel@tonic-gate } 18130Sstevel@tonic-gate 18140Sstevel@tonic-gate /* metadevice */ 18150Sstevel@tonic-gate p = strrchr(bname, '/'); 18160Sstevel@tonic-gate assert(p != NULL); 18170Sstevel@tonic-gate ++p; 18180Sstevel@tonic-gate if (metaislocalset(sp)) { 18190Sstevel@tonic-gate if (np->cname) 18200Sstevel@tonic-gate Free(np->cname); 18210Sstevel@tonic-gate np->cname = Strdup(p); 18220Sstevel@tonic-gate } else { 18230Sstevel@tonic-gate assert(sname[0] != '\0'); 18240Sstevel@tonic-gate if (np->cname) 18250Sstevel@tonic-gate Free(np->cname); 18260Sstevel@tonic-gate len = strlen(sname) + 1 + strlen(p) + 1; 18270Sstevel@tonic-gate np->cname = Malloc(len); 18280Sstevel@tonic-gate (void) snprintf(np->cname, len, "%s/%s", sname, p); 18290Sstevel@tonic-gate } 18300Sstevel@tonic-gate } 18310Sstevel@tonic-gate 18320Sstevel@tonic-gate /* 18330Sstevel@tonic-gate * get dev 18340Sstevel@tonic-gate */ 18350Sstevel@tonic-gate int 18360Sstevel@tonic-gate meta_getdev( 18370Sstevel@tonic-gate mdsetname_t *sp, 18380Sstevel@tonic-gate mdname_t *np, 18390Sstevel@tonic-gate md_error_t *ep 18400Sstevel@tonic-gate ) 18410Sstevel@tonic-gate { 18420Sstevel@tonic-gate struct stat statbuf; 18430Sstevel@tonic-gate 18440Sstevel@tonic-gate /* get dev */ 18450Sstevel@tonic-gate if (meta_stat(np->rname, &statbuf) != 0) 18460Sstevel@tonic-gate return (mdsyserror(ep, errno, np->rname)); 18470Sstevel@tonic-gate else if (! S_ISCHR(statbuf.st_mode)) 18480Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, NODEV64, np->rname)); 18490Sstevel@tonic-gate np->dev = meta_expldev(statbuf.st_rdev); 18500Sstevel@tonic-gate 18510Sstevel@tonic-gate assert(np->drivenamep->type != MDT_FAST_META && 18520Sstevel@tonic-gate np->drivenamep->type != MDT_FAST_COMP); 18530Sstevel@tonic-gate 18540Sstevel@tonic-gate /* check set */ 18550Sstevel@tonic-gate assert((np->drivenamep->type == MDT_META) ? 18560Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1); 18570Sstevel@tonic-gate 18580Sstevel@tonic-gate /* return sucess */ 18590Sstevel@tonic-gate return (0); 18600Sstevel@tonic-gate } 18610Sstevel@tonic-gate 18620Sstevel@tonic-gate /* 18630Sstevel@tonic-gate * set up names for a slice 18640Sstevel@tonic-gate */ 18650Sstevel@tonic-gate static int 18660Sstevel@tonic-gate getnames( 18670Sstevel@tonic-gate mdsetname_t *sp, 18680Sstevel@tonic-gate mdname_t *np, 18690Sstevel@tonic-gate char *rname, 18700Sstevel@tonic-gate md_error_t *ep 18710Sstevel@tonic-gate ) 18720Sstevel@tonic-gate { 18730Sstevel@tonic-gate /* get names */ 18740Sstevel@tonic-gate if (np->rname) 18750Sstevel@tonic-gate Free(np->rname); 18760Sstevel@tonic-gate np->rname = Strdup(rname); 18770Sstevel@tonic-gate if (getbname(np, ep) != 0) 18780Sstevel@tonic-gate return (-1); 18790Sstevel@tonic-gate getcname(sp, np); 18800Sstevel@tonic-gate if (meta_getdev(sp, np, ep) != 0) 18810Sstevel@tonic-gate return (-1); 18820Sstevel@tonic-gate 18830Sstevel@tonic-gate /* return success */ 18840Sstevel@tonic-gate return (0); 18850Sstevel@tonic-gate } 18860Sstevel@tonic-gate 18870Sstevel@tonic-gate /* 18880Sstevel@tonic-gate * fake up names for a slice 18890Sstevel@tonic-gate */ 18900Sstevel@tonic-gate static void 18910Sstevel@tonic-gate getfakenames( 18920Sstevel@tonic-gate mdsetname_t *sp, 18930Sstevel@tonic-gate mdname_t *np, 18940Sstevel@tonic-gate char *rname 18950Sstevel@tonic-gate ) 18960Sstevel@tonic-gate { 18970Sstevel@tonic-gate char *p; 18980Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1]; 18990Sstevel@tonic-gate uint_t d = 0; 19000Sstevel@tonic-gate int l = 0; 19010Sstevel@tonic-gate 19020Sstevel@tonic-gate /* fake names */ 19030Sstevel@tonic-gate if (np->rname != NULL) 19040Sstevel@tonic-gate Free(np->rname); 19050Sstevel@tonic-gate np->rname = Strdup(rname); 19060Sstevel@tonic-gate 19070Sstevel@tonic-gate if (np->bname != NULL) 19080Sstevel@tonic-gate Free(np->bname); 19090Sstevel@tonic-gate np->bname = Strdup(rname); 19100Sstevel@tonic-gate 19110Sstevel@tonic-gate /* 19120Sstevel@tonic-gate * Fixup old style names 19130Sstevel@tonic-gate */ 19140Sstevel@tonic-gate if (sscanf(rname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 19150Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 19160Sstevel@tonic-gate onmb, &d, snm, &l) == 3 && l == strlen(rname)) 19170Sstevel@tonic-gate (void) snprintf(np->bname, l, "/dev/%s%u%s", onmb, d, snm); 19180Sstevel@tonic-gate 19190Sstevel@tonic-gate /* 19200Sstevel@tonic-gate * Fixup new style names 19210Sstevel@tonic-gate */ 19220Sstevel@tonic-gate if ((p = strstr(np->bname, "/rdsk/")) != NULL) { 19230Sstevel@tonic-gate for (++p; (*(p + 1) != '\0'); ++p) 19240Sstevel@tonic-gate *p = *(p + 1); 19250Sstevel@tonic-gate *p = '\0'; 19260Sstevel@tonic-gate } 19270Sstevel@tonic-gate 19280Sstevel@tonic-gate if (np->cname != NULL) 19290Sstevel@tonic-gate Free(np->cname); 19300Sstevel@tonic-gate getcname(sp, np); 19310Sstevel@tonic-gate } 19320Sstevel@tonic-gate 19330Sstevel@tonic-gate static mdname_t * 19340Sstevel@tonic-gate setup_slice( 19350Sstevel@tonic-gate mdsetname_t *sp, 19360Sstevel@tonic-gate mddrivename_t *dnp, 19370Sstevel@tonic-gate char *uname, 19380Sstevel@tonic-gate char *rname, 19390Sstevel@tonic-gate char *dname, 19400Sstevel@tonic-gate uint_t partno, 19410Sstevel@tonic-gate md_error_t *ep 19420Sstevel@tonic-gate ) 19430Sstevel@tonic-gate { 19440Sstevel@tonic-gate char *srname = NULL; 19450Sstevel@tonic-gate mdname_t *np; 19460Sstevel@tonic-gate 19470Sstevel@tonic-gate /* must have a set */ 19480Sstevel@tonic-gate assert(sp != NULL); 19490Sstevel@tonic-gate assert(partno < dnp->parts.parts_len); 19500Sstevel@tonic-gate assert(dname != NULL); 19510Sstevel@tonic-gate 19520Sstevel@tonic-gate np = &dnp->parts.parts_val[partno]; 19530Sstevel@tonic-gate 19540Sstevel@tonic-gate if (rname) 19550Sstevel@tonic-gate srname = rname; 19560Sstevel@tonic-gate else if (is_metaname(dname)) 19570Sstevel@tonic-gate srname = dname; 19580Sstevel@tonic-gate else { 19590Sstevel@tonic-gate char onmb[BUFSIZ+1]; 19600Sstevel@tonic-gate uint_t d = 0; 19610Sstevel@tonic-gate int l = 0, cl = strlen(dname); 19620Sstevel@tonic-gate size_t len; 19630Sstevel@tonic-gate 19640Sstevel@tonic-gate len = cl + 20 + 1; 19650Sstevel@tonic-gate srname = Malloc(len); 19660Sstevel@tonic-gate 19670Sstevel@tonic-gate /* 19680Sstevel@tonic-gate * Handle /dev/rXXNN. 19690Sstevel@tonic-gate */ 19700Sstevel@tonic-gate if (sscanf(dname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%n", 19710Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 19720Sstevel@tonic-gate (void) snprintf(srname, len, "/dev/r%s%u%c", onmb, d, 19730Sstevel@tonic-gate 'a' + partno); 19740Sstevel@tonic-gate } else if (sscanf(dname, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%n", 19750Sstevel@tonic-gate onmb, &d, &l) == 2 && l == cl) { 19760Sstevel@tonic-gate (void) snprintf(srname, len, "/dev/%s%u%c", onmb, d, 19770Sstevel@tonic-gate 'a' + partno); 19780Sstevel@tonic-gate } else { 19790Sstevel@tonic-gate /* build the slice that is wanted */ 19800Sstevel@tonic-gate (void) snprintf(srname, len, "%ss%u", dname, partno); 19810Sstevel@tonic-gate } 19820Sstevel@tonic-gate } 19830Sstevel@tonic-gate 19840Sstevel@tonic-gate if (getnames(sp, np, srname, ep) != 0) { 19850Sstevel@tonic-gate if (dnp->type == MDT_UNKNOWN) { 19860Sstevel@tonic-gate mdclrerror(ep); 19870Sstevel@tonic-gate getfakenames(sp, np, srname); 19880Sstevel@tonic-gate } else if (dnp->type == MDT_COMP && mdissyserror(ep, ENOENT)) { 19890Sstevel@tonic-gate dnp->type = MDT_UNKNOWN; 19900Sstevel@tonic-gate if (mdanysyserror(ep)) { 19910Sstevel@tonic-gate dnp->errnum = 19920Sstevel@tonic-gate ep->info.md_error_info_t_u.sys_error.errnum; 19930Sstevel@tonic-gate } else { 19940Sstevel@tonic-gate dnp->errnum = ENOENT; 19950Sstevel@tonic-gate } 19960Sstevel@tonic-gate mdclrerror(ep); 19970Sstevel@tonic-gate getfakenames(sp, np, srname); 19980Sstevel@tonic-gate } else { 19990Sstevel@tonic-gate mdclrerror(ep); 20000Sstevel@tonic-gate if (getnames(sp, np, dname, ep) != 0) { 20010Sstevel@tonic-gate np = NULL; 20020Sstevel@tonic-gate goto fixup; 20030Sstevel@tonic-gate } 20040Sstevel@tonic-gate } 20050Sstevel@tonic-gate } 20060Sstevel@tonic-gate 20070Sstevel@tonic-gate out: 20080Sstevel@tonic-gate if ((srname != rname) && (srname != dname)) 20090Sstevel@tonic-gate Free(srname); 20100Sstevel@tonic-gate 20110Sstevel@tonic-gate /* return name */ 20120Sstevel@tonic-gate return (np); 20130Sstevel@tonic-gate 20140Sstevel@tonic-gate fixup: 20150Sstevel@tonic-gate if (mdanysyserror(ep)) { 20160Sstevel@tonic-gate char *p; 20170Sstevel@tonic-gate int errnum = ep->info.md_error_info_t_u.sys_error.errnum; 20180Sstevel@tonic-gate 20190Sstevel@tonic-gate mdclrerror(ep); 20200Sstevel@tonic-gate if (uname && *uname) { 20210Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL) 20220Sstevel@tonic-gate (void) mdsyserror(ep, errnum, ++p); 20230Sstevel@tonic-gate else 20240Sstevel@tonic-gate (void) mdsyserror(ep, errnum, uname); 20250Sstevel@tonic-gate } else { 20260Sstevel@tonic-gate if ((p = strrchr(srname, '/')) != NULL) 20270Sstevel@tonic-gate (void) mdsyserror(ep, errnum, ++p); 20280Sstevel@tonic-gate else 20290Sstevel@tonic-gate (void) mdsyserror(ep, errnum, srname); 20300Sstevel@tonic-gate } 20310Sstevel@tonic-gate } 20320Sstevel@tonic-gate goto out; 20330Sstevel@tonic-gate } 20340Sstevel@tonic-gate 20350Sstevel@tonic-gate /* 20360Sstevel@tonic-gate * flush the fast name cache 20370Sstevel@tonic-gate */ 20380Sstevel@tonic-gate static void 20390Sstevel@tonic-gate metafreefastnm(mdname_t **np) 20400Sstevel@tonic-gate { 20410Sstevel@tonic-gate mddrivename_t *dnp; 20420Sstevel@tonic-gate 20430Sstevel@tonic-gate assert(np != NULL && *np != NULL); 20440Sstevel@tonic-gate 20450Sstevel@tonic-gate if ((dnp = (*np)->drivenamep) != NULL) { 20460Sstevel@tonic-gate if (dnp->cname != NULL) 20470Sstevel@tonic-gate Free(dnp->cname); 20480Sstevel@tonic-gate if (dnp->rname != NULL) 20490Sstevel@tonic-gate Free(dnp->rname); 20500Sstevel@tonic-gate if (dnp->miscname != NULL) 20510Sstevel@tonic-gate Free(dnp->miscname); 20520Sstevel@tonic-gate meta_free_unit(dnp); 20530Sstevel@tonic-gate Free(dnp); 20540Sstevel@tonic-gate } 20550Sstevel@tonic-gate if ((*np)->cname != NULL) 20560Sstevel@tonic-gate Free((*np)->cname); 20570Sstevel@tonic-gate if ((*np)->bname != NULL) 20580Sstevel@tonic-gate Free((*np)->bname); 20590Sstevel@tonic-gate if ((*np)->rname != NULL) 20600Sstevel@tonic-gate Free((*np)->rname); 20610Sstevel@tonic-gate if ((*np)->devicesname != NULL) 20620Sstevel@tonic-gate Free((*np)->devicesname); 20630Sstevel@tonic-gate Free(*np); 20640Sstevel@tonic-gate *np = NULL; 20650Sstevel@tonic-gate } 20660Sstevel@tonic-gate 20670Sstevel@tonic-gate /* 20680Sstevel@tonic-gate * flush the fast name cache 20690Sstevel@tonic-gate */ 20700Sstevel@tonic-gate static void 20710Sstevel@tonic-gate metaflushfastnames() 20720Sstevel@tonic-gate { 20730Sstevel@tonic-gate mdnamelist_t *p, *n; 20740Sstevel@tonic-gate 20750Sstevel@tonic-gate for (p = fastnmlp, n = NULL; (p != NULL); p = n) { 20760Sstevel@tonic-gate n = p->next; 20770Sstevel@tonic-gate metafreefastnm(&p->namep); 20780Sstevel@tonic-gate Free(p); 20790Sstevel@tonic-gate } 20800Sstevel@tonic-gate fastnmlp = NULL; 20810Sstevel@tonic-gate } 20820Sstevel@tonic-gate 20830Sstevel@tonic-gate static char * 20840Sstevel@tonic-gate getrname_fast(char *unm, md_error_t *ep) 20850Sstevel@tonic-gate { 20860Sstevel@tonic-gate uint_t d = 0; 20870Sstevel@tonic-gate int l = 0; 20880Sstevel@tonic-gate int cl = strlen(unm); 20890Sstevel@tonic-gate char onmb[BUFSIZ+1], snm[BUFSIZ+1], cnmb[BUFSIZ]; 20900Sstevel@tonic-gate char *rnm; 20910Sstevel@tonic-gate char *p; 20920Sstevel@tonic-gate size_t len; 20930Sstevel@tonic-gate 20940Sstevel@tonic-gate if (is_metaname(unm)) { 20950Sstevel@tonic-gate /* without set */ 20960Sstevel@tonic-gate if (sscanf(unm, "d%u%n", &d, &l) == 1 && cl == l) { 20970Sstevel@tonic-gate rnm = Zalloc(14 + cl + 1); 20980Sstevel@tonic-gate (void) sprintf(rnm, "/dev/md/rdsk/d%u", d); 20990Sstevel@tonic-gate return (rnm); 21000Sstevel@tonic-gate } 21010Sstevel@tonic-gate 21020Sstevel@tonic-gate /* fully-qualified without set */ 21030Sstevel@tonic-gate if ((sscanf(unm, "/dev/md/dsk/d%u%n", &d, &l) == 1 || 21040Sstevel@tonic-gate sscanf(unm, "/dev/md/rdsk/d%u%n", &d, &l) == 1) && 21050Sstevel@tonic-gate cl == l) { 21060Sstevel@tonic-gate rnm = Zalloc(14 + cl + 1); 21070Sstevel@tonic-gate (void) sprintf(rnm, "/dev/md/rdsk/d%u", d); 21080Sstevel@tonic-gate return (rnm); 21090Sstevel@tonic-gate } 21100Sstevel@tonic-gate 21110Sstevel@tonic-gate /* with set */ 21120Sstevel@tonic-gate if ((sscanf(unm, 21130Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[^/]/d%u%n", snm, &d, &l) == 2 || 21140Sstevel@tonic-gate sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/d%u%n", 21150Sstevel@tonic-gate snm, &d, &l) == 2 || 21160Sstevel@tonic-gate sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/rdsk/d%u%n", 21170Sstevel@tonic-gate snm, &d, &l) == 2) && cl == l) { 21180Sstevel@tonic-gate len = 14 + cl + strlen(snm) + 1; 21190Sstevel@tonic-gate rnm = Zalloc(len); 21200Sstevel@tonic-gate (void) snprintf(rnm, len, "/dev/md/%s/rdsk/d%u", 21210Sstevel@tonic-gate snm, d); 21220Sstevel@tonic-gate return (rnm); 21230Sstevel@tonic-gate } 21240Sstevel@tonic-gate } 21250Sstevel@tonic-gate 21260Sstevel@tonic-gate /* NOT Fully qualified path, done */ 21270Sstevel@tonic-gate if (unm[0] != '/') { 21280Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, unm); 21290Sstevel@tonic-gate return (NULL); 21300Sstevel@tonic-gate } 21310Sstevel@tonic-gate 21320Sstevel@tonic-gate /* 21330Sstevel@tonic-gate * Get slice information from old style names of the form 21340Sstevel@tonic-gate * /dev/rXXNN[a-h] or /dev/XXNN[a-h], must be done before regular 21350Sstevel@tonic-gate * devices, but after metadevices. 21360Sstevel@tonic-gate */ 21370Sstevel@tonic-gate if ((sscanf(unm, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 21380Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 21390Sstevel@tonic-gate onmb, &d, snm, &l) == 3 || 21400Sstevel@tonic-gate sscanf(unm, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u" 21410Sstevel@tonic-gate "%" VAL2STR(BUFSIZ) "[a-h]%n", 21420Sstevel@tonic-gate onmb, &d, snm, &l) == 3) && l == cl) { 21430Sstevel@tonic-gate if ((p = strchr("abcdefgh", snm[0])) != NULL) { 21440Sstevel@tonic-gate (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u%s", 21450Sstevel@tonic-gate onmb, d, snm); 21460Sstevel@tonic-gate return (Strdup(cnmb)); 21470Sstevel@tonic-gate } 21480Sstevel@tonic-gate } 21490Sstevel@tonic-gate 21500Sstevel@tonic-gate if ((p = strstr(unm, "/dsk/")) != NULL) { /* /.../dsk/... */ 21510Sstevel@tonic-gate ++p; 21520Sstevel@tonic-gate rnm = Zalloc(strlen(unm) + 1 + 1); 21530Sstevel@tonic-gate (void) strncpy(rnm, unm, (p - unm)); 21540Sstevel@tonic-gate rnm[(p - unm)] = 'r'; 21550Sstevel@tonic-gate (void) strcpy(&rnm[(p - unm) + 1], p); 21560Sstevel@tonic-gate return (rnm); 21570Sstevel@tonic-gate } else if (strstr(unm, "/rdsk/") != NULL) { /* /.../rdsk/... */ 21580Sstevel@tonic-gate return (Strdup(unm)); 21590Sstevel@tonic-gate } 21600Sstevel@tonic-gate 21610Sstevel@tonic-gate /* 21620Sstevel@tonic-gate * Shouldn't get here but if we do then we have an unrecognized 21630Sstevel@tonic-gate * fully qualified path - error 21640Sstevel@tonic-gate */ 21650Sstevel@tonic-gate (void) mdsyserror(ep, EINVAL, unm); 21660Sstevel@tonic-gate return (NULL); 21670Sstevel@tonic-gate } 21680Sstevel@tonic-gate 21690Sstevel@tonic-gate static mdname_t * 21700Sstevel@tonic-gate metainitfastname( 21710Sstevel@tonic-gate mdsetname_t *sp, 21720Sstevel@tonic-gate char *uname, 21730Sstevel@tonic-gate md_error_t *ep 21740Sstevel@tonic-gate ) 21750Sstevel@tonic-gate { 21760Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0, s = 0; 21770Sstevel@tonic-gate int l = 0; 21780Sstevel@tonic-gate mddrivename_t *dnp; 21790Sstevel@tonic-gate mdname_t *np; 21800Sstevel@tonic-gate mdnamelist_t **fnlpp; 21810Sstevel@tonic-gate 21820Sstevel@tonic-gate for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) { 21830Sstevel@tonic-gate np = (*fnlpp)->namep; 21840Sstevel@tonic-gate 21850Sstevel@tonic-gate if (strcmp(np->bname, uname) == 0) 21860Sstevel@tonic-gate return (np); 21870Sstevel@tonic-gate } 21880Sstevel@tonic-gate 21890Sstevel@tonic-gate *fnlpp = Zalloc(sizeof (**fnlpp)); 21900Sstevel@tonic-gate np = (*fnlpp)->namep = Zalloc(sizeof (mdname_t)); 21910Sstevel@tonic-gate metainitname(np); 21920Sstevel@tonic-gate dnp = np->drivenamep = Zalloc(sizeof (mddrivename_t)); 21930Sstevel@tonic-gate metainitdrivename(dnp); 21940Sstevel@tonic-gate 21950Sstevel@tonic-gate 21960Sstevel@tonic-gate /* Metadevices */ 21970Sstevel@tonic-gate if (is_metaname(uname)) { 21980Sstevel@tonic-gate char *p; 21990Sstevel@tonic-gate size_t len; 22000Sstevel@tonic-gate 22010Sstevel@tonic-gate if ((p = strrchr(uname, '/')) != NULL) 22020Sstevel@tonic-gate ++p; 22030Sstevel@tonic-gate else 22040Sstevel@tonic-gate p = uname; 22050Sstevel@tonic-gate 22060Sstevel@tonic-gate if (metaislocalset(sp)) { 22070Sstevel@tonic-gate if (np->cname) 22080Sstevel@tonic-gate Free(np->cname); 22090Sstevel@tonic-gate np->cname = Strdup(p); 22100Sstevel@tonic-gate } else { 22110Sstevel@tonic-gate if (np->cname) 22120Sstevel@tonic-gate Free(np->cname); 22130Sstevel@tonic-gate len = strlen(sp->setname) + 1 + strlen(p) + 1; 22140Sstevel@tonic-gate np->cname = Zalloc(len); 22150Sstevel@tonic-gate (void) snprintf(np->cname, len, "%s/%s", 22160Sstevel@tonic-gate sp->setname, p); 22170Sstevel@tonic-gate } 22180Sstevel@tonic-gate dnp->type = MDT_FAST_META; 22190Sstevel@tonic-gate goto done; 22200Sstevel@tonic-gate } 22210Sstevel@tonic-gate 22220Sstevel@tonic-gate /* Others */ 22230Sstevel@tonic-gate dnp->type = MDT_FAST_COMP; 22240Sstevel@tonic-gate 22250Sstevel@tonic-gate if (((sscanf(uname, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d, 22260Sstevel@tonic-gate &s, &l) == 4 || 22270Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d, 22280Sstevel@tonic-gate &s, &l) == 4 || 22290Sstevel@tonic-gate sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c, &t, &d, 22300Sstevel@tonic-gate &s, &l) == 4 || 22310Sstevel@tonic-gate sscanf(uname, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c, &t, &d, 22320Sstevel@tonic-gate &s, &l) == 4 || 22330Sstevel@tonic-gate sscanf(uname, "/dev/did/rdsk/d%us%u%n", &t, &s, &l) == 2 || 22340Sstevel@tonic-gate sscanf(uname, "/dev/did/dsk/d%us%u%n", &t, &s, &l) == 2|| 22350Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 || 22360Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 || 22370Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 || 22380Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 || 22390Sstevel@tonic-gate sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 || 22400Sstevel@tonic-gate sscanf(uname, "/dev/ap/dsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 || 22410Sstevel@tonic-gate sscanf(uname, "/dev/did/rdsk/d%u%n", &t, &l) == 1 || 22420Sstevel@tonic-gate sscanf(uname, "/dev/did/dsk/d%u%n", &t, &l) == 1 || 22430Sstevel@tonic-gate sscanf(uname, "/dev/rdsk/c%ud%u%n", &c, &d, &l) == 2 || 22440Sstevel@tonic-gate sscanf(uname, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2) && 22450Sstevel@tonic-gate l == strlen(uname))) { 22460Sstevel@tonic-gate if ((np->cname = strrchr(uname, '/')) == NULL) 22470Sstevel@tonic-gate np->cname = Strdup(uname); 22480Sstevel@tonic-gate else 22490Sstevel@tonic-gate np->cname = Strdup(++np->cname); 22500Sstevel@tonic-gate } else { 22510Sstevel@tonic-gate np->cname = Strdup(uname); 22520Sstevel@tonic-gate } 22530Sstevel@tonic-gate 22540Sstevel@tonic-gate done: 22550Sstevel@tonic-gate /* Driver always gives us block names */ 22560Sstevel@tonic-gate np->bname = Strdup(uname); 22570Sstevel@tonic-gate 22580Sstevel@tonic-gate /* canonical disk name */ 22590Sstevel@tonic-gate if ((dnp->cname = metadiskname(np->cname)) == NULL) 22600Sstevel@tonic-gate dnp->cname = Strdup(np->cname); 22610Sstevel@tonic-gate 22620Sstevel@tonic-gate if ((np->rname = getrname_fast(uname, ep)) != NULL) { 22630Sstevel@tonic-gate if ((dnp->rname = metadiskname(np->rname)) == NULL) 22640Sstevel@tonic-gate dnp->rname = Strdup(np->rname); 22650Sstevel@tonic-gate } else { 22660Sstevel@tonic-gate metafreefastnm(&(*fnlpp)->namep); 22670Sstevel@tonic-gate Free(*fnlpp); 22680Sstevel@tonic-gate *fnlpp = NULL; 22690Sstevel@tonic-gate return (NULL); 22700Sstevel@tonic-gate } 22710Sstevel@tonic-gate 22720Sstevel@tonic-gate /* cleanup, return success */ 22730Sstevel@tonic-gate return (np); 22740Sstevel@tonic-gate } 22750Sstevel@tonic-gate 22760Sstevel@tonic-gate /* 22770Sstevel@tonic-gate * set up names for a device 22780Sstevel@tonic-gate */ 22790Sstevel@tonic-gate static mdname_t * 22800Sstevel@tonic-gate metaname_common( 22810Sstevel@tonic-gate mdsetname_t **spp, 22820Sstevel@tonic-gate char *uname, 22830Sstevel@tonic-gate int fast, 22840Sstevel@tonic-gate md_error_t *ep 22850Sstevel@tonic-gate ) 22860Sstevel@tonic-gate { 22870Sstevel@tonic-gate mddrivenamelist_t **tail; 22880Sstevel@tonic-gate mddrivename_t *dnp; 22890Sstevel@tonic-gate uint_t slice; 22900Sstevel@tonic-gate mdname_t *np; 22910Sstevel@tonic-gate char *rname = NULL; 22920Sstevel@tonic-gate char *dname = NULL; 22930Sstevel@tonic-gate char *cname = NULL; 22940Sstevel@tonic-gate uint_t nparts, partno; 22950Sstevel@tonic-gate 22960Sstevel@tonic-gate assert(uname != NULL); 22970Sstevel@tonic-gate 22980Sstevel@tonic-gate /* check setname */ 22990Sstevel@tonic-gate if ((cname = meta_name_getname(spp, uname, ep)) == NULL) 23000Sstevel@tonic-gate return (NULL); 23010Sstevel@tonic-gate 23020Sstevel@tonic-gate assert(*spp != NULL); 23030Sstevel@tonic-gate Free(cname); 23040Sstevel@tonic-gate 23050Sstevel@tonic-gate /* get raw name (rname) of the slice and drive (dname) we have */ 23060Sstevel@tonic-gate if ((rname = getrawnames(spp, uname, &dname, ep)) == NULL) { 23070Sstevel@tonic-gate return (NULL); 23080Sstevel@tonic-gate } 23090Sstevel@tonic-gate 23100Sstevel@tonic-gate /* look in cache first */ 23110Sstevel@tonic-gate for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 23120Sstevel@tonic-gate dnp = (*tail)->drivenamep; 23130Sstevel@tonic-gate 23140Sstevel@tonic-gate /* check to see if the drive name is already in the cache */ 23150Sstevel@tonic-gate if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) { 23160Sstevel@tonic-gate 23170Sstevel@tonic-gate Free(rname); 23180Sstevel@tonic-gate if (dname != NULL) 23190Sstevel@tonic-gate Free(dname); 23200Sstevel@tonic-gate 23210Sstevel@tonic-gate if (uname2sliceno(uname, &partno, ep) < 0) 23220Sstevel@tonic-gate return (NULL); 23230Sstevel@tonic-gate 23240Sstevel@tonic-gate return (metaslicename(dnp, partno, ep)); 23250Sstevel@tonic-gate } 23260Sstevel@tonic-gate } 23270Sstevel@tonic-gate 23280Sstevel@tonic-gate /* 23290Sstevel@tonic-gate * If a fast names is OK, then get one, and be done. 23300Sstevel@tonic-gate */ 23310Sstevel@tonic-gate if (fast) { 23320Sstevel@tonic-gate Free(rname); 23330Sstevel@tonic-gate if (dname != NULL) 23340Sstevel@tonic-gate Free(dname); 23350Sstevel@tonic-gate 23360Sstevel@tonic-gate return (metainitfastname(*spp, uname, ep)); 23370Sstevel@tonic-gate } 23380Sstevel@tonic-gate 23390Sstevel@tonic-gate /* allocate new list element and drive */ 23400Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 23410Sstevel@tonic-gate dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp)); 23420Sstevel@tonic-gate 23430Sstevel@tonic-gate metainitdrivename(dnp); 23440Sstevel@tonic-gate 23450Sstevel@tonic-gate /* get parts info */ 23460Sstevel@tonic-gate if (getparts(dnp, rname, dname, &nparts, &partno, ep) != 0) 23470Sstevel@tonic-gate goto out; 23480Sstevel@tonic-gate 23490Sstevel@tonic-gate /* 23500Sstevel@tonic-gate * libmeta needs at least V_NUMPAR partitions. 23510Sstevel@tonic-gate * If we have an EFI partition with less than V_NUMPAR slices, 23520Sstevel@tonic-gate * we nevertheless reserve space for V_NUMPAR 23530Sstevel@tonic-gate */ 23540Sstevel@tonic-gate if (nparts < V_NUMPAR) { 23550Sstevel@tonic-gate nparts = V_NUMPAR; 23560Sstevel@tonic-gate } 23570Sstevel@tonic-gate 23580Sstevel@tonic-gate /* allocate and link in parts */ 23590Sstevel@tonic-gate dnp->parts.parts_len = nparts; 23600Sstevel@tonic-gate dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) * 23610Sstevel@tonic-gate dnp->parts.parts_len); 23620Sstevel@tonic-gate for (slice = 0; (slice < nparts); ++slice) { 23630Sstevel@tonic-gate np = &dnp->parts.parts_val[slice]; 23640Sstevel@tonic-gate metainitname(np); 23650Sstevel@tonic-gate np->drivenamep = dnp; 23660Sstevel@tonic-gate } 23670Sstevel@tonic-gate 23680Sstevel@tonic-gate /* setup name_t (or slice) wanted */ 23690Sstevel@tonic-gate if ((np = setup_slice(*spp, dnp, uname, rname, dname, partno, ep)) 23700Sstevel@tonic-gate == NULL) 23710Sstevel@tonic-gate goto out; 23720Sstevel@tonic-gate 23730Sstevel@tonic-gate /* canonical disk name */ 23740Sstevel@tonic-gate if ((dnp->cname = metadiskname(np->cname)) == NULL) 23750Sstevel@tonic-gate dnp->cname = Strdup(np->cname); 23760Sstevel@tonic-gate if ((dnp->rname = metadiskname(np->rname)) == NULL) 23770Sstevel@tonic-gate dnp->rname = Strdup(np->rname); 23780Sstevel@tonic-gate 23790Sstevel@tonic-gate /* cleanup, return success */ 23800Sstevel@tonic-gate if (dname != NULL) 23810Sstevel@tonic-gate Free(dname); 23820Sstevel@tonic-gate Free(rname); 23830Sstevel@tonic-gate return (np); 23840Sstevel@tonic-gate 23850Sstevel@tonic-gate /* cleanup, return error */ 23860Sstevel@tonic-gate out: 23870Sstevel@tonic-gate if (dname != NULL) 23880Sstevel@tonic-gate Free(dname); 23890Sstevel@tonic-gate if (rname != NULL) 23900Sstevel@tonic-gate Free(rname); 23910Sstevel@tonic-gate 23920Sstevel@tonic-gate metafreedrivename(dnp); 23930Sstevel@tonic-gate Free(dnp); 23940Sstevel@tonic-gate Free(*tail); 23950Sstevel@tonic-gate *tail = NULL; 23960Sstevel@tonic-gate return (NULL); 23970Sstevel@tonic-gate } 23980Sstevel@tonic-gate 23990Sstevel@tonic-gate mdname_t * 24000Sstevel@tonic-gate metaname( 24010Sstevel@tonic-gate mdsetname_t **spp, 24020Sstevel@tonic-gate char *uname, 24030Sstevel@tonic-gate md_error_t *ep 24040Sstevel@tonic-gate ) 24050Sstevel@tonic-gate { 24060Sstevel@tonic-gate return (metaname_common(spp, uname, 0, ep)); 24070Sstevel@tonic-gate } 24080Sstevel@tonic-gate 24090Sstevel@tonic-gate mdname_t * 24100Sstevel@tonic-gate metaname_fast( 24110Sstevel@tonic-gate mdsetname_t **spp, 24120Sstevel@tonic-gate char *uname, 24130Sstevel@tonic-gate md_error_t *ep 24140Sstevel@tonic-gate ) 24150Sstevel@tonic-gate { 24160Sstevel@tonic-gate return (metaname_common(spp, uname, 1, ep)); 24170Sstevel@tonic-gate } 24180Sstevel@tonic-gate 24190Sstevel@tonic-gate /* 24200Sstevel@tonic-gate * set up names for a drive 24210Sstevel@tonic-gate */ 24220Sstevel@tonic-gate mddrivename_t * 24230Sstevel@tonic-gate metadrivename( 24240Sstevel@tonic-gate mdsetname_t **spp, 24250Sstevel@tonic-gate char *uname, 24260Sstevel@tonic-gate md_error_t *ep 24270Sstevel@tonic-gate ) 24280Sstevel@tonic-gate { 24290Sstevel@tonic-gate char *slicename; 24300Sstevel@tonic-gate mdname_t *np; 24310Sstevel@tonic-gate 24320Sstevel@tonic-gate char *cname; 24330Sstevel@tonic-gate mddrivenamelist_t **tail; 24340Sstevel@tonic-gate mddrivename_t *dnp; 24350Sstevel@tonic-gate char *dname; 24360Sstevel@tonic-gate int i; 24370Sstevel@tonic-gate int mplen; 24380Sstevel@tonic-gate size_t len; 24390Sstevel@tonic-gate 24400Sstevel@tonic-gate /* check setname, get comparison name */ 24410Sstevel@tonic-gate assert(uname != NULL); 24420Sstevel@tonic-gate if ((cname = meta_name_getname(spp, uname, ep)) == NULL) { 24430Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 24440Sstevel@tonic-gate return (NULL); 24450Sstevel@tonic-gate } 24460Sstevel@tonic-gate 24470Sstevel@tonic-gate assert(*spp != NULL); 24480Sstevel@tonic-gate 24490Sstevel@tonic-gate if ((dname = metadiskname(cname)) == NULL) { 24500Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, cname); 24510Sstevel@tonic-gate Free(cname); 24520Sstevel@tonic-gate return (NULL); 24530Sstevel@tonic-gate } 24540Sstevel@tonic-gate 24550Sstevel@tonic-gate /* look in cache first */ 24560Sstevel@tonic-gate for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 24570Sstevel@tonic-gate dnp = (*tail)->drivenamep; 24580Sstevel@tonic-gate if ((dnp->cname != NULL && 24590Sstevel@tonic-gate (strcmp(dnp->cname, dname) == 0)) || 24600Sstevel@tonic-gate (dnp->rname != NULL && 24610Sstevel@tonic-gate (strcmp(dnp->rname, dname) == 0))) { 24620Sstevel@tonic-gate Free(cname); 24630Sstevel@tonic-gate Free(dname); 24640Sstevel@tonic-gate return (dnp); 24650Sstevel@tonic-gate } 24660Sstevel@tonic-gate } 24670Sstevel@tonic-gate 24680Sstevel@tonic-gate /* Check each possible slice name based on MD_MAX_PARTS. */ 24690Sstevel@tonic-gate 24700Sstevel@tonic-gate /* 24710Sstevel@tonic-gate * Figure out how much string space to reserve to fit 24720Sstevel@tonic-gate * (MD_MAX_PARTS - 1) into the name string; the loop will 24730Sstevel@tonic-gate * increment the mplen counter once for each decimal digit in 24740Sstevel@tonic-gate * (MD_MAX_PARTS - 1). 24750Sstevel@tonic-gate */ 24760Sstevel@tonic-gate for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen); 24770Sstevel@tonic-gate len = strlen(uname) + mplen + 2; 24780Sstevel@tonic-gate slicename = Malloc(len); 24790Sstevel@tonic-gate 24800Sstevel@tonic-gate /* Check for each slice in turn until we find one */ 24810Sstevel@tonic-gate for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) { 24820Sstevel@tonic-gate (void) snprintf(slicename, len, "%ss%d", uname, i); 24830Sstevel@tonic-gate np = metaname(spp, slicename, ep); 24840Sstevel@tonic-gate } 24850Sstevel@tonic-gate Free(slicename); 24860Sstevel@tonic-gate 24870Sstevel@tonic-gate if (np == NULL) { 24880Sstevel@tonic-gate char *dname; 24890Sstevel@tonic-gate 24900Sstevel@tonic-gate if ((mdissyserror(ep, ENOENT)) && 24910Sstevel@tonic-gate ((dname = metadiskname(uname)) != NULL)) { 24920Sstevel@tonic-gate Free(dname); 24930Sstevel@tonic-gate (void) mderror(ep, MDE_NOT_DRIVENAME, uname); 24940Sstevel@tonic-gate } 24950Sstevel@tonic-gate return (NULL); 24960Sstevel@tonic-gate } 24970Sstevel@tonic-gate return (np->drivenamep); 24980Sstevel@tonic-gate } 24990Sstevel@tonic-gate 25000Sstevel@tonic-gate /* 25010Sstevel@tonic-gate * FUNCTION: metaslicename() 25020Sstevel@tonic-gate * INPUT: dnp - the drivename structure 25030Sstevel@tonic-gate * sliceno - the slice on the drive to return 25040Sstevel@tonic-gate * OUTPUT: ep - return error pointer 25050Sstevel@tonic-gate * RETURNS: mdname_t- pointer the the slice name structure 25060Sstevel@tonic-gate * PURPOSE: interface to the parts struct in the drive name struct 25070Sstevel@tonic-gate * Since there is no guarantee that the slice name 25080Sstevel@tonic-gate * structures are populated users should call this 25090Sstevel@tonic-gate * function rather than accessing the structure directly 25100Sstevel@tonic-gate * since it will populate the structure values if they 25110Sstevel@tonic-gate * haven't already been populated before returning. 25120Sstevel@tonic-gate */ 25130Sstevel@tonic-gate mdname_t * 25140Sstevel@tonic-gate metaslicename( 25150Sstevel@tonic-gate mddrivename_t *dnp, 25160Sstevel@tonic-gate uint_t sliceno, 25170Sstevel@tonic-gate md_error_t *ep 25180Sstevel@tonic-gate ) 25190Sstevel@tonic-gate { 25200Sstevel@tonic-gate mdsetname_t *sp = NULL; 25210Sstevel@tonic-gate char *namep = NULL; 25220Sstevel@tonic-gate mdname_t *np; 25230Sstevel@tonic-gate 25240Sstevel@tonic-gate assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 25250Sstevel@tonic-gate 25260Sstevel@tonic-gate if (sliceno >= dnp->parts.parts_len) { 25270Sstevel@tonic-gate (void) mderror(ep, MDE_NOSLICE, dnp->cname); 25280Sstevel@tonic-gate return (NULL); 25290Sstevel@tonic-gate } 25300Sstevel@tonic-gate 25310Sstevel@tonic-gate np = &dnp->parts.parts_val[sliceno]; 25320Sstevel@tonic-gate 25330Sstevel@tonic-gate /* check to see if the struct is already populated */ 25340Sstevel@tonic-gate if (np->cname) { 25350Sstevel@tonic-gate return (np); 25360Sstevel@tonic-gate } 25370Sstevel@tonic-gate 25380Sstevel@tonic-gate if ((namep = meta_name_getname(&sp, dnp->cname, ep)) == NULL) 25390Sstevel@tonic-gate return (NULL); 25400Sstevel@tonic-gate 25410Sstevel@tonic-gate np = setup_slice(sp, dnp, NULL, NULL, dnp->rname, sliceno, ep); 25420Sstevel@tonic-gate 25430Sstevel@tonic-gate Free(namep); 25440Sstevel@tonic-gate 25450Sstevel@tonic-gate return (np); 25460Sstevel@tonic-gate } 25470Sstevel@tonic-gate 25480Sstevel@tonic-gate /* 25490Sstevel@tonic-gate * set up metadevice name from id 25500Sstevel@tonic-gate */ 25510Sstevel@tonic-gate mdname_t * 25520Sstevel@tonic-gate metamnumname( 25530Sstevel@tonic-gate mdsetname_t **spp, 25540Sstevel@tonic-gate minor_t mnum, 25550Sstevel@tonic-gate int fast, 25560Sstevel@tonic-gate md_error_t *ep 25570Sstevel@tonic-gate ) 25580Sstevel@tonic-gate { 25590Sstevel@tonic-gate set_t setno = MD_MIN2SET(mnum); 25600Sstevel@tonic-gate mdsetname_t *sp = NULL; 25610Sstevel@tonic-gate char *uname; 25620Sstevel@tonic-gate mdname_t *np; 25630Sstevel@tonic-gate size_t len; 25640Sstevel@tonic-gate 25650Sstevel@tonic-gate /* check set first */ 25660Sstevel@tonic-gate if (spp == NULL) 25670Sstevel@tonic-gate spp = &sp; 25680Sstevel@tonic-gate if (chksetno(spp, setno, ep) != 0) 25690Sstevel@tonic-gate return (NULL); 25700Sstevel@tonic-gate assert(*spp != NULL); 25710Sstevel@tonic-gate sp = *spp; 25720Sstevel@tonic-gate 25730Sstevel@tonic-gate /* build corresponding device name */ 25740Sstevel@tonic-gate if (metaislocalset(sp)) { 25750Sstevel@tonic-gate uname = Malloc(20); 25760Sstevel@tonic-gate (void) sprintf(uname, "d%lu", MD_MIN2UNIT(mnum)); 25770Sstevel@tonic-gate } else { 25780Sstevel@tonic-gate len = strlen(sp->setname) + 1 + 20; 25790Sstevel@tonic-gate uname = Malloc(len); 25800Sstevel@tonic-gate (void) snprintf(uname, len, "%s/d%lu", sp->setname, 25810Sstevel@tonic-gate MD_MIN2UNIT(mnum)); 25820Sstevel@tonic-gate } 25830Sstevel@tonic-gate 25840Sstevel@tonic-gate /* setup name */ 25850Sstevel@tonic-gate if (fast) { 25860Sstevel@tonic-gate np = metaname_fast(spp, uname, ep); 25870Sstevel@tonic-gate np->dev = metamakedev(mnum); 25880Sstevel@tonic-gate } else 25890Sstevel@tonic-gate np = metaname(spp, uname, ep); 25900Sstevel@tonic-gate 25910Sstevel@tonic-gate Free(uname); 25920Sstevel@tonic-gate return (np); 25930Sstevel@tonic-gate } 25940Sstevel@tonic-gate 25950Sstevel@tonic-gate /* 25960Sstevel@tonic-gate * return metadevice name 25970Sstevel@tonic-gate */ 25980Sstevel@tonic-gate char * 25990Sstevel@tonic-gate get_mdname( 26000Sstevel@tonic-gate minor_t mnum 26010Sstevel@tonic-gate ) 26020Sstevel@tonic-gate { 26030Sstevel@tonic-gate mdname_t *np; 26040Sstevel@tonic-gate md_error_t status = mdnullerror; 26050Sstevel@tonic-gate 26060Sstevel@tonic-gate /* get name */ 26070Sstevel@tonic-gate if ((np = metamnumname(NULL, mnum, 0, &status)) == NULL) { 26080Sstevel@tonic-gate mdclrerror(&status); 26090Sstevel@tonic-gate return (NULL); 26100Sstevel@tonic-gate } 26110Sstevel@tonic-gate assert(meta_getminor(np->dev) == mnum); 26120Sstevel@tonic-gate 26130Sstevel@tonic-gate /* return name */ 26140Sstevel@tonic-gate return (np->cname); 26150Sstevel@tonic-gate } 26160Sstevel@tonic-gate 26170Sstevel@tonic-gate /* 26180Sstevel@tonic-gate * check for device type 26190Sstevel@tonic-gate */ 26200Sstevel@tonic-gate int 26210Sstevel@tonic-gate metaismeta( 26220Sstevel@tonic-gate mdname_t *np 26230Sstevel@tonic-gate ) 26240Sstevel@tonic-gate { 26250Sstevel@tonic-gate return (np->drivenamep->type == MDT_META || 26260Sstevel@tonic-gate np->drivenamep->type == MDT_FAST_META); 26270Sstevel@tonic-gate } 26280Sstevel@tonic-gate 26290Sstevel@tonic-gate int 26300Sstevel@tonic-gate metachkmeta( 26310Sstevel@tonic-gate mdname_t *np, 26320Sstevel@tonic-gate md_error_t *ep 26330Sstevel@tonic-gate ) 26340Sstevel@tonic-gate { 26350Sstevel@tonic-gate if (! metaismeta(np)) { 26360Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_META, np->dev, 26370Sstevel@tonic-gate np->cname)); 26380Sstevel@tonic-gate } 26390Sstevel@tonic-gate return (0); 26400Sstevel@tonic-gate } 26410Sstevel@tonic-gate 26420Sstevel@tonic-gate int 26430Sstevel@tonic-gate metachkdisk( 26440Sstevel@tonic-gate mdname_t *np, 26450Sstevel@tonic-gate md_error_t *ep 26460Sstevel@tonic-gate ) 26470Sstevel@tonic-gate { 26480Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep; 26490Sstevel@tonic-gate 26500Sstevel@tonic-gate assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 26510Sstevel@tonic-gate 26520Sstevel@tonic-gate if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) { 26530Sstevel@tonic-gate switch (dnp->type) { 26540Sstevel@tonic-gate case MDT_ACCES: 26550Sstevel@tonic-gate case MDT_UNKNOWN: 26560Sstevel@tonic-gate return (mdsyserror(ep, dnp->errnum, np->bname)); 26570Sstevel@tonic-gate default: 26580Sstevel@tonic-gate assert(0); 26590Sstevel@tonic-gate return (mddeverror(ep, MDE_NOT_DISK, np->dev, 26600Sstevel@tonic-gate np->cname)); 26610Sstevel@tonic-gate } 26620Sstevel@tonic-gate } 26630Sstevel@tonic-gate return (0); 26640Sstevel@tonic-gate } 26650Sstevel@tonic-gate 26660Sstevel@tonic-gate int 26670Sstevel@tonic-gate metachkcomp( 26680Sstevel@tonic-gate mdname_t *np, 26690Sstevel@tonic-gate md_error_t *ep 26700Sstevel@tonic-gate ) 26710Sstevel@tonic-gate { 26720Sstevel@tonic-gate if (metaismeta(np)) { 26730Sstevel@tonic-gate return (mddeverror(ep, MDE_IS_META, np->dev, 26740Sstevel@tonic-gate np->cname)); 26750Sstevel@tonic-gate } 26760Sstevel@tonic-gate return (metachkdisk(np, ep)); 26770Sstevel@tonic-gate } 26780Sstevel@tonic-gate 26790Sstevel@tonic-gate /* 26800Sstevel@tonic-gate * free list of names 26810Sstevel@tonic-gate */ 26820Sstevel@tonic-gate void 26830Sstevel@tonic-gate metafreenamelist( 26840Sstevel@tonic-gate mdnamelist_t *nlp 26850Sstevel@tonic-gate ) 26860Sstevel@tonic-gate { 26870Sstevel@tonic-gate mdnamelist_t *next = NULL; 26880Sstevel@tonic-gate 26890Sstevel@tonic-gate for (/* void */; (nlp != NULL); nlp = next) { 26900Sstevel@tonic-gate next = nlp->next; 26910Sstevel@tonic-gate Free(nlp); 26920Sstevel@tonic-gate } 26930Sstevel@tonic-gate } 26940Sstevel@tonic-gate 26950Sstevel@tonic-gate /* 26960Sstevel@tonic-gate * build list of names 26970Sstevel@tonic-gate */ 26980Sstevel@tonic-gate int 26990Sstevel@tonic-gate metanamelist( 27000Sstevel@tonic-gate mdsetname_t **spp, 27010Sstevel@tonic-gate mdnamelist_t **nlpp, 27020Sstevel@tonic-gate int argc, 27030Sstevel@tonic-gate char *argv[], 27040Sstevel@tonic-gate md_error_t *ep 27050Sstevel@tonic-gate ) 27060Sstevel@tonic-gate { 27070Sstevel@tonic-gate mdnamelist_t **tailpp = nlpp; 27080Sstevel@tonic-gate int count = 0; 27090Sstevel@tonic-gate 27100Sstevel@tonic-gate for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 27110Sstevel@tonic-gate mdnamelist_t *nlp = Zalloc(sizeof (*nlp)); 27120Sstevel@tonic-gate 27130Sstevel@tonic-gate if ((nlp->namep = metaname(spp, argv[0], ep)) == NULL) { 27140Sstevel@tonic-gate metafreenamelist(*nlpp); 27150Sstevel@tonic-gate *nlpp = NULL; 27160Sstevel@tonic-gate return (-1); 27170Sstevel@tonic-gate } 27180Sstevel@tonic-gate *tailpp = nlp; 27190Sstevel@tonic-gate tailpp = &nlp->next; 27200Sstevel@tonic-gate } 27210Sstevel@tonic-gate return (count); 27220Sstevel@tonic-gate } 27230Sstevel@tonic-gate 27240Sstevel@tonic-gate /* 27250Sstevel@tonic-gate * append to end of name list 27260Sstevel@tonic-gate */ 27270Sstevel@tonic-gate mdname_t * 27280Sstevel@tonic-gate metanamelist_append( 27290Sstevel@tonic-gate mdnamelist_t **nlpp, 27300Sstevel@tonic-gate mdname_t *np 27310Sstevel@tonic-gate ) 27320Sstevel@tonic-gate { 27330Sstevel@tonic-gate mdnamelist_t *nlp; 27340Sstevel@tonic-gate 27350Sstevel@tonic-gate /* run to end of list */ 27360Sstevel@tonic-gate for (; (*nlpp != NULL); nlpp = &(*nlpp)->next) 27370Sstevel@tonic-gate ; 27380Sstevel@tonic-gate 27390Sstevel@tonic-gate /* allocate new list element */ 27400Sstevel@tonic-gate nlp = *nlpp = Zalloc(sizeof (*nlp)); 27410Sstevel@tonic-gate 27420Sstevel@tonic-gate /* append name */ 27430Sstevel@tonic-gate nlp->namep = np; 27440Sstevel@tonic-gate return (np); 27450Sstevel@tonic-gate } 27460Sstevel@tonic-gate 27470Sstevel@tonic-gate /* 27480Sstevel@tonic-gate * FUNCTION: meta_namelist_append_wrapper() 27490Sstevel@tonic-gate * INPUT: tailpp - pointer to the list tail pointer 27500Sstevel@tonic-gate * np - name node to be appended to list 27510Sstevel@tonic-gate * OUTPUT: none 27520Sstevel@tonic-gate * RETURNS: mdnamelist_t * - new tail of the list. 27530Sstevel@tonic-gate * PURPOSE: wrapper to meta_namelist_append for performance. 27540Sstevel@tonic-gate * metanamelist_append finds the tail each time which slows 27550Sstevel@tonic-gate * down long lists. By keeping track of the tail ourselves 27560Sstevel@tonic-gate * we can change metanamelist_append into a constant time 27570Sstevel@tonic-gate * operation. 27580Sstevel@tonic-gate */ 27590Sstevel@tonic-gate mdnamelist_t ** 27600Sstevel@tonic-gate meta_namelist_append_wrapper( 27610Sstevel@tonic-gate mdnamelist_t **tailpp, 27620Sstevel@tonic-gate mdname_t *np 27630Sstevel@tonic-gate ) 27640Sstevel@tonic-gate { 27650Sstevel@tonic-gate (void) metanamelist_append(tailpp, np); 27660Sstevel@tonic-gate 27670Sstevel@tonic-gate /* If it's the first item in the list, return it instead of the next */ 27680Sstevel@tonic-gate if ((*tailpp)->next == NULL) 27690Sstevel@tonic-gate return (tailpp); 27700Sstevel@tonic-gate 27710Sstevel@tonic-gate return (&(*tailpp)->next); 27720Sstevel@tonic-gate } 27730Sstevel@tonic-gate 27740Sstevel@tonic-gate 27750Sstevel@tonic-gate /* 27760Sstevel@tonic-gate * mdhspname_t stuff 27770Sstevel@tonic-gate */ 27780Sstevel@tonic-gate 27790Sstevel@tonic-gate /* 27800Sstevel@tonic-gate * initialize hspname 27810Sstevel@tonic-gate */ 27820Sstevel@tonic-gate static void 27830Sstevel@tonic-gate metainithspname( 27840Sstevel@tonic-gate mdhspname_t *hspnamep 27850Sstevel@tonic-gate ) 27860Sstevel@tonic-gate { 27870Sstevel@tonic-gate (void) memset(hspnamep, '\0', sizeof (*hspnamep)); 27880Sstevel@tonic-gate hspnamep->hsp = MD_HSP_NONE; 27890Sstevel@tonic-gate } 27900Sstevel@tonic-gate 27910Sstevel@tonic-gate /* 27920Sstevel@tonic-gate * free allocated hspname 27930Sstevel@tonic-gate */ 27940Sstevel@tonic-gate static void 27950Sstevel@tonic-gate metafreehspname( 27960Sstevel@tonic-gate mdhspname_t *hspnamep 27970Sstevel@tonic-gate ) 27980Sstevel@tonic-gate { 27990Sstevel@tonic-gate if (hspnamep->hspname != NULL) 28000Sstevel@tonic-gate Free(hspnamep->hspname); 28010Sstevel@tonic-gate if (hspnamep->unitp != NULL) 28020Sstevel@tonic-gate meta_invalidate_hsp(hspnamep); 28030Sstevel@tonic-gate metainithspname(hspnamep); 28040Sstevel@tonic-gate } 28050Sstevel@tonic-gate 28060Sstevel@tonic-gate /* 28070Sstevel@tonic-gate * clear the hspname cache 28080Sstevel@tonic-gate */ 28090Sstevel@tonic-gate static void 28100Sstevel@tonic-gate metaflushhspnames() 28110Sstevel@tonic-gate { 28120Sstevel@tonic-gate mdhspnamelist_t *p, *n; 28130Sstevel@tonic-gate 28140Sstevel@tonic-gate for (p = hsplistp, n = NULL; (p != NULL); p = n) { 28150Sstevel@tonic-gate n = p->next; 28160Sstevel@tonic-gate metafreehspname(p->hspnamep); 28170Sstevel@tonic-gate Free(p->hspnamep); 28180Sstevel@tonic-gate Free(p); 28190Sstevel@tonic-gate } 28200Sstevel@tonic-gate hsplistp = NULL; 28210Sstevel@tonic-gate } 28220Sstevel@tonic-gate 28230Sstevel@tonic-gate /* 28240Sstevel@tonic-gate * check set and get comparison name 28250Sstevel@tonic-gate */ 28260Sstevel@tonic-gate static char * 28270Sstevel@tonic-gate gethspname( 28280Sstevel@tonic-gate mdsetname_t **spp, 28290Sstevel@tonic-gate char *uname, 28300Sstevel@tonic-gate hsp_t *hspp, 28310Sstevel@tonic-gate md_error_t *ep 28320Sstevel@tonic-gate ) 28330Sstevel@tonic-gate { 28340Sstevel@tonic-gate char *sname = NULL; 28350Sstevel@tonic-gate 28360Sstevel@tonic-gate /* check setname */ 28370Sstevel@tonic-gate assert(uname != NULL); 28380Sstevel@tonic-gate if (parse_hsp(uname, &sname, hspp) != 0) { 28390Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, uname); 28400Sstevel@tonic-gate return (NULL); 28410Sstevel@tonic-gate } 28420Sstevel@tonic-gate if (chksetname(spp, sname, ep) != 0) { 28430Sstevel@tonic-gate if (sname != NULL) 28440Sstevel@tonic-gate Free(sname); 28450Sstevel@tonic-gate return (NULL); 28460Sstevel@tonic-gate } 28470Sstevel@tonic-gate if (sname != NULL) 28480Sstevel@tonic-gate Free(sname); 28490Sstevel@tonic-gate 28500Sstevel@tonic-gate /* return comparison name */ 28510Sstevel@tonic-gate return (canon_hsp((*spp)->setname, *hspp)); 28520Sstevel@tonic-gate } 28530Sstevel@tonic-gate 28540Sstevel@tonic-gate /* 28550Sstevel@tonic-gate * set up names for a hotspare pool 28560Sstevel@tonic-gate */ 28570Sstevel@tonic-gate mdhspname_t * 28580Sstevel@tonic-gate metahspname( 28590Sstevel@tonic-gate mdsetname_t **spp, 28600Sstevel@tonic-gate char *uname, 28610Sstevel@tonic-gate md_error_t *ep 28620Sstevel@tonic-gate ) 28630Sstevel@tonic-gate { 28640Sstevel@tonic-gate char *cname; 28650Sstevel@tonic-gate hsp_t hsp; 28660Sstevel@tonic-gate mdhspnamelist_t **tail; 28670Sstevel@tonic-gate mdhspname_t *hspnp; 28680Sstevel@tonic-gate 28690Sstevel@tonic-gate /* check setname */ 28700Sstevel@tonic-gate assert(uname != NULL); 28710Sstevel@tonic-gate if ((cname = gethspname(spp, uname, &hsp, ep)) == NULL) 28720Sstevel@tonic-gate return (NULL); 28730Sstevel@tonic-gate assert(*spp != NULL); 28740Sstevel@tonic-gate 28750Sstevel@tonic-gate /* look in cache first */ 28760Sstevel@tonic-gate for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) { 28770Sstevel@tonic-gate hspnp = (*tail)->hspnamep; 28780Sstevel@tonic-gate if (strcmp(hspnp->hspname, cname) == 0) { 28790Sstevel@tonic-gate Free(cname); 28800Sstevel@tonic-gate return (hspnp); 28810Sstevel@tonic-gate } 28820Sstevel@tonic-gate } 28830Sstevel@tonic-gate 28840Sstevel@tonic-gate /* allocate new list element and hspname */ 28850Sstevel@tonic-gate *tail = Zalloc(sizeof (**tail)); 28860Sstevel@tonic-gate hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp)); 28870Sstevel@tonic-gate metainithspname(hspnp); 28880Sstevel@tonic-gate 28890Sstevel@tonic-gate /* save hspname and number */ 28900Sstevel@tonic-gate hspnp->hspname = cname; 28910Sstevel@tonic-gate hspnp->hsp = MAKE_HSP_ID((*spp)->setno, hsp); 28920Sstevel@tonic-gate 28930Sstevel@tonic-gate /* success */ 28940Sstevel@tonic-gate return (hspnp); 28950Sstevel@tonic-gate 28960Sstevel@tonic-gate /* cleanup, return error */ 28970Sstevel@tonic-gate out: 28980Sstevel@tonic-gate metafreehspname(hspnp); 28990Sstevel@tonic-gate Free(hspnp); 29000Sstevel@tonic-gate Free(*tail); 29010Sstevel@tonic-gate *tail = NULL; 29020Sstevel@tonic-gate return (NULL); 29030Sstevel@tonic-gate 29040Sstevel@tonic-gate 29050Sstevel@tonic-gate } 29060Sstevel@tonic-gate 29070Sstevel@tonic-gate /* 29080Sstevel@tonic-gate * set up hotspare pool name from id 29090Sstevel@tonic-gate */ 29100Sstevel@tonic-gate mdhspname_t * 29110Sstevel@tonic-gate metahsphspname( 29120Sstevel@tonic-gate mdsetname_t **spp, 29130Sstevel@tonic-gate hsp_t hsp, 29140Sstevel@tonic-gate md_error_t *ep 29150Sstevel@tonic-gate ) 29160Sstevel@tonic-gate { 29170Sstevel@tonic-gate set_t setno = HSP_SET(hsp); 29180Sstevel@tonic-gate mdsetname_t *sp = NULL; 29190Sstevel@tonic-gate char *uname; 29200Sstevel@tonic-gate mdhspname_t *hspnp; 29210Sstevel@tonic-gate size_t len; 29220Sstevel@tonic-gate 29230Sstevel@tonic-gate /* check set first */ 29240Sstevel@tonic-gate if (spp == NULL) 29250Sstevel@tonic-gate spp = &sp; 29260Sstevel@tonic-gate if (chksetno(spp, setno, ep) != 0) 29270Sstevel@tonic-gate return (NULL); 29280Sstevel@tonic-gate assert(*spp != NULL); 29290Sstevel@tonic-gate sp = *spp; 29300Sstevel@tonic-gate 29310Sstevel@tonic-gate /* build corresponding hotspare pool name */ 29320Sstevel@tonic-gate if (metaislocalset(sp)) { 29330Sstevel@tonic-gate uname = Malloc(20); 29340Sstevel@tonic-gate (void) sprintf(uname, "hsp%03u", HSP_ID(hsp)); 29350Sstevel@tonic-gate } else { 29360Sstevel@tonic-gate len = strlen(sp->setname) + 1 + 20; 29370Sstevel@tonic-gate uname = Malloc(len); 29380Sstevel@tonic-gate (void) snprintf(uname, len, "%s/hsp%03lu", sp->setname, 29390Sstevel@tonic-gate HSP_ID(hsp)); 29400Sstevel@tonic-gate } 29410Sstevel@tonic-gate 29420Sstevel@tonic-gate /* setup name */ 29430Sstevel@tonic-gate hspnp = metahspname(spp, uname, ep); 29440Sstevel@tonic-gate Free(uname); 29450Sstevel@tonic-gate return (hspnp); 29460Sstevel@tonic-gate } 29470Sstevel@tonic-gate 29480Sstevel@tonic-gate /* 29490Sstevel@tonic-gate * return hotspare pool name 29500Sstevel@tonic-gate */ 29510Sstevel@tonic-gate char * 29520Sstevel@tonic-gate get_hspname(hsp_t hsp) 29530Sstevel@tonic-gate { 29540Sstevel@tonic-gate mdhspname_t *hspnp; 29550Sstevel@tonic-gate md_error_t status = mdnullerror; 29560Sstevel@tonic-gate 29570Sstevel@tonic-gate /* get name */ 29580Sstevel@tonic-gate if ((hspnp = metahsphspname(NULL, hsp, &status)) == NULL) { 29590Sstevel@tonic-gate mdclrerror(&status); 29600Sstevel@tonic-gate return (NULL); 29610Sstevel@tonic-gate } 29620Sstevel@tonic-gate 29630Sstevel@tonic-gate /* return name */ 29640Sstevel@tonic-gate return (hspnp->hspname); 29650Sstevel@tonic-gate } 29660Sstevel@tonic-gate 29670Sstevel@tonic-gate /* 29680Sstevel@tonic-gate * free hotspare pool list 29690Sstevel@tonic-gate */ 29700Sstevel@tonic-gate void 29710Sstevel@tonic-gate metafreehspnamelist(mdhspnamelist_t *hspnlp) 29720Sstevel@tonic-gate { 29730Sstevel@tonic-gate mdhspnamelist_t *next = NULL; 29740Sstevel@tonic-gate 29750Sstevel@tonic-gate for (/* void */; (hspnlp != NULL); hspnlp = next) { 29760Sstevel@tonic-gate next = hspnlp->next; 29770Sstevel@tonic-gate Free(hspnlp); 29780Sstevel@tonic-gate } 29790Sstevel@tonic-gate } 29800Sstevel@tonic-gate 29810Sstevel@tonic-gate /* 29820Sstevel@tonic-gate * build list of hotspare pool names 29830Sstevel@tonic-gate */ 29840Sstevel@tonic-gate int 29850Sstevel@tonic-gate metahspnamelist( 29860Sstevel@tonic-gate mdsetname_t **spp, 29870Sstevel@tonic-gate mdhspnamelist_t **hspnlpp, 29880Sstevel@tonic-gate int argc, 29890Sstevel@tonic-gate char *argv[], 29900Sstevel@tonic-gate md_error_t *ep 29910Sstevel@tonic-gate ) 29920Sstevel@tonic-gate { 29930Sstevel@tonic-gate mdhspnamelist_t **tailpp = hspnlpp; 29940Sstevel@tonic-gate int count = 0; 29950Sstevel@tonic-gate 29960Sstevel@tonic-gate for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 29970Sstevel@tonic-gate mdhspnamelist_t *hspnlp = Zalloc(sizeof (*hspnlp)); 29980Sstevel@tonic-gate 29990Sstevel@tonic-gate if ((hspnlp->hspnamep = metahspname(spp, argv[0], 30000Sstevel@tonic-gate ep)) == NULL) { 30010Sstevel@tonic-gate metafreehspnamelist(*hspnlpp); 30020Sstevel@tonic-gate *hspnlpp = NULL; 30030Sstevel@tonic-gate return (-1); 30040Sstevel@tonic-gate } 30050Sstevel@tonic-gate *tailpp = hspnlp; 30060Sstevel@tonic-gate tailpp = &hspnlp->next; 30070Sstevel@tonic-gate } 30080Sstevel@tonic-gate return (count); 30090Sstevel@tonic-gate } 30100Sstevel@tonic-gate 30110Sstevel@tonic-gate /* 30120Sstevel@tonic-gate * append to end of hotspare pool list 30130Sstevel@tonic-gate */ 30140Sstevel@tonic-gate mdhspname_t * 30150Sstevel@tonic-gate metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp) 30160Sstevel@tonic-gate { 30170Sstevel@tonic-gate mdhspnamelist_t *hspnlp; 30180Sstevel@tonic-gate 30190Sstevel@tonic-gate /* run to end of list */ 30200Sstevel@tonic-gate for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next) 30210Sstevel@tonic-gate ; 30220Sstevel@tonic-gate 30230Sstevel@tonic-gate /* allocate new list element */ 30240Sstevel@tonic-gate hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp)); 30250Sstevel@tonic-gate 30260Sstevel@tonic-gate /* append hotspare pool name */ 30270Sstevel@tonic-gate hspnlp->hspnamep = hspnp; 30280Sstevel@tonic-gate return (hspnp); 30290Sstevel@tonic-gate } 30300Sstevel@tonic-gate 30310Sstevel@tonic-gate /* 30320Sstevel@tonic-gate * get name from dev 30330Sstevel@tonic-gate */ 30340Sstevel@tonic-gate mdname_t * 30350Sstevel@tonic-gate metadevname( 30360Sstevel@tonic-gate mdsetname_t **spp, 30370Sstevel@tonic-gate md_dev64_t dev, 30380Sstevel@tonic-gate md_error_t *ep) 30390Sstevel@tonic-gate { 30400Sstevel@tonic-gate char *device_name; 30410Sstevel@tonic-gate mdname_t *namep; 30420Sstevel@tonic-gate mdkey_t key; 30430Sstevel@tonic-gate 30440Sstevel@tonic-gate /* short circuit metadevices */ 30450Sstevel@tonic-gate assert(dev != NODEV64); 30460Sstevel@tonic-gate if (meta_dev_ismeta(dev)) 30470Sstevel@tonic-gate return (metamnumname(spp, meta_getminor(dev), 0, ep)); 30480Sstevel@tonic-gate 30490Sstevel@tonic-gate /* create local set, if necessary */ 30500Sstevel@tonic-gate if (*spp == NULL) { 30510Sstevel@tonic-gate if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 30520Sstevel@tonic-gate return (NULL); 30530Sstevel@tonic-gate } 30540Sstevel@tonic-gate 30550Sstevel@tonic-gate /* get name from namespace */ 30560Sstevel@tonic-gate if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD, 30570Sstevel@tonic-gate dev, NULL, NULL, &key, ep)) == NULL) { 30580Sstevel@tonic-gate return (NULL); 30590Sstevel@tonic-gate } 30600Sstevel@tonic-gate namep = metaname_fast(spp, device_name, ep); 30610Sstevel@tonic-gate if (namep != NULL) 30620Sstevel@tonic-gate namep->key = key; 30630Sstevel@tonic-gate 30640Sstevel@tonic-gate Free(device_name); 30650Sstevel@tonic-gate return (namep); 30660Sstevel@tonic-gate } 30670Sstevel@tonic-gate 30680Sstevel@tonic-gate /* 30690Sstevel@tonic-gate * return cached name from md_dev64_t 30700Sstevel@tonic-gate */ 30710Sstevel@tonic-gate static char * 30720Sstevel@tonic-gate metadevtocachename(md_dev64_t dev) 30730Sstevel@tonic-gate { 30740Sstevel@tonic-gate mddrivenamelist_t *dnlp; 30750Sstevel@tonic-gate 30760Sstevel@tonic-gate /* look in cache */ 30770Sstevel@tonic-gate for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) { 30780Sstevel@tonic-gate mddrivename_t *dnp = dnlp->drivenamep; 30790Sstevel@tonic-gate uint_t i; 30800Sstevel@tonic-gate 30810Sstevel@tonic-gate for (i = 0; (i < dnp->parts.parts_len); ++i) { 30820Sstevel@tonic-gate mdname_t *np = &dnp->parts.parts_val[i]; 30830Sstevel@tonic-gate 30840Sstevel@tonic-gate if (np->dev == dev) 30850Sstevel@tonic-gate return (np->cname); 30860Sstevel@tonic-gate } 30870Sstevel@tonic-gate } 30880Sstevel@tonic-gate 30890Sstevel@tonic-gate /* not found */ 30900Sstevel@tonic-gate return (NULL); 30910Sstevel@tonic-gate } 30920Sstevel@tonic-gate 30930Sstevel@tonic-gate /* 30940Sstevel@tonic-gate * Ask the driver for the name, which has been stored in the 30950Sstevel@tonic-gate * metadevice state database (on behalf of the utilities). 30960Sstevel@tonic-gate * (by devno) 30970Sstevel@tonic-gate */ 30980Sstevel@tonic-gate char * 30990Sstevel@tonic-gate get_devname( 31000Sstevel@tonic-gate set_t setno, 31010Sstevel@tonic-gate md_dev64_t dev) 31020Sstevel@tonic-gate { 31030Sstevel@tonic-gate mdsetname_t *sp; 31040Sstevel@tonic-gate mdname_t *np; 31050Sstevel@tonic-gate md_error_t status = mdnullerror; 31060Sstevel@tonic-gate 31070Sstevel@tonic-gate /* get name */ 31080Sstevel@tonic-gate if ((setno == MD_SET_BAD) || 31090Sstevel@tonic-gate ((sp = metasetnosetname(setno, &status)) == NULL) || 31100Sstevel@tonic-gate ((np = metadevname(&sp, dev, &status)) == NULL)) { 31110Sstevel@tonic-gate mdclrerror(&status); 31120Sstevel@tonic-gate return (metadevtocachename(dev)); 31130Sstevel@tonic-gate } 31140Sstevel@tonic-gate 31150Sstevel@tonic-gate /* return name */ 31160Sstevel@tonic-gate return (np->cname); 31170Sstevel@tonic-gate } 31180Sstevel@tonic-gate 31190Sstevel@tonic-gate /* 31200Sstevel@tonic-gate * get name from key 31210Sstevel@tonic-gate */ 31220Sstevel@tonic-gate mdname_t * 31230Sstevel@tonic-gate metakeyname( 31240Sstevel@tonic-gate mdsetname_t **spp, 31250Sstevel@tonic-gate mdkey_t key, 31260Sstevel@tonic-gate int fast, 31270Sstevel@tonic-gate md_error_t *ep 31280Sstevel@tonic-gate ) 31290Sstevel@tonic-gate { 31300Sstevel@tonic-gate char *device_name; 31310Sstevel@tonic-gate md_dev64_t dev = NODEV64; 31320Sstevel@tonic-gate mdname_t *namep; 31330Sstevel@tonic-gate 31340Sstevel@tonic-gate /* create local set, if necessary */ 31350Sstevel@tonic-gate if (*spp == NULL) { 31360Sstevel@tonic-gate if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 31370Sstevel@tonic-gate return (NULL); 31380Sstevel@tonic-gate } 31390Sstevel@tonic-gate 31400Sstevel@tonic-gate /* get name from namespace */ 31410Sstevel@tonic-gate if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD, 31420Sstevel@tonic-gate key, NULL, NULL, &dev, ep)) == NULL) { 31430Sstevel@tonic-gate return (NULL); 31440Sstevel@tonic-gate } 31450Sstevel@tonic-gate if (fast) 31460Sstevel@tonic-gate namep = metaname_fast(spp, device_name, ep); 31470Sstevel@tonic-gate else 31480Sstevel@tonic-gate namep = metaname(spp, device_name, ep); 31490Sstevel@tonic-gate 31500Sstevel@tonic-gate assert(dev != NODEV64); 31510Sstevel@tonic-gate if (namep) 31520Sstevel@tonic-gate namep->dev = dev; 31530Sstevel@tonic-gate Free(device_name); 31540Sstevel@tonic-gate return (namep); 31550Sstevel@tonic-gate } 31560Sstevel@tonic-gate 31570Sstevel@tonic-gate /* 31580Sstevel@tonic-gate * completely flush the caches 31590Sstevel@tonic-gate */ 31600Sstevel@tonic-gate void 31610Sstevel@tonic-gate metaflushnames(int flush_sr_cache) 31620Sstevel@tonic-gate { 31630Sstevel@tonic-gate metaflushhspnames(); 31640Sstevel@tonic-gate metaflushdrivenames(); 31650Sstevel@tonic-gate metaflushsetnames(); 31660Sstevel@tonic-gate metaflushctlrcache(); 31670Sstevel@tonic-gate metaflushfastnames(); 31680Sstevel@tonic-gate metaflushstatcache(); 31690Sstevel@tonic-gate if (flush_sr_cache) 31700Sstevel@tonic-gate sr_cache_flush(0); 31710Sstevel@tonic-gate } 31720Sstevel@tonic-gate 31730Sstevel@tonic-gate /* 31740Sstevel@tonic-gate * meta_get_hotspare_names 31750Sstevel@tonic-gate * returns an mdnamelist_t of hot spare names 31760Sstevel@tonic-gate */ 31770Sstevel@tonic-gate 31780Sstevel@tonic-gate int 31790Sstevel@tonic-gate meta_get_hotspare_names( 31800Sstevel@tonic-gate mdsetname_t *sp, 31810Sstevel@tonic-gate mdnamelist_t **nlpp, 31820Sstevel@tonic-gate int options, 31830Sstevel@tonic-gate md_error_t *ep 31840Sstevel@tonic-gate ) 31850Sstevel@tonic-gate { 31860Sstevel@tonic-gate mdhspnamelist_t *hspnlp = NULL; 31870Sstevel@tonic-gate mdhspnamelist_t *hspp; 31880Sstevel@tonic-gate int cnt = 0; 31890Sstevel@tonic-gate 31900Sstevel@tonic-gate assert(nlpp != NULL); 31910Sstevel@tonic-gate 31920Sstevel@tonic-gate /* get hotspare names */ 31930Sstevel@tonic-gate if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) { 31940Sstevel@tonic-gate cnt = -1; 31950Sstevel@tonic-gate goto out; 31960Sstevel@tonic-gate } 31970Sstevel@tonic-gate 31980Sstevel@tonic-gate /* build name list */ 31990Sstevel@tonic-gate for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) { 32000Sstevel@tonic-gate md_hsp_t *hsp; 32010Sstevel@tonic-gate int i; 32020Sstevel@tonic-gate 32030Sstevel@tonic-gate if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) { 32040Sstevel@tonic-gate cnt = -1; 32050Sstevel@tonic-gate goto out; 32060Sstevel@tonic-gate } 32070Sstevel@tonic-gate for (i = 0; (i < hsp->hotspares.hotspares_len); i++) { 32080Sstevel@tonic-gate md_hs_t *hs = &hsp->hotspares.hotspares_val[i]; 32090Sstevel@tonic-gate 32100Sstevel@tonic-gate (void) metanamelist_append(nlpp, hs->hsnamep); 32110Sstevel@tonic-gate ++cnt; 32120Sstevel@tonic-gate } 32130Sstevel@tonic-gate } 32140Sstevel@tonic-gate 32150Sstevel@tonic-gate /* cleanup and return count or error */ 32160Sstevel@tonic-gate out: 32170Sstevel@tonic-gate metafreehspnamelist(hspnlp); 32180Sstevel@tonic-gate if ((cnt == -1) && mdisok(ep)) { 32190Sstevel@tonic-gate /* 32200Sstevel@tonic-gate * At least try to give some sort of meaningful error 32210Sstevel@tonic-gate */ 32220Sstevel@tonic-gate (void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error"); 32230Sstevel@tonic-gate } 32240Sstevel@tonic-gate 32250Sstevel@tonic-gate return (cnt); 32260Sstevel@tonic-gate } 32270Sstevel@tonic-gate /* 32280Sstevel@tonic-gate * meta_create_non_dup_list 32290Sstevel@tonic-gate * INPUT: mdnp mdname_t pointer to add to the list if a new name 32300Sstevel@tonic-gate * ldevidp list of non-duplicate names. 32310Sstevel@tonic-gate * OUTPUT: ldevidp list of non-duplicate names. 32320Sstevel@tonic-gate * meta_create_non_dup_list will take a mdname_t pointer and if the device 32330Sstevel@tonic-gate * is not in the list (ldevidp) will add it to the list. 32340Sstevel@tonic-gate * User needs to free allocated memory. 32350Sstevel@tonic-gate */ 32360Sstevel@tonic-gate void 32370Sstevel@tonic-gate meta_create_non_dup_list( 32380Sstevel@tonic-gate mdname_t *mdnp, 32390Sstevel@tonic-gate mddevid_t **ldevidpp 32400Sstevel@tonic-gate ) 32410Sstevel@tonic-gate { 32420Sstevel@tonic-gate char *lcname; 32430Sstevel@tonic-gate mddevid_t *tmp; 32440Sstevel@tonic-gate mddevid_t *lastdevidp; 32450Sstevel@tonic-gate mddevid_t *lldevidp; 32460Sstevel@tonic-gate char *ctd, *slice; 32470Sstevel@tonic-gate mddevid_t *ldevidp; 32480Sstevel@tonic-gate 32490Sstevel@tonic-gate if (mdnp == NULL) 32500Sstevel@tonic-gate return; 32510Sstevel@tonic-gate 32520Sstevel@tonic-gate ldevidp = *ldevidpp; 32530Sstevel@tonic-gate /* 32540Sstevel@tonic-gate * Grab the name of the device and strip off slice information 32550Sstevel@tonic-gate */ 32560Sstevel@tonic-gate lcname = Strdup(mdnp->cname); 32570Sstevel@tonic-gate if (lcname == NULL) { 32580Sstevel@tonic-gate return; 32590Sstevel@tonic-gate } 32600Sstevel@tonic-gate ctd = strrchr(lcname, '/'); 32610Sstevel@tonic-gate if (ctd != NULL) 32620Sstevel@tonic-gate slice = strrchr(ctd, 's'); 32630Sstevel@tonic-gate else 32640Sstevel@tonic-gate slice = strrchr(lcname, 's'); 32650Sstevel@tonic-gate 32660Sstevel@tonic-gate if (slice != NULL) 32670Sstevel@tonic-gate *slice = '\0'; 32680Sstevel@tonic-gate 32690Sstevel@tonic-gate if (ldevidp == NULL) { 32700Sstevel@tonic-gate /* first item in list */ 32710Sstevel@tonic-gate ldevidp = Zalloc(sizeof (mddevid_t)); 32720Sstevel@tonic-gate ldevidp->ctdname = lcname; 32730Sstevel@tonic-gate ldevidp->key = mdnp->key; 32740Sstevel@tonic-gate *ldevidpp = ldevidp; 32750Sstevel@tonic-gate } else { 32760Sstevel@tonic-gate for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) { 32770Sstevel@tonic-gate if (strcmp(tmp->ctdname, lcname) == 0) { 32780Sstevel@tonic-gate /* already there so just return */ 32790Sstevel@tonic-gate Free(lcname); 32800Sstevel@tonic-gate return; 32810Sstevel@tonic-gate } 32820Sstevel@tonic-gate lastdevidp = tmp; 32830Sstevel@tonic-gate } 32840Sstevel@tonic-gate lldevidp = Zalloc(sizeof (mddevid_t)); 32850Sstevel@tonic-gate lldevidp->ctdname = lcname; 32860Sstevel@tonic-gate lldevidp->key = mdnp->key; 32870Sstevel@tonic-gate lastdevidp->next = lldevidp; 32880Sstevel@tonic-gate } 32890Sstevel@tonic-gate } 3290