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