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 2007 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 * mirror operations 38 */ 39 40#include <meta.h> 41#include <sys/lvm/md_mirror.h> 42#include <sys/lvm/md_convert.h> 43 44#include <ctype.h> 45#include <stddef.h> 46 47/* 48 * FUNCTION: meta_get_mirror_names() 49 * INPUT: sp - the set name to get mirrors from 50 * options - options from the command line 51 * OUTPUT: nlpp - list of all mirror names 52 * ep - return error pointer 53 * RETURNS: int - -1 if error, 0 success 54 * PURPOSE: returns a list of all mirrors in the metadb 55 * for all devices in the specified set 56 */ 57int 58meta_get_mirror_names( 59 mdsetname_t *sp, 60 mdnamelist_t **nlpp, 61 int options, 62 md_error_t *ep 63) 64{ 65 return (meta_get_names(MD_MIRROR, sp, nlpp, options, ep)); 66} 67 68/* 69 * free mirror unit 70 */ 71void 72meta_free_mirror( 73 md_mirror_t *mirrorp 74) 75{ 76 Free(mirrorp); 77} 78 79/* 80 * get mirror unit 81 */ 82static md_mirror_t * 83meta_get_mirror_common( 84 mdsetname_t *sp, 85 mdname_t *mirnp, 86 int fast, 87 md_error_t *ep 88) 89{ 90 mddrivename_t *dnp = mirnp->drivenamep; 91 char *miscname; 92 mm_unit_t *mm; 93 md_mirror_t *mirrorp; 94 uint_t smi, nsm; 95 md_resync_ioctl_t ri; 96 97 /* must have set */ 98 assert(sp != NULL); 99 100 /* short circuit */ 101 if (dnp->unitp != NULL) { 102 assert(dnp->unitp->type == MD_METAMIRROR); 103 return ((md_mirror_t *)dnp->unitp); 104 } 105 106 /* get miscname and unit */ 107 if ((miscname = metagetmiscname(mirnp, ep)) == NULL) 108 return (NULL); 109 if (strcmp(miscname, MD_MIRROR) != 0) { 110 (void) mdmderror(ep, MDE_NOT_MM, meta_getminor(mirnp->dev), 111 mirnp->cname); 112 return (NULL); 113 } 114 if ((mm = (mm_unit_t *)meta_get_mdunit(sp, mirnp, ep)) == NULL) 115 return (NULL); 116 assert(mm->c.un_type == MD_METAMIRROR); 117 118 /* allocate mirror */ 119 mirrorp = Zalloc(sizeof (*mirrorp)); 120 121 /* get common info */ 122 mirrorp->common.namep = mirnp; 123 mirrorp->common.type = mm->c.un_type; 124 mirrorp->common.state = mm->c.un_status; 125 mirrorp->common.capabilities = mm->c.un_capabilities; 126 mirrorp->common.parent = mm->c.un_parent; 127 mirrorp->common.size = mm->c.un_total_blocks; 128 mirrorp->common.user_flags = mm->c.un_user_flags; 129 mirrorp->common.revision = mm->c.un_revision; 130 131 /* get options */ 132 mirrorp->read_option = mm->un_read_option; 133 mirrorp->write_option = mm->un_write_option; 134 mirrorp->pass_num = mm->un_pass_num; 135 136 /* get submirrors */ 137 for (smi = 0, nsm = 0; (smi < NMIRROR); ++smi) { 138 mm_submirror_t *mmsp = &mm->un_sm[smi]; 139 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 140 141 /* get submirror state */ 142 mdsp->state = mmsp->sm_state; 143 if (mdsp->state == SMS_UNUSED) 144 continue; 145 ++nsm; 146 147 /* get submirror time of last state change */ 148 mdsp->timestamp = mmsp->sm_timestamp; 149 150 /* get submirror flags */ 151 mdsp->flags = mmsp->sm_flags; 152 153 /* get submirror name */ 154 mdsp->submirnamep = metakeyname(&sp, mmsp->sm_key, fast, ep); 155 if (mdsp->submirnamep == NULL) 156 goto out; 157 } 158 assert(nsm == mm->un_nsm); 159 160 /* get resync info */ 161 (void) memset(&ri, 0, sizeof (ri)); 162 ri.ri_mnum = meta_getminor(mirnp->dev); 163 MD_SETDRIVERNAME(&ri, MD_MIRROR, sp->setno); 164 if (metaioctl(MD_IOCGETSYNC, &ri, &ri.mde, mirnp->cname) != 0) { 165 (void) mdstealerror(ep, &ri.mde); 166 goto out; 167 } 168 mirrorp->percent_done = ri.ri_percent_done; 169 mirrorp->percent_dirty = ri.ri_percent_dirty; 170 171 /* cleanup, return success */ 172 Free(mm); 173 dnp->unitp = (md_common_t *)mirrorp; 174 return (mirrorp); 175 176 /* cleanup, return error */ 177out: 178 Free(mm); 179 meta_free_mirror(mirrorp); 180 return (NULL); 181} 182 183/* 184 * get mirror unit 185 */ 186md_mirror_t * 187meta_get_mirror( 188 mdsetname_t *sp, 189 mdname_t *mirnp, 190 md_error_t *ep 191) 192{ 193 return (meta_get_mirror_common(sp, mirnp, 0, ep)); 194} 195 196/* 197 * check mirror for dev 198 */ 199static int 200in_mirror( 201 mdsetname_t *sp, 202 mdname_t *mirnp, 203 mdname_t *np, 204 diskaddr_t slblk, 205 diskaddr_t nblks, 206 md_error_t *ep 207) 208{ 209 md_mirror_t *mirrorp; 210 uint_t smi; 211 212 /* should be in the same set */ 213 assert(sp != NULL); 214 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 215 216 /* get unit */ 217 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 218 return (-1); 219 220 /* look in submirrors */ 221 for (smi = 0; (smi < NMIRROR); ++smi) { 222 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 223 mdname_t *submirnp = mdsp->submirnamep; 224 225 /* skip unused submirrors */ 226 if (submirnp == NULL) { 227 assert(mdsp->state == SMS_UNUSED); 228 continue; 229 } 230 231 /* check overlap */ 232 if (metaismeta(submirnp)) 233 continue; 234 if (meta_check_overlap(mirnp->cname, np, slblk, nblks, 235 submirnp, 0, -1, ep) != 0) 236 return (-1); 237 } 238 239 /* return success */ 240 return (0); 241} 242 243/* 244 * check to see if we're in a mirror 245 */ 246int 247meta_check_inmirror( 248 mdsetname_t *sp, 249 mdname_t *np, 250 diskaddr_t slblk, 251 diskaddr_t nblks, 252 md_error_t *ep 253) 254{ 255 mdnamelist_t *mirrornlp = NULL; 256 mdnamelist_t *p; 257 int rval = 0; 258 259 /* should have a set */ 260 assert(sp != NULL); 261 262 /* for each mirror */ 263 if (meta_get_mirror_names(sp, &mirrornlp, 0, ep) < 0) 264 return (-1); 265 for (p = mirrornlp; (p != NULL); p = p->next) { 266 mdname_t *mirnp = p->namep; 267 268 /* check mirror */ 269 if (in_mirror(sp, mirnp, np, slblk, nblks, ep) != 0) { 270 rval = -1; 271 break; 272 } 273 } 274 275 /* cleanup, return success */ 276 metafreenamelist(mirrornlp); 277 return (rval); 278} 279 280/* 281 * Check to see if the primary mirror is built on top of a 282 * root slice which is mounted. This check is primarily to 283 * account for this case - 284 * 285 * # metainit -f d1 1 1 <root slice> 286 * # metainit d0 -m d1 287 * # metainit d2 1 1 ctds 288 * # metattach d0 d2 289 * 290 * The metattach here needs to fail if the root slice is 291 * being mirrored; otherwise there is a potential for 292 * data corruption. 293 */ 294static int 295meta_check_primary_mirror( 296 mdsetname_t *sp, 297 mdname_t *mirnp, 298 md_error_t *ep 299) 300{ 301 int smi; 302 char *curroot; 303 char *temproot; 304 mdname_t *rootnp; 305 md_mirror_t *mirrorp; 306 md_stripe_t *stripep; 307 md_row_t *rp; 308 md_comp_t *cp; 309 310 if ((curroot = meta_get_current_root(ep)) == NULL) 311 return (-1); 312 313 /* 314 * We need to take the canonical name here otherwise the call to 315 * metaname will add a bad entry to the drivelistp cache and 316 * things will get nasty later on. 317 * However we also need to trap the case where we have a logical 318 * device name and meta_canonicalize returns NULL. 319 */ 320 temproot = meta_canonicalize(sp, curroot); 321 if (temproot != NULL) { 322 curroot = Strdup(temproot); 323 Free(temproot); 324 } 325 326 /* 327 * Get device name of current root metadevice. If root 328 * is net mounted as happens if we're part of the 329 * install process, rootnp will be set to NULL and we 330 * return success. 331 * 332 * Since curroot should be a complete path, we only 333 * need to check whether the device is a logical device. 334 * The metaname below returns NULL if curroot is not a logical 335 * device. 336 */ 337 if ((rootnp = metaname(&sp, curroot, LOGICAL_DEVICE, ep)) == NULL) 338 return (0); 339 /* 340 * If we're here, the curroot is a mounted on a logical device. 341 * Make sure this mirror is not on the root logical device. 342 */ 343 if (metaismeta(mirnp)) { 344 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 345 return (-1); 346 347 for (smi = 0; (smi < NMIRROR); ++smi) { 348 /* Check all submirrors */ 349 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 350 mdname_t *submirnamep = mdsp->submirnamep; 351 352 /* skip unused submirrors */ 353 if (submirnamep == NULL) { 354 assert(mdsp->state == SMS_UNUSED); 355 continue; 356 } 357 /* check if submirror is a stripe or not */ 358 if (strcmp(metagetmiscname(submirnamep, ep), MD_STRIPE) 359 != 0) 360 return (-1); 361 if ((stripep = meta_get_stripe(sp, submirnamep, ep)) 362 == NULL) 363 return (-1); 364 365 /* 366 * Examine the first component of the first row and 367 * check to see if it has a mounted root slice 368 */ 369 rp = &stripep->rows.rows_val[0]; 370 cp = &rp->comps.comps_val[0]; 371 /* 372 * we just care about the component built on 373 * top of a raw device 374 */ 375 if (!metaismeta(cp->compnamep)) { 376 /* 377 * If root device is the 1st component of 378 * the stripe, then fail. 379 */ 380 if (strcmp(rootnp->cname, cp->compnamep->cname) 381 == 0) { 382 (void) mduseerror(ep, MDE_IS_MOUNTED, 383 rootnp->dev, "/", rootnp->cname); 384 return (-1); 385 } 386 } 387 } 388 } 389 /* return success */ 390 return (0); 391} 392 393/* 394 * check submirror 395 */ 396int 397meta_check_submirror( 398 mdsetname_t *sp, 399 mdname_t *np, 400 mdname_t *mirnp, 401 int force, 402 md_error_t *ep 403) 404{ 405 mdchkopts_t options = 0; 406 md_common_t *mdp; 407 408 /* make sure we have a metadevice disk */ 409 if (metachkmeta(np, ep) != 0) 410 return (-1); 411 412 /* 413 * Check to see if the primary mirror consists of a root 414 * mounted device 415 */ 416 if (mirnp && (!force) && ((meta_check_primary_mirror(sp, mirnp, ep) 417 != 0))) 418 return (-1); 419 420 /* check to ensure that it is not already in use */ 421 if ((! force) && 422 (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0)) { 423 return (-1); 424 } 425 426 /* make sure it is in the set */ 427 if (meta_check_inset(sp, np, ep) != 0) 428 return (-1); 429 430 /* make sure its not in a metadevice */ 431 if (! metaismeta(np)) { /* Non-metadevices */ 432 if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0) 433 return (-1); 434 } else { /* Metadevices only! */ 435 /* make sure it can be parented */ 436 if ((mdp = meta_get_unit(sp, np, ep)) == NULL) 437 return (-1); 438 439 if ((! (mdp->capabilities & MD_CAN_PARENT)) || 440 (! (mdp->capabilities & MD_CAN_SUB_MIRROR)) || 441 (mdp->parent != MD_NO_PARENT)) { 442 return (mdmderror(ep, MDE_INVAL_UNIT, 443 meta_getminor(np->dev), np->cname)); 444 } 445 } 446 447 /* return success */ 448 return (0); 449} 450 451/* 452 * convert read options 453 */ 454char * 455rd_opt_to_name( 456 mm_rd_opt_t opt 457) 458{ 459 switch (opt) { 460 case RD_LOAD_BAL: 461 return ("roundrobin"); 462 case RD_GEOMETRY: 463 return ("geometric"); 464 case RD_FIRST: 465 return ("first"); 466 default: 467 assert(0); 468 return (dgettext(TEXT_DOMAIN, "invalid")); 469 } 470} 471 472static char * 473rd_opt_to_opt( 474 mm_rd_opt_t opt 475) 476{ 477 switch (opt) { 478 case RD_LOAD_BAL: 479 return (NULL); /* default */ 480 case RD_GEOMETRY: 481 return ("-g"); 482 case RD_FIRST: 483 return ("-r"); 484 default: 485 assert(0); 486 return (dgettext(TEXT_DOMAIN, "invalid")); 487 } 488} 489 490int 491name_to_rd_opt( 492 char *uname, 493 char *name, 494 mm_rd_opt_t *optp, 495 md_error_t *ep 496) 497{ 498 if (strcasecmp(name, "roundrobin") == 0) { 499 *optp = RD_LOAD_BAL; 500 return (0); 501 } 502 if (strcasecmp(name, "geometric") == 0) { 503 *optp = RD_GEOMETRY; 504 return (0); 505 } 506 if (strcasecmp(name, "first") == 0) { 507 *optp = RD_FIRST; 508 return (0); 509 } 510 return (meta_cook_syntax(ep, MDE_BAD_RD_OPT, uname, 1, &name)); 511} 512 513/* 514 * convert write options 515 */ 516char * 517wr_opt_to_name( 518 mm_wr_opt_t opt 519) 520{ 521 switch (opt) { 522 case WR_PARALLEL: 523 return ("parallel"); 524 case WR_SERIAL: 525 return ("serial"); 526 default: 527 assert(0); 528 return (dgettext(TEXT_DOMAIN, "invalid")); 529 } 530} 531 532static char * 533wr_opt_to_opt( 534 mm_wr_opt_t opt 535) 536{ 537 switch (opt) { 538 case WR_PARALLEL: 539 return (NULL); /* default */ 540 case WR_SERIAL: 541 return ("-S"); 542 default: 543 assert(0); 544 return (dgettext(TEXT_DOMAIN, "invalid")); 545 } 546} 547 548int 549name_to_wr_opt( 550 char *uname, 551 char *name, 552 mm_wr_opt_t *optp, 553 md_error_t *ep 554) 555{ 556 if (strcasecmp(name, "parallel") == 0) { 557 *optp = WR_PARALLEL; 558 return (0); 559 } 560 if (strcasecmp(name, "serial") == 0) { 561 *optp = WR_SERIAL; 562 return (0); 563 } 564 return (meta_cook_syntax(ep, MDE_BAD_WR_OPT, uname, 1, &name)); 565} 566 567/* 568 * convert pass numbers 569 */ 570int 571name_to_pass_num( 572 char *uname, 573 char *name, 574 mm_pass_num_t *passp, 575 md_error_t *ep 576) 577{ 578 if ((sscanf(name, "%hd", passp) != 1) || 579 (*passp < 0) || (*passp > MD_PASS_MAX)) { 580 return (meta_cook_syntax(ep, MDE_BAD_PASS_NUM, 581 uname, 1, &name)); 582 } 583 return (0); 584} 585 586/* 587 * convert resync option 588 */ 589 590static char * 591resync_opt_to_name( 592 uint_t tstate 593) 594{ 595 if (tstate & MD_ABR_CAP) 596 return (dgettext(TEXT_DOMAIN, "application based")); 597 else 598 return (dgettext(TEXT_DOMAIN, "optimized resync")); 599} 600 601/* 602 * print mirror 603 */ 604static int 605mirror_print( 606 md_mirror_t *mirrorp, 607 char *fname, 608 FILE *fp, 609 mdprtopts_t options, 610 md_error_t *ep 611) 612{ 613 uint_t smi; 614 char *p; 615 int rval = -1; 616 617 618 if (options & PRINT_LARGEDEVICES) { 619 if ((mirrorp->common.revision & MD_64BIT_META_DEV) == 0) { 620 rval = 0; 621 goto out; 622 } 623 } 624 625 if (options & PRINT_FN) { 626 if ((mirrorp->common.revision & MD_FN_META_DEV) == 0) { 627 rval = 0; 628 goto out; 629 } 630 } 631 632 /* print name and -m */ 633 if (fprintf(fp, "%s -m", mirrorp->common.namep->cname) == EOF) 634 goto out; 635 636 /* print submirrors */ 637 for (smi = 0; (smi < NMIRROR); ++smi) { 638 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 639 mdname_t *submirnamep = mdsp->submirnamep; 640 641 /* skip unused submirrors */ 642 if (submirnamep == NULL) { 643 assert(mdsp->state == SMS_UNUSED); 644 continue; 645 } 646 647 /* print submirror */ 648 if (fprintf(fp, " %s", submirnamep->rname) == EOF) 649 goto out; 650 } 651 652 /* print options */ 653 if ((p = rd_opt_to_opt(mirrorp->read_option)) != NULL) { 654 if (fprintf(fp, " %s", p) == EOF) 655 goto out; 656 } 657 if ((p = wr_opt_to_opt(mirrorp->write_option)) != NULL) { 658 if (fprintf(fp, " %s", p) == EOF) 659 goto out; 660 } 661 if (fprintf(fp, " %u\n", mirrorp->pass_num) == EOF) 662 goto out; 663 664 /* success */ 665 rval = 0; 666 667 /* cleanup, return error */ 668out: 669 if (rval != 0) 670 (void) mdsyserror(ep, errno, fname); 671 return (rval); 672} 673 674/* 675 * convert submirror state to name 676 */ 677char * 678sm_state_to_name( 679 md_submirror_t *mdsp, 680 md_status_t mirror_status, 681 md_timeval32_t *tvp, 682 uint_t tstate 683) 684{ 685 static char state_to_str[100]; 686 sm_state_t state = mdsp->state; 687 uint_t is_target = mdsp->flags & MD_SM_RESYNC_TARGET; 688 689 /* grab time */ 690 if (tvp != NULL) 691 *tvp = mdsp->timestamp; 692 693 /* 694 * Only return Unavailable if there is no flagged error on the 695 * submirror. If the mirror has received any writes since the submirror 696 * went into Unavailable state a resync is required. To alert the 697 * administrator to this we return a 'Needs maintenance' message. 698 */ 699 if ((tstate != 0) && (state & SMS_RUNNING)) { 700 return (dgettext(TEXT_DOMAIN, "Unavailable")); 701 } 702 703 /* all is well */ 704 if (state & SMS_RUNNING) { 705 if (!(mirror_status & MD_UN_OPT_NOT_DONE) || 706 ((mirror_status & MD_UN_OPT_NOT_DONE) && !is_target)) { 707 return (dgettext(TEXT_DOMAIN, "Okay")); 708 } 709 } 710 711 /* resyncing, needs repair */ 712 if ((state & (SMS_COMP_RESYNC | SMS_ATTACHED_RESYNC | 713 SMS_OFFLINE_RESYNC)) || 714 (mirror_status & MD_UN_OPT_NOT_DONE)) { 715 if (mirror_status & MD_UN_RESYNC_ACTIVE) { 716 return (dgettext(TEXT_DOMAIN, "Resyncing")); 717 } 718 if (mirror_status & MD_UN_RESYNC_CANCEL) { 719 return (dgettext(TEXT_DOMAIN, "Resync cancelled")); 720 } 721 return (dgettext(TEXT_DOMAIN, "Needs maintenance")); 722 } 723 724 /* needs repair */ 725 if (state & (SMS_COMP_ERRED | SMS_ATTACHED | SMS_OFFLINE)) { 726 if (mirror_status & MD_UN_RESYNC_CANCEL) { 727 return (dgettext(TEXT_DOMAIN, "Resync cancelled")); 728 } 729 return (dgettext(TEXT_DOMAIN, "Needs maintenance")); 730 } 731 732 /* unknown */ 733 assert(0); 734 (void) sprintf(state_to_str, "0x%x", state); 735 return (state_to_str); 736} 737 738/* 739 * convert submirror state to repair action 740 */ 741int 742sm_state_to_action( 743 mdsetname_t *sp, 744 md_submirror_t *mdsp, 745 md_status_t mirror_status, 746 md_mirror_t *mirrorp, 747 char **actionp, 748 md_error_t *ep 749) 750{ 751 static char buf[1024]; 752 mdname_t *submirnamep = mdsp->submirnamep; 753 sm_state_t state = mdsp->state; 754 char *miscname; 755 756 /* all is well */ 757 *actionp = NULL; 758 if (mirror_status & MD_UN_RESYNC_ACTIVE) 759 return (0); 760 if ((state == SMS_RUNNING) && !(mirror_status & MD_UN_OPT_NOT_DONE)) 761 return (0); 762 763 /* complete cancelled resync */ 764 if (mirror_status & MD_UN_RESYNC_CANCEL) { 765 (void) snprintf(buf, sizeof (buf), 766 dgettext(TEXT_DOMAIN, "metasync %s"), 767 mirrorp->common.namep->cname); 768 *actionp = buf; 769 return (0); 770 } 771 772 /* replace stripe component */ 773 if ((metaismeta(submirnamep)) && (state & SMS_COMP_ERRED)) { 774 if ((miscname = metagetmiscname(submirnamep, ep)) == NULL) 775 return (-1); 776 if (strcmp(miscname, MD_STRIPE) == 0) { 777 mdname_t *compnamep; 778 comp_state_t compstate; 779 780 if (meta_find_erred_comp(sp, submirnamep, 781 &compnamep, &compstate, ep) != 0) { 782 return (-1); 783 } 784 if (compstate != CS_LAST_ERRED) 785 (void) snprintf(buf, sizeof (buf), 786 "metareplace %s %s <%s>", 787 mirrorp->common.namep->cname, 788 compnamep->cname, 789 dgettext(TEXT_DOMAIN, "new device")); 790 else 791 (void) snprintf(buf, sizeof (buf), 792 dgettext(TEXT_DOMAIN, 793 "after replacing \"Maintenance\" " 794 "components:\n" 795 "\t\tmetareplace %s %s <new device>"), 796 mirrorp->common.namep->cname, 797 compnamep->cname); 798 *actionp = buf; 799 return (0); 800 } 801 } 802 803 /* resync mirror */ 804 if ((state & (SMS_ATTACHED_RESYNC | SMS_OFFLINE_RESYNC | 805 SMS_COMP_RESYNC | SMS_ATTACHED)) || 806 (mirror_status & MD_UN_OPT_NOT_DONE)) { 807 (void) snprintf(buf, sizeof (buf), "metasync %s", 808 mirrorp->common.namep->cname); 809 *actionp = buf; 810 return (0); 811 } 812 813 /* online submirror */ 814 if (state & SMS_OFFLINE) { 815 (void) snprintf(buf, sizeof (buf), "metaonline %s %s", 816 mirrorp->common.namep->cname, submirnamep->cname); 817 *actionp = buf; 818 return (0); 819 } 820 821 /* unknown action */ 822 *actionp = dgettext(TEXT_DOMAIN, "???"); 823 return (0); 824} 825 826/* 827 * print mirror options 828 */ 829int 830meta_print_mirror_options( 831 mm_rd_opt_t read_option, 832 mm_wr_opt_t write_option, 833 mm_pass_num_t pass_num, 834 uint_t tstate, 835 char *fname, 836 mdsetname_t *sp, 837 FILE *fp, 838 md_error_t *ep 839) 840{ 841 char *p; 842 int rval = -1; 843 844 /* print options */ 845 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Pass: %u\n"), 846 pass_num) == EOF) { 847 goto out; 848 } 849 if ((p = rd_opt_to_opt(read_option)) == NULL) 850 p = dgettext(TEXT_DOMAIN, "default"); 851 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Read option: %s (%s)\n"), 852 rd_opt_to_name(read_option), p) == EOF) { 853 goto out; 854 } 855 if ((p = wr_opt_to_opt(write_option)) == NULL) 856 p = dgettext(TEXT_DOMAIN, "default"); 857 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Write option: %s (%s)\n"), 858 wr_opt_to_name(write_option), p) == EOF) { 859 goto out; 860 } 861 /* Display resync option for mirror, if MultiNode set */ 862 if (meta_is_mn_set(sp, ep)) { 863 if (fprintf(fp, dgettext(TEXT_DOMAIN, 864 " Resync option: %s\n"), 865 resync_opt_to_name(tstate)) == EOF) { 866 goto out; 867 } 868 } 869 870 /* success */ 871 rval = 0; 872 873 /* cleanup, return error */ 874out: 875 if (rval != 0) 876 (void) mdsyserror(ep, errno, fname); 877 return (rval); 878} 879 880static char * 881get_node_name(uint_t nid, md_error_t *ep) 882{ 883 mndiskset_membershiplist_t *nl, *p; 884 int n; 885 char *node_nm; 886 887 /* get the known membership list */ 888 if (meta_read_nodelist(&n, &nl, ep)) { 889 return (NULL); 890 } 891 892 /* find the matching node and return the name */ 893 for (p = nl; (p != NULL); p = p->next) { 894 if (nid == p->msl_node_id) { 895 /* match found */ 896 node_nm = Strdup(p->msl_node_name); 897 goto out; 898 } 899 } 900 901 /* match not found */ 902 node_nm = Strdup(dgettext(TEXT_DOMAIN, "None")); 903 904out: 905 meta_free_nodelist(nl); 906 return (node_nm); 907} 908 909/* 910 * report mirror 911 */ 912static int 913mirror_report( 914 mdsetname_t *sp, 915 md_mirror_t *mirrorp, 916 mdnamelist_t **nlpp, 917 char *fname, 918 FILE *fp, 919 mdprtopts_t options, 920 md_error_t *ep 921) 922{ 923 md_status_t status = mirrorp->common.state; 924 uint_t smi; 925 char *p; 926 int rval = -1; 927 uint_t tstate = 0; 928 929 /* 930 * check for the -B option. If -B and the metadevice is 931 * a 64 bit device, get the dev for relocation information 932 * printout. If not a 64 bit device, just don't print this 933 * information out but you need to go down to the subdevice 934 * level and print there if appropriate. 935 */ 936 if (options & PRINT_LARGEDEVICES) { 937 if ((mirrorp->common.revision & MD_64BIT_META_DEV) == 0) { 938 for (smi = 0; (smi < NMIRROR); ++smi) { 939 md_submirror_t *mdsp = 940 &mirrorp->submirrors[smi]; 941 mdname_t *submirnamep = 942 mdsp->submirnamep; 943 if (submirnamep == NULL) { 944 continue; 945 } 946 if ((metaismeta(submirnamep)) && 947 (meta_print_name(sp, submirnamep, nlpp, 948 fname, fp, options | PRINT_SUBDEVS, NULL, 949 ep) != 0)) { 950 return (-1); 951 } 952 } 953 rval = 0; 954 goto out; 955 } else { 956 if (meta_getdevs(sp, mirrorp->common.namep, 957 nlpp, ep) != 0) 958 goto out; 959 } 960 } 961 962 /* 963 * check for the -D option. If -D and the name is 964 * a descriptive name, get the dev for relocation information 965 * printout. If not a descriptive name, don't print this 966 * information out but you need to go down to the subdevice 967 * level and print there if appropriate. 968 */ 969 if (options & PRINT_FN) { 970 if ((mirrorp->common.revision & MD_FN_META_DEV) == 0) { 971 for (smi = 0; (smi < NMIRROR); ++smi) { 972 md_submirror_t *mdsp = 973 &mirrorp->submirrors[smi]; 974 mdname_t *submirnamep = 975 mdsp->submirnamep; 976 if (submirnamep == NULL) { 977 continue; 978 } 979 if ((metaismeta(submirnamep)) && 980 (meta_print_name(sp, submirnamep, nlpp, 981 fname, fp, options | PRINT_SUBDEVS, NULL, 982 ep) != 0)) { 983 return (-1); 984 } 985 } 986 rval = 0; 987 goto out; 988 } else { 989 if (meta_getdevs(sp, mirrorp->common.namep, 990 nlpp, ep) != 0) 991 goto out; 992 } 993 } 994 995 /* print header */ 996 if (options & PRINT_HEADER) { 997 if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: Mirror\n"), 998 mirrorp->common.namep->cname) == EOF) { 999 goto out; 1000 } 1001 } 1002 1003 /* print submirrors, adjust status */ 1004 for (smi = 0; (smi < NMIRROR); ++smi) { 1005 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 1006 mdname_t *submirnamep = mdsp->submirnamep; 1007 char *sm_state; 1008 md_timeval32_t tv; 1009 char *timep; 1010 1011 /* skip unused submirrors */ 1012 if (submirnamep == NULL) { 1013 assert(mdsp->state == SMS_UNUSED); 1014 continue; 1015 } 1016 1017 if (mdsp->state & SMS_OFFLINE) 1018 status &= ~MD_UN_OPT_NOT_DONE; 1019 1020 /* print submirror */ 1021 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Submirror %u: %s\n"), 1022 smi, submirnamep->cname) == EOF) { 1023 goto out; 1024 } 1025 1026 /* print state */ 1027 if (metaismeta(mdsp->submirnamep)) { 1028 if (meta_get_tstate(mdsp->submirnamep->dev, &tstate, 1029 ep) != 0) 1030 return (-1); 1031 } 1032 sm_state = sm_state_to_name(mdsp, status, &tv, 1033 tstate & MD_DEV_ERRORED); 1034 if (options & PRINT_TIMES) { 1035 timep = meta_print_time(&tv); 1036 } else { 1037 timep = ""; 1038 } 1039 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1040 " State: %-12s %s\n"), 1041 sm_state, timep) == EOF) { 1042 goto out; 1043 } 1044 } 1045 1046 /* print resync status */ 1047 if (status & MD_UN_RESYNC_CANCEL) { 1048 /* Resync was cancelled but is restartable */ 1049 if (mirrorp->common.revision & MD_64BIT_META_DEV) { 1050 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1051 " Resync cancelled: %2d.%1d %% done\n"), 1052 mirrorp->percent_done/10, 1053 mirrorp->percent_done%10) == EOF) { 1054 goto out; 1055 } 1056 } else { 1057 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1058 " Resync cancelled: %d %% done\n"), 1059 mirrorp->percent_done) == EOF) { 1060 goto out; 1061 } 1062 } 1063 } else if (status & MD_UN_RESYNC_ACTIVE) { 1064 if (mirrorp->common.revision & MD_64BIT_META_DEV) { 1065 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1066 " Resync in progress: %2d.%1d %% done\n"), 1067 mirrorp->percent_done/10, 1068 mirrorp->percent_done%10) == EOF) { 1069 goto out; 1070 } 1071 } else { 1072 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1073 " Resync in progress: %d %% done\n"), 1074 mirrorp->percent_done) == EOF) { 1075 goto out; 1076 } 1077 } 1078 } 1079 1080 /* print options */ 1081 if (meta_get_tstate(mirrorp->common.namep->dev, &tstate, ep) != 0) 1082 return (-1); 1083 1084 if (meta_print_mirror_options(mirrorp->read_option, 1085 mirrorp->write_option, mirrorp->pass_num, 1086 tstate, fname, sp, fp, ep) != 0) 1087 return (-1); 1088 1089 /* print mirror owner for multi-node metadevice */ 1090 if (meta_is_mn_set(sp, ep)) { 1091 md_set_mmown_params_t ownpar; 1092 mdname_t *mirnp = mirrorp->common.namep; 1093 char *node_name; 1094 1095 (void) memset(&ownpar, 0, sizeof (ownpar)); 1096 ownpar.d.mnum = meta_getminor(mirnp->dev); 1097 MD_SETDRIVERNAME(&ownpar, MD_MIRROR, sp->setno); 1098 1099 if (metaioctl(MD_MN_GET_MM_OWNER, &ownpar, ep, 1100 "MD_MN_GET_MM_OWNER") != 0) { 1101 return (-1); 1102 } 1103 1104 node_name = get_node_name(ownpar.d.owner, ep); 1105 if (node_name == NULL) 1106 return (-1); 1107 else if (fprintf(fp, dgettext(TEXT_DOMAIN, " Owner: %s\n"), 1108 node_name) == EOF) { 1109 Free(node_name); 1110 goto out; 1111 } 1112 Free(node_name); 1113 1114 } 1115 1116 /* print size */ 1117 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"), 1118 mirrorp->common.size, 1119 meta_number_to_string(mirrorp->common.size, DEV_BSIZE)) 1120 == EOF) { 1121 goto out; 1122 } 1123 1124 /* MD_DEBUG stuff */ 1125 if (options & PRINT_DEBUG) { 1126 mdname_t *mirnp = mirrorp->common.namep; 1127 mm_unit_t *mm; 1128 mddb_optloc_t optloc; 1129 uint_t i; 1130 1131 /* get real mirror unit */ 1132 if ((mm = (mm_unit_t *)meta_get_mdunit(sp, mirnp, ep)) 1133 == NULL) { 1134 return (-1); 1135 } 1136 assert(mm->c.un_type == MD_METAMIRROR); 1137 1138 /* print dirty regions */ 1139 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1140" Regions which are dirty: %d%% (blksize %d num %d)\n"), 1141 mirrorp->percent_dirty, mm->un_rrd_blksize, 1142 mm->un_rrd_num) == EOF) { 1143 Free(mm); 1144 goto out; 1145 } 1146 1147 /* print optimized resync record locations */ 1148 (void) memset(&optloc, 0, sizeof (optloc)); 1149 optloc.recid = mm->un_rr_dirty_recid; 1150 if (metaioctl(MD_DB_GETOPTLOC, &optloc, ep, 1151 "MD_DB_GETOPTLOC") != 0) { 1152 Free(mm); 1153 return (-1); 1154 } 1155 for (i = 0; (i < ((sizeof optloc.li) / sizeof (optloc.li[0]))); 1156 ++i) { 1157 mddb_config_t dbconf; 1158 char *devname; 1159 1160 (void) memset(&dbconf, 0, sizeof (dbconf)); 1161 dbconf.c_id = optloc.li[i]; 1162 dbconf.c_setno = sp->setno; 1163 dbconf.c_subcmd = MDDB_CONFIG_ABS; 1164 /* Don't need device id information from this ioctl */ 1165 dbconf.c_locator.l_devid = (uint64_t)0; 1166 dbconf.c_locator.l_devid_flags = 0; 1167 if (metaioctl(MD_DB_ENDDEV, &dbconf, &dbconf.c_mde, 1168 "MD_DB_ENDDEV") != 0) { 1169 Free(mm); 1170 return (mdstealerror(ep, &dbconf.c_mde)); 1171 } 1172 if ((devname = splicename(&dbconf.c_devname)) 1173 == NULL) { 1174 devname = Strdup(dgettext(TEXT_DOMAIN, 1175 "unknown")); 1176 } 1177 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1178 " Resync record[%u]: %d (%s %d %d)\n"), i, 1179 optloc.li[i], devname, dbconf.c_locator.l_blkno, 1180 (dbconf.c_dbend - dbconf.c_locator.l_blkno + 1)) 1181 == EOF) { 1182 Free(mm); 1183 Free(devname); 1184 goto out; 1185 } 1186 Free(devname); 1187 } 1188 Free(mm); 1189 } 1190 1191 /* print submirror details */ 1192 for (smi = 0; (smi < NMIRROR); ++smi) { 1193 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 1194 mdname_t *submirnamep = mdsp->submirnamep; 1195 char *sm_state; 1196 md_timeval32_t tv; 1197 char *timep; 1198 md_stripe_t *stripep; 1199 1200 /* skip unused submirrors */ 1201 if (submirnamep == NULL) { 1202 assert(mdsp->state == SMS_UNUSED); 1203 continue; 1204 } 1205 1206 if (options & PRINT_FN) { 1207 /* get unit structure */ 1208 if ((stripep = meta_get_stripe_common(sp, submirnamep, 1209 ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL) 1210 goto out; 1211 1212 if ((stripep->common.revision & MD_FN_META_DEV) 1213 == 0) 1214 continue; 1215 } 1216 1217 /* add extra line */ 1218 if (fprintf(fp, "\n") == EOF) 1219 goto out; 1220 1221 /* print submirror */ 1222 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1223 "%s: Submirror of %s\n"), 1224 submirnamep->cname, 1225 mirrorp->common.namep->cname) == EOF) { 1226 goto out; 1227 } 1228 1229 /* print state */ 1230 if (metaismeta(mdsp->submirnamep)) { 1231 if (meta_get_tstate(mdsp->submirnamep->dev, &tstate, ep) 1232 != 0) 1233 return (-1); 1234 } 1235 sm_state = sm_state_to_name(mdsp, status, &tv, NULL); 1236 if (options & PRINT_TIMES) { 1237 timep = meta_print_time(&tv); 1238 } else { 1239 timep = ""; 1240 } 1241 1242 if ((tstate & MD_DEV_ERRORED) == 0) { 1243 if (fprintf(fp, dgettext(TEXT_DOMAIN, 1244 " State: %-12s %s\n"), 1245 sm_state, timep) == EOF) { 1246 goto out; 1247 } 1248 1249 /* print what to do */ 1250 if (sm_state_to_action(sp, mdsp, status, 1251 mirrorp, &p, ep) != 0) 1252 return (-1); 1253 if ((p != NULL) && 1254 (fprintf(fp, dgettext(TEXT_DOMAIN, 1255 " Invoke: %s\n"), p) == EOF)) { 1256 goto out; 1257 } 1258 } 1259 1260 /* print underlying metadevice */ 1261 if ((metaismeta(submirnamep)) && 1262 (meta_print_name(sp, submirnamep, nlpp, fname, fp, 1263 ((options & ~PRINT_HEADER) | PRINT_SUBDEVS), 1264 NULL, ep) != 0)) { 1265 return (-1); 1266 } 1267 } 1268 1269 /* add extra line */ 1270 if (fprintf(fp, "\n") == EOF) 1271 goto out; 1272 1273 /* success */ 1274 rval = 0; 1275 1276 /* cleanup, return error */ 1277out: 1278 if (rval != 0) 1279 (void) mdsyserror(ep, errno, fname); 1280 return (rval); 1281} 1282 1283/* 1284 * print/report mirror 1285 */ 1286int 1287meta_mirror_print( 1288 mdsetname_t *sp, 1289 mdname_t *mirnp, 1290 mdnamelist_t **nlpp, 1291 char *fname, 1292 FILE *fp, 1293 mdprtopts_t options, 1294 md_error_t *ep 1295) 1296{ 1297 md_mirror_t *mirrorp; 1298 uint_t smi; 1299 1300 /* should have same set */ 1301 assert(sp != NULL); 1302 assert((mirnp == NULL) || 1303 (sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)))); 1304 1305 /* print all mirrors */ 1306 if (mirnp == NULL) { 1307 mdnamelist_t *nlp = NULL; 1308 mdnamelist_t *p; 1309 int cnt; 1310 int rval = 0; 1311 1312 /* get list */ 1313 if ((cnt = meta_get_mirror_names(sp, &nlp, options, ep)) < 0) 1314 return (-1); 1315 else if (cnt == 0) 1316 return (0); 1317 1318 /* recurse */ 1319 for (p = nlp; (p != NULL); p = p->next) { 1320 mdname_t *np = p->namep; 1321 1322 if (meta_mirror_print(sp, np, nlpp, fname, fp, 1323 options, ep) != 0) 1324 rval = -1; 1325 } 1326 1327 /* cleanup, return success */ 1328 metafreenamelist(nlp); 1329 return (rval); 1330 } 1331 1332 /* get unit structure */ 1333 if ((mirrorp = meta_get_mirror_common(sp, mirnp, 1334 ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL) 1335 return (-1); 1336 1337 /* check for parented */ 1338 if ((! (options & PRINT_SUBDEVS)) && 1339 (MD_HAS_PARENT(mirrorp->common.parent))) { 1340 return (0); 1341 } 1342 1343 /* print appropriate detail */ 1344 if (options & PRINT_SHORT) { 1345 /* print mirror */ 1346 if (mirror_print(mirrorp, fname, fp, options, ep) != 0) 1347 return (-1); 1348 1349 /* print underlying metadevices */ 1350 for (smi = 0; (smi < NMIRROR); ++smi) { 1351 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 1352 mdname_t *submirnamep = mdsp->submirnamep; 1353 1354 /* skip unused submirrors */ 1355 if (submirnamep == NULL) { 1356 assert(mdsp->state == SMS_UNUSED); 1357 continue; 1358 } 1359 1360 /* print submirror */ 1361 if (metaismeta(submirnamep)) { 1362 if (meta_print_name(sp, submirnamep, nlpp, 1363 fname, fp, (options | PRINT_SUBDEVS), NULL, 1364 ep) != 0) { 1365 return (-1); 1366 } 1367 } 1368 } 1369 1370 /* return success */ 1371 return (0); 1372 } else { 1373 return (mirror_report(sp, mirrorp, nlpp, fname, fp, 1374 options, ep)); 1375 } 1376} 1377 1378/* 1379 * online submirror 1380 */ 1381int 1382meta_mirror_online( 1383 mdsetname_t *sp, 1384 mdname_t *mirnp, 1385 mdname_t *submirnp, 1386 mdcmdopts_t options, 1387 md_error_t *ep 1388) 1389{ 1390 md_i_off_on_t mio; 1391 md_mirror_t *mirrorp; 1392 md_set_desc *sd; 1393 uint_t tstate; 1394 1395 /* should have same set */ 1396 assert(sp != NULL); 1397 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 1398 1399 /* check name */ 1400 if (metachkmeta(mirnp, ep) != 0) 1401 return (-1); 1402 1403 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 1404 return (-1); 1405 1406 /* Only valid for mirror without ABR set */ 1407 if (meta_get_tstate(mirrorp->common.namep->dev, &tstate, ep) != 0) 1408 return (-1); 1409 if (tstate & MD_ABR_CAP) { 1410 (void) mderror(ep, MDE_ABR_SET, NULL); 1411 return (-1); 1412 } 1413 1414 /* 1415 * In a MN set, the master always executes the online command first. 1416 * Before the master executes the IOC_ONLINE ioctl, 1417 * the master sends a message to all nodes to suspend writes to 1418 * this mirror. Then the master executes the IOC_ONLINE ioctl 1419 * which resumes writes to this mirror from the master node. 1420 * As each slave executes the online command, each slave will 1421 * call the IOC_ONLINE ioctl which will resume writes to this mirror 1422 * from that slave node. 1423 */ 1424 if (! metaislocalset(sp)) { 1425 if ((sd = metaget_setdesc(sp, ep)) == NULL) 1426 return (-1); 1427 if ((MD_MNSET_DESC(sd)) && sd->sd_mn_am_i_master) 1428 if (meta_mn_send_suspend_writes( 1429 meta_getminor(mirnp->dev), ep) != 0) 1430 return (-1); 1431 } 1432 1433 /* online submirror */ 1434 (void) memset(&mio, 0, sizeof (mio)); 1435 mio.mnum = meta_getminor(mirnp->dev); 1436 MD_SETDRIVERNAME(&mio, MD_MIRROR, sp->setno); 1437 mio.submirror = submirnp->dev; 1438 if (metaioctl(MD_IOCONLINE, &mio, &mio.mde, NULL) != 0) 1439 return (mdstealerror(ep, &mio.mde)); 1440 1441 /* clear cache */ 1442 meta_invalidate_name(mirnp); 1443 meta_invalidate_name(submirnp); 1444 1445 /* let em know */ 1446 if (options & MDCMD_PRINT) { 1447 (void) printf(dgettext(TEXT_DOMAIN, 1448 "%s: submirror %s is onlined\n"), 1449 mirnp->cname, submirnp->cname); 1450 (void) fflush(stdout); 1451 } 1452 1453 /* return success */ 1454 return (0); 1455} 1456 1457/* 1458 * offline submirror 1459 */ 1460int 1461meta_mirror_offline( 1462 mdsetname_t *sp, 1463 mdname_t *mirnp, 1464 mdname_t *submirnp, 1465 mdcmdopts_t options, 1466 md_error_t *ep 1467) 1468{ 1469 int force = ((options & MDCMD_FORCE) ? 1 : 0); 1470 md_i_off_on_t mio; 1471 md_mirror_t *mirrorp; 1472 md_set_desc *sd; 1473 uint_t tstate; 1474 1475 /* should have same set */ 1476 assert(sp != NULL); 1477 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 1478 1479 /* check name */ 1480 if (metachkmeta(mirnp, ep) != 0) 1481 return (-1); 1482 1483 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 1484 return (-1); 1485 1486 /* Only valid for mirror without ABR set */ 1487 if (meta_get_tstate(mirrorp->common.namep->dev, &tstate, ep) != 0) 1488 return (-1); 1489 if (tstate & MD_ABR_CAP) { 1490 (void) mderror(ep, MDE_ABR_SET, NULL); 1491 return (-1); 1492 } 1493 1494 /* 1495 * In a MN set, the master always executes the offline command first. 1496 * Before the master executes the IOC_OFFLINE ioctl, 1497 * the master sends a message to all nodes to suspend writes to 1498 * this mirror. Then the master executes the IOC_OFFLINE ioctl 1499 * which resumes writes to this mirror from the master node. 1500 * As each slave executes the offline command, each slave will 1501 * call the IOC_OFFLINE ioctl which will resume writes to this mirror 1502 * from that slave node. 1503 */ 1504 if (! metaislocalset(sp)) { 1505 if ((sd = metaget_setdesc(sp, ep)) == NULL) 1506 return (-1); 1507 if ((MD_MNSET_DESC(sd)) && sd->sd_mn_am_i_master) 1508 if (meta_mn_send_suspend_writes( 1509 meta_getminor(mirnp->dev), ep) != 0) 1510 return (-1); 1511 } 1512 1513 /* offline submirror */ 1514 (void) memset(&mio, 0, sizeof (mio)); 1515 mio.mnum = meta_getminor(mirnp->dev); 1516 MD_SETDRIVERNAME(&mio, MD_MIRROR, sp->setno); 1517 mio.submirror = submirnp->dev; 1518 mio.force_offline = force; 1519 if (metaioctl(MD_IOCOFFLINE, &mio, &mio.mde, NULL) != 0) 1520 return (mdstealerror(ep, &mio.mde)); 1521 1522 /* clear cache */ 1523 meta_invalidate_name(mirnp); 1524 meta_invalidate_name(submirnp); 1525 1526 /* let em know */ 1527 if (options & MDCMD_PRINT) { 1528 (void) printf(dgettext(TEXT_DOMAIN, 1529 "%s: submirror %s is offlined\n"), 1530 mirnp->cname, submirnp->cname); 1531 (void) fflush(stdout); 1532 } 1533 1534 /* return success */ 1535 return (0); 1536} 1537 1538/* 1539 * attach submirror to mirror 1540 * we actually never have to worry about crossing a thresh hold here. 1541 * 2 cases 1) attach and the only way the mirror can be 64 bit is if 1542 * one of the submirrors already is. 2) grow and the only way the mirror 1543 * is 64 bit is if one of the submirror's already is. 1544 */ 1545int 1546meta_mirror_attach( 1547 mdsetname_t *sp, 1548 mdname_t *mirnp, 1549 mdname_t *submirnp, 1550 mdcmdopts_t options, 1551 md_error_t *ep 1552) 1553{ 1554 md_att_struct_t att; 1555 md_set_desc *sd; 1556 1557 /* should have same set */ 1558 assert(sp != NULL); 1559 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 1560 1561 /* check name */ 1562 if (metachkmeta(mirnp, ep) != 0) 1563 return (-1); 1564 1565 /* just grow */ 1566 if (submirnp == NULL) { 1567 return (meta_concat_generic(sp, mirnp, NULL, ep)); 1568 } 1569 1570 /* check submirror */ 1571 if (meta_check_submirror(sp, submirnp, mirnp, 0, ep) != 0) 1572 return (-1); 1573 1574 /* In dryrun mode (DOIT not set) we must not alter the mddb */ 1575 if (options & MDCMD_DOIT) { 1576 /* store name in namespace */ 1577 if (add_key_name(sp, submirnp, NULL, ep) != 0) 1578 return (-1); 1579 } 1580 1581 /* 1582 * In a MN set, the master always executes the attach command first. 1583 * Before the master executes the IOC_ATTACH ioctl, in non-DRYRUN mode 1584 * the master sends a message to all nodes to suspend writes to 1585 * this mirror. Then the master executes the IOC_ATTACH ioctl 1586 * which resumes writes to this mirror from the master node. 1587 * As each slave executes the attach command, each slave will 1588 * call the IOC_ATTACH ioctl which will resume writes to this mirror 1589 * from that slave node. 1590 */ 1591 if (! metaislocalset(sp)) { 1592 if ((sd = metaget_setdesc(sp, ep)) == NULL) 1593 return (-1); 1594 if ((MD_MNSET_DESC(sd)) && (options & MDCMD_DOIT) && 1595 sd->sd_mn_am_i_master) 1596 if (meta_mn_send_suspend_writes( 1597 meta_getminor(mirnp->dev), ep) != 0) 1598 return (-1); 1599 } 1600 1601 /* attach submirror */ 1602 (void) memset(&att, 0, sizeof (att)); 1603 att.mnum = meta_getminor(mirnp->dev); 1604 MD_SETDRIVERNAME(&att, MD_MIRROR, sp->setno); 1605 att.submirror = submirnp->dev; 1606 att.key = submirnp->key; 1607 /* if the comamnd was issued with -n option, use dryrun mode */ 1608 if ((options & MDCMD_DOIT) == 0) { 1609 att.options = MDIOCTL_DRYRUN; 1610 } 1611 if (metaioctl(MD_IOCATTACH, &att, &att.mde, NULL) != 0) { 1612 /* In dryrun mode (DOIT not set) we must not alter the mddb */ 1613 if (options & MDCMD_DOIT) { 1614 (void) del_key_name(sp, submirnp, ep); 1615 } 1616 return (mdstealerror(ep, &att.mde)); 1617 } 1618 1619 /* In dryrun mode (DOIT not set) we must not alter the mddb */ 1620 if (options & MDCMD_DOIT) { 1621 /* clear cache */ 1622 meta_invalidate_name(mirnp); 1623 meta_invalidate_name(submirnp); 1624 } 1625 1626 /* let em know */ 1627 if (options & MDCMD_PRINT) { 1628 (void) printf(dgettext(TEXT_DOMAIN, 1629 "%s: submirror %s %s\n"), mirnp->cname, submirnp->cname, 1630 (options & MDCMD_DOIT) ? "is attached" : "would attach"); 1631 (void) fflush(stdout); 1632 } 1633 1634 /* return success */ 1635 return (0); 1636} 1637 1638/* 1639 * detach submirror 1640 */ 1641int 1642meta_mirror_detach( 1643 mdsetname_t *sp, 1644 mdname_t *mirnp, 1645 mdname_t *submirnp, 1646 mdcmdopts_t options, 1647 md_error_t *ep 1648) 1649{ 1650 int force = ((options & MDCMD_FORCE) ? 1 : 0); 1651 md_detach_params_t detach; 1652 md_set_desc *sd; 1653 1654 /* should have same set */ 1655 assert(sp != NULL); 1656 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 1657 1658 /* check name */ 1659 if (metachkmeta(mirnp, ep) != 0) 1660 return (-1); 1661 1662 /* 1663 * In a MN set, the master always executes the detach command first. 1664 * Before the master executes the IOC_DETACH ioctl, 1665 * the master sends a message to all nodes to suspend writes to 1666 * this mirror. Then the master executes the IOC_DETACH ioctl 1667 * which resumes writes to this mirror from the master node. 1668 * As each slave executes the detach command, each slave will 1669 * call the IOC_DETACH ioctl which will resume writes to this mirror 1670 * from that slave node. 1671 */ 1672 if (! metaislocalset(sp)) { 1673 if ((sd = metaget_setdesc(sp, ep)) == NULL) 1674 return (-1); 1675 if ((MD_MNSET_DESC(sd)) && sd->sd_mn_am_i_master) 1676 if (meta_mn_send_suspend_writes( 1677 meta_getminor(mirnp->dev), ep) != 0) 1678 return (-1); 1679 } 1680 1681 /* detach submirror */ 1682 (void) memset(&detach, 0, sizeof (detach)); 1683 detach.mnum = meta_getminor(mirnp->dev); 1684 MD_SETDRIVERNAME(&detach, MD_MIRROR, sp->setno); 1685 detach.submirror = submirnp->dev; 1686 detach.force_detach = force; 1687 if (metaioctl(MD_IOCDETACH, &detach, &detach.mde, NULL) != 0) 1688 return (mdstealerror(ep, &detach.mde)); 1689 1690 /* clear cache */ 1691 meta_invalidate_name(mirnp); 1692 meta_invalidate_name(submirnp); 1693 1694 /* let em know */ 1695 if (options & MDCMD_PRINT) { 1696 (void) printf(dgettext(TEXT_DOMAIN, 1697 "%s: submirror %s is detached\n"), 1698 mirnp->cname, submirnp->cname); 1699 (void) fflush(stdout); 1700 } 1701 1702 /* return success */ 1703 return (0); 1704} 1705 1706/* 1707 * get mirror parameters 1708 */ 1709int 1710meta_mirror_get_params( 1711 mdsetname_t *sp, 1712 mdname_t *mirnp, 1713 mm_params_t *paramsp, 1714 md_error_t *ep 1715) 1716{ 1717 md_mirror_t *mirrorp; 1718 1719 /* should have a set */ 1720 assert(sp != NULL); 1721 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 1722 1723 /* check name */ 1724 if (metachkmeta(mirnp, ep) != 0) 1725 return (-1); 1726 1727 /* get unit */ 1728 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 1729 return (-1); 1730 1731 /* return parameters */ 1732 (void) memset(paramsp, 0, sizeof (*paramsp)); 1733 paramsp->read_option = mirrorp->read_option; 1734 paramsp->write_option = mirrorp->write_option; 1735 paramsp->pass_num = mirrorp->pass_num; 1736 return (0); 1737} 1738 1739/* 1740 * set mirror parameters 1741 */ 1742int 1743meta_mirror_set_params( 1744 mdsetname_t *sp, 1745 mdname_t *mirnp, 1746 mm_params_t *paramsp, 1747 md_error_t *ep 1748) 1749{ 1750 md_mirror_params_t mmp; 1751 1752 /* should have a set */ 1753 assert(sp != NULL); 1754 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 1755 1756 /* check name */ 1757 if (metachkmeta(mirnp, ep) != 0) 1758 return (-1); 1759 1760 /* set parameters */ 1761 (void) memset(&mmp, 0, sizeof (mmp)); 1762 MD_SETDRIVERNAME(&mmp, MD_MIRROR, sp->setno); 1763 mmp.mnum = meta_getminor(mirnp->dev); 1764 mmp.params = *paramsp; 1765 if (metaioctl(MD_IOCCHANGE, &mmp, &mmp.mde, mirnp->cname) != 0) 1766 return (mdstealerror(ep, &mmp.mde)); 1767 1768 /* clear cache */ 1769 meta_invalidate_name(mirnp); 1770 1771 /* return success */ 1772 return (0); 1773} 1774 1775/* 1776 * invalidate submirror names 1777 */ 1778static int 1779invalidate_submirrors( 1780 mdsetname_t *sp, 1781 mdname_t *mirnp, 1782 md_error_t *ep 1783) 1784{ 1785 md_mirror_t *mirrorp; 1786 uint_t smi; 1787 1788 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 1789 return (-1); 1790 for (smi = 0; (smi < NMIRROR); ++smi) { 1791 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 1792 mdname_t *submirnp = mdsp->submirnamep; 1793 1794 if (submirnp == NULL) { 1795 assert(mdsp->state == SMS_UNUSED); 1796 continue; 1797 } 1798 meta_invalidate_name(submirnp); 1799 } 1800 return (0); 1801} 1802 1803/* 1804 * replace mirror component 1805 */ 1806int 1807meta_mirror_replace( 1808 mdsetname_t *sp, 1809 mdname_t *mirnp, 1810 mdname_t *oldnp, 1811 mdname_t *newnp, 1812 mdcmdopts_t options, 1813 md_error_t *ep 1814) 1815{ 1816 md_mirror_t *mirrorp; 1817 uint_t smi; 1818 replace_params_t params; 1819 diskaddr_t size, label, start_blk; 1820 md_dev64_t old_dev, new_dev; 1821 diskaddr_t new_start_blk, new_end_blk; 1822 int rebind; 1823 md_set_desc *sd; 1824 char *new_devidp = NULL; 1825 int ret; 1826 md_error_t xep = mdnullerror; 1827 1828 /* should have same set */ 1829 assert(sp != NULL); 1830 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 1831 1832 /* check name */ 1833 if (metachkmeta(mirnp, ep) != 0) 1834 return (-1); 1835 1836 /* save new binding incase this is a rebind where oldnp==newnp */ 1837 new_dev = newnp->dev; 1838 new_start_blk = newnp->start_blk; 1839 new_end_blk = newnp->end_blk; 1840 1841 /* invalidate, then get the mirror (fill in oldnp from metadb) */ 1842 meta_invalidate_name(mirnp); 1843 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 1844 return (-1); 1845 for (smi = 0; (smi < NMIRROR); ++smi) { 1846 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 1847 mdname_t *submirnp = mdsp->submirnamep; 1848 1849 if (submirnp == NULL) { 1850 assert(mdsp->state == SMS_UNUSED); 1851 continue; 1852 } 1853 1854 if (! metaismeta(submirnp)) 1855 continue; 1856 1857 meta_invalidate_name(submirnp); 1858 if (meta_get_unit(sp, submirnp, ep) == NULL) 1859 return (-1); 1860 } 1861 1862 /* the old device binding is now established */ 1863 if ((old_dev = oldnp->dev) == NODEV64) 1864 return (mdsyserror(ep, ENODEV, oldnp->cname)); 1865 1866 /* 1867 * check for the case where oldnp and newnp indicate the same 1868 * device, but the dev_t of the device has changed between old 1869 * and new. This is called a rebind. On entry the dev_t 1870 * represents the new device binding determined from the 1871 * filesystem (meta_getdev). After calling meta_get_unit 1872 * oldnp (and maybe newnp if this is a rebind) is updated based 1873 * to the old binding from the metadb (done by metakeyname). 1874 */ 1875 if ((strcmp(oldnp->rname, newnp->rname) == 0) && 1876 (old_dev != new_dev)) { 1877 rebind = 1; 1878 } else { 1879 rebind = 0; 1880 } 1881 if (rebind) { 1882 newnp->dev = new_dev; 1883 newnp->start_blk = new_start_blk; 1884 newnp->end_blk = new_end_blk; 1885 } 1886 1887 /* 1888 * Save a copy of the devid associated with the new disk, the reason 1889 * is that if we are rebinding then the call to meta_check_component() 1890 * will cause the devid of the disk to be overwritten with what is in 1891 * the replica namespace. The function that actually overwrites the 1892 * devid is dr2drivedesc(). 1893 */ 1894 if (newnp->drivenamep->devid != NULL) 1895 new_devidp = Strdup(newnp->drivenamep->devid); 1896 1897 /* if it's a multi-node diskset clear new_devidp */ 1898 if (!metaislocalset(sp)) { 1899 if ((sd = metaget_setdesc(sp, ep)) == NULL) 1900 return (-1); 1901 if (MD_MNSET_DESC(sd)) 1902 new_devidp = NULL; 1903 } 1904 1905 /* check it out (dup on rebind is ok) */ 1906 if (meta_check_component(sp, newnp, 0, ep) != 0) { 1907 if ((! rebind) || (! mdisuseerror(ep, MDE_ALREADY))) { 1908 Free(new_devidp); 1909 return (-1); 1910 } 1911 mdclrerror(ep); 1912 } 1913 if ((size = metagetsize(newnp, ep)) == MD_DISKADDR_ERROR) { 1914 Free(new_devidp); 1915 return (-1); 1916 } 1917 if ((label = metagetlabel(newnp, ep)) == MD_DISKADDR_ERROR) { 1918 Free(new_devidp); 1919 return (-1); 1920 } 1921 if ((start_blk = metagetstart(sp, newnp, ep)) == MD_DISKADDR_ERROR) { 1922 Free(new_devidp); 1923 return (-1); 1924 } 1925 if (start_blk >= size) { 1926 (void) mdsyserror(ep, ENOSPC, newnp->cname); 1927 Free(new_devidp); 1928 return (-1); 1929 } 1930 1931 /* 1932 * Copy back the saved devid. 1933 */ 1934 Free(newnp->drivenamep->devid); 1935 if (new_devidp != NULL) { 1936 newnp->drivenamep->devid = Strdup(new_devidp); 1937 Free(new_devidp); 1938 } 1939 1940 /* store name in namespace, allocate new key */ 1941 if (add_key_name(sp, newnp, NULL, ep) != 0) 1942 return (-1); 1943 1944 /* 1945 * In a MN set, the master always executes the replace command first. 1946 * Before the master executes the IOC_REPLACE ioctl, in non-DRYRUN mode 1947 * the master sends a message to all nodes to suspend writes to 1948 * this mirror. Then the master executes the IOC_REPLACE ioctl 1949 * which resumes writes to this mirror from the master node. 1950 * As each slave executes the replace command, each slave will 1951 * call the IOC_REPLACE ioctl which will resume writes to this mirror 1952 * from that slave node. 1953 */ 1954 if (! metaislocalset(sp)) { 1955 if ((MD_MNSET_DESC(sd)) && (options & MDCMD_DOIT) && 1956 sd->sd_mn_am_i_master) 1957 if (meta_mn_send_suspend_writes( 1958 meta_getminor(mirnp->dev), ep) != 0) 1959 return (-1); 1960 } 1961 1962 if (rebind && !metaislocalset(sp)) { 1963 /* 1964 * We are 'rebind'ing a disk that is in a diskset so as well 1965 * as updating the diskset's namespace the local set needs 1966 * to be updated because it also contains a reference to 1967 * the disk in question. 1968 */ 1969 ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET, 1970 newnp->cname, ep); 1971 1972 if (ret != METADEVADM_SUCCESS) { 1973 (void) del_key_name(sp, newnp, &xep); 1974 return (-1); 1975 } 1976 } 1977 1978 /* replace component */ 1979 (void) memset(¶ms, 0, sizeof (params)); 1980 params.mnum = meta_getminor(mirnp->dev); 1981 MD_SETDRIVERNAME(¶ms, MD_MIRROR, sp->setno); 1982 params.cmd = REPLACE_COMP; 1983 params.old_dev = old_dev; 1984 params.new_dev = new_dev; 1985 params.start_blk = start_blk; 1986 params.has_label = ((label > 0) ? 1 : 0); 1987 params.number_blks = size; 1988 params.new_key = newnp->key; 1989 /* Is this just a dryrun ? */ 1990 if ((options & MDCMD_DOIT) == 0) { 1991 params.options |= MDIOCTL_DRYRUN; 1992 } 1993 if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) { 1994 (void) del_key_name(sp, newnp, ep); 1995 return (mdstealerror(ep, ¶ms.mde)); 1996 } 1997 1998 /* clear cache */ 1999 meta_invalidate_name(oldnp); 2000 meta_invalidate_name(newnp); 2001 if (invalidate_submirrors(sp, mirnp, ep) != 0) { 2002 meta_invalidate_name(mirnp); 2003 return (-1); 2004 } 2005 meta_invalidate_name(mirnp); 2006 2007 /* let em know */ 2008 if (options & MDCMD_PRINT) { 2009 (void) printf(dgettext(TEXT_DOMAIN, 2010 "%s: device %s is replaced with %s\n"), 2011 mirnp->cname, oldnp->cname, newnp->cname); 2012 (void) fflush(stdout); 2013 } 2014 2015 /* return success */ 2016 return (0); 2017} 2018 2019/* 2020 * enable mirror component 2021 */ 2022int 2023meta_mirror_enable( 2024 mdsetname_t *sp, 2025 mdname_t *mirnp, 2026 mdname_t *compnp, 2027 mdcmdopts_t options, 2028 md_error_t *ep 2029) 2030{ 2031 md_mirror_t *mirrorp; 2032 uint_t smi; 2033 replace_params_t params; 2034 diskaddr_t size, label, start_blk; 2035 md_dev64_t fs_dev; 2036 md_set_desc *sd; 2037 int ret; 2038 2039 /* should have same set */ 2040 assert(sp != NULL); 2041 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 2042 2043 /* check name */ 2044 if (metachkmeta(mirnp, ep) != 0) 2045 return (-1); 2046 2047 /* get the file_system dev binding */ 2048 if (meta_getdev(sp, compnp, ep) != 0) 2049 return (-1); 2050 fs_dev = compnp->dev; 2051 2052 /* get the mirror unit (fill in compnp->dev with metadb version) */ 2053 meta_invalidate_name(mirnp); 2054 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 2055 return (-1); 2056 2057 for (smi = 0; (smi < NMIRROR); ++smi) { 2058 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 2059 mdname_t *submirnp = mdsp->submirnamep; 2060 2061 if (submirnp == NULL) { 2062 assert(mdsp->state == SMS_UNUSED); 2063 continue; 2064 } 2065 2066 if (! metaismeta(submirnp)) 2067 continue; 2068 2069 meta_invalidate_name(submirnp); 2070 if (meta_get_unit(sp, submirnp, ep) == NULL) 2071 return (-1); 2072 } 2073 2074 /* the metadb device binding is now established */ 2075 if (compnp->dev == NODEV64) 2076 return (mdsyserror(ep, ENODEV, compnp->cname)); 2077 2078 /* 2079 * check for the case where the dev_t has changed between the 2080 * filesystem and the metadb. This is called a rebind, and 2081 * is handled by meta_mirror_replace. 2082 */ 2083 if (fs_dev != compnp->dev) { 2084 /* establish file system binding with invalid start/end */ 2085 compnp->dev = fs_dev; 2086 compnp->start_blk = -1; 2087 compnp->end_blk = -1; 2088 return (meta_mirror_replace(sp, mirnp, 2089 compnp, compnp, options, ep)); 2090 } 2091 2092 /* setup mirror info */ 2093 (void) memset(¶ms, 0, sizeof (params)); 2094 params.mnum = meta_getminor(mirnp->dev); 2095 MD_SETDRIVERNAME(¶ms, MD_MIRROR, sp->setno); 2096 params.cmd = ENABLE_COMP; 2097 2098 /* check it out */ 2099 if (meta_check_component(sp, compnp, 0, ep) != 0) { 2100 if (! mdisuseerror(ep, MDE_ALREADY)) 2101 return (-1); 2102 mdclrerror(ep); 2103 } 2104 2105 if ((size = metagetsize(compnp, ep)) == MD_DISKADDR_ERROR) 2106 return (-1); 2107 if ((label = metagetlabel(compnp, ep)) == MD_DISKADDR_ERROR) 2108 return (-1); 2109 if ((start_blk = metagetstart(sp, compnp, ep)) == MD_DISKADDR_ERROR) 2110 return (-1); 2111 if (start_blk >= size) { 2112 (void) mdsyserror(ep, ENOSPC, compnp->cname); 2113 return (-1); 2114 } 2115 2116 /* 2117 * In a MN set, the master always executes the replace command first. 2118 * Before the master executes the IOC_REPLACE ioctl, in non-DRYRUN mode 2119 * the master sends a message to all nodes to suspend writes to 2120 * this mirror. Then the master executes the IOC_REPLACE ioctl 2121 * which resumes writes to this mirror from the master node. 2122 * As each slave executes the replace command, each slave will 2123 * call the IOC_REPLACE ioctl which will resume writes to this mirror 2124 * from that slave node. 2125 */ 2126 if (! metaislocalset(sp)) { 2127 if ((sd = metaget_setdesc(sp, ep)) == NULL) 2128 return (-1); 2129 if ((MD_MNSET_DESC(sd)) && (options & MDCMD_DOIT) && 2130 sd->sd_mn_am_i_master) 2131 if (meta_mn_send_suspend_writes( 2132 meta_getminor(mirnp->dev), ep) != 0) 2133 return (-1); 2134 } 2135 2136 /* enable component */ 2137 params.old_dev = compnp->dev; 2138 params.new_dev = compnp->dev; 2139 params.start_blk = start_blk; 2140 params.has_label = ((label > 0) ? 1 : 0); 2141 params.number_blks = size; 2142 2143 /* Is this just a dryrun ? */ 2144 if ((options & MDCMD_DOIT) == 0) { 2145 params.options |= MDIOCTL_DRYRUN; 2146 } 2147 if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) 2148 return (mdstealerror(ep, ¶ms.mde)); 2149 2150 /* 2151 * Are we dealing with a non-local set? If so need to update the 2152 * local namespace so that the disk record has the correct devid. 2153 */ 2154 if (!metaislocalset(sp)) { 2155 ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET, compnp->cname, 2156 ep); 2157 2158 if (ret != METADEVADM_SUCCESS) { 2159 /* 2160 * Failed to update the local set. Nothing to do here 2161 * apart from report the error. The namespace is 2162 * most likely broken and some form of remedial 2163 * recovery is going to be required. 2164 */ 2165 mde_perror(ep, ""); 2166 mdclrerror(ep); 2167 } 2168 } 2169 2170 /* clear cache */ 2171 meta_invalidate_name(compnp); 2172 if (invalidate_submirrors(sp, mirnp, ep) != 0) { 2173 meta_invalidate_name(mirnp); 2174 return (-1); 2175 } 2176 meta_invalidate_name(mirnp); 2177 2178 /* let em know */ 2179 if (options & MDCMD_PRINT) { 2180 (void) printf(dgettext(TEXT_DOMAIN, 2181 "%s: device %s is enabled\n"), 2182 mirnp->cname, compnp->cname); 2183 (void) fflush(stdout); 2184 } 2185 2186 /* return success */ 2187 return (0); 2188} 2189 2190/* 2191 * check for dups in the mirror itself 2192 */ 2193static int 2194check_twice( 2195 md_mirror_t *mirrorp, 2196 uint_t smi, 2197 md_error_t *ep 2198) 2199{ 2200 mdname_t *mirnp = mirrorp->common.namep; 2201 mdname_t *thisnp; 2202 uint_t s; 2203 2204 thisnp = mirrorp->submirrors[smi].submirnamep; 2205 for (s = 0; (s < smi); ++s) { 2206 md_submirror_t *mdsp = &mirrorp->submirrors[s]; 2207 mdname_t *submirnp = mdsp->submirnamep; 2208 2209 if (submirnp == NULL) 2210 continue; 2211 2212 if (meta_check_overlap(mirnp->cname, thisnp, 0, -1, 2213 submirnp, 0, -1, ep) != 0) { 2214 return (-1); 2215 } 2216 } 2217 return (0); 2218} 2219 2220/* 2221 * check mirror 2222 */ 2223int 2224meta_check_mirror( 2225 mdsetname_t *sp, 2226 md_mirror_t *mirrorp, 2227 mdcmdopts_t options, 2228 md_error_t *ep 2229) 2230{ 2231 mdname_t *mirnp = mirrorp->common.namep; 2232 int force = ((options & MDCMD_FORCE) ? 1 : 0); 2233 int doit = ((options & MDCMD_DOIT) ? 1 : 0); 2234 uint_t nsm = 0; 2235 uint_t smi; 2236 2237 /* check submirrors */ 2238 for (smi = 0; (smi < NMIRROR); ++smi) { 2239 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 2240 mdname_t *submirnp = mdsp->submirnamep; 2241 2242 if (submirnp == NULL) 2243 continue; 2244 ++nsm; 2245 } 2246 if (nsm < 1) { 2247 return (mdmderror(ep, MDE_BAD_MIRROR, 2248 meta_getminor(mirnp->dev), mirnp->cname)); 2249 } 2250 for (smi = 0; (smi < NMIRROR); ++smi) { 2251 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 2252 mdname_t *submirnp = mdsp->submirnamep; 2253 diskaddr_t size; 2254 2255 /* skip unused submirrors */ 2256 if (submirnp == NULL) { 2257 if (mdsp->state != SMS_UNUSED) { 2258 return (mdmderror(ep, MDE_BAD_MIRROR, 2259 meta_getminor(mirnp->dev), mirnp->cname)); 2260 } 2261 continue; 2262 } 2263 2264 /* check submirror */ 2265 if (doit) { 2266 if (meta_check_submirror(sp, submirnp, NULL, force, 2267 ep) != 0) 2268 return (-1); 2269 if ((size = metagetsize(submirnp, ep)) == 2270 MD_DISKADDR_ERROR) { 2271 return (-1); 2272 } else if (size == 0) { 2273 return (mdsyserror(ep, ENOSPC, 2274 submirnp->cname)); 2275 } 2276 } 2277 2278 /* check this mirror too */ 2279 if (check_twice(mirrorp, smi, ep) != 0) 2280 return (-1); 2281 } 2282 2283 /* check read option */ 2284 switch (mirrorp->read_option) { 2285 case RD_LOAD_BAL: 2286 case RD_GEOMETRY: 2287 case RD_FIRST: 2288 break; 2289 default: 2290 return (mderror(ep, MDE_BAD_RD_OPT, mirnp->cname)); 2291 } 2292 2293 /* check write option */ 2294 switch (mirrorp->write_option) { 2295 case WR_PARALLEL: 2296 case WR_SERIAL: 2297 break; 2298 default: 2299 return (mderror(ep, MDE_BAD_WR_OPT, mirnp->cname)); 2300 } 2301 2302 /* check pass number */ 2303 if ((mirrorp->pass_num < 0) || (mirrorp->pass_num > MD_PASS_MAX)) 2304 return (mderror(ep, MDE_BAD_PASS_NUM, mirnp->cname)); 2305 2306 /* return success */ 2307 return (0); 2308} 2309 2310/* 2311 * setup mirror geometry 2312 */ 2313static int 2314mirror_geom( 2315 md_mirror_t *mirrorp, 2316 mm_unit_t *mm, 2317 md_error_t *ep 2318) 2319{ 2320 uint_t write_reinstruct = 0; 2321 uint_t read_reinstruct = 0; 2322 uint_t round_cyl = 1; 2323 mdname_t *smnp = NULL; 2324 uint_t smi; 2325 mdgeom_t *geomp; 2326 2327 /* get worst reinstructs */ 2328 for (smi = 0; (smi < NMIRROR); ++smi) { 2329 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 2330 mdname_t *submirnp = mdsp->submirnamep; 2331 2332 if (submirnp == NULL) 2333 continue; 2334 2335 if ((geomp = metagetgeom(submirnp, ep)) == NULL) 2336 return (-1); 2337 if (geomp->write_reinstruct > write_reinstruct) 2338 write_reinstruct = geomp->write_reinstruct; 2339 if (geomp->read_reinstruct > read_reinstruct) 2340 read_reinstruct = geomp->read_reinstruct; 2341 2342 if (smnp == NULL) 2343 smnp = submirnp; 2344 } 2345 2346 /* setup geometry from first submirror */ 2347 assert(smnp != NULL); 2348 if ((geomp = metagetgeom(smnp, ep)) == NULL) 2349 return (-1); 2350 if (meta_setup_geom((md_unit_t *)mm, mirrorp->common.namep, geomp, 2351 write_reinstruct, read_reinstruct, round_cyl, ep) != 0) 2352 return (-1); 2353 2354 /* return success */ 2355 return (0); 2356} 2357 2358/* 2359 * create mirror 2360 */ 2361int 2362meta_create_mirror( 2363 mdsetname_t *sp, 2364 md_mirror_t *mirrorp, 2365 mdcmdopts_t options, 2366 md_error_t *ep 2367) 2368{ 2369 mdname_t *mirnp = mirrorp->common.namep; 2370 mm_unit_t *mm; 2371 diskaddr_t submir_size = MD_DISKADDR_ERROR; 2372 ushort_t nsm = 0; 2373 uint_t smi; 2374 mdnamelist_t *keynlp = NULL; 2375 md_set_params_t set_params; 2376 int rval = -1; 2377 md_timeval32_t creation_time; 2378 int create_flag = MD_CRO_32BIT; 2379 2380 /* validate mirror */ 2381 if (meta_check_mirror(sp, mirrorp, options, ep) != 0) 2382 return (-1); 2383 2384 2385 /* allocate mirror unit */ 2386 mm = Zalloc(sizeof (*mm)); 2387 2388 if (meta_gettimeofday(&creation_time) == -1) 2389 return (mdsyserror(ep, errno, NULL)); 2390 2391 /* do submirrors */ 2392 for (smi = 0; (smi < NMIRROR); ++smi) { 2393 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 2394 mdname_t *submirnp = mdsp->submirnamep; 2395 mm_submirror_t *mmsp = &mm->un_sm[smi]; 2396 diskaddr_t size; 2397 2398 /* skip unused submirrors */ 2399 if (submirnp == NULL) { 2400 assert(mdsp->state == SMS_UNUSED); 2401 continue; 2402 } 2403 ++nsm; 2404 2405 /* get size */ 2406 if ((size = metagetsize(submirnp, ep)) == MD_DISKADDR_ERROR) 2407 goto out; 2408 assert(size > 0); 2409 2410 /* adjust for smallest submirror */ 2411 if (submir_size == MD_DISKADDR_ERROR) { 2412 submir_size = size; 2413 } else if (size < submir_size) { 2414 submir_size = size; 2415 } 2416 2417 if (options & MDCMD_DOIT) { 2418 /* store name in namespace */ 2419 if (add_key_name(sp, submirnp, &keynlp, ep) != 0) 2420 goto out; 2421 } 2422 2423 /* setup submirror */ 2424 mmsp->sm_key = submirnp->key; 2425 mmsp->sm_dev = submirnp->dev; 2426 mmsp->sm_state = SMS_RUNNING; 2427 mmsp->sm_timestamp = creation_time; 2428 } 2429 2430 /* setup unit */ 2431 mm->c.un_type = MD_METAMIRROR; 2432 MD_SID(mm) = meta_getminor(mirnp->dev); 2433 mm->c.un_actual_tb = submir_size; 2434 mm->c.un_size = offsetof(mm_unit_t, un_smic); 2435 mm->un_nsm = nsm; 2436 mm->un_read_option = mirrorp->read_option; 2437 mm->un_write_option = mirrorp->write_option; 2438 mm->un_pass_num = mirrorp->pass_num; 2439 if (mirror_geom(mirrorp, mm, ep) != 0) 2440 goto out; 2441 2442 /* fill in the size of the mirror */ 2443 if (options & MDCMD_UPDATE) { 2444 mirrorp->common.size = mm->c.un_total_blocks; 2445 } 2446 2447 /* if we're not doing anything, return success */ 2448 if (! (options & MDCMD_DOIT)) { 2449 rval = 0; /* success */ 2450 goto out; 2451 } 2452 2453 /* create mirror */ 2454 (void) memset(&set_params, 0, sizeof (set_params)); 2455 /* did the user tell us to generate a large device? */ 2456 create_flag = meta_check_devicesize(mm->c.un_total_blocks); 2457 if (create_flag == MD_CRO_64BIT) { 2458 mm->c.un_revision |= MD_64BIT_META_DEV; 2459 set_params.options = MD_CRO_64BIT; 2460 } else { 2461 mm->c.un_revision &= ~MD_64BIT_META_DEV; 2462 set_params.options = MD_CRO_32BIT; 2463 } 2464 set_params.mnum = MD_SID(mm); 2465 set_params.size = mm->c.un_size; 2466 set_params.mdp = (uintptr_t)mm; 2467 MD_SETDRIVERNAME(&set_params, MD_MIRROR, MD_MIN2SET(set_params.mnum)); 2468 if (metaioctl(MD_IOCSET, &set_params, &set_params.mde, 2469 mirnp->cname) != 0) { 2470 (void) mdstealerror(ep, &set_params.mde); 2471 goto out; 2472 } 2473 rval = 0; /* success */ 2474 2475 /* cleanup, return success */ 2476out: 2477 Free(mm); 2478 if (rval != 0) { 2479 (void) del_key_names(sp, keynlp, NULL); 2480 } 2481 metafreenamelist(keynlp); 2482 if ((rval == 0) && (options & MDCMD_DOIT)) { 2483 if (invalidate_submirrors(sp, mirnp, ep) != 0) 2484 rval = -1; 2485 meta_invalidate_name(mirnp); 2486 } 2487 return (rval); 2488} 2489 2490/* 2491 * initialize mirror 2492 * NOTE: this functions is metainit(1m)'s command line parser! 2493 */ 2494int 2495meta_init_mirror( 2496 mdsetname_t **spp, 2497 int argc, 2498 char *argv[], 2499 mdcmdopts_t options, 2500 md_error_t *ep 2501) 2502{ 2503 char *uname = argv[0]; 2504 mdname_t *mirnp = NULL; 2505 int old_optind; 2506 int c; 2507 md_mirror_t *mirrorp = NULL; 2508 uint_t smi; 2509 int rval = -1; 2510 2511 /* get mirror name */ 2512 assert(argc > 0); 2513 if (argc < 1) 2514 goto syntax; 2515 if ((mirnp = metaname(spp, uname, META_DEVICE, ep)) == NULL) 2516 goto out; 2517 assert(*spp != NULL); 2518 uname = mirnp->cname; 2519 if (metachkmeta(mirnp, ep) != 0) 2520 goto out; 2521 2522 if (!(options & MDCMD_NOLOCK)) { 2523 /* grab set lock */ 2524 if (meta_lock(*spp, TRUE, ep) != 0) 2525 goto out; 2526 2527 if (meta_check_ownership(*spp, ep) != 0) 2528 goto out; 2529 } 2530 2531 /* see if it exists already */ 2532 if (metagetmiscname(mirnp, ep) != NULL) { 2533 (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP, 2534 meta_getminor(mirnp->dev), uname); 2535 goto out; 2536 } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) { 2537 goto out; 2538 } else { 2539 mdclrerror(ep); 2540 } 2541 --argc, ++argv; 2542 2543 /* grab -m */ 2544 if ((argc < 1) || (strcmp(argv[0], "-m") != 0)) 2545 goto syntax; 2546 --argc, ++argv; 2547 2548 if (argc == 0) 2549 goto syntax; 2550 2551 /* parse general options */ 2552 optind = 0; 2553 opterr = 0; 2554 if (getopt(argc, argv, "") != -1) 2555 goto options; 2556 2557 /* allocate mirror */ 2558 mirrorp = Zalloc(sizeof (*mirrorp)); 2559 2560 /* setup common */ 2561 mirrorp->common.namep = mirnp; 2562 mirrorp->common.type = MD_METAMIRROR; 2563 2564 /* parse submirrors */ 2565 for (smi = 0; ((argc > 0) && (argv[0][0] != '-') && 2566 (! isdigit(argv[0][0]))); ++smi) { 2567 md_submirror_t *mdsm = &mirrorp->submirrors[smi]; 2568 mdname_t *submirnamep; 2569 2570 /* check for room */ 2571 if (smi >= NMIRROR) { 2572 (void) mdmderror(ep, MDE_MIRROR_FULL, 2573 meta_getminor(mirnp->dev), uname); 2574 goto out; 2575 } 2576 2577 /* parse submirror name */ 2578 if ((submirnamep = metaname(spp, argv[0], 2579 META_DEVICE, ep)) == NULL) 2580 goto out; 2581 mdsm->submirnamep = submirnamep; 2582 --argc, ++argv; 2583 } 2584 if (smi == 0) { 2585 (void) mdmderror(ep, MDE_NSUBMIRS, meta_getminor(mirnp->dev), 2586 uname); 2587 goto out; 2588 } 2589 2590 /* dangerous n-way mirror creation */ 2591 if ((smi > 1) && (options & MDCMD_PRINT)) { 2592 md_eprintf(dgettext(TEXT_DOMAIN, 2593"%s: WARNING: This form of metainit is not recommended.\n" 2594"The submirrors may not have the same data.\n" 2595"Please see ERRORS in metainit(1M) for additional information.\n"), 2596 uname); 2597 } 2598 2599 /* parse mirror options */ 2600 mirrorp->read_option = RD_LOAD_BAL; 2601 mirrorp->write_option = WR_PARALLEL; 2602 mirrorp->pass_num = MD_PASS_DEFAULT; 2603 old_optind = optind = 0; 2604 opterr = 0; 2605 while ((c = getopt(argc, argv, "grS")) != -1) { 2606 switch (c) { 2607 case 'g': 2608 if (mirrorp->read_option != RD_LOAD_BAL) { 2609 (void) mderror(ep, MDE_BAD_RD_OPT, uname); 2610 goto out; 2611 } 2612 mirrorp->read_option = RD_GEOMETRY; 2613 break; 2614 2615 case 'r': 2616 if (mirrorp->read_option != RD_LOAD_BAL) { 2617 (void) mderror(ep, MDE_BAD_RD_OPT, uname); 2618 goto out; 2619 } 2620 mirrorp->read_option = RD_FIRST; 2621 break; 2622 2623 case 'S': 2624 if (mirrorp->write_option != WR_PARALLEL) { 2625 (void) mderror(ep, MDE_BAD_WR_OPT, uname); 2626 goto out; 2627 } 2628 mirrorp->write_option = WR_SERIAL; 2629 break; 2630 2631 default: 2632 argc -= old_optind; 2633 argv += old_optind; 2634 goto options; 2635 } 2636 old_optind = optind; 2637 } 2638 argc -= optind; 2639 argv += optind; 2640 2641 /* parse pass number */ 2642 if ((argc > 0) && (isdigit(argv[0][0]))) { 2643 if (name_to_pass_num(uname, argv[0], 2644 &mirrorp->pass_num, ep) != 0) { 2645 goto out; 2646 } 2647 --argc, ++argv; 2648 } 2649 2650 /* we should be at the end */ 2651 if (argc != 0) 2652 goto syntax; 2653 2654 /* create mirror */ 2655 if (meta_create_mirror(*spp, mirrorp, options, ep) != 0) 2656 goto out; 2657 rval = 0; /* success */ 2658 2659 /* let em know */ 2660 if (options & MDCMD_PRINT) { 2661 (void) printf(dgettext(TEXT_DOMAIN, 2662 "%s: Mirror is setup\n"), 2663 uname); 2664 (void) fflush(stdout); 2665 } 2666 goto out; 2667 2668 /* syntax error */ 2669syntax: 2670 rval = meta_cook_syntax(ep, MDE_SYNTAX, uname, argc, argv); 2671 goto out; 2672 2673 /* options error */ 2674options: 2675 rval = meta_cook_syntax(ep, MDE_OPTION, uname, argc, argv); 2676 goto out; 2677 2678 /* cleanup, return error */ 2679out: 2680 if (mirrorp != NULL) 2681 meta_free_mirror(mirrorp); 2682 return (rval); 2683} 2684 2685/* 2686 * reset mirrors 2687 */ 2688int 2689meta_mirror_reset( 2690 mdsetname_t *sp, 2691 mdname_t *mirnp, 2692 mdcmdopts_t options, 2693 md_error_t *ep 2694) 2695{ 2696 md_mirror_t *mirrorp; 2697 uint_t smi; 2698 int rval = -1; 2699 2700 /* should have same set */ 2701 assert(sp != NULL); 2702 assert((mirnp == NULL) || 2703 (sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)))); 2704 2705 /* reset all mirrors */ 2706 if (mirnp == NULL) { 2707 mdnamelist_t *mirrornlp = NULL; 2708 mdnamelist_t *p; 2709 2710 /* for each mirror */ 2711 rval = 0; 2712 if (meta_get_mirror_names(sp, &mirrornlp, 0, ep) < 0) 2713 return (-1); 2714 for (p = mirrornlp; (p != NULL); p = p->next) { 2715 /* reset mirror */ 2716 mirnp = p->namep; 2717 /* 2718 * If this is a multi-node set, we send a series 2719 * of individual metaclear commands. 2720 */ 2721 if (meta_is_mn_set(sp, ep)) { 2722 if (meta_mn_send_metaclear_command(sp, 2723 mirnp->cname, options, 0, ep) != 0) { 2724 rval = -1; 2725 break; 2726 } 2727 } else { 2728 if (meta_mirror_reset(sp, mirnp, options, 2729 ep) != 0) { 2730 rval = -1; 2731 break; 2732 } 2733 } 2734 } 2735 2736 /* cleanup return success */ 2737 metafreenamelist(mirrornlp); 2738 return (rval); 2739 } 2740 2741 /* check name */ 2742 if (metachkmeta(mirnp, ep) != 0) 2743 return (-1); 2744 2745 /* get unit structure */ 2746 if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) 2747 return (-1); 2748 2749 /* make sure nobody owns us */ 2750 if (MD_HAS_PARENT(mirrorp->common.parent)) { 2751 return (mdmderror(ep, MDE_IN_USE, meta_getminor(mirnp->dev), 2752 mirnp->cname)); 2753 } 2754 2755 /* clear subdevices cache */ 2756 if (invalidate_submirrors(sp, mirnp, ep) != 0) 2757 return (-1); 2758 2759 /* clear metadevice */ 2760 if (meta_reset(sp, mirnp, options, ep) != 0) 2761 goto out; 2762 rval = 0; /* success */ 2763 2764 /* let em know */ 2765 if (options & MDCMD_PRINT) { 2766 (void) printf(dgettext(TEXT_DOMAIN, 2767 "%s: Mirror is cleared\n"), mirnp->cname); 2768 (void) fflush(stdout); 2769 } 2770 2771 /* clear subdevices */ 2772 if (! (options & MDCMD_RECURSE)) 2773 goto out; 2774 for (smi = 0; (smi < NMIRROR); ++smi) { 2775 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 2776 mdname_t *submirnp = mdsp->submirnamep; 2777 2778 /* skip unused submirrors */ 2779 if (submirnp == NULL) { 2780 assert(mdsp->state == SMS_UNUSED); 2781 continue; 2782 } 2783 2784 /* make sure we have a metadevice */ 2785 if (! metaismeta(submirnp)) 2786 continue; 2787 2788 /* clear submirror */ 2789 if (meta_reset_by_name(sp, submirnp, options, ep) != 0) 2790 rval = -1; 2791 } 2792 2793 /* cleanup, return success */ 2794out: 2795 meta_invalidate_name(mirnp); 2796 return (rval); 2797} 2798 2799/* 2800 * reports TRUE if any mirror component is in error 2801 */ 2802int 2803meta_mirror_anycomp_is_err(mdsetname_t *sp, mdnamelist_t *mirror_names) 2804{ 2805 mdnamelist_t *nlp; 2806 md_error_t status = mdnullerror; 2807 md_error_t *ep = &status; 2808 int any_errs = FALSE; 2809 2810 for (nlp = mirror_names; nlp; nlp = nlp->next) { 2811 md_mirror_t *mirrorp; 2812 int smi; 2813 2814 if ((mirrorp = meta_get_mirror(sp, nlp->namep, ep)) == NULL) { 2815 any_errs |= TRUE; 2816 goto out; 2817 } 2818 2819 for (smi = 0; smi < NMIRROR; ++smi) { 2820 md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 2821 2822 if (mdsp->state & 2823 (SMS_COMP_ERRED|SMS_ATTACHED|SMS_OFFLINE)) { 2824 any_errs |= TRUE; 2825 goto out; 2826 } 2827 } 2828 } 2829out: 2830 if (!mdisok(ep)) 2831 mdclrerror(ep); 2832 2833 return (any_errs); 2834} 2835