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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Just in case we're not in a build environment, make sure that 28 * TEXT_DOMAIN gets set to something. 29 */ 30 #if !defined(TEXT_DOMAIN) 31 #define TEXT_DOMAIN "SYS_TEST" 32 #endif 33 34 /* 35 * stripe operations 36 */ 37 38 #include <limits.h> 39 #include <stdlib.h> 40 #include <meta.h> 41 #include <sys/lvm/md_stripe.h> 42 #include <sys/lvm/md_convert.h> 43 44 #define QUOTE(x) #x 45 #define VAL2STR(x) QUOTE(x) 46 47 /* 48 * replace stripe/concat 49 */ 50 int 51 meta_stripe_replace( 52 mdsetname_t *sp, 53 mdname_t *stripenp, 54 mdname_t *oldnp, 55 mdname_t *newnp, 56 mdcmdopts_t options, 57 md_error_t *ep 58 ) 59 { 60 replace_params_t params; 61 md_dev64_t old_dev, new_dev; 62 diskaddr_t new_start_blk; 63 diskaddr_t new_end_blk, label, size, start_blk; 64 65 /* should have same set */ 66 assert(sp != NULL); 67 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 68 69 new_dev = newnp->dev; 70 new_start_blk = newnp->start_blk; 71 new_end_blk = newnp->end_blk; 72 73 meta_invalidate_name(stripenp); 74 75 /* the old device binding is now established */ 76 if ((old_dev = oldnp->dev) == NODEV64) 77 return (mdsyserror(ep, ENODEV, oldnp->cname)); 78 79 if (((strcmp(oldnp->rname, newnp->rname) == 0) && 80 (old_dev != new_dev))) { 81 newnp->dev = new_dev; 82 newnp->start_blk = new_start_blk; 83 newnp->end_blk = new_end_blk; 84 } 85 86 if ((size = metagetsize(newnp, ep)) == MD_DISKADDR_ERROR) 87 return (-1); 88 if ((label = metagetlabel(newnp, ep)) == MD_DISKADDR_ERROR) 89 return (-1); 90 if ((start_blk = metagetstart(sp, newnp, ep)) == MD_DISKADDR_ERROR) 91 return (-1); 92 if (start_blk >= size) { 93 (void) mdsyserror(ep, ENOSPC, newnp->cname); 94 return (-1); 95 } 96 97 /* In dryrun mode (DOIT not set) we must not alter the mddb */ 98 if (options & MDCMD_DOIT) { 99 if (add_key_name(sp, newnp, NULL, ep) != 0) 100 return (-1); 101 } 102 103 /* 104 * There is no need to call meta_fixdevid() here as this function is 105 * only called by the metareplace -c command which actually does 106 * nothing (in terms of a resync) and thus does nothing with the devid. 107 */ 108 109 (void) memset(¶ms, 0, sizeof (params)); 110 params.mnum = meta_getminor(stripenp->dev); 111 MD_SETDRIVERNAME(¶ms, MD_STRIPE, sp->setno); 112 113 params.cmd = REPLACE_COMP; 114 params.old_dev = old_dev; 115 params.new_dev = new_dev; 116 params.new_key = newnp->key; 117 params.start_blk = newnp->start_blk; 118 params.number_blks = size; 119 /* Is this just a dryrun ? */ 120 if ((options & MDCMD_DOIT) == 0) { 121 params.options |= MDIOCTL_DRYRUN; 122 } 123 if (label == 0) 124 params.has_label = 0; 125 else 126 params.has_label = 1; 127 if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) { 128 if (options & MDCMD_DOIT) 129 (void) del_key_name(sp, newnp, ep); 130 return (mdstealerror(ep, ¶ms.mde)); 131 } 132 meta_invalidate_name(oldnp); 133 meta_invalidate_name(newnp); 134 meta_invalidate_name(stripenp); 135 136 if (options & MDCMD_PRINT) { 137 (void) printf(dgettext(TEXT_DOMAIN, 138 "%s: device %s is replaced with %s\n"), 139 stripenp->cname, oldnp->cname, newnp->cname); 140 141 } 142 return (0); 143 } 144 145 146 /* 147 * FUNCTION: meta_get_stripe_names() 148 * INPUT: sp - the set name to get stripes from 149 * options - options from the command line 150 * OUTPUT: nlpp - list of all stripe names 151 * ep - return error pointer 152 * RETURNS: int - -1 if error, 0 success 153 * PURPOSE: returns a list of all stripes in the metadb 154 * for all devices in the specified set 155 */ 156 int 157 meta_get_stripe_names( 158 mdsetname_t *sp, 159 mdnamelist_t **nlpp, 160 int options, 161 md_error_t *ep 162 ) 163 { 164 return (meta_get_names(MD_STRIPE, sp, nlpp, options, ep)); 165 } 166 167 /* 168 * free stripe 169 */ 170 void 171 meta_free_stripe( 172 md_stripe_t *stripep 173 ) 174 { 175 uint_t row; 176 177 for (row = 0; (row < stripep->rows.rows_len); ++row) { 178 md_row_t *rp = &stripep->rows.rows_val[row]; 179 180 if (rp->comps.comps_val != NULL) { 181 assert(rp->comps.comps_len > 0); 182 Free(rp->comps.comps_val); 183 } 184 } 185 if (stripep->rows.rows_val != NULL) { 186 assert(stripep->rows.rows_len > 0); 187 Free(stripep->rows.rows_val); 188 } 189 Free(stripep); 190 } 191 192 193 /* 194 * get stripe (common) 195 */ 196 md_stripe_t * 197 meta_get_stripe_common( 198 mdsetname_t *sp, 199 mdname_t *stripenp, 200 int fast, 201 md_error_t *ep 202 ) 203 { 204 mddrivename_t *dnp = stripenp->drivenamep; 205 char *miscname; 206 ms_unit_t *ms; 207 md_stripe_t *stripep; 208 uint_t row; 209 210 /* must have set */ 211 assert(sp != NULL); 212 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 213 214 /* short circuit */ 215 if (dnp->unitp != NULL) { 216 assert(dnp->unitp->type == MD_DEVICE); 217 return ((md_stripe_t *)dnp->unitp); 218 } 219 220 /* get miscname and unit */ 221 if ((miscname = metagetmiscname(stripenp, ep)) == NULL) 222 return (NULL); 223 if (strcmp(miscname, MD_STRIPE) != 0) { 224 (void) mdmderror(ep, MDE_NOT_STRIPE, 225 meta_getminor(stripenp->dev), stripenp->cname); 226 return (NULL); 227 } 228 if ((ms = (ms_unit_t *)meta_get_mdunit(sp, stripenp, ep)) == NULL) 229 return (NULL); 230 assert(ms->c.un_type == MD_DEVICE); 231 232 /* allocate stripe */ 233 stripep = Zalloc(sizeof (*stripep)); 234 235 /* allocate rows */ 236 assert(ms->un_nrows > 0); 237 stripep->rows.rows_len = ms->un_nrows; 238 stripep->rows.rows_val = Zalloc(stripep->rows.rows_len * 239 sizeof (*stripep->rows.rows_val)); 240 241 /* get common info */ 242 stripep->common.namep = stripenp; 243 stripep->common.type = ms->c.un_type; 244 stripep->common.state = ms->c.un_status; 245 stripep->common.capabilities = ms->c.un_capabilities; 246 stripep->common.parent = ms->c.un_parent; 247 stripep->common.size = ms->c.un_total_blocks; 248 stripep->common.user_flags = ms->c.un_user_flags; 249 stripep->common.revision = ms->c.un_revision; 250 251 /* get options */ 252 if ((ms->un_hsp_id != MD_HSP_NONE) && 253 ((stripep->hspnamep = metahsphspname(&sp, ms->un_hsp_id, 254 ep)) == NULL)) { 255 goto out; 256 } 257 258 /* get rows */ 259 for (row = 0; (row < ms->un_nrows); ++row) { 260 struct ms_row *mdr = &ms->un_row[row]; 261 struct ms_comp *mdcomp = (void *)&((char *)ms)[ms->un_ocomp]; 262 md_row_t *rp = &stripep->rows.rows_val[row]; 263 uint_t comp, c; 264 265 /* get interlace */ 266 rp->interlace = mdr->un_interlace; 267 268 /* allocate comps */ 269 assert(mdr->un_ncomp > 0); 270 rp->comps.comps_len = mdr->un_ncomp; 271 rp->comps.comps_val = Zalloc(rp->comps.comps_len * 272 sizeof (*rp->comps.comps_val)); 273 274 /* get components */ 275 for (comp = 0, c = mdr->un_icomp; (comp < mdr->un_ncomp); 276 ++comp, ++c) { 277 struct ms_comp *mdc = &mdcomp[c]; 278 diskaddr_t comp_start_blk = mdc->un_start_block; 279 md_comp_t *cp = &rp->comps.comps_val[comp]; 280 281 /* get the component name */ 282 cp->compnamep = metakeyname(&sp, mdc->un_key, fast, ep); 283 if (cp->compnamep == NULL) 284 goto out; 285 286 /* if hotspared */ 287 if (mdc->un_mirror.ms_hs_id != 0) { 288 diskaddr_t hs_start_blk = mdc->un_start_block; 289 290 /* get the hotspare name */ 291 cp->hsnamep = metakeyname(&sp, 292 mdc->un_mirror.ms_hs_key, fast, ep); 293 if (cp->hsnamep == NULL) 294 goto out; 295 296 if (getenv("META_DEBUG_START_BLK") != NULL) { 297 if (metagetstart(sp, cp->hsnamep, 298 ep) == MD_DISKADDR_ERROR) 299 mdclrerror(ep); 300 301 if ((cp->hsnamep->start_blk == 0) && 302 (hs_start_blk != 0)) 303 md_eprintf(dgettext(TEXT_DOMAIN, 304 "%s: suspected bad" 305 "start block," 306 " seems labelled" 307 "[stripe/hs]\n"), 308 cp->hsnamep->cname); 309 310 if ((cp->hsnamep->start_blk > 0) && 311 (hs_start_blk == 0) && 312 ! ((row == 0) && (comp == 0))) 313 md_eprintf(dgettext(TEXT_DOMAIN, 314 "%s: suspected bad" 315 "start block, " 316 "seems unlabelled" 317 "[stripe/hs]\n"), 318 cp->hsnamep->cname); 319 } 320 /* override any start_blk */ 321 cp->hsnamep->start_blk = hs_start_blk; 322 323 /* get the right component start_blk */ 324 comp_start_blk = mdc->un_mirror.ms_orig_blk; 325 } else { 326 if (getenv("META_DEBUG_START_BLK") != NULL) { 327 if (metagetstart(sp, cp->compnamep, 328 ep) == MD_DISKADDR_ERROR) 329 mdclrerror(ep); 330 331 if ((cp->compnamep->start_blk == 0) && 332 (comp_start_blk != 0)) 333 md_eprintf(dgettext(TEXT_DOMAIN, 334 "%s: suspected bad" 335 "start block," 336 " seems labelled" 337 "[stripe]"), 338 cp->compnamep->cname); 339 340 if ((cp->compnamep->start_blk > 0) && 341 (comp_start_blk == 0) && 342 ! ((row == 0) && (comp == 0))) 343 md_eprintf(dgettext(TEXT_DOMAIN, 344 "%s: suspected bad" 345 "start block, " 346 "seems unlabelled" 347 "[stripe]"), 348 cp->compnamep->cname); 349 } 350 } 351 352 /* override any start_blk */ 353 cp->compnamep->start_blk = comp_start_blk; 354 355 /* get state */ 356 cp->state = mdc->un_mirror.ms_state; 357 358 /* get time of last state change */ 359 cp->timestamp = mdc->un_mirror.ms_timestamp; 360 361 /* get lasterr count */ 362 cp->lasterrcnt = mdc->un_mirror.ms_lasterrcnt; 363 } 364 } 365 366 /* cleanup, return success */ 367 Free(ms); 368 dnp->unitp = (md_common_t *)stripep; 369 return (stripep); 370 371 /* cleanup, return error */ 372 out: 373 Free(ms); 374 meta_free_stripe(stripep); 375 return (NULL); 376 } 377 378 /* 379 * get stripe 380 */ 381 md_stripe_t * 382 meta_get_stripe( 383 mdsetname_t *sp, 384 mdname_t *stripenp, 385 md_error_t *ep 386 ) 387 { 388 return (meta_get_stripe_common(sp, stripenp, 0, ep)); 389 } 390 391 /* 392 * check stripe for dev 393 */ 394 static int 395 in_stripe( 396 mdsetname_t *sp, 397 mdname_t *stripenp, 398 mdname_t *np, 399 diskaddr_t slblk, 400 diskaddr_t nblks, 401 md_error_t *ep 402 ) 403 { 404 md_stripe_t *stripep; 405 uint_t row; 406 407 /* should be in the same set */ 408 assert(sp != NULL); 409 410 /* get unit */ 411 if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL) 412 return (-1); 413 414 /* look in rows */ 415 for (row = 0; (row < stripep->rows.rows_len); ++row) { 416 md_row_t *rp = &stripep->rows.rows_val[row]; 417 uint_t comp; 418 419 /* look in columns */ 420 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 421 md_comp_t *cp = &rp->comps.comps_val[comp]; 422 mdname_t *compnp = cp->compnamep; 423 diskaddr_t comp_sblk; 424 int err; 425 426 /* check same drive since metagetstart() can fail */ 427 if ((err = meta_check_samedrive(np, compnp, ep)) < 0) 428 return (-1); 429 else if (err == 0) 430 continue; 431 432 /* check overlap */ 433 if ((comp_sblk = metagetstart(sp, compnp, ep)) == 434 MD_DISKADDR_ERROR) 435 return (-1); 436 if (meta_check_overlap(stripenp->cname, np, 437 slblk, nblks, compnp, comp_sblk, -1, 438 ep) != 0) { 439 return (-1); 440 } 441 } 442 } 443 444 /* return success */ 445 return (0); 446 } 447 448 /* 449 * check to see if we're in a stripe 450 */ 451 int 452 meta_check_instripe( 453 mdsetname_t *sp, 454 mdname_t *np, 455 diskaddr_t slblk, 456 diskaddr_t nblks, 457 md_error_t *ep 458 ) 459 { 460 mdnamelist_t *stripenlp = NULL; 461 mdnamelist_t *p; 462 int rval = 0; 463 464 /* should have a set */ 465 assert(sp != NULL); 466 467 /* for each stripe */ 468 if (meta_get_stripe_names(sp, &stripenlp, 0, ep) < 0) 469 return (-1); 470 for (p = stripenlp; (p != NULL); p = p->next) { 471 mdname_t *stripenp = p->namep; 472 473 /* check stripe */ 474 if (in_stripe(sp, stripenp, np, slblk, nblks, ep) != 0) { 475 rval = -1; 476 break; 477 } 478 } 479 480 /* cleanup, return success */ 481 metafreenamelist(stripenlp); 482 return (rval); 483 } 484 485 /* 486 * check component 487 */ 488 int 489 meta_check_component( 490 mdsetname_t *sp, 491 mdname_t *np, 492 int force, 493 md_error_t *ep 494 ) 495 { 496 mdchkopts_t options = (MDCHK_ALLOW_MDDB); 497 md_common_t *mdp; 498 499 /* 500 * See if we are a soft partition: meta_sp_issp() returns 0 if 501 * np points to a soft partition, so the if and else clauses 502 * here represent "not a soft partition" and "soft partition," 503 * respectively. 504 */ 505 if (meta_sp_issp(sp, np, ep) != 0) { 506 /* make sure we have a disk */ 507 if (metachkcomp(np, ep) != 0) 508 return (-1); 509 } else { 510 /* make sure soft partition can parent & doesn't have parent */ 511 if ((mdp = meta_get_unit(sp, np, ep)) == NULL) 512 return (mdmderror(ep, MDE_INVAL_UNIT, NULL, 513 np->cname)); 514 if (mdp->capabilities == MD_CANT_PARENT) 515 return (mdmderror(ep, MDE_INVAL_UNIT, NULL, 516 np->cname)); 517 if (MD_HAS_PARENT(mdp->parent)) { 518 mdname_t *pnp; 519 520 pnp = metamnumname(&sp, mdp->parent, 0, ep); 521 if (pnp == NULL) { 522 return (-1); 523 } 524 525 return (mduseerror(ep, MDE_ALREADY, np->dev, 526 pnp->cname, np->cname)); 527 } 528 } 529 530 /* check to ensure that it is not already in use */ 531 if ((! force) && 532 (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0)) { 533 return (-1); 534 } 535 536 /* make sure it is in the set */ 537 if (meta_check_inset(sp, np, ep) != 0) 538 return (-1); 539 540 /* make sure its not in a metadevice */ 541 if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0) 542 return (-1); 543 544 /* return success */ 545 return (0); 546 } 547 548 /* 549 * print stripe 550 */ 551 static int 552 stripe_print( 553 md_stripe_t *stripep, 554 char *fname, 555 FILE *fp, 556 mdprtopts_t options, 557 md_error_t *ep 558 ) 559 { 560 uint_t row; 561 int rval = -1; 562 563 if (options & PRINT_LARGEDEVICES) { 564 if (stripep->common.revision != MD_64BIT_META_DEV) { 565 rval = 0; 566 goto out; 567 } 568 } 569 570 if (options & PRINT_FN) { 571 if (stripep->common.revision != MD_FN_META_DEV) { 572 rval = 0; 573 goto out; 574 } 575 } 576 577 /* print name and num rows */ 578 if (fprintf(fp, "%s %u", 579 stripep->common.namep->cname, stripep->rows.rows_len) == EOF) 580 goto out; 581 582 /* print rows */ 583 for (row = 0; (row < stripep->rows.rows_len); ++row) { 584 md_row_t *rp = &stripep->rows.rows_val[row]; 585 uint_t comp; 586 587 /* print num components */ 588 if (fprintf(fp, " %u", rp->comps.comps_len) == EOF) 589 goto out; 590 591 /* 592 * Print components. Always print the full path name. 593 */ 594 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 595 md_comp_t *cp = &rp->comps.comps_val[comp]; 596 597 if (fprintf(fp, " %s", cp->compnamep->rname) == EOF) 598 goto out; 599 } 600 601 /* print interlace */ 602 if (rp->comps.comps_len > 1) 603 if (fprintf(fp, " -i %lldb", rp->interlace) == EOF) 604 goto out; 605 606 /* print continuation */ 607 if (row != (stripep->rows.rows_len - 1)) 608 if (fprintf(fp, " \\\n\t") == EOF) 609 goto out; 610 } 611 612 /* print hotspare name */ 613 if (stripep->hspnamep != NULL) 614 if (fprintf(fp, " -h %s", stripep->hspnamep->hspname) == EOF) 615 goto out; 616 617 /* terminate last line */ 618 if (fprintf(fp, "\n") == EOF) 619 goto out; 620 621 /* success */ 622 rval = 0; 623 624 /* cleanup, return error */ 625 out: 626 if (rval != 0) 627 (void) mdsyserror(ep, errno, fname); 628 return (rval); 629 } 630 631 /* 632 * convert component state to name 633 */ 634 char * 635 comp_state_to_name( 636 md_comp_t *mdcp, 637 md_timeval32_t *tvp, 638 uint_t tstate /* Errored tstate flags */ 639 ) 640 { 641 comp_state_t state = mdcp->state; 642 643 /* grab time */ 644 if (tvp != NULL) 645 *tvp = mdcp->timestamp; 646 647 if (tstate != 0) { 648 return (dgettext(TEXT_DOMAIN, "Unavailable")); 649 } 650 651 /* return state */ 652 switch (state) { 653 case CS_OKAY: 654 return (dgettext(TEXT_DOMAIN, "Okay")); 655 case CS_ERRED: 656 return (dgettext(TEXT_DOMAIN, "Maintenance")); 657 case CS_LAST_ERRED: 658 return (dgettext(TEXT_DOMAIN, "Last Erred")); 659 case CS_RESYNC: 660 return (dgettext(TEXT_DOMAIN, "Resyncing")); 661 default: 662 return (dgettext(TEXT_DOMAIN, "invalid")); 663 } 664 } 665 666 /* 667 * print subdevice stripe row 668 */ 669 static int 670 subdev_row_report( 671 mdsetname_t *sp, 672 md_row_t *rp, 673 char *fname, 674 FILE *fp, 675 mdprtopts_t options, 676 uint_t top_tstate, /* Errored tstate flags */ 677 md_error_t *ep 678 ) 679 { 680 uint_t comp; 681 int rval = -1; 682 ddi_devid_t dtp; 683 int len = 0; 684 685 686 /* 687 * building a format string on the fly that will be used 688 * in fprintf. This is to allow really really long ctd names 689 */ 690 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 691 md_comp_t *cp = &rp->comps.comps_val[comp]; 692 char *cname = cp->compnamep->cname; 693 694 len = max(len, strlen(cname)); 695 } 696 697 len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device"))); 698 len += 2; 699 /* print header */ 700 if (! (options & PRINT_TIMES)) { 701 if (fprintf(fp, 702 "\t%-*.*s %-12.12s %5.5s %12.12s %5.5s %s\n", 703 len, len, 704 dgettext(TEXT_DOMAIN, "Device"), 705 dgettext(TEXT_DOMAIN, "Start Block"), 706 dgettext(TEXT_DOMAIN, "Dbase"), 707 dgettext(TEXT_DOMAIN, "State"), 708 dgettext(TEXT_DOMAIN, "Reloc"), 709 dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) { 710 goto out; 711 } 712 } else { 713 if (fprintf(fp, 714 "\t%-*s %5s %5s %-11s %-5s %-9s %s\n", 715 len, 716 dgettext(TEXT_DOMAIN, "Device"), 717 dgettext(TEXT_DOMAIN, "Start"), 718 dgettext(TEXT_DOMAIN, "Dbase"), 719 dgettext(TEXT_DOMAIN, "State"), 720 dgettext(TEXT_DOMAIN, "Reloc"), 721 dgettext(TEXT_DOMAIN, "Hot Spare"), 722 dgettext(TEXT_DOMAIN, "Time")) == EOF) { 723 goto out; 724 } 725 } 726 727 728 /* print components */ 729 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 730 md_comp_t *cp = &rp->comps.comps_val[comp]; 731 mdname_t *namep = cp->compnamep; 732 char *cname = namep->cname; 733 diskaddr_t start_blk; 734 int has_mddb; 735 char *has_mddb_str; 736 char *comp_state; 737 md_timeval32_t tv; 738 char *hsname = ((cp->hsnamep != NULL) ? 739 cp->hsnamep->cname : ""); 740 char *devid = " "; 741 mdname_t *didnp = NULL; 742 uint_t tstate = 0; 743 744 /* get info */ 745 if ((start_blk = metagetstart(sp, namep, ep)) == 746 MD_DISKADDR_ERROR) { 747 return (-1); 748 } 749 if ((has_mddb = metahasmddb(sp, namep, ep)) < 0) { 750 return (-1); 751 } 752 if (has_mddb) 753 has_mddb_str = dgettext(TEXT_DOMAIN, "Yes"); 754 else 755 has_mddb_str = dgettext(TEXT_DOMAIN, "No"); 756 757 /* 758 * If the component is a metadevice, print out either 759 * unavailable or the state of the metadevice, if not 760 * a metadevice, print nothing if the state of the 761 * stripe is unavailable 762 */ 763 if (metaismeta(namep)) { 764 if (meta_get_tstate(namep->dev, &tstate, ep) != 0) 765 return (-1); 766 comp_state = comp_state_to_name(cp, &tv, tstate & 767 MD_DEV_ERRORED); 768 } else { 769 /* 770 * if top_tstate is set, that implies that you have 771 * a ctd type device with an unavailable metadevice 772 * on top of it. If so, print a - for it's state 773 */ 774 if (top_tstate != 0) 775 comp_state = "-"; 776 else 777 comp_state = comp_state_to_name(cp, &tv, 778 tstate & MD_DEV_ERRORED); 779 } 780 781 /* populate the key in the name_p structure */ 782 if ((didnp = metadevname(&sp, namep->dev, ep)) 783 == NULL) { 784 return (-1); 785 } 786 787 /* determine if devid does NOT exist */ 788 if (options & PRINT_DEVID) { 789 if ((dtp = meta_getdidbykey(sp->setno, 790 getmyside(sp, ep), didnp->key, ep)) == NULL) 791 devid = dgettext(TEXT_DOMAIN, "No "); 792 else { 793 devid = dgettext(TEXT_DOMAIN, "Yes"); 794 free(dtp); 795 } 796 } 797 /* print info */ 798 /* 799 * building a format string on the fly that will be used 800 * in fprintf. This is to allow really really long ctd names 801 */ 802 if (! (options & PRINT_TIMES)) { 803 if (fprintf(fp, 804 "\t%-*s %8lld %-5.5s %12.12s %5.5s %s\n", 805 len, cname, start_blk, 806 has_mddb_str, comp_state, devid, hsname) == EOF) { 807 goto out; 808 } 809 } else { 810 char *timep = meta_print_time(&tv); 811 812 if (fprintf(fp, 813 "\t%-*s %5lld %-5s %-11s %-5s %-9s %s\n", 814 len, cname, start_blk, 815 has_mddb_str, comp_state, devid, hsname, 816 timep) == EOF) { 817 goto out; 818 } 819 } 820 } 821 822 /* success */ 823 rval = 0; 824 825 /* cleanup, return error */ 826 out: 827 if (rval != 0) 828 (void) mdsyserror(ep, errno, fname); 829 return (rval); 830 } 831 832 /* 833 * print toplevel stripe row 834 */ 835 /*ARGSUSED4*/ 836 static int 837 toplev_row_report( 838 mdsetname_t *sp, 839 md_row_t *rp, 840 char *fname, 841 FILE *fp, 842 mdprtopts_t options, 843 md_error_t *ep 844 ) 845 { 846 uint_t comp; 847 int rval = -1; 848 char *devid = " "; 849 mdname_t *didnp = NULL; 850 int len = 0; 851 852 /* 853 * building a format string on the fly that will be used 854 * in fprintf. This is to allow really really long ctd names 855 */ 856 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 857 len = max(len, 858 strlen(rp->comps.comps_val[comp].compnamep->cname)); 859 } 860 861 len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device"))); 862 len += 2; 863 /* print header */ 864 if (fprintf(fp, 865 "\t%-*.*s %-12.12s %-5.5s\t%s\n", 866 len, len, 867 dgettext(TEXT_DOMAIN, "Device"), 868 dgettext(TEXT_DOMAIN, "Start Block"), 869 dgettext(TEXT_DOMAIN, "Dbase"), 870 dgettext(TEXT_DOMAIN, "Reloc")) == EOF) { 871 goto out; 872 } 873 874 /* print components */ 875 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 876 md_comp_t *cp = &rp->comps.comps_val[comp]; 877 mdname_t *namep = cp->compnamep; 878 char *cname = namep->cname; 879 diskaddr_t start_blk; 880 int has_mddb; 881 char *has_mddb_str; 882 ddi_devid_t dtp; 883 884 /* get info */ 885 if ((start_blk = metagetstart(sp, namep, ep)) == 886 MD_DISKADDR_ERROR) { 887 return (-1); 888 } 889 if ((has_mddb = metahasmddb(sp, namep, ep)) < 0) { 890 return (-1); 891 } 892 if (has_mddb) 893 has_mddb_str = dgettext(TEXT_DOMAIN, "Yes"); 894 else 895 has_mddb_str = dgettext(TEXT_DOMAIN, "No"); 896 897 /* populate the key in the name_p structure */ 898 if ((didnp = metadevname(&sp, namep->dev, ep)) 899 == NULL) { 900 return (-1); 901 } 902 903 /* determine if devid does NOT exist */ 904 if (options & PRINT_DEVID) { 905 if ((dtp = meta_getdidbykey(sp->setno, 906 getmyside(sp, ep), didnp->key, ep)) == NULL) { 907 devid = dgettext(TEXT_DOMAIN, "No "); 908 } else { 909 devid = dgettext(TEXT_DOMAIN, "Yes"); 910 free(dtp); 911 } 912 } 913 /* print info */ 914 /* 915 * building a format string on the fly that will be used 916 * in fprintf. This is to allow really really long ctd names 917 */ 918 if (fprintf(fp, 919 "\t%-*s %8lld %-5.5s\t%s\n", len, 920 cname, start_blk, has_mddb_str, devid) == EOF) { 921 goto out; 922 } 923 } 924 925 /* success */ 926 rval = 0; 927 928 /* cleanup, return error */ 929 out: 930 if (rval != 0) 931 (void) mdsyserror(ep, errno, fname); 932 return (rval); 933 } 934 935 /* 936 * print stripe options 937 */ 938 int 939 meta_print_stripe_options( 940 mdhspname_t *hspnamep, 941 char *fname, 942 FILE *fp, 943 md_error_t *ep 944 ) 945 { 946 char *hspname = ((hspnamep != NULL) ? hspnamep->hspname : 947 dgettext(TEXT_DOMAIN, "none")); 948 int rval = -1; 949 950 /* print options */ 951 if (fprintf(fp, dgettext(TEXT_DOMAIN, 952 " Hot spare pool: %s\n"), hspname) == EOF) { 953 goto out; 954 } 955 956 /* success */ 957 rval = 0; 958 959 /* cleanup, return error */ 960 out: 961 if (rval != 0) 962 (void) mdsyserror(ep, errno, fname); 963 return (rval); 964 } 965 966 /* 967 * report stripe 968 */ 969 static int 970 stripe_report( 971 mdsetname_t *sp, 972 md_stripe_t *stripep, 973 mdnamelist_t **nlpp, 974 char *fname, 975 FILE *fp, 976 mdprtopts_t options, 977 md_error_t *ep 978 ) 979 { 980 uint_t row; 981 int rval = -1; 982 uint_t tstate = 0; 983 984 /* 985 * if the -B option has been specified check to see if the 986 * metadevice is s "big" one and print if so, also if a 987 * big device we need to store the ctd involved for use in 988 * printing out the relocation information. 989 */ 990 if (options & PRINT_LARGEDEVICES) { 991 if ((stripep->common.revision & MD_64BIT_META_DEV) == 0) { 992 rval = 0; 993 goto out; 994 } else { 995 if (meta_getdevs(sp, stripep->common.namep, 996 nlpp, ep) != 0) 997 goto out; 998 } 999 } 1000 1001 /* 1002 * if the -D option has been specified check to see if the 1003 * metadevice has a descriptive name and print if so, also if a 1004 * descriptive device name we need to store the ctd involved 1005 * for use in printing out the relocation information. 1006 */ 1007 if (options & PRINT_FN) { 1008 if ((stripep->common.revision & MD_FN_META_DEV) == 0) { 1009 rval = 0; 1010 goto out; 1011 } else { 1012 if (meta_getdevs(sp, stripep->common.namep, 1013 nlpp, ep) != 0) 1014 goto out; 1015 } 1016 } 1017 1018 /* print header */ 1019 if (options & PRINT_HEADER) { 1020 if (fprintf(fp, "%s: Concat/Stripe\n", 1021 stripep->common.namep->cname) == EOF) { 1022 goto out; 1023 } 1024 1025 } 1026 1027 /* print hotspare pool */ 1028 if (stripep->hspnamep != NULL) { 1029 if (meta_print_stripe_options(stripep->hspnamep, 1030 fname, fp, ep) != 0) { 1031 return (-1); 1032 } 1033 } 1034 1035 if (metaismeta(stripep->common.namep)) { 1036 if (meta_get_tstate(stripep->common.namep->dev, &tstate, ep) 1037 != 0) 1038 return (-1); 1039 } 1040 if ((tstate & MD_DEV_ERRORED) != 0) { 1041 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1042 " State: Unavailable\n" 1043 " Reconnect disk and invoke: metastat -i\n")) == EOF) { 1044 goto out; 1045 } 1046 } 1047 1048 /* print size */ 1049 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"), 1050 stripep->common.size, 1051 meta_number_to_string(stripep->common.size, DEV_BSIZE)) 1052 == EOF) { 1053 goto out; 1054 } 1055 1056 /* print rows */ 1057 for (row = 0; (row < stripep->rows.rows_len); ++row) { 1058 md_row_t *rp = &stripep->rows.rows_val[row]; 1059 1060 /* print stripe and interlace */ 1061 if (rp->comps.comps_len > 1) { 1062 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1063 " Stripe %u: (interlace: %lld blocks)\n"), 1064 row, rp->interlace) == EOF) { 1065 goto out; 1066 } 1067 } else { 1068 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1069 " Stripe %u:\n"), 1070 row) == EOF) { 1071 goto out; 1072 } 1073 } 1074 1075 /* print components appropriately */ 1076 if (MD_HAS_PARENT(stripep->common.parent)) { 1077 if (subdev_row_report(sp, rp, fname, fp, options, 1078 tstate & MD_DEV_ERRORED, ep) != 0) { 1079 return (-1); 1080 } 1081 } else { 1082 if (toplev_row_report(sp, rp, fname, fp, options, 1083 ep) != 0) { 1084 return (-1); 1085 } 1086 } 1087 } 1088 1089 /* add extra line */ 1090 if (fprintf(fp, "\n") == EOF) 1091 goto out; 1092 1093 /* success */ 1094 rval = 0; 1095 1096 /* cleanup, return error */ 1097 out: 1098 if (rval != 0) 1099 (void) mdsyserror(ep, errno, fname); 1100 return (rval); 1101 } 1102 1103 /* 1104 * print/report stripe 1105 */ 1106 int 1107 meta_stripe_print( 1108 mdsetname_t *sp, 1109 mdname_t *stripenp, 1110 mdnamelist_t **nlpp, 1111 char *fname, 1112 FILE *fp, 1113 mdprtopts_t options, 1114 md_error_t *ep 1115 ) 1116 { 1117 md_stripe_t *stripep; 1118 int row, comp; 1119 1120 /* should have same set */ 1121 assert(sp != NULL); 1122 assert((stripenp == NULL) || 1123 (sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)))); 1124 1125 /* print all stripes */ 1126 if (stripenp == NULL) { 1127 mdnamelist_t *nlp = NULL; 1128 mdnamelist_t *p; 1129 int cnt; 1130 int rval = 0; 1131 1132 /* get list */ 1133 if ((cnt = meta_get_stripe_names(sp, &nlp, options, ep)) < 0) 1134 return (-1); 1135 else if (cnt == 0) 1136 return (0); 1137 1138 /* recurse */ 1139 for (p = nlp; (p != NULL); p = p->next) { 1140 mdname_t *np = p->namep; 1141 1142 if (meta_stripe_print(sp, np, nlpp, fname, fp, 1143 options, ep) != 0) 1144 rval = -1; 1145 } 1146 1147 /* cleanup, return success */ 1148 metafreenamelist(nlp); 1149 return (rval); 1150 } 1151 1152 /* get unit structure */ 1153 if ((stripep = meta_get_stripe_common(sp, stripenp, 1154 ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL) 1155 return (-1); 1156 1157 /* check for parented */ 1158 if ((! (options & PRINT_SUBDEVS)) && 1159 (MD_HAS_PARENT(stripep->common.parent))) { 1160 return (0); 1161 } 1162 1163 /* print appropriate detail */ 1164 if (options & PRINT_SHORT) { 1165 if (stripe_print(stripep, fname, fp, options, ep) != 0) 1166 return (-1); 1167 } else { 1168 if (stripe_report(sp, stripep, nlpp, fname, fp, options, 1169 ep) != 0) 1170 return (-1); 1171 } 1172 1173 /* Recurse on components that are metadevices */ 1174 for (row = 0; (row < stripep->rows.rows_len); ++row) { 1175 md_row_t *rp = &stripep->rows.rows_val[row]; 1176 1177 /* look for components that are metadevices */ 1178 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1179 md_comp_t *cp = &rp->comps.comps_val[comp]; 1180 mdname_t *namep = cp->compnamep; 1181 1182 if ((metaismeta(namep)) && 1183 (meta_print_name(sp, namep, nlpp, fname, fp, 1184 (options | PRINT_HEADER | PRINT_SUBDEVS), 1185 NULL, ep) != 0)) { 1186 return (-1); 1187 } 1188 } 1189 } 1190 return (0); 1191 } 1192 1193 /* 1194 * find stripe component to replace 1195 */ 1196 int 1197 meta_find_erred_comp( 1198 mdsetname_t *sp, 1199 mdname_t *stripenp, 1200 mdname_t **compnpp, 1201 comp_state_t *compstate, 1202 md_error_t *ep 1203 ) 1204 { 1205 md_stripe_t *stripep; 1206 md_comp_t *compp = NULL; 1207 uint_t lasterrcnt = 0; 1208 uint_t row; 1209 1210 /* get stripe */ 1211 *compnpp = NULL; 1212 if ((stripep = meta_get_stripe_common(sp, stripenp, 1, ep)) == NULL) 1213 return (-1); 1214 1215 /* 1216 * Try to find the first erred component. 1217 * If there is not one, then look for the 1218 * first last_erred component. 1219 */ 1220 for (row = 0; (row < stripep->rows.rows_len); ++row) { 1221 md_row_t *rp = &stripep->rows.rows_val[row]; 1222 uint_t comp; 1223 1224 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1225 md_comp_t *cp = &rp->comps.comps_val[comp]; 1226 1227 if ((cp->state == CS_ERRED) && ((compp == NULL) || 1228 (cp->lasterrcnt < lasterrcnt))) { 1229 compp = cp; 1230 lasterrcnt = cp->lasterrcnt; 1231 } 1232 } 1233 } 1234 for (row = 0; (row < stripep->rows.rows_len); ++row) { 1235 md_row_t *rp = &stripep->rows.rows_val[row]; 1236 uint_t comp; 1237 1238 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1239 md_comp_t *cp = &rp->comps.comps_val[comp]; 1240 1241 if ((cp->state == CS_LAST_ERRED) && ((compp == NULL) || 1242 (cp->lasterrcnt < lasterrcnt))) { 1243 compp = cp; 1244 lasterrcnt = cp->lasterrcnt; 1245 } 1246 } 1247 } 1248 1249 /* return component */ 1250 if (compp != NULL) { 1251 *compnpp = compp->compnamep; 1252 *compstate = compp->state; 1253 } 1254 1255 /* return success */ 1256 return (0); 1257 } 1258 1259 /* 1260 * invalidate component names 1261 */ 1262 static int 1263 invalidate_components( 1264 mdsetname_t *sp, 1265 mdname_t *stripenp, 1266 md_error_t *ep 1267 ) 1268 { 1269 md_stripe_t *stripep; 1270 uint_t row; 1271 1272 if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL) 1273 return (-1); 1274 for (row = 0; (row < stripep->rows.rows_len); ++row) { 1275 md_row_t *rp = &stripep->rows.rows_val[row]; 1276 uint_t comp; 1277 1278 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1279 md_comp_t *cp = &rp->comps.comps_val[comp]; 1280 mdname_t *compnp = cp->compnamep; 1281 1282 meta_invalidate_name(compnp); 1283 } 1284 } 1285 return (0); 1286 } 1287 1288 /* 1289 * attach components to stripe 1290 */ 1291 int 1292 meta_stripe_attach( 1293 mdsetname_t *sp, 1294 mdname_t *stripenp, 1295 mdnamelist_t *nlp, 1296 diskaddr_t interlace, 1297 mdcmdopts_t options, 1298 md_error_t *ep 1299 ) 1300 { 1301 mdnamelist_t *lp; 1302 ms_unit_t *old_un, *new_un; 1303 struct ms_row *mdr, *new_mdr; 1304 uint_t newcomps, ncomps, icomp; 1305 uint_t row; 1306 size_t mdsize, first_comp; 1307 diskaddr_t new_blks; 1308 diskaddr_t limit; 1309 diskaddr_t disk_size = 0; 1310 ms_comp_t *mdcomp, *new_comp; 1311 uint_t write_reinstruct = 0; 1312 uint_t read_reinstruct = 0; 1313 mdnamelist_t *keynlp = NULL; 1314 uint_t round_cyl = 1; 1315 minor_t parent; 1316 md_grow_params_t mgp; 1317 int rval = -1; 1318 md_timeval32_t creation_time; 1319 int create_flag = MD_CRO_32BIT; 1320 1321 /* should have a set */ 1322 assert(sp != NULL); 1323 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 1324 1325 /* check type */ 1326 if (metachkmeta(stripenp, ep) != 0) 1327 return (-1); 1328 1329 /* check and count components */ 1330 assert(nlp != NULL); 1331 newcomps = 0; 1332 for (lp = nlp; (lp != NULL); lp = lp->next) { 1333 mdname_t *np = lp->namep; 1334 mdnamelist_t *p; 1335 1336 /* check against existing devices */ 1337 if (meta_check_component(sp, np, 0, ep) != 0) 1338 return (-1); 1339 1340 /* check against ourselves */ 1341 for (p = lp->next; (p != NULL); p = p->next) { 1342 if (meta_check_overlap(np->cname, np, 0, -1, 1343 p->namep, 0, -1, ep) != 0) { 1344 return (-1); 1345 } 1346 } 1347 1348 /* count */ 1349 ++newcomps; 1350 } 1351 1352 /* get old unit */ 1353 if ((old_un = (ms_unit_t *)meta_get_mdunit(sp, stripenp, ep)) == NULL) 1354 return (-1); 1355 1356 /* if zero, inherit the last rows interlace value */ 1357 if (interlace == 0) { 1358 mdr = &old_un->un_row[old_un->un_nrows - 1]; 1359 interlace = mdr->un_interlace; 1360 } 1361 1362 /* 1363 * calculate size of new unit structure 1364 */ 1365 1366 /* unit + rows */ 1367 mdsize = sizeof (ms_unit_t) - sizeof (struct ms_row); 1368 mdsize += sizeof (struct ms_row) * (old_un->un_nrows + 1); 1369 1370 /* number of new components being added */ 1371 ncomps = newcomps; 1372 1373 /* count the # of components in the old unit */ 1374 mdr = &old_un->un_row[0]; 1375 for (row = 0; (row < old_un->un_nrows); row++) 1376 ncomps += mdr[row].un_ncomp; 1377 first_comp = roundup(mdsize, sizeof (long long)); 1378 mdsize += sizeof (ms_comp_t) * ncomps + (first_comp - mdsize); 1379 1380 /* allocate new unit */ 1381 new_un = Zalloc(mdsize); 1382 new_un->un_ocomp = first_comp; 1383 1384 /* compute new data */ 1385 new_mdr = &new_un->un_row[old_un->un_nrows]; 1386 new_mdr->un_icomp = ncomps - newcomps; 1387 new_mdr->un_ncomp = newcomps; 1388 new_mdr->un_blocks = 0; 1389 new_mdr->un_cum_blocks = 1390 old_un->un_row[old_un->un_nrows - 1].un_cum_blocks; 1391 new_mdr->un_interlace = interlace; 1392 1393 /* for each new device */ 1394 mdcomp = (struct ms_comp *)(void *)&((char *)new_un)[new_un->un_ocomp]; 1395 icomp = new_mdr->un_icomp; 1396 if (meta_gettimeofday(&creation_time) == -1) 1397 return (mdsyserror(ep, errno, NULL)); 1398 for (lp = nlp; (lp != NULL); lp = lp->next) { 1399 mdname_t *np = lp->namep; 1400 diskaddr_t size, start_blk; 1401 mdgeom_t *geomp; 1402 1403 /* figure out how big */ 1404 if ((size = metagetsize(np, ep)) == MD_DISKADDR_ERROR) 1405 goto out; 1406 if ((start_blk = metagetstart(sp, np, ep)) == 1407 MD_DISKADDR_ERROR) 1408 goto out; 1409 if (start_blk >= size) { 1410 (void) mdsyserror(ep, ENOSPC, np->cname); 1411 goto out; 1412 } 1413 size -= start_blk; 1414 if (newcomps > 1) 1415 size = rounddown(size, interlace); 1416 1417 /* adjust for smallest disk */ 1418 if (disk_size == 0) { 1419 disk_size = size; 1420 } else if (size < disk_size) { 1421 disk_size = size; 1422 } 1423 1424 /* get worst reinstructs */ 1425 if ((geomp = metagetgeom(np, ep)) == NULL) 1426 goto out; 1427 if (geomp->write_reinstruct > write_reinstruct) 1428 write_reinstruct = geomp->write_reinstruct; 1429 if (geomp->read_reinstruct > read_reinstruct) 1430 read_reinstruct = geomp->read_reinstruct; 1431 1432 /* In dryrun mode (DOIT not set) we must not alter the mddb */ 1433 if (options & MDCMD_DOIT) { 1434 /* store name in namespace */ 1435 if (add_key_name(sp, np, &keynlp, ep) != 0) 1436 goto out; 1437 } 1438 1439 /* build new component */ 1440 new_comp = &mdcomp[icomp++]; 1441 new_comp->un_key = np->key; 1442 new_comp->un_dev = np->dev; 1443 new_comp->un_start_block = start_blk; 1444 new_comp->un_mirror.ms_state = CS_OKAY; 1445 new_comp->un_mirror.ms_timestamp = creation_time; 1446 } 1447 1448 limit = LLONG_MAX; 1449 1450 /* compute new size */ 1451 new_mdr->un_blocks = new_mdr->un_ncomp * disk_size; 1452 new_blks = new_mdr->un_cum_blocks + new_mdr->un_blocks; 1453 if (new_blks > limit) { 1454 new_mdr->un_cum_blocks = limit; 1455 new_blks = limit; 1456 md_eprintf(dgettext(TEXT_DOMAIN, 1457 "unit size overflow, limit is %lld blocks\n"), 1458 limit); 1459 } else { 1460 new_mdr->un_cum_blocks += new_mdr->un_blocks; 1461 } 1462 new_un->c.un_actual_tb = new_mdr->un_cum_blocks; 1463 new_un->un_nrows = old_un->un_nrows + 1; 1464 1465 /* adjust geometry */ 1466 new_un->c.un_nhead = old_un->c.un_nhead; 1467 new_un->c.un_nsect = old_un->c.un_nsect; 1468 new_un->c.un_rpm = old_un->c.un_rpm; 1469 new_un->c.un_wr_reinstruct = old_un->c.un_wr_reinstruct; 1470 new_un->c.un_rd_reinstruct = old_un->c.un_rd_reinstruct; 1471 if (meta_adjust_geom((md_unit_t *)new_un, stripenp, 1472 write_reinstruct, read_reinstruct, round_cyl, ep) != 0) 1473 goto out; 1474 1475 /* if in dryrun mode, we are done here. */ 1476 if ((options & MDCMD_DOIT) == 0) { 1477 if (options & MDCMD_PRINT) { 1478 if (newcomps == 1) { 1479 (void) printf(dgettext(TEXT_DOMAIN, 1480 "%s: attaching component would suceed\n"), 1481 stripenp->cname); 1482 } else { 1483 (void) printf(dgettext(TEXT_DOMAIN, 1484 "%s: attaching components would suceed\n"), 1485 stripenp->cname); 1486 } 1487 } 1488 rval = 0; /* success */ 1489 goto out; 1490 } 1491 1492 create_flag = meta_check_devicesize(new_un->c.un_total_blocks); 1493 1494 /* grow stripe */ 1495 (void) memset(&mgp, 0, sizeof (mgp)); 1496 mgp.mnum = MD_SID(old_un); 1497 MD_SETDRIVERNAME(&mgp, MD_STRIPE, sp->setno); 1498 mgp.size = mdsize; 1499 mgp.mdp = (uintptr_t)new_un; 1500 mgp.nrows = old_un->un_nrows; 1501 if (create_flag == MD_CRO_32BIT) { 1502 mgp.options = MD_CRO_32BIT; 1503 new_un->c.un_revision &= ~MD_64BIT_META_DEV; 1504 } else { 1505 mgp.options = MD_CRO_64BIT; 1506 new_un->c.un_revision |= MD_64BIT_META_DEV; 1507 } 1508 1509 if ((MD_HAS_PARENT(old_un->c.un_parent)) && 1510 (old_un->c.un_parent != MD_MULTI_PARENT)) { 1511 mgp.npar = 1; 1512 parent = old_un->c.un_parent; 1513 mgp.par = (uintptr_t)(&parent); 1514 } 1515 1516 if (metaioctl(MD_IOCGROW, &mgp, &mgp.mde, NULL) != 0) { 1517 (void) mdstealerror(ep, &mgp.mde); 1518 goto out; 1519 } 1520 1521 /* clear cache */ 1522 if (invalidate_components(sp, stripenp, ep) != 0) 1523 goto out; 1524 meta_invalidate_name(stripenp); 1525 1526 /* let em know */ 1527 if (options & MDCMD_PRINT) { 1528 if (newcomps == 1) { 1529 (void) printf(dgettext(TEXT_DOMAIN, 1530 "%s: component is attached\n"), stripenp->cname); 1531 } else { 1532 (void) printf(dgettext(TEXT_DOMAIN, 1533 "%s: components are attached\n"), stripenp->cname); 1534 } 1535 (void) fflush(stdout); 1536 } 1537 1538 /* grow any parents */ 1539 if (meta_concat_parent(sp, stripenp, ep) != 0) 1540 return (-1); 1541 1542 rval = 0; /* success */ 1543 1544 /* cleanup, return error */ 1545 out: 1546 Free(old_un); 1547 Free(new_un); 1548 if (options & MDCMD_DOIT) { 1549 if (rval != 0) 1550 (void) del_key_names(sp, keynlp, NULL); 1551 metafreenamelist(keynlp); 1552 } 1553 return (rval); 1554 } 1555 1556 /* 1557 * get stripe parameters 1558 */ 1559 int 1560 meta_stripe_get_params( 1561 mdsetname_t *sp, 1562 mdname_t *stripenp, 1563 ms_params_t *paramsp, 1564 md_error_t *ep 1565 ) 1566 { 1567 md_stripe_t *stripep; 1568 1569 /* should have a set */ 1570 assert(sp != NULL); 1571 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 1572 1573 /* check name */ 1574 if (metachkmeta(stripenp, ep) != 0) 1575 return (-1); 1576 1577 /* get unit */ 1578 if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL) 1579 return (-1); 1580 1581 /* return parameters */ 1582 (void) memset(paramsp, 0, sizeof (*paramsp)); 1583 if (stripep->hspnamep == NULL) 1584 paramsp->hsp_id = MD_HSP_NONE; 1585 else 1586 paramsp->hsp_id = stripep->hspnamep->hsp; 1587 return (0); 1588 } 1589 1590 /* 1591 * set stripe parameters 1592 */ 1593 int 1594 meta_stripe_set_params( 1595 mdsetname_t *sp, 1596 mdname_t *stripenp, 1597 ms_params_t *paramsp, 1598 md_error_t *ep 1599 ) 1600 { 1601 md_stripe_params_t msp; 1602 1603 /* should have a set */ 1604 assert(sp != NULL); 1605 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 1606 1607 /* check name */ 1608 if (metachkmeta(stripenp, ep) != 0) 1609 return (-1); 1610 1611 /* set parameters */ 1612 (void) memset(&msp, 0, sizeof (msp)); 1613 MD_SETDRIVERNAME(&msp, MD_STRIPE, sp->setno); 1614 msp.mnum = meta_getminor(stripenp->dev); 1615 msp.params = *paramsp; 1616 if (metaioctl(MD_IOCCHANGE, &msp, &msp.mde, stripenp->cname) != 0) 1617 return (mdstealerror(ep, &msp.mde)); 1618 1619 /* clear cache */ 1620 meta_invalidate_name(stripenp); 1621 1622 /* return success */ 1623 return (0); 1624 } 1625 1626 /* 1627 * check for dups in the stripe itself 1628 */ 1629 static int 1630 check_twice( 1631 md_stripe_t *stripep, 1632 uint_t row, 1633 uint_t comp, 1634 md_error_t *ep 1635 ) 1636 { 1637 mdname_t *stripenp = stripep->common.namep; 1638 mdname_t *thisnp; 1639 uint_t r; 1640 1641 thisnp = stripep->rows.rows_val[row].comps.comps_val[comp].compnamep; 1642 for (r = 0; (r <= row); ++r) { 1643 md_row_t *rp = &stripep->rows.rows_val[r]; 1644 uint_t e = ((r == row) ? comp : rp->comps.comps_len); 1645 uint_t c; 1646 1647 for (c = 0; (c < e); ++c) { 1648 md_comp_t *cp = &rp->comps.comps_val[c]; 1649 mdname_t *compnp = cp->compnamep; 1650 1651 if (meta_check_overlap(stripenp->cname, thisnp, 0, -1, 1652 compnp, 0, -1, ep) != 0) { 1653 return (-1); 1654 } 1655 } 1656 } 1657 return (0); 1658 } 1659 1660 /* 1661 * default stripe interlace 1662 */ 1663 diskaddr_t 1664 meta_default_stripe_interlace(void) 1665 { 1666 diskaddr_t interlace; 1667 1668 /* default to 512k, round up if necessary */ 1669 interlace = btodb(512 * 1024); 1670 if (interlace < btodb(MININTERLACE)) 1671 interlace = roundup(MININTERLACE, interlace); 1672 return (interlace); 1673 } 1674 1675 /* 1676 * convert interlaces 1677 */ 1678 int 1679 meta_stripe_check_interlace( 1680 diskaddr_t interlace, 1681 char *uname, 1682 md_error_t *ep 1683 ) 1684 { 1685 if ((interlace < btodb(MININTERLACE)) || 1686 (interlace > btodb(MAXINTERLACE))) { 1687 return (mderror(ep, MDE_BAD_INTERLACE, uname)); 1688 } 1689 return (0); 1690 } 1691 1692 1693 /* 1694 * check stripe 1695 */ 1696 int 1697 meta_check_stripe( 1698 mdsetname_t *sp, 1699 md_stripe_t *stripep, 1700 mdcmdopts_t options, 1701 md_error_t *ep 1702 ) 1703 { 1704 mdname_t *stripenp = stripep->common.namep; 1705 int force = ((options & MDCMD_FORCE) ? 1 : 0); 1706 int doit = ((options & MDCMD_DOIT) ? 1 : 0); 1707 int updateit = ((options & MDCMD_UPDATE) ? 1 : 0); 1708 uint_t row; 1709 1710 /* check rows */ 1711 if (stripep->rows.rows_len < 1) { 1712 return (mdmderror(ep, MDE_BAD_STRIPE, 1713 meta_getminor(stripenp->dev), stripenp->cname)); 1714 } 1715 for (row = 0; (row < stripep->rows.rows_len); ++row) { 1716 md_row_t *rp = &stripep->rows.rows_val[row]; 1717 uint_t comp; 1718 1719 /* check number */ 1720 if (rp->comps.comps_len < 1) { 1721 return (mdmderror(ep, MDE_BAD_STRIPE, 1722 meta_getminor(stripenp->dev), stripenp->cname)); 1723 } 1724 1725 /* compute default interlace */ 1726 if (rp->interlace == 0) { 1727 rp->interlace = meta_default_stripe_interlace(); 1728 } 1729 1730 /* check interlace */ 1731 if (meta_stripe_check_interlace(rp->interlace, stripenp->cname, 1732 ep) != 0) { 1733 return (-1); 1734 } 1735 1736 /* check components */ 1737 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1738 md_comp_t *cp = &rp->comps.comps_val[comp]; 1739 mdname_t *compnp = cp->compnamep; 1740 diskaddr_t start_blk, size; 1741 1742 /* check component */ 1743 if (!updateit) { 1744 if (meta_check_component(sp, compnp, 1745 force, ep) != 0) 1746 return (-1); 1747 if (((start_blk = metagetstart(sp, compnp, 1748 ep)) == MD_DISKADDR_ERROR) || 1749 ((size = metagetsize(compnp, ep)) == 1750 MD_DISKADDR_ERROR)) { 1751 return (-1); 1752 } 1753 if (start_blk >= size) 1754 return (mdsyserror(ep, ENOSPC, 1755 compnp->cname)); 1756 size -= start_blk; 1757 size = rounddown(size, rp->interlace); 1758 if (size == 0) 1759 return (mdsyserror(ep, ENOSPC, 1760 compnp->cname)); 1761 } 1762 1763 /* check this stripe too */ 1764 if (check_twice(stripep, row, comp, ep) != 0) 1765 return (-1); 1766 } 1767 } 1768 1769 /* check hotspare pool name */ 1770 if (doit) { 1771 if ((stripep->hspnamep != NULL) && 1772 (metachkhsp(sp, stripep->hspnamep, ep) != 0)) { 1773 return (-1); 1774 } 1775 } 1776 1777 /* return success */ 1778 return (0); 1779 } 1780 1781 /* 1782 * setup stripe geometry 1783 */ 1784 static int 1785 stripe_geom( 1786 md_stripe_t *stripep, 1787 ms_unit_t *ms, 1788 md_error_t *ep 1789 ) 1790 { 1791 uint_t nrow = stripep->rows.rows_len; 1792 uint_t write_reinstruct = 0; 1793 uint_t read_reinstruct = 0; 1794 uint_t round_cyl = 1; 1795 uint_t row; 1796 mdgeom_t *geomp; 1797 diskaddr_t first_row_size = 0; 1798 char *miscname; 1799 int is_sp = 0; 1800 1801 /* get worst reinstructs */ 1802 for (row = 0; (row < nrow); ++row) { 1803 md_row_t *rp = &stripep->rows.rows_val[row]; 1804 uint_t ncomp = rp->comps.comps_len; 1805 uint_t comp; 1806 1807 for (comp = 0; (comp < ncomp); ++comp) { 1808 md_comp_t *cp = &rp->comps.comps_val[comp]; 1809 mdname_t *compnp = cp->compnamep; 1810 1811 if ((geomp = metagetgeom(compnp, ep)) == NULL) 1812 return (-1); 1813 if (geomp->write_reinstruct > write_reinstruct) 1814 write_reinstruct = geomp->write_reinstruct; 1815 if (geomp->read_reinstruct > read_reinstruct) 1816 read_reinstruct = geomp->read_reinstruct; 1817 } 1818 } 1819 1820 if ((geomp = metagetgeom( 1821 stripep->rows.rows_val[0].comps.comps_val[0].compnamep, 1822 ep)) == NULL) { 1823 return (-1); 1824 } 1825 /* 1826 * Figure out if the first component is a softpartition as the 1827 * truncation check only occurs on them. 1828 */ 1829 if ((miscname = metagetmiscname( 1830 stripep->rows.rows_val[0].comps.comps_val[0].compnamep, 1831 ep)) == NULL) { 1832 if (!mdisdeverror(ep, MDE_NOT_META)) 1833 return (-1); 1834 } else if (strcmp(miscname, MD_SP) == 0) { 1835 is_sp = 1; 1836 } 1837 1838 /* 1839 * If the stripe is to be multi-terabyte we should 1840 * use EFI geometries, else we can get rounding errors 1841 * in meta_setup_geom(). 1842 */ 1843 1844 if (ms->c.un_actual_tb > MD_MAX_BLKS_FOR_SMALL_DEVS) { 1845 geomp->nhead = MD_EFI_FG_HEADS; 1846 geomp->nsect = MD_EFI_FG_SECTORS; 1847 geomp->rpm = MD_EFI_FG_RPM; 1848 } 1849 1850 /* setup geometry from first device */ 1851 if (meta_setup_geom((md_unit_t *)ms, stripep->common.namep, geomp, 1852 write_reinstruct, read_reinstruct, round_cyl, ep) != 0) 1853 return (-1); 1854 1855 /* 1856 * Here we want to make sure that any truncation did not 1857 * result in lost data (or, more appropriately, inaccessible 1858 * data). 1859 * 1860 * This is mainly a danger for (1, 1) concats, but it is 1861 * mathematically possible for other somewhat contrived 1862 * arrangements where in the sum of the lengths of each row 1863 * beyond the first is smaller than the cylinder size of the 1864 * only component in the first row. 1865 * 1866 * It is tempting to simply test for truncation here, by 1867 * (md->c.un_total_blocks < md->c.un_actual_tb). That does 1868 * not tell us, however, if rounding resulted in data loss, 1869 * rather only that it occurred. The somewhat less obvious 1870 * test below covers both the obvious (1, 1) case and the 1871 * aforementioned corner case. 1872 */ 1873 first_row_size = ms->un_row[0].un_blocks; 1874 if (is_sp == 1) { 1875 md_unit_t *md = (md_unit_t *)ms; 1876 1877 if (md->c.un_total_blocks < first_row_size) { 1878 char buf[] = VAL2STR(ULLONG_MAX); 1879 1880 /* 1881 * The only difference here is the text of the error 1882 * message, since the remediation is slightly 1883 * different in the one-component versus 1884 * multiple-component cases. 1885 */ 1886 if (nrow == 1) { 1887 (void) mderror(ep, MDE_STRIPE_TRUNC_SINGLE, 1888 stripep->common.namep->cname); 1889 } else { 1890 (void) mderror(ep, MDE_STRIPE_TRUNC_MULTIPLE, 1891 stripep->common.namep->cname); 1892 } 1893 1894 /* 1895 * By the size comparison above and the initialization 1896 * of buf[] in terms of ULLONG_MAX, we guarantee that 1897 * the value arg is non-negative and that we won't 1898 * overflow the container. 1899 */ 1900 mderrorextra(ep, ulltostr((md->c.un_total_blocks + 1901 (geomp->nhead * geomp->nsect)) 1902 - first_row_size, &buf[sizeof (buf) - 1])); 1903 1904 return (-1); 1905 } 1906 } 1907 1908 /* return success */ 1909 return (0); 1910 } 1911 1912 /* 1913 * create stripe 1914 */ 1915 int 1916 meta_create_stripe( 1917 mdsetname_t *sp, 1918 md_stripe_t *stripep, 1919 mdcmdopts_t options, 1920 md_error_t *ep 1921 ) 1922 { 1923 mdname_t *stripenp = stripep->common.namep; 1924 int force = ((options & MDCMD_FORCE) ? 1 : 0); 1925 int doall = ((options & MDCMD_ALLOPTION) ? 1 : 0); 1926 uint_t nrow = stripep->rows.rows_len; 1927 uint_t ncomp = 0; 1928 uint_t icomp = 0; 1929 diskaddr_t cum_blocks = 0; 1930 diskaddr_t limit; 1931 size_t mdsize, first_comp; 1932 uint_t row; 1933 ms_unit_t *ms; 1934 ms_comp_t *mdcomp; 1935 mdnamelist_t *keynlp = NULL; 1936 md_set_params_t set_params; 1937 int rval = -1; 1938 md_timeval32_t creation_time; 1939 int create_flag = MD_CRO_32BIT; 1940 1941 /* validate stripe */ 1942 if (meta_check_stripe(sp, stripep, options, ep) != 0) 1943 return (-1); 1944 1945 /* allocate stripe unit */ 1946 mdsize = sizeof (*ms) - sizeof (ms->un_row[0]); 1947 mdsize += sizeof (ms->un_row) * nrow; 1948 for (row = 0; (row < nrow); ++row) { 1949 md_row_t *rp = &stripep->rows.rows_val[row]; 1950 1951 ncomp += rp->comps.comps_len; 1952 } 1953 first_comp = roundup(mdsize, sizeof (long long)); 1954 mdsize += (first_comp - mdsize) + (ncomp * sizeof (ms_comp_t)); 1955 ms = Zalloc(mdsize); 1956 ms->un_ocomp = first_comp; 1957 if (meta_gettimeofday(&creation_time) == -1) 1958 return (mdsyserror(ep, errno, NULL)); 1959 1960 /* do rows */ 1961 mdcomp = (ms_comp_t *)(void *)&((char *)ms)[ms->un_ocomp]; 1962 for (row = 0; (row < nrow); ++row) { 1963 md_row_t *rp = &stripep->rows.rows_val[row]; 1964 uint_t ncomp = rp->comps.comps_len; 1965 struct ms_row *mdr = &ms->un_row[row]; 1966 diskaddr_t disk_size = 0; 1967 uint_t comp; 1968 1969 /* setup component count and offfset */ 1970 mdr->un_icomp = icomp; 1971 mdr->un_ncomp = ncomp; 1972 1973 /* do components */ 1974 for (comp = 0; (comp < ncomp); ++comp) { 1975 md_comp_t *cp = &rp->comps.comps_val[comp]; 1976 mdname_t *compnp = cp->compnamep; 1977 ms_comp_t *mdc = &mdcomp[icomp++]; 1978 diskaddr_t size, start_blk; 1979 1980 /* 1981 * get start and size 1982 * if first component is labelled, include label 1983 */ 1984 if ((size = metagetsize(compnp, ep)) == 1985 MD_DISKADDR_ERROR) 1986 goto out; 1987 if ((start_blk = metagetstart(sp, compnp, ep)) == 1988 MD_DISKADDR_ERROR) 1989 goto out; 1990 if ((row == 0) && (comp == 0)) { 1991 diskaddr_t label; 1992 int has_db; 1993 1994 if ((has_db = metahasmddb(sp, compnp, ep)) < 0) 1995 goto out; 1996 if ((label = metagetlabel(compnp, ep)) == 1997 MD_DISKADDR_ERROR) 1998 goto out; 1999 if ((has_db == 0) && (label != 0)) { 2000 ms->c.un_flag |= MD_LABELED; 2001 start_blk = compnp->start_blk = 0; 2002 } 2003 } 2004 /* make sure we still have something left */ 2005 if (start_blk >= size) { 2006 (void) mdsyserror(ep, ENOSPC, compnp->cname); 2007 goto out; 2008 } 2009 size -= start_blk; 2010 2011 /* 2012 * round down by interlace: this only applies 2013 * if this row is a stripe, as indicated by 2014 * (ncomp > 1) 2015 */ 2016 if (ncomp > 1) 2017 size = rounddown(size, rp->interlace); 2018 2019 if (size == 0) { 2020 (void) mdsyserror(ep, ENOSPC, compnp->cname); 2021 goto out; 2022 } 2023 2024 /* 2025 * adjust for smallest disk: for a concat (any 2026 * row with only one component), this will 2027 * never hit the second conditional. 2028 */ 2029 if (disk_size == 0) { 2030 disk_size = size; 2031 } else if (size < disk_size) { 2032 disk_size = size; 2033 } 2034 2035 if (options & MDCMD_DOIT) { 2036 /* store name in namespace */ 2037 if (add_key_name(sp, compnp, &keynlp, ep) != 0) 2038 goto out; 2039 } 2040 2041 /* setup component */ 2042 mdc->un_key = compnp->key; 2043 mdc->un_dev = compnp->dev; 2044 mdc->un_start_block = start_blk; 2045 mdc->un_mirror.ms_state = CS_OKAY; 2046 mdc->un_mirror.ms_timestamp = creation_time; 2047 } 2048 limit = LLONG_MAX; 2049 2050 /* setup row */ 2051 mdr->un_blocks = mdr->un_ncomp * disk_size; 2052 cum_blocks += mdr->un_blocks; 2053 if (cum_blocks > limit) { 2054 cum_blocks = limit; 2055 md_eprintf(dgettext(TEXT_DOMAIN, 2056 "unit size overflow, limit is %lld blocks\n"), 2057 limit); 2058 } 2059 mdr->un_cum_blocks = cum_blocks; 2060 mdr->un_interlace = rp->interlace; 2061 } 2062 2063 /* setup unit */ 2064 ms->c.un_type = MD_DEVICE; 2065 MD_SID(ms) = meta_getminor(stripenp->dev); 2066 ms->c.un_actual_tb = cum_blocks; 2067 ms->c.un_size = mdsize; 2068 if (stripep->hspnamep != NULL) 2069 ms->un_hsp_id = stripep->hspnamep->hsp; 2070 else 2071 ms->un_hsp_id = MD_HSP_NONE; 2072 ms->un_nrows = nrow; 2073 2074 /* fill in the size of the stripe */ 2075 if (options & MDCMD_UPDATE) { 2076 stripep->common.size = ms->c.un_total_blocks; 2077 for (row = 0; (row < nrow); ++row) { 2078 stripep->rows.rows_val[row].row_size = 2079 ms->un_row[row].un_blocks; 2080 } 2081 } 2082 2083 if (stripe_geom(stripep, ms, ep) != 0) { 2084 /* 2085 * If the device is being truncated then only allow this 2086 * if the user is aware (using the -f option) or they 2087 * are in a recovery/complete build situation (using the -a 2088 * option). 2089 */ 2090 if ((mdiserror(ep, MDE_STRIPE_TRUNC_SINGLE) || 2091 mdiserror(ep, MDE_STRIPE_TRUNC_MULTIPLE)) && 2092 (force || doall)) { 2093 md_eprintf(dgettext(TEXT_DOMAIN, 2094 "%s: WARNING: This form of metainit is not recommended.\n" 2095 "The stripe is truncating the size of the underlying device.\n" 2096 "Please see ERRORS in metainit(1M) for additional information.\n"), 2097 stripenp->cname); 2098 mdclrerror(ep); 2099 } else { 2100 goto out; 2101 } 2102 } 2103 2104 create_flag = meta_check_devicesize(ms->c.un_total_blocks); 2105 2106 /* if we're not doing anything, return success */ 2107 if (! (options & MDCMD_DOIT)) { 2108 rval = 0; /* success */ 2109 goto out; 2110 } 2111 2112 /* create stripe */ 2113 (void) memset(&set_params, 0, sizeof (set_params)); 2114 2115 /* did the user tell us to generate a large device? */ 2116 if (create_flag == MD_CRO_64BIT) { 2117 ms->c.un_revision |= MD_64BIT_META_DEV; 2118 set_params.options = MD_CRO_64BIT; 2119 } else { 2120 ms->c.un_revision &= ~MD_64BIT_META_DEV; 2121 set_params.options = MD_CRO_32BIT; 2122 } 2123 2124 set_params.mnum = MD_SID(ms); 2125 set_params.size = ms->c.un_size; 2126 set_params.mdp = (uintptr_t)ms; 2127 MD_SETDRIVERNAME(&set_params, MD_STRIPE, MD_MIN2SET(set_params.mnum)); 2128 if (metaioctl(MD_IOCSET, &set_params, &set_params.mde, 2129 stripenp->cname) != 0) { 2130 (void) mdstealerror(ep, &set_params.mde); 2131 goto out; 2132 } 2133 rval = 0; /* success */ 2134 2135 /* cleanup, return success */ 2136 out: 2137 Free(ms); 2138 if (rval != 0) { 2139 (void) del_key_names(sp, keynlp, NULL); 2140 } 2141 2142 metafreenamelist(keynlp); 2143 if ((rval == 0) && (options & MDCMD_DOIT)) { 2144 if (invalidate_components(sp, stripenp, ep) != 0) 2145 rval = -1; 2146 meta_invalidate_name(stripenp); 2147 } 2148 return (rval); 2149 } 2150 2151 /* 2152 * initialize stripe 2153 * NOTE: this functions is metainit(1m)'s command line parser! 2154 */ 2155 int 2156 meta_init_stripe( 2157 mdsetname_t **spp, 2158 int argc, 2159 char *argv[], 2160 mdcmdopts_t options, 2161 md_error_t *ep 2162 ) 2163 { 2164 char *uname = argv[0]; 2165 mdname_t *stripenp = NULL; 2166 int old_optind; 2167 int c; 2168 md_stripe_t *stripep = NULL; 2169 uint_t nrow, row; 2170 int rval = -1; 2171 2172 /* get stripe name */ 2173 assert(argc > 0); 2174 if (argc < 1) 2175 goto syntax; 2176 2177 if ((stripenp = metaname(spp, uname, META_DEVICE, ep)) == NULL) 2178 goto out; 2179 assert(*spp != NULL); 2180 uname = stripenp->cname; 2181 if (metachkmeta(stripenp, ep) != 0) 2182 goto out; 2183 2184 if (!(options & MDCMD_NOLOCK)) { 2185 /* grab set lock */ 2186 if (meta_lock(*spp, TRUE, ep)) 2187 goto out; 2188 2189 if (meta_check_ownership(*spp, ep) != 0) 2190 goto out; 2191 } 2192 2193 /* see if it exists already */ 2194 if (metagetmiscname(stripenp, ep) != NULL) { 2195 (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP, 2196 meta_getminor(stripenp->dev), uname); 2197 goto out; 2198 } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) { 2199 goto out; 2200 } else { 2201 mdclrerror(ep); 2202 } 2203 --argc, ++argv; 2204 2205 /* parse general options */ 2206 optind = 0; 2207 opterr = 0; 2208 if (getopt(argc, argv, "") != -1) 2209 goto options; 2210 2211 /* allocate stripe */ 2212 stripep = Zalloc(sizeof (*stripep)); 2213 2214 /* setup common */ 2215 stripep->common.namep = stripenp; 2216 stripep->common.type = MD_DEVICE; 2217 2218 /* allocate and parse rows */ 2219 if (argc < 1) { 2220 (void) mdmderror(ep, MDE_NROWS, meta_getminor(stripenp->dev), 2221 uname); 2222 goto out; 2223 } else if ((sscanf(argv[0], "%u", &nrow) != 1) || ((int)nrow < 0)) { 2224 goto syntax; 2225 } else if (nrow < 1) { 2226 (void) mdmderror(ep, MDE_NROWS, meta_getminor(stripenp->dev), 2227 uname); 2228 goto out; 2229 } 2230 --argc, ++argv; 2231 stripep->rows.rows_len = nrow; 2232 stripep->rows.rows_val = 2233 Zalloc(nrow * sizeof (*stripep->rows.rows_val)); 2234 for (row = 0; (row < nrow); ++row) { 2235 md_row_t *mdr = &stripep->rows.rows_val[row]; 2236 uint_t ncomp, comp; 2237 2238 /* allocate and parse components */ 2239 if (argc < 1) { 2240 (void) mdmderror(ep, MDE_NROWS, 2241 meta_getminor(stripenp->dev), uname); 2242 goto out; 2243 } else if ((sscanf(argv[0], "%u", &ncomp) != 1) || 2244 ((int)ncomp < 0)) { 2245 goto syntax; 2246 } else if (ncomp < 1) { 2247 (void) mdmderror(ep, MDE_NCOMPS, 2248 meta_getminor(stripenp->dev), uname); 2249 goto out; 2250 } 2251 --argc, ++argv; 2252 mdr->comps.comps_len = ncomp; 2253 mdr->comps.comps_val = 2254 Zalloc(ncomp * sizeof (*mdr->comps.comps_val)); 2255 for (comp = 0; (comp < ncomp); ++comp) { 2256 md_comp_t *mdc = &mdr->comps.comps_val[comp]; 2257 mdname_t *compnp; 2258 2259 /* parse component name */ 2260 if (argc < 1) { 2261 (void) mdmderror(ep, MDE_NCOMPS, 2262 meta_getminor(stripenp->dev), uname); 2263 goto out; 2264 } 2265 if ((compnp = metaname(spp, argv[0], UNKNOWN, 2266 ep)) == NULL) { 2267 goto out; 2268 } 2269 /* check for soft partition */ 2270 if (meta_sp_issp(*spp, compnp, ep) != 0) { 2271 /* check disk */ 2272 if (metachkcomp(compnp, ep) != 0) { 2273 goto out; 2274 } 2275 } 2276 mdc->compnamep = compnp; 2277 --argc, ++argv; 2278 } 2279 2280 /* parse row options */ 2281 old_optind = optind = 0; 2282 opterr = 0; 2283 while ((c = getopt(argc, argv, "i:")) != -1) { 2284 switch (c) { 2285 case 'i': 2286 if (parse_interlace(uname, optarg, 2287 &mdr->interlace, ep) != 0) { 2288 goto out; 2289 } 2290 if (meta_stripe_check_interlace(mdr->interlace, 2291 uname, ep)) 2292 goto out; 2293 break; 2294 2295 default: 2296 optind = old_optind; /* bomb out later */ 2297 goto done_row_opts; 2298 } 2299 old_optind = optind; 2300 } 2301 done_row_opts: 2302 argc -= optind; 2303 argv += optind; 2304 } 2305 2306 /* parse stripe options */ 2307 old_optind = optind = 0; 2308 opterr = 0; 2309 while ((c = getopt(argc, argv, "h:")) != -1) { 2310 switch (c) { 2311 case 'h': 2312 if ((stripep->hspnamep = metahspname(spp, optarg, 2313 ep)) == NULL) { 2314 goto out; 2315 } 2316 2317 /* 2318 * Get out if the specified hotspare pool really 2319 * doesn't exist. 2320 */ 2321 if (stripep->hspnamep->hsp == MD_HSP_NONE) { 2322 (void) mdhsperror(ep, MDE_INVAL_HSP, 2323 stripep->hspnamep->hsp, optarg); 2324 goto out; 2325 } 2326 break; 2327 2328 default: 2329 argc += old_optind; 2330 argv += old_optind; 2331 goto options; 2332 } 2333 old_optind = optind; 2334 } 2335 argc -= optind; 2336 argv += optind; 2337 2338 /* we should be at the end */ 2339 if (argc != 0) 2340 goto syntax; 2341 2342 /* create stripe */ 2343 if (meta_create_stripe(*spp, stripep, options, ep) != 0) 2344 goto out; 2345 rval = 0; /* success */ 2346 2347 /* let em know */ 2348 if (options & MDCMD_PRINT) { 2349 (void) printf(dgettext(TEXT_DOMAIN, 2350 "%s: Concat/Stripe is setup\n"), 2351 uname); 2352 (void) fflush(stdout); 2353 } 2354 goto out; 2355 2356 /* syntax error */ 2357 syntax: 2358 rval = meta_cook_syntax(ep, MDE_SYNTAX, uname, argc, argv); 2359 goto out; 2360 2361 /* options error */ 2362 options: 2363 rval = meta_cook_syntax(ep, MDE_OPTION, uname, argc, argv); 2364 goto out; 2365 2366 /* cleanup, return error */ 2367 out: 2368 if (stripep != NULL) 2369 meta_free_stripe(stripep); 2370 return (rval); 2371 } 2372 2373 /* 2374 * reset stripes 2375 */ 2376 int 2377 meta_stripe_reset( 2378 mdsetname_t *sp, 2379 mdname_t *stripenp, 2380 mdcmdopts_t options, 2381 md_error_t *ep 2382 ) 2383 { 2384 md_stripe_t *stripep; 2385 int rval = -1; 2386 int row, comp; 2387 2388 /* should have same set */ 2389 assert(sp != NULL); 2390 assert((stripenp == NULL) || 2391 (sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)))); 2392 2393 /* reset all stripes */ 2394 if (stripenp == NULL) { 2395 mdnamelist_t *stripenlp = NULL; 2396 mdnamelist_t *p; 2397 2398 /* for each stripe */ 2399 rval = 0; 2400 if (meta_get_stripe_names(sp, &stripenlp, 0, ep) < 0) 2401 return (-1); 2402 for (p = stripenlp; (p != NULL); p = p->next) { 2403 /* reset stripe */ 2404 stripenp = p->namep; 2405 2406 /* 2407 * If this is a multi-node set, we send a series 2408 * of individual metaclear commands. 2409 */ 2410 if (meta_is_mn_set(sp, ep)) { 2411 if (meta_mn_send_metaclear_command(sp, 2412 stripenp->cname, options, 0, ep) != 0) { 2413 rval = -1; 2414 break; 2415 } 2416 } else { 2417 if (meta_stripe_reset(sp, stripenp, 2418 options, ep) != 0) { 2419 rval = -1; 2420 break; 2421 } 2422 } 2423 } 2424 2425 /* cleanup, return success */ 2426 metafreenamelist(stripenlp); 2427 return (rval); 2428 } 2429 2430 /* check name */ 2431 if (metachkmeta(stripenp, ep) != 0) 2432 return (-1); 2433 2434 /* get unit structure */ 2435 if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL) 2436 return (-1); 2437 2438 /* make sure nobody owns us */ 2439 if (MD_HAS_PARENT(stripep->common.parent)) { 2440 return (mdmderror(ep, MDE_IN_USE, meta_getminor(stripenp->dev), 2441 stripenp->cname)); 2442 } 2443 2444 /* clear subdevices cache */ 2445 if (invalidate_components(sp, stripenp, ep) != 0) 2446 return (-1); 2447 2448 /* clear metadevice */ 2449 if (meta_reset(sp, stripenp, options, ep) != 0) 2450 goto out; 2451 rval = 0; /* success */ 2452 2453 /* let em know */ 2454 if (options & MDCMD_PRINT) { 2455 (void) printf(dgettext(TEXT_DOMAIN, 2456 "%s: Concat/Stripe is cleared\n"), 2457 stripenp->cname); 2458 (void) fflush(stdout); 2459 } 2460 2461 /* clear subdevices */ 2462 if (! (options & MDCMD_RECURSE)) 2463 goto out; 2464 2465 for (row = 0; (row < stripep->rows.rows_len); ++row) { 2466 md_row_t *rp = &stripep->rows.rows_val[row]; 2467 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 2468 md_comp_t *cp = &rp->comps.comps_val[comp]; 2469 mdname_t *compnp = cp->compnamep; 2470 2471 /* only recurse on metadevices */ 2472 if (! metaismeta(compnp)) 2473 continue; 2474 2475 if (meta_reset_by_name(sp, compnp, options, ep) != 0) 2476 rval = -1; 2477 } 2478 } 2479 2480 /* cleanup, return success */ 2481 out: 2482 meta_invalidate_name(stripenp); 2483 return (rval); 2484 } 2485 2486 /* 2487 * reports TRUE if any stripe component is in error 2488 */ 2489 int 2490 meta_stripe_anycomp_is_err(mdsetname_t *sp, mdnamelist_t *stripe_names) 2491 { 2492 mdnamelist_t *nlp; 2493 md_error_t status = mdnullerror; 2494 md_error_t *ep = &status; 2495 int any_errs = FALSE; 2496 2497 for (nlp = stripe_names; nlp; nlp = nlp->next) { 2498 md_stripe_t *stripep; 2499 int row; 2500 2501 if ((stripep = meta_get_stripe(sp, nlp->namep, ep)) == NULL) { 2502 any_errs |= TRUE; 2503 goto out; 2504 } 2505 2506 for (row = 0; row < stripep->rows.rows_len; ++row) { 2507 md_row_t *rp = &stripep->rows.rows_val[row]; 2508 uint_t comp; 2509 2510 for (comp = 0; comp < rp->comps.comps_len; ++comp) { 2511 md_comp_t *cp = &rp->comps.comps_val[comp]; 2512 2513 if (cp->state != CS_OKAY) { 2514 any_errs |= TRUE; 2515 goto out; 2516 } 2517 } 2518 } 2519 } 2520 out: 2521 if (!mdisok(ep)) 2522 mdclrerror(ep); 2523 2524 return (any_errs); 2525 } 2526 2527 int 2528 meta_stripe_check_component( 2529 mdsetname_t *sp, 2530 mdname_t *np, 2531 md_dev64_t mydevs, 2532 md_error_t *ep 2533 ) 2534 { 2535 md_stripe_t *stripe; 2536 mdnm_params_t nm; 2537 md_getdevs_params_t mgd; 2538 side_t sideno; 2539 char *miscname; 2540 md_dev64_t *mydev = NULL; 2541 mdkey_t key; 2542 char *pname = NULL, *t; 2543 char *ctd_name = NULL; 2544 char *devname = NULL; 2545 int len; 2546 int cnt, i; 2547 int rval = -1; 2548 2549 (void) memset(&nm, '\0', sizeof (nm)); 2550 if ((stripe = meta_get_stripe_common(sp, np, 0, ep)) == NULL) 2551 return (-1); 2552 2553 if ((miscname = metagetmiscname(np, ep)) == NULL) 2554 return (-1); 2555 2556 sideno = getmyside(sp, ep); 2557 2558 2559 /* get count of underlying devices */ 2560 2561 (void) memset(&mgd, '\0', sizeof (mgd)); 2562 MD_SETDRIVERNAME(&mgd, miscname, sp->setno); 2563 mgd.mnum = meta_getminor(np->dev); 2564 mgd.cnt = 0; 2565 mgd.devs = NULL; 2566 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) { 2567 (void) mdstealerror(ep, &mgd.mde); 2568 rval = 0; 2569 goto out; 2570 } else if (mgd.cnt <= 0) { 2571 assert(mgd.cnt >= 0); 2572 rval = 0; 2573 goto out; 2574 } 2575 2576 /* 2577 * Now get the data from the unit structure. 2578 * The compnamep stuff contains the data from 2579 * the namespace and we need the un_dev 2580 * from the unit structure. 2581 */ 2582 mydev = Zalloc(sizeof (*mydev) * mgd.cnt); 2583 mgd.devs = (uintptr_t)mydev; 2584 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) { 2585 (void) mdstealerror(ep, &mgd.mde); 2586 rval = 0; 2587 goto out; 2588 } else if (mgd.cnt <= 0) { 2589 assert(mgd.cnt >= 0); 2590 rval = 0; 2591 goto out; 2592 } 2593 2594 for (cnt = 0, i = 0; i < stripe->rows.rows_len; i++) { 2595 md_row_t *rp = &stripe->rows.rows_val[i]; 2596 uint_t comp; 2597 for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 2598 md_comp_t *cp = &rp->comps.comps_val[comp]; 2599 mdname_t *compnp = cp->compnamep; 2600 2601 if (mydevs == mydev[cnt]) { 2602 /* Get the devname from the name space. */ 2603 if ((devname = meta_getnmentbydev(sp->setno, 2604 sideno, compnp->dev, NULL, NULL, 2605 &key, ep)) == NULL) { 2606 goto out; 2607 } 2608 2609 if (compnp->dev != meta_getminor(mydev[cnt])) { 2610 /* 2611 * The minor numbers are different. 2612 * Update the namespace with the 2613 * information from the component. 2614 */ 2615 2616 t = strrchr(devname, '/'); 2617 t++; 2618 ctd_name = Strdup(t); 2619 2620 len = strlen(devname); 2621 t = strrchr(devname, '/'); 2622 t++; 2623 pname = Zalloc((len - strlen(t)) + 1); 2624 (void) strncpy(pname, devname, 2625 (len - strlen(t))); 2626 2627 if (meta_update_namespace(sp->setno, 2628 sideno, ctd_name, mydev[i], 2629 key, pname, ep) != 0) { 2630 goto out; 2631 } 2632 } 2633 rval = 0; 2634 break; 2635 } /* End of if (mydevs == mydev[i]) */ 2636 cnt++; 2637 } /* End of second for loop */ 2638 } /* End of first for loop */ 2639 out: 2640 if (pname != NULL) 2641 Free(pname); 2642 if (ctd_name != NULL) 2643 Free(ctd_name); 2644 if (devname != NULL) 2645 Free(devname); 2646 if (mydev != NULL) 2647 Free(mydev); 2648 return (rval); 2649 } 2650