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