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