1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <dlfcn.h> 30*0Sstevel@tonic-gate #include <meta.h> 31*0Sstevel@tonic-gate #include <metadyn.h> 32*0Sstevel@tonic-gate #include <ctype.h> 33*0Sstevel@tonic-gate #include <dirent.h> 34*0Sstevel@tonic-gate #include <devid.h> 35*0Sstevel@tonic-gate #include <sys/param.h> 36*0Sstevel@tonic-gate #include <sys/scsi/impl/uscsi.h> 37*0Sstevel@tonic-gate #include <sys/scsi/generic/commands.h> 38*0Sstevel@tonic-gate #include <sys/scsi/generic/inquiry.h> 39*0Sstevel@tonic-gate #include <sys/efi_partition.h> 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #define MD_EFI_FG_HEADS 128 42*0Sstevel@tonic-gate #define MD_EFI_FG_SECTORS 256 43*0Sstevel@tonic-gate #define MD_EFI_FG_RPM 7200 44*0Sstevel@tonic-gate #define MD_EFI_FG_WRI 1 45*0Sstevel@tonic-gate #define MD_EFI_FG_RRI 1 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate typedef struct ctlr_cache { 49*0Sstevel@tonic-gate char *ctlr_nm; 50*0Sstevel@tonic-gate int ctlr_ty; 51*0Sstevel@tonic-gate struct ctlr_cache *ctlr_nx; 52*0Sstevel@tonic-gate } ctlr_cache_t; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate static ctlr_cache_t *ctlr_cache = NULL; 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate /* 58*0Sstevel@tonic-gate * return set for a device 59*0Sstevel@tonic-gate */ 60*0Sstevel@tonic-gate mdsetname_t * 61*0Sstevel@tonic-gate metagetset( 62*0Sstevel@tonic-gate mdname_t *np, 63*0Sstevel@tonic-gate int bypass_daemon, 64*0Sstevel@tonic-gate md_error_t *ep 65*0Sstevel@tonic-gate ) 66*0Sstevel@tonic-gate { 67*0Sstevel@tonic-gate mdsetname_t *sp; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* metadevice */ 70*0Sstevel@tonic-gate if (metaismeta(np)) 71*0Sstevel@tonic-gate return (metasetnosetname(MD_MIN2SET(meta_getminor(np->dev)), 72*0Sstevel@tonic-gate ep)); 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate /* regular device */ 75*0Sstevel@tonic-gate if (meta_is_drive_in_anyset(np->drivenamep, &sp, bypass_daemon, 76*0Sstevel@tonic-gate ep) != 0) 77*0Sstevel@tonic-gate return (NULL); 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate if (sp != NULL) 80*0Sstevel@tonic-gate return (sp); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate return (metasetnosetname(MD_LOCAL_SET, ep)); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * convert system to md types 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate static void 89*0Sstevel@tonic-gate meta_geom_to_md( 90*0Sstevel@tonic-gate struct dk_geom *gp, 91*0Sstevel@tonic-gate mdgeom_t *mdgp 92*0Sstevel@tonic-gate ) 93*0Sstevel@tonic-gate { 94*0Sstevel@tonic-gate (void) memset(mdgp, '\0', sizeof (*mdgp)); 95*0Sstevel@tonic-gate mdgp->ncyl = gp->dkg_ncyl; 96*0Sstevel@tonic-gate mdgp->nhead = gp->dkg_nhead; 97*0Sstevel@tonic-gate mdgp->nsect = gp->dkg_nsect; 98*0Sstevel@tonic-gate mdgp->rpm = gp->dkg_rpm; 99*0Sstevel@tonic-gate mdgp->write_reinstruct = gp->dkg_write_reinstruct; 100*0Sstevel@tonic-gate mdgp->read_reinstruct = gp->dkg_read_reinstruct; 101*0Sstevel@tonic-gate mdgp->blk_sz = DEV_BSIZE; 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate /* 105*0Sstevel@tonic-gate * convert efi to md types 106*0Sstevel@tonic-gate */ 107*0Sstevel@tonic-gate static void 108*0Sstevel@tonic-gate meta_efi_to_mdgeom(struct dk_gpt *gpt, mdgeom_t *mdgp) 109*0Sstevel@tonic-gate { 110*0Sstevel@tonic-gate (void) memset(mdgp, '\0', sizeof (*mdgp)); 111*0Sstevel@tonic-gate mdgp->ncyl = (gpt->efi_last_u_lba - gpt->efi_first_u_lba) / 112*0Sstevel@tonic-gate (MD_EFI_FG_HEADS * MD_EFI_FG_SECTORS); 113*0Sstevel@tonic-gate mdgp->nhead = MD_EFI_FG_HEADS; 114*0Sstevel@tonic-gate mdgp->nsect = MD_EFI_FG_SECTORS; 115*0Sstevel@tonic-gate mdgp->rpm = MD_EFI_FG_RPM; 116*0Sstevel@tonic-gate mdgp->write_reinstruct = MD_EFI_FG_WRI; 117*0Sstevel@tonic-gate mdgp->read_reinstruct = MD_EFI_FG_RRI; 118*0Sstevel@tonic-gate mdgp->blk_sz = DEV_BSIZE; 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate static void 122*0Sstevel@tonic-gate meta_efi_to_mdvtoc(struct dk_gpt *gpt, mdvtoc_t *mdvp) 123*0Sstevel@tonic-gate { 124*0Sstevel@tonic-gate char typename[EFI_PART_NAME_LEN]; 125*0Sstevel@tonic-gate uint_t i; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate (void) memset(mdvp, '\0', sizeof (*mdvp)); 128*0Sstevel@tonic-gate mdvp->nparts = gpt->efi_nparts; 129*0Sstevel@tonic-gate if (mdvp->nparts > MD_MAX_PARTS) 130*0Sstevel@tonic-gate return; 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate mdvp->first_lba = gpt->efi_first_u_lba; 133*0Sstevel@tonic-gate mdvp->last_lba = gpt->efi_last_u_lba; 134*0Sstevel@tonic-gate mdvp->lbasize = gpt->efi_lbasize; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate for (i = 0; (i < gpt->efi_nparts); ++i) { 137*0Sstevel@tonic-gate mdvp->parts[i].start = gpt->efi_parts[i].p_start; 138*0Sstevel@tonic-gate mdvp->parts[i].size = gpt->efi_parts[i].p_size; 139*0Sstevel@tonic-gate mdvp->parts[i].tag = gpt->efi_parts[i].p_tag; 140*0Sstevel@tonic-gate mdvp->parts[i].flag = gpt->efi_parts[i].p_flag; 141*0Sstevel@tonic-gate /* 142*0Sstevel@tonic-gate * Due to the lack of a label for the entire partition table, 143*0Sstevel@tonic-gate * we use p_name of the reserved partition 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate if ((gpt->efi_parts[i].p_tag == V_RESERVED) && 146*0Sstevel@tonic-gate (gpt->efi_parts[i].p_name != NULL)) { 147*0Sstevel@tonic-gate (void) strlcpy(typename, gpt->efi_parts[i].p_name, 148*0Sstevel@tonic-gate EFI_PART_NAME_LEN); 149*0Sstevel@tonic-gate /* Stop at first (if any) space or tab */ 150*0Sstevel@tonic-gate (void) strtok(typename, " \t"); 151*0Sstevel@tonic-gate mdvp->typename = Strdup(typename); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate static void 157*0Sstevel@tonic-gate meta_mdvtoc_to_efi(mdvtoc_t *mdvp, struct dk_gpt **gpt) 158*0Sstevel@tonic-gate { 159*0Sstevel@tonic-gate char typename[EFI_PART_NAME_LEN]; 160*0Sstevel@tonic-gate uint_t i; 161*0Sstevel@tonic-gate uint_t lastpart; 162*0Sstevel@tonic-gate size_t size; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate /* first we count how many partitions we have to send */ 165*0Sstevel@tonic-gate for (i = 0; i < MD_MAX_PARTS; i++) { 166*0Sstevel@tonic-gate if ((mdvp->parts[i].start == 0) && 167*0Sstevel@tonic-gate (mdvp->parts[i].size == 0) && 168*0Sstevel@tonic-gate (mdvp->parts[i].tag != V_RESERVED)) { 169*0Sstevel@tonic-gate continue; 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate /* if we are here, we know the partition is really used */ 172*0Sstevel@tonic-gate lastpart = i; 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate size = sizeof (struct dk_gpt) + (sizeof (struct dk_part) * lastpart); 175*0Sstevel@tonic-gate *gpt = calloc(size, sizeof (char)); 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate (*gpt)->efi_nparts = lastpart + 1; 178*0Sstevel@tonic-gate (*gpt)->efi_first_u_lba = mdvp->first_lba; 179*0Sstevel@tonic-gate (*gpt)->efi_last_u_lba = mdvp->last_lba; 180*0Sstevel@tonic-gate (*gpt)->efi_lbasize = mdvp->lbasize; 181*0Sstevel@tonic-gate for (i = 0; (i < (*gpt)->efi_nparts); ++i) { 182*0Sstevel@tonic-gate (*gpt)->efi_parts[i].p_start = mdvp->parts[i].start; 183*0Sstevel@tonic-gate (*gpt)->efi_parts[i].p_size = mdvp->parts[i].size; 184*0Sstevel@tonic-gate (*gpt)->efi_parts[i].p_tag = mdvp->parts[i].tag; 185*0Sstevel@tonic-gate (*gpt)->efi_parts[i].p_flag = mdvp->parts[i].flag; 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * Due to the lack of a label for the entire partition table, 188*0Sstevel@tonic-gate * we use p_name of the reserved partition 189*0Sstevel@tonic-gate */ 190*0Sstevel@tonic-gate if (((*gpt)->efi_parts[i].p_tag == V_RESERVED) && 191*0Sstevel@tonic-gate (mdvp->typename != NULL)) { 192*0Sstevel@tonic-gate (void) strlcpy((*gpt)->efi_parts[i].p_name, typename, 193*0Sstevel@tonic-gate EFI_PART_NAME_LEN); 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate void 200*0Sstevel@tonic-gate ctlr_cache_add(char *nm, int ty) 201*0Sstevel@tonic-gate { 202*0Sstevel@tonic-gate ctlr_cache_t **ccpp; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate for (ccpp = &ctlr_cache; *ccpp != NULL; ccpp = &(*ccpp)->ctlr_nx) 205*0Sstevel@tonic-gate if (strcmp((*ccpp)->ctlr_nm, nm) == 0) 206*0Sstevel@tonic-gate return; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate *ccpp = Zalloc(sizeof (ctlr_cache_t)); 209*0Sstevel@tonic-gate (*ccpp)->ctlr_nm = Strdup(nm); 210*0Sstevel@tonic-gate (*ccpp)->ctlr_ty = ty; 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate int 214*0Sstevel@tonic-gate ctlr_cache_look(char *nm) 215*0Sstevel@tonic-gate { 216*0Sstevel@tonic-gate ctlr_cache_t *tcp; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate for (tcp = ctlr_cache; tcp != NULL; tcp = tcp->ctlr_nx) 219*0Sstevel@tonic-gate if (strcmp(tcp->ctlr_nm, nm) == 0) 220*0Sstevel@tonic-gate return (tcp->ctlr_ty); 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate return (-1); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate void 227*0Sstevel@tonic-gate metaflushctlrcache(void) 228*0Sstevel@tonic-gate { 229*0Sstevel@tonic-gate ctlr_cache_t *cp, *np; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate for (cp = ctlr_cache, np = NULL; cp != NULL; cp = np) { 232*0Sstevel@tonic-gate np = cp->ctlr_nx; 233*0Sstevel@tonic-gate Free(cp->ctlr_nm); 234*0Sstevel@tonic-gate Free(cp); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate ctlr_cache = NULL; 237*0Sstevel@tonic-gate } 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate /* 240*0Sstevel@tonic-gate * getdrvnode -- return the driver name based on mdname_t->bname 241*0Sstevel@tonic-gate * Need to free pointer when finished. 242*0Sstevel@tonic-gate */ 243*0Sstevel@tonic-gate char * 244*0Sstevel@tonic-gate getdrvnode(mdname_t *np, md_error_t *ep) 245*0Sstevel@tonic-gate { 246*0Sstevel@tonic-gate char *devicespath, 247*0Sstevel@tonic-gate *drvnode, 248*0Sstevel@tonic-gate *cp; 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate if ((devicespath = metagetdevicesname(np, ep)) == NULL) 251*0Sstevel@tonic-gate return (NULL); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * At this point devicespath should be like the following 255*0Sstevel@tonic-gate * "/devices/<unknow_and_dont_care>/xxxx@vvvv" 256*0Sstevel@tonic-gate * 257*0Sstevel@tonic-gate * There's a couple of 'if' statements below which could 258*0Sstevel@tonic-gate * return an error condition, but I've decide to allow 259*0Sstevel@tonic-gate * a more open approach regarding the mapping so as to 260*0Sstevel@tonic-gate * not restrict possible future projects. 261*0Sstevel@tonic-gate */ 262*0Sstevel@tonic-gate if (drvnode = strrchr(devicespath, '/')) 263*0Sstevel@tonic-gate /* 264*0Sstevel@tonic-gate * drvnode now just "xxxx@vvvv" 265*0Sstevel@tonic-gate */ 266*0Sstevel@tonic-gate drvnode++; 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate if (cp = strrchr(drvnode, '@')) 269*0Sstevel@tonic-gate /* 270*0Sstevel@tonic-gate * Now drvnode is just the driver name "xxxx" 271*0Sstevel@tonic-gate */ 272*0Sstevel@tonic-gate *cp = '\0'; 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate cp = Strdup(drvnode); 275*0Sstevel@tonic-gate Free(devicespath); 276*0Sstevel@tonic-gate np->devicesname = NULL; 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate return (cp); 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate /* 282*0Sstevel@tonic-gate * meta_load_dl -- open dynamic library using LDLIBRARYPATH, a debug 283*0Sstevel@tonic-gate * environment variable METALDPATH, or the default location. 284*0Sstevel@tonic-gate */ 285*0Sstevel@tonic-gate static void * 286*0Sstevel@tonic-gate meta_load_dl(mdname_t *np, md_error_t *ep) 287*0Sstevel@tonic-gate { 288*0Sstevel@tonic-gate char *drvnode, 289*0Sstevel@tonic-gate newpath[MAXPATHLEN], 290*0Sstevel@tonic-gate *p; 291*0Sstevel@tonic-gate void *cookie; 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate if ((drvnode = getdrvnode(np, ep)) != NULL) { 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate /* 296*0Sstevel@tonic-gate * Library seach algorithm: 297*0Sstevel@tonic-gate * 1) Use LDLIBRARYPATH which is implied when a non-absolute 298*0Sstevel@tonic-gate * path name is passed to dlopen() 299*0Sstevel@tonic-gate * 2) Use the value of METALDPATH as the directory. Mainly 300*0Sstevel@tonic-gate * used for debugging 301*0Sstevel@tonic-gate * 3) Last search the default location of "/usr/lib" 302*0Sstevel@tonic-gate */ 303*0Sstevel@tonic-gate (void) snprintf(newpath, sizeof (newpath), "lib%s.so.1", 304*0Sstevel@tonic-gate drvnode); 305*0Sstevel@tonic-gate if ((cookie = dlopen(newpath, RTLD_LAZY)) == NULL) { 306*0Sstevel@tonic-gate if ((p = getenv("METALDPATH")) == NULL) 307*0Sstevel@tonic-gate p = METALDPATH_DEFAULT; 308*0Sstevel@tonic-gate (void) snprintf(newpath, sizeof (newpath), 309*0Sstevel@tonic-gate "%s/lib%s.so.1", p, drvnode); 310*0Sstevel@tonic-gate Free(drvnode); 311*0Sstevel@tonic-gate if ((cookie = dlopen(newpath, RTLD_LAZY)) != NULL) { 312*0Sstevel@tonic-gate /* 313*0Sstevel@tonic-gate * Common failure here would be failing to 314*0Sstevel@tonic-gate * find a libXX.so.1 such as libsd.so.1 315*0Sstevel@tonic-gate * Some controllers will not have a library 316*0Sstevel@tonic-gate * because there's no enclosure or name 317*0Sstevel@tonic-gate * translation required. 318*0Sstevel@tonic-gate */ 319*0Sstevel@tonic-gate return (cookie); 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate } else { 322*0Sstevel@tonic-gate Free(drvnode); 323*0Sstevel@tonic-gate return (cookie); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate return (NULL); 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate /* 330*0Sstevel@tonic-gate * meta_match_names -- possibly convert the driver names returned by CINFO 331*0Sstevel@tonic-gate */ 332*0Sstevel@tonic-gate static void 333*0Sstevel@tonic-gate meta_match_names(mdname_t *np, struct dk_cinfo *cp, mdcinfo_t *mdcp, 334*0Sstevel@tonic-gate md_error_t *ep) 335*0Sstevel@tonic-gate { 336*0Sstevel@tonic-gate void *cookie; 337*0Sstevel@tonic-gate meta_convert_e ((*fptr)(mdname_t *, struct dk_cinfo *, mdcinfo_t *, 338*0Sstevel@tonic-gate md_error_t *)); 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate if ((cookie = meta_load_dl(np, ep)) != NULL) { 341*0Sstevel@tonic-gate fptr = (meta_convert_e (*)(mdname_t *, struct dk_cinfo *, 342*0Sstevel@tonic-gate mdcinfo_t *, md_error_t *))dlsym(cookie, "convert_path"); 343*0Sstevel@tonic-gate if (fptr != NULL) 344*0Sstevel@tonic-gate (void) (*fptr)(np, cp, mdcp, ep); 345*0Sstevel@tonic-gate (void) dlclose(cookie); 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate /* 350*0Sstevel@tonic-gate * meta_match_enclosure -- return any enclosure info if found 351*0Sstevel@tonic-gate */ 352*0Sstevel@tonic-gate int 353*0Sstevel@tonic-gate meta_match_enclosure(mdname_t *np, mdcinfo_t *mdcp, md_error_t *ep) 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate meta_enclosure_e e, 356*0Sstevel@tonic-gate ((*fptr)(mdname_t *, mdcinfo_t *, 357*0Sstevel@tonic-gate md_error_t *)); 358*0Sstevel@tonic-gate void *cookie; 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate if ((cookie = meta_load_dl(np, ep)) != NULL) { 361*0Sstevel@tonic-gate fptr = (meta_enclosure_e (*)(mdname_t *, mdcinfo_t *, 362*0Sstevel@tonic-gate md_error_t *))dlsym(cookie, "get_enclosure"); 363*0Sstevel@tonic-gate if (fptr != NULL) { 364*0Sstevel@tonic-gate e = (*fptr)(np, mdcp, ep); 365*0Sstevel@tonic-gate switch (e) { 366*0Sstevel@tonic-gate case Enclosure_Error: 367*0Sstevel@tonic-gate /* 368*0Sstevel@tonic-gate * Looks like this library wanted to handle 369*0Sstevel@tonic-gate * our device and had an internal error. 370*0Sstevel@tonic-gate */ 371*0Sstevel@tonic-gate return (1); 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate case Enclosure_Okay: 374*0Sstevel@tonic-gate /* 375*0Sstevel@tonic-gate * Found a library to handle the request so 376*0Sstevel@tonic-gate * just return with data provided. 377*0Sstevel@tonic-gate */ 378*0Sstevel@tonic-gate return (0); 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate case Enclosure_Noop: 381*0Sstevel@tonic-gate /* 382*0Sstevel@tonic-gate * Need to continue the search 383*0Sstevel@tonic-gate */ 384*0Sstevel@tonic-gate break; 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate (void) dlclose(cookie); 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate return (0); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate static int 393*0Sstevel@tonic-gate meta_cinfo_to_md(mdname_t *np, struct dk_cinfo *cp, mdcinfo_t *mdcp, 394*0Sstevel@tonic-gate md_error_t *ep) 395*0Sstevel@tonic-gate { 396*0Sstevel@tonic-gate /* default */ 397*0Sstevel@tonic-gate (void) memset(mdcp, '\0', sizeof (*mdcp)); 398*0Sstevel@tonic-gate (void) strncpy(mdcp->cname, cp->dki_cname, 399*0Sstevel@tonic-gate min((sizeof (mdcp->cname) - 1), sizeof (cp->dki_cname))); 400*0Sstevel@tonic-gate mdcp->ctype = MHD_CTLR_GENERIC; 401*0Sstevel@tonic-gate mdcp->cnum = cp->dki_cnum; 402*0Sstevel@tonic-gate (void) strncpy(mdcp->dname, cp->dki_dname, 403*0Sstevel@tonic-gate min((sizeof (mdcp->dname) - 1), sizeof (cp->dki_dname))); 404*0Sstevel@tonic-gate mdcp->unit = cp->dki_unit; 405*0Sstevel@tonic-gate mdcp->maxtransfer = cp->dki_maxtransfer; 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate /* 408*0Sstevel@tonic-gate * See if the driver name returned from DKIOCINFO 409*0Sstevel@tonic-gate * is valid or not. In somecases, such as the ap_dmd 410*0Sstevel@tonic-gate * driver, we need to modify the name that's return 411*0Sstevel@tonic-gate * for everything to work. 412*0Sstevel@tonic-gate */ 413*0Sstevel@tonic-gate meta_match_names(np, cp, mdcp, ep); 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate if (meta_match_enclosure(np, mdcp, ep)) 416*0Sstevel@tonic-gate return (-1); 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate /* return success */ 419*0Sstevel@tonic-gate return (0); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate static void 423*0Sstevel@tonic-gate meta_vtoc_to_md( 424*0Sstevel@tonic-gate struct vtoc *vp, 425*0Sstevel@tonic-gate mdvtoc_t *mdvp 426*0Sstevel@tonic-gate ) 427*0Sstevel@tonic-gate { 428*0Sstevel@tonic-gate char typename[sizeof (vp->v_asciilabel) + 1]; 429*0Sstevel@tonic-gate uint_t i; 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate (void) memset(mdvp, '\0', sizeof (*mdvp)); 432*0Sstevel@tonic-gate (void) strncpy(typename, vp->v_asciilabel, 433*0Sstevel@tonic-gate sizeof (vp->v_asciilabel)); 434*0Sstevel@tonic-gate typename[sizeof (typename) - 1] = '\0'; 435*0Sstevel@tonic-gate for (i = 0; ((i < sizeof (typename)) && (typename[i] != '\0')); ++i) { 436*0Sstevel@tonic-gate if ((typename[i] == ' ') || (typename[i] == '\t')) { 437*0Sstevel@tonic-gate typename[i] = '\0'; 438*0Sstevel@tonic-gate break; 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate } 441*0Sstevel@tonic-gate mdvp->typename = Strdup(typename); 442*0Sstevel@tonic-gate mdvp->nparts = vp->v_nparts; 443*0Sstevel@tonic-gate for (i = 0; (i < vp->v_nparts); ++i) { 444*0Sstevel@tonic-gate mdvp->parts[i].start = vp->v_part[i].p_start; 445*0Sstevel@tonic-gate mdvp->parts[i].size = vp->v_part[i].p_size; 446*0Sstevel@tonic-gate mdvp->parts[i].tag = vp->v_part[i].p_tag; 447*0Sstevel@tonic-gate mdvp->parts[i].flag = vp->v_part[i].p_flag; 448*0Sstevel@tonic-gate if (vp->v_part[i].p_start == 0 && vp->v_part[i].p_size > 0) 449*0Sstevel@tonic-gate mdvp->parts[i].label = btodb(DK_LABEL_SIZE); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate /* 454*0Sstevel@tonic-gate * free allocations in vtoc 455*0Sstevel@tonic-gate */ 456*0Sstevel@tonic-gate void 457*0Sstevel@tonic-gate metafreevtoc( 458*0Sstevel@tonic-gate mdvtoc_t *vtocp 459*0Sstevel@tonic-gate ) 460*0Sstevel@tonic-gate { 461*0Sstevel@tonic-gate if (vtocp->typename != NULL) 462*0Sstevel@tonic-gate Free(vtocp->typename); 463*0Sstevel@tonic-gate (void) memset(vtocp, 0, sizeof (*vtocp)); 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate /* 467*0Sstevel@tonic-gate * return md types 468*0Sstevel@tonic-gate */ 469*0Sstevel@tonic-gate mdvtoc_t * 470*0Sstevel@tonic-gate metagetvtoc( 471*0Sstevel@tonic-gate mdname_t *np, /* only rname, drivenamep, are setup */ 472*0Sstevel@tonic-gate int nocache, 473*0Sstevel@tonic-gate uint_t *partnop, 474*0Sstevel@tonic-gate md_error_t *ep 475*0Sstevel@tonic-gate ) 476*0Sstevel@tonic-gate { 477*0Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep; 478*0Sstevel@tonic-gate struct dk_geom geom; 479*0Sstevel@tonic-gate char *minor_name = NULL; 480*0Sstevel@tonic-gate char *rname = np->rname; 481*0Sstevel@tonic-gate int fd; 482*0Sstevel@tonic-gate int partno; 483*0Sstevel@tonic-gate int err = 0; /* saves errno from ioctl */ 484*0Sstevel@tonic-gate ddi_devid_t devid; 485*0Sstevel@tonic-gate char *p; 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate /* short circuit */ 488*0Sstevel@tonic-gate if ((! nocache) && (dnp->vtoc.nparts != 0)) { 489*0Sstevel@tonic-gate if (partnop != NULL) { 490*0Sstevel@tonic-gate /* 491*0Sstevel@tonic-gate * the following assigment works because the 492*0Sstevel@tonic-gate * mdname_t structs are always created as part 493*0Sstevel@tonic-gate * of the drivenamep struct. When a user 494*0Sstevel@tonic-gate * creates an mdname_t struct it either 495*0Sstevel@tonic-gate * uses an existing drivenamep struct or creates 496*0Sstevel@tonic-gate * a new one and then adds the mdname_t struct 497*0Sstevel@tonic-gate * as part of its parts_val array. So what is 498*0Sstevel@tonic-gate * being computed below is the slice offset in 499*0Sstevel@tonic-gate * the parts_val array. 500*0Sstevel@tonic-gate */ 501*0Sstevel@tonic-gate *partnop = np - np->drivenamep->parts.parts_val; 502*0Sstevel@tonic-gate assert(*partnop < dnp->parts.parts_len); 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate return (&dnp->vtoc); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate /* can't get vtoc */ 508*0Sstevel@tonic-gate if (! nocache) { 509*0Sstevel@tonic-gate switch (dnp->type) { 510*0Sstevel@tonic-gate case MDT_ACCES: 511*0Sstevel@tonic-gate case MDT_UNKNOWN: 512*0Sstevel@tonic-gate (void) mdsyserror(ep, dnp->errnum, rname); 513*0Sstevel@tonic-gate return (NULL); 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* get all the info */ 518*0Sstevel@tonic-gate if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) { 519*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, rname); 520*0Sstevel@tonic-gate return (NULL); 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate /* 524*0Sstevel@tonic-gate * The disk is open so this is a good point to get the devid 525*0Sstevel@tonic-gate * otherwise it will need to be done at another time which 526*0Sstevel@tonic-gate * means reopening it. 527*0Sstevel@tonic-gate */ 528*0Sstevel@tonic-gate if (devid_get(fd, &devid) != 0) { 529*0Sstevel@tonic-gate /* there is no devid for the disk */ 530*0Sstevel@tonic-gate if (((p = getenv("MD_DEBUG")) != NULL) && 531*0Sstevel@tonic-gate (strstr(p, "DEVID") != NULL)) { 532*0Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 533*0Sstevel@tonic-gate "%s has no device id\n"), np->rname); 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate np->minor_name = (char *)NULL; 536*0Sstevel@tonic-gate dnp->devid = NULL; 537*0Sstevel@tonic-gate } else { 538*0Sstevel@tonic-gate (void) devid_get_minor_name(fd, &minor_name); 539*0Sstevel@tonic-gate /* 540*0Sstevel@tonic-gate * The minor name could be NULL if the underlying 541*0Sstevel@tonic-gate * device driver does not support 'minor names'. 542*0Sstevel@tonic-gate * This means we do not use devid's for this device. 543*0Sstevel@tonic-gate * SunCluster did driver does not support minor names. 544*0Sstevel@tonic-gate */ 545*0Sstevel@tonic-gate if (minor_name != NULL) { 546*0Sstevel@tonic-gate np->minor_name = Strdup(minor_name); 547*0Sstevel@tonic-gate devid_str_free(minor_name); 548*0Sstevel@tonic-gate dnp->devid = devid_str_encode(devid, NULL); 549*0Sstevel@tonic-gate } else { 550*0Sstevel@tonic-gate np->minor_name = (char *)NULL; 551*0Sstevel@tonic-gate dnp->devid = NULL; 552*0Sstevel@tonic-gate 553*0Sstevel@tonic-gate if (((p = getenv("MD_DEBUG")) != NULL) && 554*0Sstevel@tonic-gate (strstr(p, "DEVID") != NULL)) { 555*0Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 556*0Sstevel@tonic-gate "%s no minor name (no devid)\n"), 557*0Sstevel@tonic-gate np->rname); 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate devid_free(devid); 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate /* 564*0Sstevel@tonic-gate * if our drivenamep points to a device not supporting DKIOCGGEOM, 565*0Sstevel@tonic-gate * it's likely to have an EFI label. 566*0Sstevel@tonic-gate */ 567*0Sstevel@tonic-gate (void) memset(&geom, 0, sizeof (geom)); 568*0Sstevel@tonic-gate if (ioctl(fd, DKIOCGGEOM, &geom) != 0) { 569*0Sstevel@tonic-gate err = errno; 570*0Sstevel@tonic-gate if (err == ENOTTY) { 571*0Sstevel@tonic-gate (void) mddeverror(ep, MDE_NOT_DISK, NODEV, rname); 572*0Sstevel@tonic-gate (void) close(fd); 573*0Sstevel@tonic-gate return (NULL); 574*0Sstevel@tonic-gate } else if (err != ENOTSUP) { 575*0Sstevel@tonic-gate (void) mdsyserror(ep, err, rname); 576*0Sstevel@tonic-gate (void) close(fd); 577*0Sstevel@tonic-gate return (NULL); 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate } 581*0Sstevel@tonic-gate /* 582*0Sstevel@tonic-gate * If we are here, there was either no failure on DKIOCGGEOM or 583*0Sstevel@tonic-gate * the failure was ENOTSUP 584*0Sstevel@tonic-gate */ 585*0Sstevel@tonic-gate if (err == ENOTSUP) { 586*0Sstevel@tonic-gate /* DKIOCGGEOM yielded ENOTSUP => try efi_alloc_and_read */ 587*0Sstevel@tonic-gate struct dk_gpt *gpt; 588*0Sstevel@tonic-gate int save_errno; 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate /* this also sets errno */ 591*0Sstevel@tonic-gate partno = efi_alloc_and_read(fd, &gpt); 592*0Sstevel@tonic-gate save_errno = errno; 593*0Sstevel@tonic-gate (void) close(fd); 594*0Sstevel@tonic-gate if (partno < 0) { 595*0Sstevel@tonic-gate efi_free(gpt); 596*0Sstevel@tonic-gate (void) mdsyserror(ep, save_errno, rname); 597*0Sstevel@tonic-gate return (NULL); 598*0Sstevel@tonic-gate } 599*0Sstevel@tonic-gate if (partno >= gpt->efi_nparts) { 600*0Sstevel@tonic-gate efi_free(gpt); 601*0Sstevel@tonic-gate (void) mddeverror(ep, MDE_INVALID_PART, NODEV64, 602*0Sstevel@tonic-gate rname); 603*0Sstevel@tonic-gate return (NULL); 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate /* convert to our format */ 607*0Sstevel@tonic-gate metafreevtoc(&dnp->vtoc); 608*0Sstevel@tonic-gate meta_efi_to_mdvtoc(gpt, &dnp->vtoc); 609*0Sstevel@tonic-gate if (dnp->vtoc.nparts > MD_MAX_PARTS) { 610*0Sstevel@tonic-gate (void) mddeverror(ep, MDE_TOO_MANY_PARTS, NODEV64, 611*0Sstevel@tonic-gate rname); 612*0Sstevel@tonic-gate return (NULL); 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate /* 615*0Sstevel@tonic-gate * libmeta needs at least V_NUMPAR partitions. 616*0Sstevel@tonic-gate * If we have an EFI partition with less than V_NUMPAR slices, 617*0Sstevel@tonic-gate * we nevertheless reserve space for V_NUMPAR 618*0Sstevel@tonic-gate */ 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate if (dnp->vtoc.nparts < V_NUMPAR) { 621*0Sstevel@tonic-gate dnp->vtoc.nparts = V_NUMPAR; 622*0Sstevel@tonic-gate } 623*0Sstevel@tonic-gate meta_efi_to_mdgeom(gpt, &dnp->geom); 624*0Sstevel@tonic-gate efi_free(gpt); 625*0Sstevel@tonic-gate } else { 626*0Sstevel@tonic-gate /* no error on DKIOCGGEOM, try meta_getvtoc */ 627*0Sstevel@tonic-gate struct vtoc vtoc; 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate if (meta_getvtoc(fd, np->cname, &vtoc, &partno, ep) < 0) { 630*0Sstevel@tonic-gate (void) close(fd); 631*0Sstevel@tonic-gate return (NULL); 632*0Sstevel@tonic-gate } 633*0Sstevel@tonic-gate (void) close(fd); 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate /* convert to our format */ 636*0Sstevel@tonic-gate meta_geom_to_md(&geom, &dnp->geom); 637*0Sstevel@tonic-gate metafreevtoc(&dnp->vtoc); 638*0Sstevel@tonic-gate meta_vtoc_to_md(&vtoc, &dnp->vtoc); 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate /* fix up any drives which are now accessible */ 642*0Sstevel@tonic-gate if ((nocache) && (dnp->type == MDT_ACCES) && 643*0Sstevel@tonic-gate (dnp->vtoc.nparts == dnp->parts.parts_len)) { 644*0Sstevel@tonic-gate dnp->type = MDT_COMP; 645*0Sstevel@tonic-gate dnp->errnum = 0; 646*0Sstevel@tonic-gate } 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate /* save partno */ 649*0Sstevel@tonic-gate assert(partno < dnp->vtoc.nparts); 650*0Sstevel@tonic-gate if (partnop != NULL) 651*0Sstevel@tonic-gate *partnop = partno; 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate /* return info */ 654*0Sstevel@tonic-gate return (&dnp->vtoc); 655*0Sstevel@tonic-gate } 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate static void 658*0Sstevel@tonic-gate meta_mdvtoc_to_vtoc( 659*0Sstevel@tonic-gate mdvtoc_t *mdvp, 660*0Sstevel@tonic-gate struct vtoc *vp 661*0Sstevel@tonic-gate ) 662*0Sstevel@tonic-gate { 663*0Sstevel@tonic-gate uint_t i; 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate (void) memset(&vp->v_part, '\0', sizeof (vp->v_part)); 666*0Sstevel@tonic-gate vp->v_nparts = (ushort_t)mdvp->nparts; 667*0Sstevel@tonic-gate for (i = 0; (i < mdvp->nparts); ++i) { 668*0Sstevel@tonic-gate vp->v_part[i].p_start = (daddr32_t)mdvp->parts[i].start; 669*0Sstevel@tonic-gate vp->v_part[i].p_size = (daddr32_t)mdvp->parts[i].size; 670*0Sstevel@tonic-gate vp->v_part[i].p_tag = mdvp->parts[i].tag; 671*0Sstevel@tonic-gate vp->v_part[i].p_flag = mdvp->parts[i].flag; 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate } 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* 676*0Sstevel@tonic-gate * Set the vtoc, but use the cached copy to get the info from. 677*0Sstevel@tonic-gate * We write np->drivenamep->vtoc to disk. 678*0Sstevel@tonic-gate * Before we can do this we read the vtoc in. 679*0Sstevel@tonic-gate * if we're dealing with a metadevice and this metadevice is a 64 bit device 680*0Sstevel@tonic-gate * we can use meta_getmdvtoc/meta_setmdvtoc 681*0Sstevel@tonic-gate * else 682*0Sstevel@tonic-gate * we use meta_getvtoc/meta_setvtoc but than we first have to convert 683*0Sstevel@tonic-gate * dnp->vtoc (actually being a mdvtoc_t) into a vtoc_t 684*0Sstevel@tonic-gate */ 685*0Sstevel@tonic-gate int 686*0Sstevel@tonic-gate metasetvtoc( 687*0Sstevel@tonic-gate mdname_t *np, 688*0Sstevel@tonic-gate md_error_t *ep 689*0Sstevel@tonic-gate ) 690*0Sstevel@tonic-gate { 691*0Sstevel@tonic-gate char *rname = np->rname; 692*0Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep; 693*0Sstevel@tonic-gate int fd; 694*0Sstevel@tonic-gate int err; 695*0Sstevel@tonic-gate int save_errno; 696*0Sstevel@tonic-gate struct dk_geom geom; 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate if ((fd = open(rname, (O_RDONLY | O_NDELAY), 0)) < 0) 699*0Sstevel@tonic-gate return (mdsyserror(ep, errno, rname)); 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate err = ioctl(fd, DKIOCGGEOM, &geom); 702*0Sstevel@tonic-gate save_errno = errno; 703*0Sstevel@tonic-gate if (err == 0) { 704*0Sstevel@tonic-gate struct vtoc vtoc; 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate if (meta_getvtoc(fd, np->cname, &vtoc, NULL, ep) < 0) { 707*0Sstevel@tonic-gate (void) close(fd); 708*0Sstevel@tonic-gate return (-1); 709*0Sstevel@tonic-gate } 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate meta_mdvtoc_to_vtoc(&dnp->vtoc, &vtoc); 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate if (meta_setvtoc(fd, np->cname, &vtoc, ep) < 0) { 714*0Sstevel@tonic-gate (void) close(fd); 715*0Sstevel@tonic-gate return (-1); 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate } else if (save_errno == ENOTSUP) { 718*0Sstevel@tonic-gate struct dk_gpt *gpt; 719*0Sstevel@tonic-gate int ret; 720*0Sstevel@tonic-gate 721*0Sstevel@tonic-gate /* allocation of gpt is done in meta_mdvtoc_to_efi */ 722*0Sstevel@tonic-gate meta_mdvtoc_to_efi(&dnp->vtoc, &gpt); 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate ret = efi_write(fd, gpt); 725*0Sstevel@tonic-gate save_errno = errno; 726*0Sstevel@tonic-gate free(gpt); 727*0Sstevel@tonic-gate if (ret != 0) { 728*0Sstevel@tonic-gate (void) close(fd); 729*0Sstevel@tonic-gate return (mdsyserror(ep, save_errno, rname)); 730*0Sstevel@tonic-gate } else { 731*0Sstevel@tonic-gate (void) close(fd); 732*0Sstevel@tonic-gate return (0); 733*0Sstevel@tonic-gate } 734*0Sstevel@tonic-gate 735*0Sstevel@tonic-gate } else { 736*0Sstevel@tonic-gate (void) close(fd); 737*0Sstevel@tonic-gate return (mdsyserror(ep, save_errno, rname)); 738*0Sstevel@tonic-gate } 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate (void) close(fd); 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate return (0); 743*0Sstevel@tonic-gate } 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate mdgeom_t * 746*0Sstevel@tonic-gate metagetgeom( 747*0Sstevel@tonic-gate mdname_t *np, /* only rname, drivenamep, are setup */ 748*0Sstevel@tonic-gate md_error_t *ep 749*0Sstevel@tonic-gate ) 750*0Sstevel@tonic-gate { 751*0Sstevel@tonic-gate if (metagetvtoc(np, FALSE, NULL, ep) == NULL) 752*0Sstevel@tonic-gate return (NULL); 753*0Sstevel@tonic-gate return (&np->drivenamep->geom); 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate mdcinfo_t * 757*0Sstevel@tonic-gate metagetcinfo( 758*0Sstevel@tonic-gate mdname_t *np, /* only rname, drivenamep, are setup */ 759*0Sstevel@tonic-gate md_error_t *ep 760*0Sstevel@tonic-gate ) 761*0Sstevel@tonic-gate { 762*0Sstevel@tonic-gate char *rname = np->rname; 763*0Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep; 764*0Sstevel@tonic-gate int fd; 765*0Sstevel@tonic-gate struct dk_cinfo cinfo; 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate /* short circuit */ 768*0Sstevel@tonic-gate if (dnp->cinfo.cname[0] != '\0') 769*0Sstevel@tonic-gate return (&dnp->cinfo); 770*0Sstevel@tonic-gate 771*0Sstevel@tonic-gate /* get controller info */ 772*0Sstevel@tonic-gate if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) { 773*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, rname); 774*0Sstevel@tonic-gate return (NULL); 775*0Sstevel@tonic-gate } 776*0Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &cinfo) != 0) { 777*0Sstevel@tonic-gate int save = errno; 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate (void) close(fd); 780*0Sstevel@tonic-gate if (save == ENOTTY) { 781*0Sstevel@tonic-gate (void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname); 782*0Sstevel@tonic-gate } else { 783*0Sstevel@tonic-gate (void) mdsyserror(ep, save, rname); 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate return (NULL); 786*0Sstevel@tonic-gate } 787*0Sstevel@tonic-gate (void) close(fd); /* sd/ssd bug */ 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate /* convert to our format */ 790*0Sstevel@tonic-gate if (meta_cinfo_to_md(np, &cinfo, &dnp->cinfo, ep) != 0) 791*0Sstevel@tonic-gate return (NULL); 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate /* return info */ 794*0Sstevel@tonic-gate return (&dnp->cinfo); 795*0Sstevel@tonic-gate } 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate /* 798*0Sstevel@tonic-gate * get partition number 799*0Sstevel@tonic-gate */ 800*0Sstevel@tonic-gate int 801*0Sstevel@tonic-gate metagetpartno( 802*0Sstevel@tonic-gate mdname_t *np, 803*0Sstevel@tonic-gate md_error_t *ep 804*0Sstevel@tonic-gate ) 805*0Sstevel@tonic-gate { 806*0Sstevel@tonic-gate mdvtoc_t *vtocp; 807*0Sstevel@tonic-gate uint_t partno; 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL) 810*0Sstevel@tonic-gate return (-1); 811*0Sstevel@tonic-gate assert(partno < vtocp->nparts); 812*0Sstevel@tonic-gate return (partno); 813*0Sstevel@tonic-gate } 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate /* 816*0Sstevel@tonic-gate * get size of device 817*0Sstevel@tonic-gate */ 818*0Sstevel@tonic-gate diskaddr_t 819*0Sstevel@tonic-gate metagetsize( 820*0Sstevel@tonic-gate mdname_t *np, 821*0Sstevel@tonic-gate md_error_t *ep 822*0Sstevel@tonic-gate ) 823*0Sstevel@tonic-gate { 824*0Sstevel@tonic-gate mdvtoc_t *vtocp; 825*0Sstevel@tonic-gate uint_t partno; 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL) 828*0Sstevel@tonic-gate return (MD_DISKADDR_ERROR); 829*0Sstevel@tonic-gate assert(partno < vtocp->nparts); 830*0Sstevel@tonic-gate return (vtocp->parts[partno].size); 831*0Sstevel@tonic-gate } 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate /* 834*0Sstevel@tonic-gate * get label of device 835*0Sstevel@tonic-gate */ 836*0Sstevel@tonic-gate diskaddr_t 837*0Sstevel@tonic-gate metagetlabel( 838*0Sstevel@tonic-gate mdname_t *np, 839*0Sstevel@tonic-gate md_error_t *ep 840*0Sstevel@tonic-gate ) 841*0Sstevel@tonic-gate { 842*0Sstevel@tonic-gate mdvtoc_t *vtocp; 843*0Sstevel@tonic-gate uint_t partno; 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL) 846*0Sstevel@tonic-gate return (MD_DISKADDR_ERROR); 847*0Sstevel@tonic-gate assert(partno < vtocp->nparts); 848*0Sstevel@tonic-gate return (vtocp->parts[partno].label); 849*0Sstevel@tonic-gate } 850*0Sstevel@tonic-gate 851*0Sstevel@tonic-gate /* 852*0Sstevel@tonic-gate * find out where database replicas end 853*0Sstevel@tonic-gate */ 854*0Sstevel@tonic-gate static int 855*0Sstevel@tonic-gate mddb_getendblk( 856*0Sstevel@tonic-gate mdsetname_t *sp, 857*0Sstevel@tonic-gate mdname_t *np, 858*0Sstevel@tonic-gate diskaddr_t *endblkp, 859*0Sstevel@tonic-gate md_error_t *ep 860*0Sstevel@tonic-gate ) 861*0Sstevel@tonic-gate { 862*0Sstevel@tonic-gate md_replicalist_t *rlp = NULL; 863*0Sstevel@tonic-gate md_replicalist_t *rl; 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate /* make sure we have a component */ 866*0Sstevel@tonic-gate *endblkp = 0; 867*0Sstevel@tonic-gate if (metaismeta(np)) 868*0Sstevel@tonic-gate return (0); 869*0Sstevel@tonic-gate 870*0Sstevel@tonic-gate /* get replicas, quit if none */ 871*0Sstevel@tonic-gate if (metareplicalist(sp, MD_BASICNAME_OK | PRINT_FAST, &rlp, ep) < 0) { 872*0Sstevel@tonic-gate if (! mdismddberror(ep, MDE_DB_NODB)) 873*0Sstevel@tonic-gate return (-1); 874*0Sstevel@tonic-gate mdclrerror(ep); 875*0Sstevel@tonic-gate return (0); 876*0Sstevel@tonic-gate } else if (rlp == NULL) 877*0Sstevel@tonic-gate return (0); 878*0Sstevel@tonic-gate 879*0Sstevel@tonic-gate /* go through all the replicas */ 880*0Sstevel@tonic-gate for (rl = rlp; (rl != NULL); rl = rl->rl_next) { 881*0Sstevel@tonic-gate md_replica_t *rp = rl->rl_repp; 882*0Sstevel@tonic-gate mdname_t *repnamep = rp->r_namep; 883*0Sstevel@tonic-gate diskaddr_t dbend; 884*0Sstevel@tonic-gate 885*0Sstevel@tonic-gate if (np->dev != repnamep->dev) 886*0Sstevel@tonic-gate continue; 887*0Sstevel@tonic-gate dbend = rp->r_blkno + rp->r_nblk - 1; 888*0Sstevel@tonic-gate if (dbend > *endblkp) 889*0Sstevel@tonic-gate *endblkp = dbend; 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate /* cleanup, return success */ 893*0Sstevel@tonic-gate metafreereplicalist(rlp); 894*0Sstevel@tonic-gate return (0); 895*0Sstevel@tonic-gate } 896*0Sstevel@tonic-gate 897*0Sstevel@tonic-gate /* 898*0Sstevel@tonic-gate * return cached start block 899*0Sstevel@tonic-gate */ 900*0Sstevel@tonic-gate static diskaddr_t 901*0Sstevel@tonic-gate metagetend( 902*0Sstevel@tonic-gate mdsetname_t *sp, 903*0Sstevel@tonic-gate mdname_t *np, 904*0Sstevel@tonic-gate md_error_t *ep 905*0Sstevel@tonic-gate ) 906*0Sstevel@tonic-gate { 907*0Sstevel@tonic-gate diskaddr_t end_blk = MD_DISKADDR_ERROR; 908*0Sstevel@tonic-gate 909*0Sstevel@tonic-gate /* short circuit */ 910*0Sstevel@tonic-gate if (np->end_blk != MD_DISKADDR_ERROR) 911*0Sstevel@tonic-gate return (np->end_blk); 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate /* look for database locations */ 914*0Sstevel@tonic-gate if (mddb_getendblk(sp, np, &end_blk, ep) != 0) 915*0Sstevel@tonic-gate return (MD_DISKADDR_ERROR); 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate /* success */ 918*0Sstevel@tonic-gate np->end_blk = end_blk; 919*0Sstevel@tonic-gate return (end_blk); 920*0Sstevel@tonic-gate } 921*0Sstevel@tonic-gate 922*0Sstevel@tonic-gate /* 923*0Sstevel@tonic-gate * does device have a metadb 924*0Sstevel@tonic-gate */ 925*0Sstevel@tonic-gate int 926*0Sstevel@tonic-gate metahasmddb( 927*0Sstevel@tonic-gate mdsetname_t *sp, 928*0Sstevel@tonic-gate mdname_t *np, 929*0Sstevel@tonic-gate md_error_t *ep 930*0Sstevel@tonic-gate ) 931*0Sstevel@tonic-gate { 932*0Sstevel@tonic-gate if (metagetend(sp, np, ep) == MD_DISKADDR_ERROR) 933*0Sstevel@tonic-gate return (-1); 934*0Sstevel@tonic-gate else if (np->end_blk > 0) 935*0Sstevel@tonic-gate return (1); 936*0Sstevel@tonic-gate else 937*0Sstevel@tonic-gate return (0); 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate 940*0Sstevel@tonic-gate /* 941*0Sstevel@tonic-gate * return cached start block 942*0Sstevel@tonic-gate */ 943*0Sstevel@tonic-gate diskaddr_t 944*0Sstevel@tonic-gate metagetstart( 945*0Sstevel@tonic-gate mdsetname_t *sp, 946*0Sstevel@tonic-gate mdname_t *np, 947*0Sstevel@tonic-gate md_error_t *ep 948*0Sstevel@tonic-gate ) 949*0Sstevel@tonic-gate { 950*0Sstevel@tonic-gate diskaddr_t start_blk = MD_DISKADDR_ERROR; 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate /* short circuit */ 953*0Sstevel@tonic-gate if (np->start_blk != MD_DISKADDR_ERROR) 954*0Sstevel@tonic-gate return (np->start_blk); 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate /* look for database locations */ 957*0Sstevel@tonic-gate if ((start_blk = metagetend(sp, np, ep)) == MD_DISKADDR_ERROR) 958*0Sstevel@tonic-gate return (MD_DISKADDR_ERROR); 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate /* check for label */ 961*0Sstevel@tonic-gate if (start_blk == 0) { 962*0Sstevel@tonic-gate start_blk = metagetlabel(np, ep); 963*0Sstevel@tonic-gate if (start_blk == MD_DISKADDR_ERROR) { 964*0Sstevel@tonic-gate return (MD_DISKADDR_ERROR); 965*0Sstevel@tonic-gate } 966*0Sstevel@tonic-gate } 967*0Sstevel@tonic-gate 968*0Sstevel@tonic-gate /* roundup to next cylinder */ 969*0Sstevel@tonic-gate if (start_blk != 0) { 970*0Sstevel@tonic-gate mdgeom_t *geomp; 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate if ((geomp = metagetgeom(np, ep)) == NULL) 973*0Sstevel@tonic-gate return (MD_DISKADDR_ERROR); 974*0Sstevel@tonic-gate start_blk = roundup(start_blk, (geomp->nhead * geomp->nsect)); 975*0Sstevel@tonic-gate } 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate /* success */ 978*0Sstevel@tonic-gate np->start_blk = start_blk; 979*0Sstevel@tonic-gate return (start_blk); 980*0Sstevel@tonic-gate } 981*0Sstevel@tonic-gate 982*0Sstevel@tonic-gate /* 983*0Sstevel@tonic-gate * return cached devices name 984*0Sstevel@tonic-gate */ 985*0Sstevel@tonic-gate char * 986*0Sstevel@tonic-gate metagetdevicesname( 987*0Sstevel@tonic-gate mdname_t *np, 988*0Sstevel@tonic-gate md_error_t *ep 989*0Sstevel@tonic-gate ) 990*0Sstevel@tonic-gate { 991*0Sstevel@tonic-gate char path[MAXPATHLEN + 1]; 992*0Sstevel@tonic-gate int len; 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate /* short circuit */ 995*0Sstevel@tonic-gate if (np->devicesname != NULL) 996*0Sstevel@tonic-gate return (np->devicesname); 997*0Sstevel@tonic-gate 998*0Sstevel@tonic-gate /* follow symlink */ 999*0Sstevel@tonic-gate if ((len = readlink(np->bname, path, (sizeof (path) - 1))) < 0) { 1000*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, np->bname); 1001*0Sstevel@tonic-gate return (NULL); 1002*0Sstevel@tonic-gate } else if (len >= sizeof (path)) { 1003*0Sstevel@tonic-gate (void) mdsyserror(ep, ENAMETOOLONG, np->bname); 1004*0Sstevel@tonic-gate return (NULL); 1005*0Sstevel@tonic-gate } 1006*0Sstevel@tonic-gate path[len] = '\0'; 1007*0Sstevel@tonic-gate if ((len = strfind(path, "/devices/")) < 0) { 1008*0Sstevel@tonic-gate (void) mddeverror(ep, MDE_DEVICES_NAME, np->dev, np->bname); 1009*0Sstevel@tonic-gate return (NULL); 1010*0Sstevel@tonic-gate } 1011*0Sstevel@tonic-gate 1012*0Sstevel@tonic-gate /* return name */ 1013*0Sstevel@tonic-gate np->devicesname = Strdup(path + len + strlen("/devices")); 1014*0Sstevel@tonic-gate return (np->devicesname); 1015*0Sstevel@tonic-gate } 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate /* 1018*0Sstevel@tonic-gate * get metadevice misc name 1019*0Sstevel@tonic-gate */ 1020*0Sstevel@tonic-gate char * 1021*0Sstevel@tonic-gate metagetmiscname( 1022*0Sstevel@tonic-gate mdname_t *np, 1023*0Sstevel@tonic-gate md_error_t *ep 1024*0Sstevel@tonic-gate ) 1025*0Sstevel@tonic-gate { 1026*0Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep; 1027*0Sstevel@tonic-gate md_i_driverinfo_t mid; 1028*0Sstevel@tonic-gate 1029*0Sstevel@tonic-gate /* short circuit */ 1030*0Sstevel@tonic-gate if (dnp->miscname != NULL) 1031*0Sstevel@tonic-gate return (dnp->miscname); 1032*0Sstevel@tonic-gate if (metachkmeta(np, ep) != 0) 1033*0Sstevel@tonic-gate return (NULL); 1034*0Sstevel@tonic-gate 1035*0Sstevel@tonic-gate /* get misc module from driver */ 1036*0Sstevel@tonic-gate (void) memset(&mid, 0, sizeof (mid)); 1037*0Sstevel@tonic-gate mid.mnum = meta_getminor(np->dev); 1038*0Sstevel@tonic-gate if (metaioctl(MD_IOCGET_DRVNM, &mid, &mid.mde, np->cname) != 0) { 1039*0Sstevel@tonic-gate (void) mdstealerror(ep, &mid.mde); 1040*0Sstevel@tonic-gate return (NULL); 1041*0Sstevel@tonic-gate } 1042*0Sstevel@tonic-gate 1043*0Sstevel@tonic-gate /* return miscname */ 1044*0Sstevel@tonic-gate dnp->miscname = Strdup(MD_PNTDRIVERNAME(&mid)); 1045*0Sstevel@tonic-gate return (dnp->miscname); 1046*0Sstevel@tonic-gate } 1047*0Sstevel@tonic-gate 1048*0Sstevel@tonic-gate /* 1049*0Sstevel@tonic-gate * get unit structure from driver 1050*0Sstevel@tonic-gate */ 1051*0Sstevel@tonic-gate md_unit_t * 1052*0Sstevel@tonic-gate meta_get_mdunit( 1053*0Sstevel@tonic-gate mdsetname_t *sp, 1054*0Sstevel@tonic-gate mdname_t *np, 1055*0Sstevel@tonic-gate md_error_t *ep 1056*0Sstevel@tonic-gate ) 1057*0Sstevel@tonic-gate { 1058*0Sstevel@tonic-gate md_i_get_t mig; 1059*0Sstevel@tonic-gate char *miscname = NULL; 1060*0Sstevel@tonic-gate 1061*0Sstevel@tonic-gate /* should have a set */ 1062*0Sstevel@tonic-gate assert(sp != NULL); 1063*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(np->dev))); 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate /* get size of unit structure */ 1066*0Sstevel@tonic-gate if (metachkmeta(np, ep) != 0) 1067*0Sstevel@tonic-gate return (NULL); 1068*0Sstevel@tonic-gate if ((miscname = metagetmiscname(np, ep)) == NULL) 1069*0Sstevel@tonic-gate return (NULL); 1070*0Sstevel@tonic-gate (void) memset(&mig, '\0', sizeof (mig)); 1071*0Sstevel@tonic-gate MD_SETDRIVERNAME(&mig, miscname, sp->setno); 1072*0Sstevel@tonic-gate mig.id = meta_getminor(np->dev); 1073*0Sstevel@tonic-gate if (metaioctl(MD_IOCGET, &mig, &mig.mde, np->cname) != 0) { 1074*0Sstevel@tonic-gate (void) mdstealerror(ep, &mig.mde); 1075*0Sstevel@tonic-gate return (NULL); 1076*0Sstevel@tonic-gate } 1077*0Sstevel@tonic-gate 1078*0Sstevel@tonic-gate /* get actual unit structure */ 1079*0Sstevel@tonic-gate assert(mig.size > 0); 1080*0Sstevel@tonic-gate mig.mdp = (uintptr_t)Zalloc(mig.size); 1081*0Sstevel@tonic-gate if (metaioctl(MD_IOCGET, &mig, &mig.mde, np->cname) != 0) { 1082*0Sstevel@tonic-gate (void) mdstealerror(ep, &mig.mde); 1083*0Sstevel@tonic-gate Free((void *)mig.mdp); 1084*0Sstevel@tonic-gate return (NULL); 1085*0Sstevel@tonic-gate } 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate return ((md_unit_t *)mig.mdp); 1088*0Sstevel@tonic-gate } 1089*0Sstevel@tonic-gate 1090*0Sstevel@tonic-gate /* 1091*0Sstevel@tonic-gate * free metadevice unit 1092*0Sstevel@tonic-gate */ 1093*0Sstevel@tonic-gate void 1094*0Sstevel@tonic-gate meta_free_unit( 1095*0Sstevel@tonic-gate mddrivename_t *dnp 1096*0Sstevel@tonic-gate ) 1097*0Sstevel@tonic-gate { 1098*0Sstevel@tonic-gate if (dnp->unitp != NULL) { 1099*0Sstevel@tonic-gate switch (dnp->unitp->type) { 1100*0Sstevel@tonic-gate case MD_DEVICE: 1101*0Sstevel@tonic-gate meta_free_stripe((md_stripe_t *)dnp->unitp); 1102*0Sstevel@tonic-gate break; 1103*0Sstevel@tonic-gate case MD_METAMIRROR: 1104*0Sstevel@tonic-gate meta_free_mirror((md_mirror_t *)dnp->unitp); 1105*0Sstevel@tonic-gate break; 1106*0Sstevel@tonic-gate case MD_METATRANS: 1107*0Sstevel@tonic-gate meta_free_trans((md_trans_t *)dnp->unitp); 1108*0Sstevel@tonic-gate break; 1109*0Sstevel@tonic-gate case MD_METARAID: 1110*0Sstevel@tonic-gate meta_free_raid((md_raid_t *)dnp->unitp); 1111*0Sstevel@tonic-gate break; 1112*0Sstevel@tonic-gate case MD_METASP: 1113*0Sstevel@tonic-gate meta_free_sp((md_sp_t *)dnp->unitp); 1114*0Sstevel@tonic-gate break; 1115*0Sstevel@tonic-gate default: 1116*0Sstevel@tonic-gate assert(0); 1117*0Sstevel@tonic-gate break; 1118*0Sstevel@tonic-gate } 1119*0Sstevel@tonic-gate dnp->unitp = NULL; 1120*0Sstevel@tonic-gate } 1121*0Sstevel@tonic-gate } 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate /* 1124*0Sstevel@tonic-gate * free metadevice name info 1125*0Sstevel@tonic-gate */ 1126*0Sstevel@tonic-gate void 1127*0Sstevel@tonic-gate meta_invalidate_name( 1128*0Sstevel@tonic-gate mdname_t *namep 1129*0Sstevel@tonic-gate ) 1130*0Sstevel@tonic-gate { 1131*0Sstevel@tonic-gate mddrivename_t *dnp = namep->drivenamep; 1132*0Sstevel@tonic-gate 1133*0Sstevel@tonic-gate /* get rid of cached name info */ 1134*0Sstevel@tonic-gate if (namep->devicesname != NULL) { 1135*0Sstevel@tonic-gate Free(namep->devicesname); 1136*0Sstevel@tonic-gate namep->devicesname = NULL; 1137*0Sstevel@tonic-gate } 1138*0Sstevel@tonic-gate namep->key = MD_KEYBAD; 1139*0Sstevel@tonic-gate namep->start_blk = -1; 1140*0Sstevel@tonic-gate namep->end_blk = -1; 1141*0Sstevel@tonic-gate 1142*0Sstevel@tonic-gate /* get rid of cached drivename info */ 1143*0Sstevel@tonic-gate (void) memset(&dnp->geom, 0, sizeof (dnp->geom)); 1144*0Sstevel@tonic-gate (void) memset(&dnp->cinfo, 0, sizeof (dnp->cinfo)); 1145*0Sstevel@tonic-gate metafreevtoc(&dnp->vtoc); 1146*0Sstevel@tonic-gate metaflushsidenames(dnp); 1147*0Sstevel@tonic-gate dnp->side_names_key = MD_KEYBAD; 1148*0Sstevel@tonic-gate if (dnp->miscname != NULL) { 1149*0Sstevel@tonic-gate Free(dnp->miscname); 1150*0Sstevel@tonic-gate dnp->miscname = NULL; 1151*0Sstevel@tonic-gate } 1152*0Sstevel@tonic-gate meta_free_unit(dnp); 1153*0Sstevel@tonic-gate } 1154*0Sstevel@tonic-gate 1155*0Sstevel@tonic-gate /* 1156*0Sstevel@tonic-gate * get metadevice unit 1157*0Sstevel@tonic-gate */ 1158*0Sstevel@tonic-gate md_common_t * 1159*0Sstevel@tonic-gate meta_get_unit( 1160*0Sstevel@tonic-gate mdsetname_t *sp, 1161*0Sstevel@tonic-gate mdname_t *np, 1162*0Sstevel@tonic-gate md_error_t *ep 1163*0Sstevel@tonic-gate ) 1164*0Sstevel@tonic-gate { 1165*0Sstevel@tonic-gate char *miscname; 1166*0Sstevel@tonic-gate 1167*0Sstevel@tonic-gate /* short circuit */ 1168*0Sstevel@tonic-gate if (np->drivenamep->unitp != NULL) 1169*0Sstevel@tonic-gate return (np->drivenamep->unitp); 1170*0Sstevel@tonic-gate if (metachkmeta(np, ep) != 0) 1171*0Sstevel@tonic-gate return (NULL); 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate /* dispatch */ 1174*0Sstevel@tonic-gate if ((miscname = metagetmiscname(np, ep)) == NULL) 1175*0Sstevel@tonic-gate return (NULL); 1176*0Sstevel@tonic-gate else if (strcmp(miscname, MD_STRIPE) == 0) 1177*0Sstevel@tonic-gate return ((md_common_t *)meta_get_stripe(sp, np, ep)); 1178*0Sstevel@tonic-gate else if (strcmp(miscname, MD_MIRROR) == 0) 1179*0Sstevel@tonic-gate return ((md_common_t *)meta_get_mirror(sp, np, ep)); 1180*0Sstevel@tonic-gate else if (strcmp(miscname, MD_TRANS) == 0) 1181*0Sstevel@tonic-gate return ((md_common_t *)meta_get_trans(sp, np, ep)); 1182*0Sstevel@tonic-gate else if (strcmp(miscname, MD_RAID) == 0) 1183*0Sstevel@tonic-gate return ((md_common_t *)meta_get_raid(sp, np, ep)); 1184*0Sstevel@tonic-gate else if (strcmp(miscname, MD_SP) == 0) 1185*0Sstevel@tonic-gate return ((md_common_t *)meta_get_sp(sp, np, ep)); 1186*0Sstevel@tonic-gate else { 1187*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(np->dev), 1188*0Sstevel@tonic-gate np->cname); 1189*0Sstevel@tonic-gate return (NULL); 1190*0Sstevel@tonic-gate } 1191*0Sstevel@tonic-gate } 1192*0Sstevel@tonic-gate 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate int 1195*0Sstevel@tonic-gate meta_isopen( 1196*0Sstevel@tonic-gate mdsetname_t *sp, 1197*0Sstevel@tonic-gate mdname_t *np, 1198*0Sstevel@tonic-gate md_error_t *ep, 1199*0Sstevel@tonic-gate mdcmdopts_t options 1200*0Sstevel@tonic-gate ) 1201*0Sstevel@tonic-gate { 1202*0Sstevel@tonic-gate md_isopen_t d; 1203*0Sstevel@tonic-gate 1204*0Sstevel@tonic-gate if (metachkmeta(np, ep) != 0) 1205*0Sstevel@tonic-gate return (-1); 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gate (void) memset(&d, '\0', sizeof (d)); 1208*0Sstevel@tonic-gate d.dev = np->dev; 1209*0Sstevel@tonic-gate if (metaioctl(MD_IOCISOPEN, &d, &d.mde, np->cname) != 0) 1210*0Sstevel@tonic-gate return (mdstealerror(ep, &d.mde)); 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gate /* 1213*0Sstevel@tonic-gate * shortcut: if the device is open, no need to check on other nodes, 1214*0Sstevel@tonic-gate * even in case of a mn metadevice 1215*0Sstevel@tonic-gate * Also return in case we're told not to check on other nodes. 1216*0Sstevel@tonic-gate */ 1217*0Sstevel@tonic-gate if ((d.isopen != 0) || ((options & MDCMD_MN_OPEN_CHECK) == 0)) { 1218*0Sstevel@tonic-gate return (d.isopen); 1219*0Sstevel@tonic-gate } 1220*0Sstevel@tonic-gate 1221*0Sstevel@tonic-gate /* 1222*0Sstevel@tonic-gate * If the device is closed locally, but it's a mn device, 1223*0Sstevel@tonic-gate * check on all other nodes, too 1224*0Sstevel@tonic-gate */ 1225*0Sstevel@tonic-gate if (sp->setno != MD_LOCAL_SET) { 1226*0Sstevel@tonic-gate (void) metaget_setdesc(sp, ep); /* not supposed to fail */ 1227*0Sstevel@tonic-gate if (sp->setdesc->sd_flags & MD_SR_MN) { 1228*0Sstevel@tonic-gate int err = 0; 1229*0Sstevel@tonic-gate md_mn_result_t *resp; 1230*0Sstevel@tonic-gate /* 1231*0Sstevel@tonic-gate * This message is never directly issued. 1232*0Sstevel@tonic-gate * So we launch it with a suspend override flag. 1233*0Sstevel@tonic-gate * If the commd is suspended, and this message comes 1234*0Sstevel@tonic-gate * along it must be sent due to replaying a metainit or 1235*0Sstevel@tonic-gate * similar. In that case we don't want this message to 1236*0Sstevel@tonic-gate * be blocked. 1237*0Sstevel@tonic-gate * If the commd is not suspended, the flag does no harm. 1238*0Sstevel@tonic-gate * Additionally we don't want the result of the message 1239*0Sstevel@tonic-gate * cached in the MCT, because we want uptodate results, 1240*0Sstevel@tonic-gate * and the message doesn't need being logged either. 1241*0Sstevel@tonic-gate * Hence NO_LOG and NO_MCT 1242*0Sstevel@tonic-gate */ 1243*0Sstevel@tonic-gate err = mdmn_send_message( 1244*0Sstevel@tonic-gate sp->setno, 1245*0Sstevel@tonic-gate MD_MN_MSG_CLU_CHECK, 1246*0Sstevel@tonic-gate MD_MSGF_NO_MCT | MD_MSGF_STOP_ON_ERROR | 1247*0Sstevel@tonic-gate MD_MSGF_NO_LOG | MD_MSGF_OVERRIDE_SUSPEND, 1248*0Sstevel@tonic-gate (char *)&d, sizeof (md_isopen_t), 1249*0Sstevel@tonic-gate &resp, ep); 1250*0Sstevel@tonic-gate if (err == 0) { 1251*0Sstevel@tonic-gate d.isopen = resp->mmr_exitval; 1252*0Sstevel@tonic-gate } else { 1253*0Sstevel@tonic-gate /* 1254*0Sstevel@tonic-gate * in case some error occurred, 1255*0Sstevel@tonic-gate * we better say the device is open 1256*0Sstevel@tonic-gate */ 1257*0Sstevel@tonic-gate d.isopen = 1; 1258*0Sstevel@tonic-gate } 1259*0Sstevel@tonic-gate if (resp != (md_mn_result_t *)NULL) { 1260*0Sstevel@tonic-gate free_result(resp); 1261*0Sstevel@tonic-gate } 1262*0Sstevel@tonic-gate 1263*0Sstevel@tonic-gate } 1264*0Sstevel@tonic-gate } 1265*0Sstevel@tonic-gate 1266*0Sstevel@tonic-gate return (d.isopen); 1267*0Sstevel@tonic-gate } 1268