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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <assert.h> 30 #include <ctype.h> 31 #include <dirent.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <libgen.h> 35 #include <libintl.h> 36 #include <libuutil.h> 37 #include <locale.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <strings.h> 42 #include <unistd.h> 43 #include <priv.h> 44 45 #include <sys/stat.h> 46 47 #include <libzfs.h> 48 49 #include "zpool_util.h" 50 51 static int zpool_do_create(int, char **); 52 static int zpool_do_destroy(int, char **); 53 54 static int zpool_do_add(int, char **); 55 56 static int zpool_do_list(int, char **); 57 static int zpool_do_iostat(int, char **); 58 static int zpool_do_status(int, char **); 59 60 static int zpool_do_online(int, char **); 61 static int zpool_do_offline(int, char **); 62 63 static int zpool_do_attach(int, char **); 64 static int zpool_do_detach(int, char **); 65 static int zpool_do_replace(int, char **); 66 67 static int zpool_do_scrub(int, char **); 68 69 static int zpool_do_import(int, char **); 70 static int zpool_do_export(int, char **); 71 72 /* 73 * These libumem hooks provide a reasonable set of defaults for the allocator's 74 * debugging facilities. 75 */ 76 const char * 77 _umem_debug_init() 78 { 79 return ("default,verbose"); /* $UMEM_DEBUG setting */ 80 } 81 82 const char * 83 _umem_logging_init(void) 84 { 85 return ("fail,contents"); /* $UMEM_LOGGING setting */ 86 } 87 88 typedef enum { 89 HELP_ADD, 90 HELP_ATTACH, 91 HELP_CREATE, 92 HELP_DESTROY, 93 HELP_DETACH, 94 HELP_EXPORT, 95 HELP_IMPORT, 96 HELP_IOSTAT, 97 HELP_LIST, 98 HELP_OFFLINE, 99 HELP_ONLINE, 100 HELP_REPLACE, 101 HELP_SCRUB, 102 HELP_STATUS 103 } zpool_help_t; 104 105 106 typedef struct zpool_command { 107 const char *name; 108 int (*func)(int, char **); 109 zpool_help_t usage; 110 } zpool_command_t; 111 112 /* 113 * Master command table. Each ZFS command has a name, associated function, and 114 * usage message. Unfortunately, the usage messages need to be 115 * iternationalized, so we have to have a function to return the usage message 116 * based on a command index. 117 * 118 * These commands are organized according to how they are displayed in the usage 119 * message. An empty command (one with a NULL name) indicates an empty line in 120 * the generic usage message. 121 */ 122 static zpool_command_t command_table[] = { 123 { "create", zpool_do_create, HELP_CREATE }, 124 { "destroy", zpool_do_destroy, HELP_DESTROY }, 125 { NULL }, 126 { "add", zpool_do_add, HELP_ADD }, 127 { NULL }, 128 { "list", zpool_do_list, HELP_LIST }, 129 { "iostat", zpool_do_iostat, HELP_IOSTAT }, 130 { "status", zpool_do_status, HELP_STATUS }, 131 { NULL }, 132 { "online", zpool_do_online, HELP_ONLINE }, 133 { "offline", zpool_do_offline, HELP_OFFLINE }, 134 { NULL }, 135 { "attach", zpool_do_attach, HELP_ATTACH }, 136 { "detach", zpool_do_detach, HELP_DETACH }, 137 { "replace", zpool_do_replace, HELP_REPLACE }, 138 { NULL }, 139 { "scrub", zpool_do_scrub, HELP_SCRUB }, 140 { NULL }, 141 { "import", zpool_do_import, HELP_IMPORT }, 142 { "export", zpool_do_export, HELP_EXPORT }, 143 }; 144 145 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 146 147 zpool_command_t *current_command; 148 149 static const char * 150 get_usage(zpool_help_t idx) { 151 switch (idx) { 152 case HELP_ADD: 153 return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 154 case HELP_ATTACH: 155 return (gettext("\tattach [-f] <pool> <device> " 156 "<new_device>\n")); 157 case HELP_CREATE: 158 return (gettext("\tcreate [-fn] [-R root] [-m mountpoint] " 159 "<pool> <vdev> ...\n")); 160 case HELP_DESTROY: 161 return (gettext("\tdestroy [-f] <pool>\n")); 162 case HELP_DETACH: 163 return (gettext("\tdetach <pool> <device>\n")); 164 case HELP_EXPORT: 165 return (gettext("\texport [-f] <pool> ...\n")); 166 case HELP_IMPORT: 167 return (gettext("\timport [-d dir]\n" 168 "\timport [-d dir] [-f] [-o opts] [-R root] -a\n" 169 "\timport [-d dir] [-f] [-o opts] [-R root ] <pool | id> " 170 "[newpool]\n")); 171 case HELP_IOSTAT: 172 return (gettext("\tiostat [-v] [pool] ... [interval " 173 "[count]]\n")); 174 case HELP_LIST: 175 return (gettext("\tlist [-H] [-o field[,field]*] " 176 "[pool] ...\n")); 177 case HELP_OFFLINE: 178 return (gettext("\toffline <pool> <device>\n")); 179 case HELP_ONLINE: 180 return (gettext("\tonline <pool> <device>\n")); 181 case HELP_REPLACE: 182 return (gettext("\treplace [-f] <pool> <device> " 183 "[new_device]\n")); 184 case HELP_SCRUB: 185 return (gettext("\tscrub [-s] <pool> ...\n")); 186 case HELP_STATUS: 187 return (gettext("\tstatus [-vx] [pool] ...\n")); 188 } 189 190 abort(); 191 /* NOTREACHED */ 192 } 193 194 /* 195 * Fields available for 'zpool list'. 196 */ 197 typedef enum { 198 ZPOOL_FIELD_NAME, 199 ZPOOL_FIELD_SIZE, 200 ZPOOL_FIELD_USED, 201 ZPOOL_FIELD_AVAILABLE, 202 ZPOOL_FIELD_CAPACITY, 203 ZPOOL_FIELD_HEALTH, 204 ZPOOL_FIELD_ROOT 205 } zpool_field_t; 206 207 #define MAX_FIELDS 10 208 209 typedef struct column_def { 210 const char *cd_title; 211 size_t cd_width; 212 enum { 213 left_justify, 214 right_justify 215 } cd_justify; 216 } column_def_t; 217 218 static column_def_t column_table[] = { 219 { "NAME", 20, left_justify }, 220 { "SIZE", 6, right_justify }, 221 { "USED", 6, right_justify }, 222 { "AVAIL", 6, right_justify }, 223 { "CAP", 5, right_justify }, 224 { "HEALTH", 9, left_justify }, 225 { "ALTROOT", 15, left_justify } 226 }; 227 228 static char *column_subopts[] = { 229 "name", 230 "size", 231 "used", 232 "available", 233 "capacity", 234 "health", 235 "root", 236 NULL 237 }; 238 239 /* 240 * Display usage message. If we're inside a command, display only the usage for 241 * that command. Otherwise, iterate over the entire command table and display 242 * a complete usage message. 243 */ 244 void 245 usage(int requested) 246 { 247 int i; 248 FILE *fp = requested ? stdout : stderr; 249 250 if (current_command == NULL) { 251 int i; 252 253 (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 254 (void) fprintf(fp, 255 gettext("where 'command' is one of the following:\n\n")); 256 257 for (i = 0; i < NCOMMAND; i++) { 258 if (command_table[i].name == NULL) 259 (void) fprintf(fp, "\n"); 260 else 261 (void) fprintf(fp, "%s", 262 get_usage(command_table[i].usage)); 263 } 264 } else { 265 (void) fprintf(fp, gettext("usage:\n")); 266 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 267 268 if (strcmp(current_command->name, "list") == 0) { 269 (void) fprintf(fp, gettext("\nwhere 'field' is one " 270 "of the following:\n\n")); 271 272 for (i = 0; column_subopts[i] != NULL; i++) 273 (void) fprintf(fp, "\t%s\n", column_subopts[i]); 274 } 275 } 276 277 exit(requested ? 0 : 2); 278 } 279 280 const char * 281 state_to_name(int state) 282 { 283 switch (state) { 284 case VDEV_STATE_CLOSED: 285 case VDEV_STATE_CANT_OPEN: 286 return (gettext("FAULTED")); 287 case VDEV_STATE_OFFLINE: 288 return (gettext("OFFLINE")); 289 case VDEV_STATE_DEGRADED: 290 return (gettext("DEGRADED")); 291 case VDEV_STATE_HEALTHY: 292 return (gettext("ONLINE")); 293 } 294 295 return (gettext("UNKNOWN")); 296 } 297 298 void 299 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent) 300 { 301 nvlist_t **child; 302 uint_t c, children; 303 char *vname; 304 305 if (name != NULL) 306 (void) printf("\t%*s%s\n", indent, "", name); 307 308 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 309 &child, &children) != 0) 310 return; 311 312 for (c = 0; c < children; c++) { 313 vname = zpool_vdev_name(zhp, child[c]); 314 print_vdev_tree(zhp, vname, child[c], indent + 2); 315 free(vname); 316 } 317 } 318 319 /* 320 * zpool add [-fn] <pool> <vdev> ... 321 * 322 * -f Force addition of devices, even if they appear in use 323 * -n Do not add the devices, but display the resulting layout if 324 * they were to be added. 325 * 326 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 327 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 328 * libzfs. 329 */ 330 int 331 zpool_do_add(int argc, char **argv) 332 { 333 int force = FALSE; 334 int dryrun = FALSE; 335 int c; 336 nvlist_t *nvroot; 337 char *poolname; 338 int ret; 339 zpool_handle_t *zhp; 340 nvlist_t *config; 341 342 /* check options */ 343 while ((c = getopt(argc, argv, "fn")) != -1) { 344 switch (c) { 345 case 'f': 346 force = TRUE; 347 break; 348 case 'n': 349 dryrun = TRUE; 350 break; 351 case '?': 352 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 353 optopt); 354 usage(FALSE); 355 } 356 } 357 358 argc -= optind; 359 argv += optind; 360 361 /* get pool name and check number of arguments */ 362 if (argc < 1) { 363 (void) fprintf(stderr, gettext("missing pool name argument\n")); 364 usage(FALSE); 365 } 366 if (argc < 2) { 367 (void) fprintf(stderr, gettext("missing vdev specification\n")); 368 usage(FALSE); 369 } 370 371 poolname = argv[0]; 372 373 argc--; 374 argv++; 375 376 if ((zhp = zpool_open(poolname)) == NULL) 377 return (1); 378 379 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 380 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 381 poolname); 382 zpool_close(zhp); 383 return (1); 384 } 385 386 /* pass off to get_vdev_spec for processing */ 387 nvroot = make_root_vdev(config, force, !force, argc, argv); 388 if (nvroot == NULL) { 389 zpool_close(zhp); 390 return (1); 391 } 392 393 if (dryrun) { 394 nvlist_t *poolnvroot; 395 396 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 397 &poolnvroot) == 0); 398 399 (void) printf(gettext("would update '%s' to the following " 400 "configuration:\n"), zpool_get_name(zhp)); 401 402 print_vdev_tree(zhp, poolname, poolnvroot, 0); 403 print_vdev_tree(zhp, NULL, nvroot, 0); 404 405 ret = 0; 406 } else { 407 ret = (zpool_add(zhp, nvroot) != 0); 408 } 409 410 return (ret); 411 } 412 413 /* 414 * zpool create [-fn] [-R root] [-m mountpoint] <pool> <dev> ... 415 * 416 * -f Force creation, even if devices appear in use 417 * -n Do not create the pool, but display the resulting layout if it 418 * were to be created. 419 * -R Create a pool under an alternate root 420 * -m Set default mountpoint for the root dataset. By default it's 421 * '/<pool>' 422 * 423 * Creates the the named pool according to the given vdev specification. The 424 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 425 * we get the nvlist back from get_vdev_spec(), we either print out the contents 426 * (if '-n' was specified), or pass it to libzfs to do the creation. 427 */ 428 int 429 zpool_do_create(int argc, char **argv) 430 { 431 int force = FALSE; 432 int dryrun = FALSE; 433 int c; 434 nvlist_t *nvroot; 435 char *poolname; 436 int ret; 437 char *altroot = NULL; 438 char *mountpoint = NULL; 439 440 /* check options */ 441 while ((c = getopt(argc, argv, ":fnR:m:")) != -1) { 442 switch (c) { 443 case 'f': 444 force = TRUE; 445 break; 446 case 'n': 447 dryrun = TRUE; 448 break; 449 case 'R': 450 altroot = optarg; 451 break; 452 case 'm': 453 mountpoint = optarg; 454 break; 455 case ':': 456 (void) fprintf(stderr, gettext("missing argument for " 457 "'%c' option\n"), optopt); 458 usage(FALSE); 459 break; 460 case '?': 461 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 462 optopt); 463 usage(FALSE); 464 } 465 } 466 467 argc -= optind; 468 argv += optind; 469 470 /* get pool name and check number of arguments */ 471 if (argc < 1) { 472 (void) fprintf(stderr, gettext("missing pool name argument\n")); 473 usage(FALSE); 474 } 475 if (argc < 2) { 476 (void) fprintf(stderr, gettext("missing vdev specification\n")); 477 usage(FALSE); 478 } 479 480 poolname = argv[0]; 481 482 /* 483 * As a special case, check for use of '/' in the name, and direct the 484 * user to use 'zfs create' instead. 485 */ 486 if (strchr(poolname, '/') != NULL) { 487 (void) fprintf(stderr, gettext("cannot create '%s': invalid " 488 "character '/' in pool name\n"), poolname); 489 (void) fprintf(stderr, gettext("use 'zfs create' to " 490 "create a dataset\n")); 491 return (1); 492 } 493 494 /* pass off to get_vdev_spec for bulk processing */ 495 nvroot = make_root_vdev(NULL, force, !force, argc - 1, argv + 1); 496 if (nvroot == NULL) 497 return (1); 498 499 if (altroot != NULL && altroot[0] != '/') { 500 (void) fprintf(stderr, gettext("invalid alternate root '%s': " 501 "must be an absolute path\n")); 502 return (1); 503 } 504 505 /* 506 * Check the validity of the mountpoint and direct the user to use the 507 * '-m' mountpoint option if it looks like its in use. 508 */ 509 if (mountpoint == NULL || 510 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 511 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 512 char buf[MAXPATHLEN]; 513 struct stat64 statbuf; 514 515 if (mountpoint && mountpoint[0] != '/') { 516 (void) fprintf(stderr, gettext("invalid mountpoint " 517 "'%s': must be an absolute path, 'legacy', or " 518 "'none'\n"), mountpoint); 519 return (1); 520 } 521 522 if (mountpoint == NULL) { 523 if (altroot != NULL) 524 (void) snprintf(buf, sizeof (buf), "%s/%s", 525 altroot, poolname); 526 else 527 (void) snprintf(buf, sizeof (buf), "/%s", 528 poolname); 529 } else { 530 if (altroot != NULL) 531 (void) snprintf(buf, sizeof (buf), "%s%s", 532 altroot, mountpoint); 533 else 534 (void) snprintf(buf, sizeof (buf), "%s", 535 mountpoint); 536 } 537 538 if (stat64(buf, &statbuf) == 0 && 539 statbuf.st_nlink != 2) { 540 if (mountpoint == NULL) 541 (void) fprintf(stderr, gettext("default " 542 "mountpoint '%s' exists and is not " 543 "empty\n"), buf); 544 else 545 (void) fprintf(stderr, gettext("mountpoint " 546 "'%s' exists and is not empty\n"), buf); 547 (void) fprintf(stderr, gettext("use '-m' " 548 "option to provide a different default\n")); 549 return (1); 550 } 551 } 552 553 554 if (dryrun) { 555 /* 556 * For a dry run invocation, print out a basic message and run 557 * through all the vdevs in the list and print out in an 558 * appropriate hierarchy. 559 * 560 * XXZFS find out of we can create the pool? 561 */ 562 (void) printf(gettext("would create '%s' with the " 563 "following layout:\n\n"), poolname); 564 565 print_vdev_tree(NULL, poolname, nvroot, 0); 566 567 ret = 0; 568 } else { 569 ret = 1; 570 /* 571 * Hand off to libzfs. 572 */ 573 if (zpool_create(poolname, nvroot, altroot) == 0) { 574 zfs_handle_t *pool = zfs_open(poolname, 575 ZFS_TYPE_FILESYSTEM); 576 if (pool != NULL) { 577 if (mountpoint != NULL) 578 verify(zfs_prop_set(pool, 579 ZFS_PROP_MOUNTPOINT, 580 mountpoint) == 0); 581 if (zfs_mount(pool, NULL, 0) == 0) 582 ret = zfs_share(pool); 583 zfs_close(pool); 584 } 585 } 586 587 } 588 589 nvlist_free(nvroot); 590 591 return (ret); 592 } 593 594 /* 595 * zpool destroy <pool> 596 * 597 * -f Forcefully unmount any datasets 598 * 599 * Destroy the given pool. Automatically unmounts any datasets in the pool. 600 */ 601 int 602 zpool_do_destroy(int argc, char **argv) 603 { 604 int force = FALSE; 605 int c; 606 char *pool; 607 zpool_handle_t *zhp; 608 int ret; 609 610 /* check options */ 611 while ((c = getopt(argc, argv, "f")) != -1) { 612 switch (c) { 613 case 'f': 614 force = TRUE; 615 break; 616 case '?': 617 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 618 optopt); 619 usage(FALSE); 620 } 621 } 622 623 argc -= optind; 624 argv += optind; 625 626 /* check arguments */ 627 if (argc < 1) { 628 (void) fprintf(stderr, gettext("missing pool argument\n")); 629 usage(FALSE); 630 } 631 if (argc > 1) { 632 (void) fprintf(stderr, gettext("too many arguments\n")); 633 usage(FALSE); 634 } 635 636 pool = argv[0]; 637 638 if ((zhp = zpool_open_canfail(pool)) == NULL) { 639 /* 640 * As a special case, check for use of '/' in the name, and 641 * direct the user to use 'zfs destroy' instead. 642 */ 643 if (strchr(pool, '/') != NULL) 644 (void) fprintf(stderr, gettext("use 'zfs destroy' to " 645 "destroy a dataset\n")); 646 return (1); 647 } 648 649 if (unmount_datasets(zhp, force) != 0) { 650 (void) fprintf(stderr, gettext("could not destroy '%s': " 651 "could not unmount datasets\n"), zpool_get_name(zhp)); 652 return (1); 653 } 654 655 ret = (zpool_destroy(zhp) != 0); 656 657 zpool_close(zhp); 658 659 return (ret); 660 } 661 662 /* 663 * zpool export [-f] <pool> ... 664 * 665 * -f Forcefully unmount datasets 666 * 667 * Export the the given pools. By default, the command will attempt to cleanly 668 * unmount any active datasets within the pool. If the '-f' flag is specified, 669 * then the datasets will be forcefully unmounted. 670 */ 671 int 672 zpool_do_export(int argc, char **argv) 673 { 674 int force = FALSE; 675 int c; 676 zpool_handle_t *zhp; 677 int ret; 678 int i; 679 680 /* check options */ 681 while ((c = getopt(argc, argv, "f")) != -1) { 682 switch (c) { 683 case 'f': 684 force = TRUE; 685 break; 686 case '?': 687 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 688 optopt); 689 usage(FALSE); 690 } 691 } 692 693 argc -= optind; 694 argv += optind; 695 696 /* check arguments */ 697 if (argc < 1) { 698 (void) fprintf(stderr, gettext("missing pool argument\n")); 699 usage(FALSE); 700 } 701 702 ret = 0; 703 for (i = 0; i < argc; i++) { 704 if ((zhp = zpool_open_canfail(argv[i])) == NULL) { 705 ret = 1; 706 continue; 707 } 708 709 if (unmount_datasets(zhp, force) != 0) { 710 ret = 1; 711 zpool_close(zhp); 712 continue; 713 } 714 715 if (zpool_export(zhp) != 0) 716 ret = 1; 717 718 zpool_close(zhp); 719 } 720 721 return (ret); 722 } 723 724 /* 725 * Given a vdev configuration, determine the maximum width needed for the device 726 * name column. 727 */ 728 static int 729 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 730 { 731 char *name = zpool_vdev_name(zhp, nv); 732 nvlist_t **child; 733 uint_t c, children; 734 int ret; 735 736 if (strlen(name) + depth > max) 737 max = strlen(name) + depth; 738 739 free(name); 740 741 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 742 &child, &children) != 0) 743 return (max); 744 745 for (c = 0; c < children; c++) 746 if ((ret = max_width(zhp, child[c], depth + 2, max)) > max) 747 max = ret; 748 749 return (max); 750 } 751 752 753 /* 754 * Print the configuration of an exported pool. Iterate over all vdevs in the 755 * pool, printing out the name and status for each one. 756 */ 757 void 758 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) 759 { 760 nvlist_t **child; 761 uint_t c, children; 762 vdev_stat_t *vs; 763 char *type, *vname; 764 765 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 766 if (strcmp(type, VDEV_TYPE_MISSING) == 0) 767 return; 768 769 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 770 (uint64_t **)&vs, &c) == 0); 771 772 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 773 774 if (vs->vs_aux != 0) { 775 (void) printf(" %-8s ", state_to_name(vs->vs_state)); 776 777 switch (vs->vs_aux) { 778 case VDEV_AUX_OPEN_FAILED: 779 (void) printf(gettext("cannot open")); 780 break; 781 782 case VDEV_AUX_BAD_GUID_SUM: 783 (void) printf(gettext("missing device")); 784 break; 785 786 case VDEV_AUX_NO_REPLICAS: 787 (void) printf(gettext("insufficient replicas")); 788 break; 789 790 default: 791 (void) printf(gettext("corrupted data")); 792 break; 793 } 794 } else { 795 (void) printf(" %s", state_to_name(vs->vs_state)); 796 } 797 (void) printf("\n"); 798 799 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 800 &child, &children) != 0) 801 return; 802 803 for (c = 0; c < children; c++) { 804 vname = zpool_vdev_name(NULL, child[c]); 805 print_import_config(vname, child[c], 806 namewidth, depth + 2); 807 free(vname); 808 } 809 } 810 811 /* 812 * Display the status for the given pool. 813 */ 814 static void 815 show_import(nvlist_t *config) 816 { 817 uint64_t pool_state; 818 vdev_stat_t *vs; 819 char *name; 820 uint64_t guid; 821 char *msgid; 822 nvlist_t *nvroot; 823 int reason; 824 char *health; 825 uint_t vsc; 826 int namewidth; 827 828 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 829 &name) == 0); 830 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 831 &guid) == 0); 832 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 833 &pool_state) == 0); 834 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_HEALTH, 835 &health) == 0); 836 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 837 &nvroot) == 0); 838 839 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 840 (uint64_t **)&vs, &vsc) == 0); 841 842 reason = zpool_import_status(config, &msgid); 843 844 (void) printf(" pool: %s\n", name); 845 (void) printf(" id: %llu\n", guid); 846 (void) printf(" state: %s\n", health); 847 848 switch (reason) { 849 case ZPOOL_STATUS_MISSING_DEV_R: 850 case ZPOOL_STATUS_MISSING_DEV_NR: 851 case ZPOOL_STATUS_BAD_GUID_SUM: 852 (void) printf(gettext("status: One or more devices are missing " 853 "from the system.\n")); 854 break; 855 856 case ZPOOL_STATUS_CORRUPT_LABEL_R: 857 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 858 (void) printf(gettext("status: One or more devices contains " 859 "corrupted data.\n")); 860 break; 861 862 case ZPOOL_STATUS_CORRUPT_DATA: 863 (void) printf(gettext("status: The pool data is corrupted.\n")); 864 break; 865 866 default: 867 /* 868 * No other status can be seen when importing pools. 869 */ 870 assert(reason == ZPOOL_STATUS_OK); 871 } 872 873 /* 874 * Print out an action according to the overall state of the pool. 875 */ 876 if (strcmp(health, gettext("ONLINE")) == 0) { 877 (void) printf(gettext("action: The pool can be imported" 878 " using its name or numeric identifier.")); 879 if (pool_state != POOL_STATE_EXPORTED) 880 (void) printf(gettext(" The\n\tpool may be active on " 881 "on another system, but can be imported using\n\t" 882 "the '-f' flag.\n")); 883 else 884 (void) printf("\n"); 885 } else if (strcmp(health, gettext("DEGRADED")) == 0) { 886 (void) printf(gettext("action: The pool can be imported " 887 "despite missing or damaged devices. The\n\tfault " 888 "tolerance of the pool may be compromised if imported.")); 889 if (pool_state != POOL_STATE_EXPORTED) 890 (void) printf(gettext(" The\n\tpool may be active on " 891 "on another system, but can be imported using\n\t" 892 "the '-f' flag.\n")); 893 else 894 (void) printf("\n"); 895 } else { 896 if (reason == ZPOOL_STATUS_MISSING_DEV_R || 897 reason == ZPOOL_STATUS_MISSING_DEV_NR || 898 reason == ZPOOL_STATUS_BAD_GUID_SUM) 899 (void) printf(gettext("action: The pool cannot be " 900 "imported. Attach the missing\n\tdevices and try " 901 "again.\n")); 902 else 903 (void) printf(gettext("action: The pool cannot be " 904 "imported due to damaged devices or data.\n")); 905 } 906 907 if (msgid != NULL) 908 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 909 msgid); 910 911 (void) printf(gettext("config:\n\n")); 912 913 namewidth = max_width(NULL, nvroot, 0, 0); 914 if (namewidth < 10) 915 namewidth = 10; 916 print_import_config(name, nvroot, namewidth, 0); 917 918 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 919 (void) printf("\n\tAdditional devices are known to " 920 "be part of this pool, though their\n\texact " 921 "configuration cannot be determined.\n"); 922 } 923 } 924 925 /* 926 * Perform the import for the given configuration. This passes the heavy 927 * lifting off to zpool_import(), and then mounts the datasets contained within 928 * the pool. 929 */ 930 static int 931 do_import(nvlist_t *config, const char *newname, const char *mntopts, 932 const char *altroot, int force) 933 { 934 zpool_handle_t *zhp; 935 char *name; 936 uint64_t state; 937 938 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 939 &name) == 0); 940 941 verify(nvlist_lookup_uint64(config, 942 ZPOOL_CONFIG_POOL_STATE, &state) == 0); 943 if (state != POOL_STATE_EXPORTED && !force) { 944 (void) fprintf(stderr, gettext("cannot import '%s': pool " 945 "may be in use from other system\n"), name); 946 (void) fprintf(stderr, gettext("use '-f' to import anyway\n")); 947 return (1); 948 } 949 950 if (zpool_import(config, newname, altroot) != 0) 951 return (1); 952 953 if (newname != NULL) 954 name = (char *)newname; 955 956 verify((zhp = zpool_open(name)) != NULL); 957 958 if (mount_share_datasets(zhp, mntopts) != 0) { 959 zpool_close(zhp); 960 return (1); 961 } 962 963 zpool_close(zhp); 964 return (0); 965 } 966 967 /* 968 * zpool import [-d dir] 969 * import [-R root] [-d dir] [-f] -a 970 * import [-R root] [-d dir] [-f] <pool | id> [newpool] 971 * 972 * -d Scan in a specific directory, other than /dev/dsk. More than 973 * one directory can be specified using multiple '-d' options. 974 * 975 * -R Temporarily import the pool, with all mountpoints relative to 976 * the given root. The pool will remain exported when the machine 977 * is rebooted. 978 * 979 * -f Force import, even if it appears that the pool is active. 980 * 981 * -a Import all pools found. 982 * 983 * The import command scans for pools to import, and import pools based on pool 984 * name and GUID. The pool can also be renamed as part of the import process. 985 */ 986 int 987 zpool_do_import(int argc, char **argv) 988 { 989 char **searchdirs = NULL; 990 int nsearch = 0; 991 int c; 992 int err; 993 nvlist_t *pools; 994 int do_all = FALSE; 995 char *altroot = NULL; 996 char *mntopts = NULL; 997 int do_force = FALSE; 998 nvpair_t *elem; 999 nvlist_t *config; 1000 uint64_t searchguid; 1001 char *searchname; 1002 nvlist_t *found_config; 1003 int first; 1004 1005 /* check options */ 1006 while ((c = getopt(argc, argv, ":fd:R:ao:")) != -1) { 1007 switch (c) { 1008 case 'a': 1009 do_all = TRUE; 1010 break; 1011 case 'd': 1012 if (searchdirs == NULL) { 1013 searchdirs = safe_malloc(sizeof (char *)); 1014 } else { 1015 char **tmp = safe_malloc((nsearch + 1) * 1016 sizeof (char *)); 1017 bcopy(searchdirs, tmp, nsearch * 1018 sizeof (char *)); 1019 free(searchdirs); 1020 searchdirs = tmp; 1021 } 1022 searchdirs[nsearch++] = optarg; 1023 break; 1024 case 'f': 1025 do_force = TRUE; 1026 break; 1027 case 'o': 1028 mntopts = optarg; 1029 break; 1030 case 'R': 1031 altroot = optarg; 1032 break; 1033 case ':': 1034 (void) fprintf(stderr, gettext("missing argument for " 1035 "'%c' option\n"), optopt); 1036 usage(FALSE); 1037 break; 1038 case '?': 1039 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1040 optopt); 1041 usage(FALSE); 1042 } 1043 } 1044 1045 argc -= optind; 1046 argv += optind; 1047 1048 if (searchdirs == NULL) { 1049 searchdirs = safe_malloc(sizeof (char *)); 1050 searchdirs[0] = "/dev/dsk"; 1051 nsearch = 1; 1052 } 1053 1054 /* check argument count */ 1055 if (do_all) { 1056 if (argc != 0) { 1057 (void) fprintf(stderr, gettext("too many arguments\n")); 1058 usage(FALSE); 1059 } 1060 } else { 1061 if (argc > 2) { 1062 (void) fprintf(stderr, gettext("too many arguments\n")); 1063 usage(FALSE); 1064 } 1065 1066 /* 1067 * Check for the SYS_CONFIG privilege. We do this explicitly 1068 * here because otherwise any attempt to discover pools will 1069 * silently fail. 1070 */ 1071 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 1072 (void) fprintf(stderr, gettext("cannot " 1073 "discover pools: permission denied\n")); 1074 return (1); 1075 } 1076 } 1077 1078 if ((pools = zpool_find_import(nsearch, searchdirs)) == NULL) 1079 return (1); 1080 1081 /* 1082 * We now have a list of all available pools in the given directories. 1083 * Depending on the arguments given, we do one of the following: 1084 * 1085 * <none> Iterate through all pools and display information about 1086 * each one. 1087 * 1088 * -a Iterate through all pools and try to import each one. 1089 * 1090 * <id> Find the pool that corresponds to the given GUID/pool 1091 * name and import that one. 1092 */ 1093 if (argc != 0) { 1094 char *endptr; 1095 1096 errno = 0; 1097 searchguid = strtoull(argv[0], &endptr, 10); 1098 if (errno != 0 || *endptr != '\0') 1099 searchname = argv[0]; 1100 else 1101 searchname = NULL; 1102 found_config = NULL; 1103 } 1104 1105 err = 0; 1106 elem = NULL; 1107 first = TRUE; 1108 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 1109 1110 verify(nvpair_value_nvlist(elem, &config) == 0); 1111 1112 if (argc == 0) { 1113 if (first) 1114 first = FALSE; 1115 else 1116 (void) printf("\n"); 1117 1118 if (do_all) 1119 err |= do_import(config, NULL, mntopts, 1120 altroot, do_force); 1121 else 1122 show_import(config); 1123 } else if (searchname != NULL) { 1124 char *name; 1125 1126 /* 1127 * We are searching for a pool based on name. 1128 */ 1129 verify(nvlist_lookup_string(config, 1130 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 1131 1132 if (strcmp(name, searchname) == 0) { 1133 if (found_config != NULL) { 1134 (void) fprintf(stderr, gettext( 1135 "cannot import '%s': more than " 1136 "one matching pool\n"), searchname); 1137 (void) fprintf(stderr, gettext( 1138 "import by numeric ID instead\n")); 1139 err = TRUE; 1140 } 1141 found_config = config; 1142 } 1143 } else { 1144 uint64_t guid; 1145 1146 /* 1147 * Search for a pool by guid. 1148 */ 1149 verify(nvlist_lookup_uint64(config, 1150 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 1151 1152 if (guid == searchguid) 1153 found_config = config; 1154 } 1155 } 1156 1157 /* 1158 * If we were searching for a specific pool, verify that we found a 1159 * pool, and then do the import. 1160 */ 1161 if (argc != 0 && err == 0) { 1162 if (found_config == NULL) { 1163 (void) fprintf(stderr, gettext("cannot import '%s': " 1164 "no such pool available\n"), argv[0]); 1165 err = TRUE; 1166 } else { 1167 err |= do_import(found_config, argc == 1 ? NULL : 1168 argv[1], mntopts, altroot, do_force); 1169 } 1170 } 1171 1172 /* 1173 * If we were just looking for pools, report an error if none were 1174 * found. 1175 */ 1176 if (argc == 0 && first) 1177 (void) fprintf(stderr, 1178 gettext("no pools available to import\n")); 1179 1180 nvlist_free(pools); 1181 1182 return (err ? 1 : 0); 1183 } 1184 1185 typedef struct iostat_cbdata { 1186 zpool_list_t *cb_list; 1187 int cb_verbose; 1188 int cb_iteration; 1189 int cb_namewidth; 1190 } iostat_cbdata_t; 1191 1192 static void 1193 print_iostat_separator(iostat_cbdata_t *cb) 1194 { 1195 int i = 0; 1196 1197 for (i = 0; i < cb->cb_namewidth; i++) 1198 (void) printf("-"); 1199 (void) printf(" ----- ----- ----- ----- ----- -----\n"); 1200 } 1201 1202 static void 1203 print_iostat_header(iostat_cbdata_t *cb) 1204 { 1205 (void) printf("%*s capacity operations bandwidth\n", 1206 cb->cb_namewidth, ""); 1207 (void) printf("%-*s used avail read write read write\n", 1208 cb->cb_namewidth, "pool"); 1209 print_iostat_separator(cb); 1210 } 1211 1212 /* 1213 * Display a single statistic. 1214 */ 1215 void 1216 print_one_stat(uint64_t value) 1217 { 1218 char buf[64]; 1219 1220 zfs_nicenum(value, buf, sizeof (buf)); 1221 (void) printf(" %5s", buf); 1222 } 1223 1224 /* 1225 * Print out all the statistics for the given vdev. This can either be the 1226 * toplevel configuration, or called recursively. If 'name' is NULL, then this 1227 * is a verbose output, and we don't want to display the toplevel pool stats. 1228 */ 1229 void 1230 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 1231 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 1232 { 1233 nvlist_t **oldchild, **newchild; 1234 uint_t c, children; 1235 vdev_stat_t *oldvs, *newvs; 1236 vdev_stat_t zerovs = { 0 }; 1237 uint64_t tdelta; 1238 double scale; 1239 char *vname; 1240 1241 if (oldnv != NULL) { 1242 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS, 1243 (uint64_t **)&oldvs, &c) == 0); 1244 } else { 1245 oldvs = &zerovs; 1246 } 1247 1248 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS, 1249 (uint64_t **)&newvs, &c) == 0); 1250 1251 if (strlen(name) + depth > cb->cb_namewidth) 1252 (void) printf("%*s%s", depth, "", name); 1253 else 1254 (void) printf("%*s%s%*s", depth, "", name, 1255 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 1256 1257 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 1258 1259 if (tdelta == 0) 1260 scale = 1.0; 1261 else 1262 scale = (double)NANOSEC / tdelta; 1263 1264 /* only toplevel vdevs have capacity stats */ 1265 if (newvs->vs_space == 0) { 1266 (void) printf(" - -"); 1267 } else { 1268 print_one_stat(newvs->vs_alloc); 1269 print_one_stat(newvs->vs_space - newvs->vs_alloc); 1270 } 1271 1272 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 1273 oldvs->vs_ops[ZIO_TYPE_READ]))); 1274 1275 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 1276 oldvs->vs_ops[ZIO_TYPE_WRITE]))); 1277 1278 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 1279 oldvs->vs_bytes[ZIO_TYPE_READ]))); 1280 1281 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 1282 oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 1283 1284 (void) printf("\n"); 1285 1286 if (!cb->cb_verbose) 1287 return; 1288 1289 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 1290 &newchild, &children) != 0) 1291 return; 1292 1293 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 1294 &oldchild, &c) != 0) 1295 return; 1296 1297 for (c = 0; c < children; c++) { 1298 vname = zpool_vdev_name(zhp, newchild[c]); 1299 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 1300 newchild[c], cb, depth + 2); 1301 free(vname); 1302 } 1303 } 1304 1305 static int 1306 refresh_iostat(zpool_handle_t *zhp, void *data) 1307 { 1308 iostat_cbdata_t *cb = data; 1309 1310 /* 1311 * If the pool has disappeared, remove it from the list and continue. 1312 */ 1313 if (zpool_refresh_stats(zhp) != 0) 1314 pool_list_remove(cb->cb_list, zhp); 1315 1316 return (0); 1317 } 1318 1319 /* 1320 * Callback to print out the iostats for the given pool. 1321 */ 1322 int 1323 print_iostat(zpool_handle_t *zhp, void *data) 1324 { 1325 iostat_cbdata_t *cb = data; 1326 nvlist_t *oldconfig, *newconfig; 1327 nvlist_t *oldnvroot, *newnvroot; 1328 1329 newconfig = zpool_get_config(zhp, &oldconfig); 1330 1331 if (cb->cb_iteration == 1) 1332 oldconfig = NULL; 1333 1334 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 1335 &newnvroot) == 0); 1336 1337 if (oldconfig == NULL) 1338 oldnvroot = NULL; 1339 else 1340 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 1341 &oldnvroot) == 0); 1342 1343 /* 1344 * Print out the statistics for the pool. 1345 */ 1346 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 1347 1348 if (cb->cb_verbose) 1349 print_iostat_separator(cb); 1350 1351 return (0); 1352 } 1353 1354 int 1355 get_namewidth(zpool_handle_t *zhp, void *data) 1356 { 1357 iostat_cbdata_t *cb = data; 1358 nvlist_t *config, *nvroot; 1359 1360 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 1361 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1362 &nvroot) == 0); 1363 if (!cb->cb_verbose) 1364 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 1365 else 1366 cb->cb_namewidth = max_width(zhp, nvroot, 0, 0); 1367 } 1368 1369 /* 1370 * The width must fall into the range [10,38]. The upper limit is the 1371 * maximum we can have and still fit in 80 columns. 1372 */ 1373 if (cb->cb_namewidth < 10) 1374 cb->cb_namewidth = 10; 1375 if (cb->cb_namewidth > 38) 1376 cb->cb_namewidth = 38; 1377 1378 return (0); 1379 } 1380 1381 /* 1382 * zpool iostat [-v] [pool] ... [interval [count]] 1383 * 1384 * -v Display statistics for individual vdevs 1385 * 1386 * This command can be tricky because we want to be able to deal with pool 1387 * creation/destruction as well as vdev configuration changes. The bulk of this 1388 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 1389 * on pool_list_update() to detect the addition of new pools. Configuration 1390 * changes are all handled within libzfs. 1391 */ 1392 int 1393 zpool_do_iostat(int argc, char **argv) 1394 { 1395 int c; 1396 int ret; 1397 int npools; 1398 unsigned long interval = 0, count = 0; 1399 zpool_list_t *list; 1400 int verbose = FALSE; 1401 iostat_cbdata_t cb; 1402 1403 /* check options */ 1404 while ((c = getopt(argc, argv, "v")) != -1) { 1405 switch (c) { 1406 case 'v': 1407 verbose = TRUE; 1408 break; 1409 case '?': 1410 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1411 optopt); 1412 usage(FALSE); 1413 } 1414 } 1415 1416 argc -= optind; 1417 argv += optind; 1418 1419 /* 1420 * Determine if the last argument is an integer or a pool name 1421 */ 1422 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1423 char *end; 1424 1425 errno = 0; 1426 interval = strtoul(argv[argc - 1], &end, 10); 1427 1428 if (*end == '\0' && errno == 0) { 1429 if (interval == 0) { 1430 (void) fprintf(stderr, gettext("interval " 1431 "cannot be zero\n")); 1432 usage(FALSE); 1433 } 1434 1435 /* 1436 * Ignore the last parameter 1437 */ 1438 argc--; 1439 } else { 1440 /* 1441 * If this is not a valid number, just plow on. The 1442 * user will get a more informative error message later 1443 * on. 1444 */ 1445 interval = 0; 1446 } 1447 } 1448 1449 /* 1450 * If the last argument is also an integer, then we have both a count 1451 * and an integer. 1452 */ 1453 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1454 char *end; 1455 1456 errno = 0; 1457 count = interval; 1458 interval = strtoul(argv[argc - 1], &end, 10); 1459 1460 if (*end == '\0' && errno == 0) { 1461 if (interval == 0) { 1462 (void) fprintf(stderr, gettext("interval " 1463 "cannot be zero\n")); 1464 usage(FALSE); 1465 } 1466 1467 /* 1468 * Ignore the last parameter 1469 */ 1470 argc--; 1471 } else { 1472 interval = 0; 1473 } 1474 } 1475 1476 /* 1477 * Construct the list of all interesting pools. 1478 */ 1479 ret = 0; 1480 if ((list = pool_list_get(argc, argv, &ret)) == NULL) 1481 return (1); 1482 1483 if (pool_list_count(list) == 0 && argc != 0) 1484 return (1); 1485 1486 if (pool_list_count(list) == 0 && interval == 0) { 1487 (void) fprintf(stderr, gettext("no pools available\n")); 1488 return (1); 1489 } 1490 1491 /* 1492 * Enter the main iostat loop. 1493 */ 1494 cb.cb_list = list; 1495 cb.cb_verbose = verbose; 1496 cb.cb_iteration = 0; 1497 cb.cb_namewidth = 0; 1498 1499 for (;;) { 1500 pool_list_update(list); 1501 1502 if ((npools = pool_list_count(list)) == 0) 1503 break; 1504 1505 /* 1506 * Refresh all statistics. This is done as an explicit step 1507 * before calculating the maximum name width, so that any 1508 * configuration changes are properly accounted for. 1509 */ 1510 (void) pool_list_iter(list, FALSE, refresh_iostat, &cb); 1511 1512 /* 1513 * Iterate over all pools to determine the maximum width 1514 * for the pool / device name column across all pools. 1515 */ 1516 cb.cb_namewidth = 0; 1517 (void) pool_list_iter(list, FALSE, get_namewidth, &cb); 1518 1519 /* 1520 * If it's the first time, or verbose mode, print the header. 1521 */ 1522 if (++cb.cb_iteration == 1 || verbose) 1523 print_iostat_header(&cb); 1524 1525 (void) pool_list_iter(list, FALSE, print_iostat, &cb); 1526 1527 /* 1528 * If there's more than one pool, and we're not in verbose mode 1529 * (which prints a separator for us), then print a separator. 1530 */ 1531 if (npools > 1 && !verbose) 1532 print_iostat_separator(&cb); 1533 1534 if (verbose) 1535 (void) printf("\n"); 1536 1537 if (interval == 0) 1538 break; 1539 1540 if (count != 0 && --count == 0) 1541 break; 1542 1543 (void) sleep(interval); 1544 } 1545 1546 pool_list_free(list); 1547 1548 return (ret); 1549 } 1550 1551 typedef struct list_cbdata { 1552 int cb_scripted; 1553 int cb_first; 1554 int cb_fields[MAX_FIELDS]; 1555 int cb_fieldcount; 1556 } list_cbdata_t; 1557 1558 /* 1559 * Given a list of columns to display, output appropriate headers for each one. 1560 */ 1561 void 1562 print_header(int *fields, size_t count) 1563 { 1564 int i; 1565 column_def_t *col; 1566 const char *fmt; 1567 1568 for (i = 0; i < count; i++) { 1569 col = &column_table[fields[i]]; 1570 if (i != 0) 1571 (void) printf(" "); 1572 if (col->cd_justify == left_justify) 1573 fmt = "%-*s"; 1574 else 1575 fmt = "%*s"; 1576 1577 (void) printf(fmt, i == count - 1 ? strlen(col->cd_title) : 1578 col->cd_width, col->cd_title); 1579 } 1580 1581 (void) printf("\n"); 1582 } 1583 1584 int 1585 list_callback(zpool_handle_t *zhp, void *data) 1586 { 1587 list_cbdata_t *cbp = data; 1588 nvlist_t *config; 1589 int i; 1590 char buf[ZPOOL_MAXNAMELEN]; 1591 uint64_t total; 1592 uint64_t used; 1593 const char *fmt; 1594 column_def_t *col; 1595 1596 if (cbp->cb_first) { 1597 if (!cbp->cb_scripted) 1598 print_header(cbp->cb_fields, cbp->cb_fieldcount); 1599 cbp->cb_first = FALSE; 1600 } 1601 1602 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 1603 config = NULL; 1604 } else { 1605 config = zpool_get_config(zhp, NULL); 1606 total = zpool_get_space_total(zhp); 1607 used = zpool_get_space_used(zhp); 1608 } 1609 1610 for (i = 0; i < cbp->cb_fieldcount; i++) { 1611 if (i != 0) { 1612 if (cbp->cb_scripted) 1613 (void) printf("\t"); 1614 else 1615 (void) printf(" "); 1616 } 1617 1618 col = &column_table[cbp->cb_fields[i]]; 1619 1620 switch (cbp->cb_fields[i]) { 1621 case ZPOOL_FIELD_NAME: 1622 (void) strlcpy(buf, zpool_get_name(zhp), sizeof (buf)); 1623 break; 1624 1625 case ZPOOL_FIELD_SIZE: 1626 if (config == NULL) 1627 (void) strlcpy(buf, "-", sizeof (buf)); 1628 else 1629 zfs_nicenum(total, buf, sizeof (buf)); 1630 break; 1631 1632 case ZPOOL_FIELD_USED: 1633 if (config == NULL) 1634 (void) strlcpy(buf, "-", sizeof (buf)); 1635 else 1636 zfs_nicenum(used, buf, sizeof (buf)); 1637 break; 1638 1639 case ZPOOL_FIELD_AVAILABLE: 1640 if (config == NULL) 1641 (void) strlcpy(buf, "-", sizeof (buf)); 1642 else 1643 zfs_nicenum(total - used, buf, sizeof (buf)); 1644 break; 1645 1646 case ZPOOL_FIELD_CAPACITY: 1647 if (config == NULL) { 1648 (void) strlcpy(buf, "-", sizeof (buf)); 1649 } else { 1650 uint64_t capacity = (total == 0 ? 0 : 1651 (used * 100 / total)); 1652 (void) snprintf(buf, sizeof (buf), "%llu%%", 1653 capacity); 1654 } 1655 break; 1656 1657 case ZPOOL_FIELD_HEALTH: 1658 if (config == NULL) { 1659 (void) strlcpy(buf, "FAULTED", sizeof (buf)); 1660 } else { 1661 nvlist_t *nvroot; 1662 vdev_stat_t *vs; 1663 uint_t vsc; 1664 1665 verify(nvlist_lookup_nvlist(config, 1666 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 1667 verify(nvlist_lookup_uint64_array(nvroot, 1668 ZPOOL_CONFIG_STATS, (uint64_t **)&vs, 1669 &vsc) == 0); 1670 (void) strlcpy(buf, state_to_name(vs->vs_state), 1671 sizeof (buf)); 1672 } 1673 break; 1674 1675 case ZPOOL_FIELD_ROOT: 1676 if (config == NULL) 1677 (void) strlcpy(buf, "-", sizeof (buf)); 1678 else if (zpool_get_root(zhp, buf, sizeof (buf)) != 0) 1679 (void) strlcpy(buf, "-", sizeof (buf)); 1680 break; 1681 } 1682 1683 if (cbp->cb_scripted) 1684 (void) printf("%s", buf); 1685 else { 1686 if (col->cd_justify == left_justify) 1687 fmt = "%-*s"; 1688 else 1689 fmt = "%*s"; 1690 1691 (void) printf(fmt, i == cbp->cb_fieldcount - 1 ? 1692 strlen(buf) : col->cd_width, buf); 1693 } 1694 } 1695 1696 (void) printf("\n"); 1697 1698 return (0); 1699 } 1700 1701 /* 1702 * zpool list [-H] [-o field[,field]*] [pool] ... 1703 * 1704 * -H Scripted mode. Don't display headers, and separate fields by 1705 * a single tab. 1706 * -o List of fields to display. Defaults to all fields, or 1707 * "name,size,used,available,capacity,health,root" 1708 * 1709 * List all pools in the system, whether or not they're healthy. Output space 1710 * statistics for each one, as well as health status summary. 1711 */ 1712 int 1713 zpool_do_list(int argc, char **argv) 1714 { 1715 int c; 1716 int ret; 1717 list_cbdata_t cb = { 0 }; 1718 static char default_fields[] = 1719 "name,size,used,available,capacity,health,root"; 1720 char *fields = default_fields; 1721 char *value; 1722 1723 /* check options */ 1724 while ((c = getopt(argc, argv, ":Ho:")) != -1) { 1725 switch (c) { 1726 case 'H': 1727 cb.cb_scripted = TRUE; 1728 break; 1729 case 'o': 1730 fields = optarg; 1731 break; 1732 case ':': 1733 (void) fprintf(stderr, gettext("missing argument for " 1734 "'%c' option\n"), optopt); 1735 usage(FALSE); 1736 break; 1737 case '?': 1738 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1739 optopt); 1740 usage(FALSE); 1741 } 1742 } 1743 1744 argc -= optind; 1745 argv += optind; 1746 1747 while (*fields != '\0') { 1748 if (cb.cb_fieldcount == MAX_FIELDS) { 1749 (void) fprintf(stderr, gettext("too many " 1750 "properties given to -o option\n")); 1751 usage(FALSE); 1752 } 1753 1754 if ((cb.cb_fields[cb.cb_fieldcount] = getsubopt(&fields, 1755 column_subopts, &value)) == -1) { 1756 (void) fprintf(stderr, gettext("invalid property " 1757 "'%s'\n"), value); 1758 usage(FALSE); 1759 } 1760 1761 cb.cb_fieldcount++; 1762 } 1763 1764 1765 cb.cb_first = TRUE; 1766 1767 ret = for_each_pool(argc, argv, TRUE, list_callback, &cb); 1768 1769 if (argc == 0 && cb.cb_first) { 1770 (void) printf(gettext("no pools available\n")); 1771 return (0); 1772 } 1773 1774 return (ret); 1775 } 1776 1777 static nvlist_t * 1778 zpool_get_vdev_by_name(nvlist_t *nv, char *name) 1779 { 1780 nvlist_t **child; 1781 uint_t c, children; 1782 nvlist_t *match; 1783 char *path; 1784 1785 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1786 &child, &children) != 0) { 1787 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1788 if (strncmp(name, "/dev/dsk/", 9) == 0) 1789 name += 9; 1790 if (strncmp(path, "/dev/dsk/", 9) == 0) 1791 path += 9; 1792 if (strcmp(name, path) == 0) 1793 return (nv); 1794 return (NULL); 1795 } 1796 1797 for (c = 0; c < children; c++) 1798 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 1799 return (match); 1800 1801 return (NULL); 1802 } 1803 1804 static int 1805 zpool_do_attach_or_replace(int argc, char **argv, int replacing) 1806 { 1807 int force = FALSE; 1808 int c; 1809 nvlist_t *nvroot; 1810 char *poolname, *old_disk, *new_disk; 1811 zpool_handle_t *zhp; 1812 nvlist_t *config; 1813 1814 /* check options */ 1815 while ((c = getopt(argc, argv, "f")) != -1) { 1816 switch (c) { 1817 case 'f': 1818 force = TRUE; 1819 break; 1820 case '?': 1821 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1822 optopt); 1823 usage(FALSE); 1824 } 1825 } 1826 1827 argc -= optind; 1828 argv += optind; 1829 1830 /* get pool name and check number of arguments */ 1831 if (argc < 1) { 1832 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1833 usage(FALSE); 1834 } 1835 1836 poolname = argv[0]; 1837 1838 if (argc < 2) { 1839 (void) fprintf(stderr, 1840 gettext("missing <device> specification\n")); 1841 usage(FALSE); 1842 } 1843 1844 old_disk = argv[1]; 1845 1846 if (argc < 3) { 1847 if (!replacing) { 1848 (void) fprintf(stderr, 1849 gettext("missing <new_device> specification\n")); 1850 usage(FALSE); 1851 } 1852 new_disk = old_disk; 1853 argc -= 1; 1854 argv += 1; 1855 } else { 1856 new_disk = argv[2]; 1857 argc -= 2; 1858 argv += 2; 1859 } 1860 1861 if (argc > 1) { 1862 (void) fprintf(stderr, gettext("too many arguments\n")); 1863 usage(FALSE); 1864 } 1865 1866 if ((zhp = zpool_open(poolname)) == NULL) 1867 return (1); 1868 1869 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 1870 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 1871 poolname); 1872 zpool_close(zhp); 1873 return (1); 1874 } 1875 1876 nvroot = make_root_vdev(config, force, B_FALSE, argc, argv); 1877 if (nvroot == NULL) { 1878 zpool_close(zhp); 1879 return (1); 1880 } 1881 1882 return (zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing)); 1883 } 1884 1885 /* 1886 * zpool replace [-f] <pool> <device> <new_device> 1887 * 1888 * -f Force attach, even if <new_device> appears to be in use. 1889 * 1890 * Replace <device> with <new_device>. 1891 */ 1892 /* ARGSUSED */ 1893 int 1894 zpool_do_replace(int argc, char **argv) 1895 { 1896 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 1897 } 1898 1899 /* 1900 * zpool attach [-f] <pool> <device> <new_device> 1901 * 1902 * -f Force attach, even if <new_device> appears to be in use. 1903 * 1904 * Attach <new_device> to the mirror containing <device>. If <device> is not 1905 * part of a mirror, then <device> will be transformed into a mirror of 1906 * <device> and <new_device>. In either case, <new_device> will begin life 1907 * with a DTL of [0, now], and will immediately begin to resilver itself. 1908 */ 1909 int 1910 zpool_do_attach(int argc, char **argv) 1911 { 1912 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 1913 } 1914 1915 /* 1916 * zpool detach [-f] <pool> <device> 1917 * 1918 * -f Force detach of <device>, even if DTLs argue against it 1919 * (not supported yet) 1920 * 1921 * Detach a device from a mirror. The operation will be refused if <device> 1922 * is the last device in the mirror, or if the DTLs indicate that this device 1923 * has the only valid copy of some data. 1924 */ 1925 /* ARGSUSED */ 1926 int 1927 zpool_do_detach(int argc, char **argv) 1928 { 1929 int c; 1930 char *poolname, *path; 1931 zpool_handle_t *zhp; 1932 1933 /* check options */ 1934 while ((c = getopt(argc, argv, "f")) != -1) { 1935 switch (c) { 1936 case 'f': 1937 case '?': 1938 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1939 optopt); 1940 usage(FALSE); 1941 } 1942 } 1943 1944 argc -= optind; 1945 argv += optind; 1946 1947 /* get pool name and check number of arguments */ 1948 if (argc < 1) { 1949 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1950 usage(FALSE); 1951 } 1952 1953 if (argc < 2) { 1954 (void) fprintf(stderr, 1955 gettext("missing <device> specification\n")); 1956 usage(FALSE); 1957 } 1958 1959 poolname = argv[0]; 1960 path = argv[1]; 1961 1962 if ((zhp = zpool_open(poolname)) == NULL) 1963 return (1); 1964 1965 return (zpool_vdev_detach(zhp, path)); 1966 } 1967 1968 /* 1969 * zpool online [-t] <pool> <device> 1970 * 1971 * -t Only bring the device on-line temporarily. The online 1972 * state will not be persistent across reboots. 1973 */ 1974 /* ARGSUSED */ 1975 int 1976 zpool_do_online(int argc, char **argv) 1977 { 1978 int c, i; 1979 char *poolname; 1980 zpool_handle_t *zhp; 1981 int ret = 0; 1982 1983 /* check options */ 1984 while ((c = getopt(argc, argv, "t")) != -1) { 1985 switch (c) { 1986 case 't': 1987 case '?': 1988 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1989 optopt); 1990 usage(FALSE); 1991 } 1992 } 1993 1994 argc -= optind; 1995 argv += optind; 1996 1997 /* get pool name and check number of arguments */ 1998 if (argc < 1) { 1999 (void) fprintf(stderr, gettext("missing pool name\n")); 2000 usage(FALSE); 2001 } 2002 if (argc < 2) { 2003 (void) fprintf(stderr, gettext("missing device name\n")); 2004 usage(FALSE); 2005 } 2006 2007 poolname = argv[0]; 2008 2009 if ((zhp = zpool_open(poolname)) == NULL) 2010 return (1); 2011 2012 for (i = 1; i < argc; i++) 2013 if (zpool_vdev_online(zhp, argv[i]) == 0) 2014 (void) printf(gettext("Bringing device %s online\n"), 2015 argv[i]); 2016 else 2017 ret = 1; 2018 2019 return (ret); 2020 } 2021 2022 /* 2023 * zpool offline [-ft] <pool> <device> 2024 * 2025 * -f Force the device into the offline state, even if doing 2026 * so would appear to compromise pool availability. 2027 * (not supported yet) 2028 * 2029 * -t Only take the device off-line temporarily. The offline 2030 * state will not be persistent across reboots. 2031 * (not supported yet) 2032 */ 2033 /* ARGSUSED */ 2034 int 2035 zpool_do_offline(int argc, char **argv) 2036 { 2037 int c, i; 2038 char *poolname; 2039 zpool_handle_t *zhp; 2040 int ret = 0; 2041 2042 /* check options */ 2043 while ((c = getopt(argc, argv, "ft")) != -1) { 2044 switch (c) { 2045 case 'f': 2046 case 't': 2047 case '?': 2048 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2049 optopt); 2050 usage(FALSE); 2051 } 2052 } 2053 2054 argc -= optind; 2055 argv += optind; 2056 2057 /* get pool name and check number of arguments */ 2058 if (argc < 1) { 2059 (void) fprintf(stderr, gettext("missing pool name\n")); 2060 usage(FALSE); 2061 } 2062 if (argc < 2) { 2063 (void) fprintf(stderr, gettext("missing device name\n")); 2064 usage(FALSE); 2065 } 2066 2067 poolname = argv[0]; 2068 2069 if ((zhp = zpool_open(poolname)) == NULL) 2070 return (1); 2071 2072 for (i = 1; i < argc; i++) 2073 if (zpool_vdev_offline(zhp, argv[i]) == 0) 2074 (void) printf(gettext("Bringing device %s offline\n"), 2075 argv[i]); 2076 else 2077 ret = 1; 2078 2079 return (ret); 2080 } 2081 2082 typedef struct scrub_cbdata { 2083 int cb_type; 2084 } scrub_cbdata_t; 2085 2086 int 2087 scrub_callback(zpool_handle_t *zhp, void *data) 2088 { 2089 scrub_cbdata_t *cb = data; 2090 2091 return (zpool_scrub(zhp, cb->cb_type) != 0); 2092 } 2093 2094 /* 2095 * zpool scrub [-s] <pool> ... 2096 * 2097 * -s Stop. Stops any in-progress scrub. 2098 */ 2099 int 2100 zpool_do_scrub(int argc, char **argv) 2101 { 2102 int c; 2103 scrub_cbdata_t cb; 2104 2105 cb.cb_type = POOL_SCRUB_EVERYTHING; 2106 2107 /* check options */ 2108 while ((c = getopt(argc, argv, "s")) != -1) { 2109 switch (c) { 2110 case 's': 2111 cb.cb_type = POOL_SCRUB_NONE; 2112 break; 2113 case '?': 2114 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2115 optopt); 2116 usage(FALSE); 2117 } 2118 } 2119 2120 argc -= optind; 2121 argv += optind; 2122 2123 if (argc < 1) { 2124 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2125 usage(FALSE); 2126 } 2127 2128 return (for_each_pool(argc, argv, TRUE, scrub_callback, &cb)); 2129 } 2130 2131 typedef struct status_cbdata { 2132 int cb_verbose; 2133 int cb_explain; 2134 int cb_count; 2135 int cb_first; 2136 } status_cbdata_t; 2137 2138 /* 2139 * Print out detailed scrub status. 2140 */ 2141 void 2142 print_scrub_status(nvlist_t *nvroot) 2143 { 2144 vdev_stat_t *vs; 2145 uint_t vsc; 2146 time_t start, end, now; 2147 double fraction_done; 2148 uint64_t examined, total, minutes_left; 2149 char *scrub_type; 2150 2151 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 2152 (uint64_t **)&vs, &vsc) == 0); 2153 2154 /* 2155 * If there's never been a scrub, there's not much to say. 2156 */ 2157 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) { 2158 (void) printf(gettext("none requested\n")); 2159 return; 2160 } 2161 2162 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2163 "resilver" : "scrub"; 2164 2165 start = vs->vs_scrub_start; 2166 end = vs->vs_scrub_end; 2167 now = time(NULL); 2168 examined = vs->vs_scrub_examined; 2169 total = vs->vs_alloc; 2170 2171 if (end != 0) { 2172 (void) printf(gettext("%s %s with %llu errors on %s"), 2173 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped", 2174 (u_longlong_t)vs->vs_scrub_errors, ctime(&end)); 2175 return; 2176 } 2177 2178 if (examined == 0) 2179 examined = 1; 2180 if (examined > total) 2181 total = examined; 2182 2183 fraction_done = (double)examined / total; 2184 minutes_left = (uint64_t)((now - start) * 2185 (1 - fraction_done) / fraction_done / 60); 2186 2187 (void) printf(gettext("%s in progress, %.2f%% done, %lluh%um to go\n"), 2188 scrub_type, 100 * fraction_done, 2189 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60)); 2190 } 2191 2192 /* 2193 * Print out configuration state as requested by status_callback. 2194 */ 2195 void 2196 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 2197 int namewidth, int depth) 2198 { 2199 nvlist_t **child; 2200 uint_t c, children; 2201 vdev_stat_t *vs; 2202 char rbuf[6], wbuf[6], cbuf[6], repaired[6]; 2203 char *vname; 2204 2205 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 2206 (uint64_t **)&vs, &c) == 0); 2207 2208 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2209 &child, &children) != 0) 2210 children = 0; 2211 2212 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 2213 name, state_to_name(vs->vs_state)); 2214 2215 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 2216 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 2217 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 2218 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 2219 2220 if (vs->vs_aux != 0) { 2221 (void) printf(" "); 2222 2223 switch (vs->vs_aux) { 2224 case VDEV_AUX_OPEN_FAILED: 2225 (void) printf(gettext("cannot open")); 2226 break; 2227 2228 case VDEV_AUX_BAD_GUID_SUM: 2229 (void) printf(gettext("missing device")); 2230 break; 2231 2232 case VDEV_AUX_NO_REPLICAS: 2233 (void) printf(gettext("insufficient replicas")); 2234 break; 2235 2236 default: 2237 (void) printf(gettext("corrupted data")); 2238 break; 2239 } 2240 } else if (vs->vs_scrub_repaired != 0 && children == 0) { 2241 /* 2242 * Report bytes resilvered/repaired on leaf devices. 2243 */ 2244 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); 2245 (void) printf(gettext(" %s %s"), repaired, 2246 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2247 "resilvered" : "repaired"); 2248 } 2249 2250 (void) printf("\n"); 2251 2252 for (c = 0; c < children; c++) { 2253 vname = zpool_vdev_name(zhp, child[c]); 2254 print_status_config(zhp, vname, child[c], 2255 namewidth, depth + 2); 2256 free(vname); 2257 } 2258 } 2259 2260 /* 2261 * Display a summary of pool status. Displays a summary such as: 2262 * 2263 * pool: tank 2264 * status: DEGRADED 2265 * reason: One or more devices ... 2266 * see: http://www.sun.com/msg/ZFS-xxxx-01 2267 * config: 2268 * mirror DEGRADED 2269 * c1t0d0 OK 2270 * c2t0d0 FAULTED 2271 * 2272 * When given the '-v' option, we print out the complete config. If the '-e' 2273 * option is specified, then we print out error rate information as well. 2274 */ 2275 int 2276 status_callback(zpool_handle_t *zhp, void *data) 2277 { 2278 status_cbdata_t *cbp = data; 2279 nvlist_t *config, *nvroot; 2280 char *msgid; 2281 int reason; 2282 char *health; 2283 2284 config = zpool_get_config(zhp, NULL); 2285 reason = zpool_get_status(zhp, &msgid); 2286 2287 cbp->cb_count++; 2288 2289 /* 2290 * If we were given 'zpool status -x', only report those pools with 2291 * problems. 2292 */ 2293 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) 2294 return (0); 2295 2296 if (cbp->cb_first) 2297 cbp->cb_first = FALSE; 2298 else 2299 (void) printf("\n"); 2300 2301 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_HEALTH, 2302 &health) == 0); 2303 2304 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 2305 (void) printf(gettext(" state: %s\n"), health); 2306 2307 switch (reason) { 2308 case ZPOOL_STATUS_MISSING_DEV_R: 2309 (void) printf(gettext("status: One or more devices could not " 2310 "be opened. Sufficient replicas exist for\n\tthe pool to " 2311 "continue functioning in a degraded state.\n")); 2312 (void) printf(gettext("action: Attach the missing device and " 2313 "online it using 'zpool online'.\n")); 2314 break; 2315 2316 case ZPOOL_STATUS_MISSING_DEV_NR: 2317 (void) printf(gettext("status: One or more devices could not " 2318 "be opened. There are insufficient\n\treplicas for the " 2319 "pool to continue functioning.\n")); 2320 (void) printf(gettext("action: Attach the missing device and " 2321 "online it using 'zpool online'.\n")); 2322 break; 2323 2324 case ZPOOL_STATUS_CORRUPT_LABEL_R: 2325 (void) printf(gettext("status: One or more devices could not " 2326 "be used because the label is missing or\n\tinvalid. " 2327 "Sufficient replicas exist for the pool to continue\n\t" 2328 "functioning in a degraded state.\n")); 2329 (void) printf(gettext("action: Replace the device using " 2330 "'zpool replace'.\n")); 2331 break; 2332 2333 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 2334 (void) printf(gettext("status: One or more devices could not " 2335 "be used because the the label is missing \n\tor invalid. " 2336 "There are insufficient replicas for the pool to " 2337 "continue\n\tfunctioning.\n")); 2338 (void) printf(gettext("action: Destroy and re-create the pool " 2339 "from a backup source.\n")); 2340 break; 2341 2342 case ZPOOL_STATUS_FAILING_DEV: 2343 (void) printf(gettext("status: One or more devices has " 2344 "experienced an unrecoverable error. An\n\tattempt was " 2345 "made to correct the error. Applications are " 2346 "unaffected.\n")); 2347 (void) printf(gettext("action: Determine if the device needs " 2348 "to be replaced, and clear the errors\n\tusing " 2349 "'zpool online' or replace the device with 'zpool " 2350 "replace'.\n")); 2351 break; 2352 2353 case ZPOOL_STATUS_OFFLINE_DEV: 2354 (void) printf(gettext("status: One or more devices has " 2355 "been taken offline by the adminstrator.\n\tSufficient " 2356 "replicas exist for the pool to continue functioning in " 2357 "a\n\tdegraded state.\n")); 2358 (void) printf(gettext("action: Online the device using " 2359 "'zpool online' or replace the device with\n\t'zpool " 2360 "replace'.\n")); 2361 break; 2362 2363 case ZPOOL_STATUS_RESILVERING: 2364 (void) printf(gettext("status: One or more devices is " 2365 "currently being resilvered. The pool will\n\tcontinue " 2366 "to function, possibly in a degraded state.\n")); 2367 (void) printf(gettext("action: Wait for the resilver to " 2368 "complete.\n")); 2369 break; 2370 2371 default: 2372 /* 2373 * The remaining errors can't actually be generated, yet. 2374 */ 2375 assert(reason == ZPOOL_STATUS_OK); 2376 } 2377 2378 if (msgid != NULL) 2379 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 2380 msgid); 2381 2382 if (config != NULL) { 2383 int namewidth; 2384 2385 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2386 &nvroot) == 0); 2387 2388 (void) printf(gettext(" scrub: ")); 2389 print_scrub_status(nvroot); 2390 2391 namewidth = max_width(zhp, nvroot, 0, 0); 2392 if (namewidth < 10) 2393 namewidth = 10; 2394 2395 (void) printf(gettext("config:\n\n")); 2396 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 2397 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 2398 print_status_config(zhp, zpool_get_name(zhp), nvroot, 2399 namewidth, 0); 2400 } else { 2401 (void) printf(gettext("config: The configuration cannot be " 2402 "determined.\n")); 2403 } 2404 2405 return (0); 2406 } 2407 2408 /* 2409 * zpool status [-vx] [pool] ... 2410 * 2411 * -v Display complete error logs 2412 * -x Display only pools with potential problems 2413 * 2414 * Describes the health status of all pools or some subset. 2415 */ 2416 int 2417 zpool_do_status(int argc, char **argv) 2418 { 2419 int c; 2420 int ret; 2421 status_cbdata_t cb = { 0 }; 2422 2423 /* check options */ 2424 while ((c = getopt(argc, argv, "vx")) != -1) { 2425 switch (c) { 2426 case 'v': 2427 cb.cb_verbose = TRUE; 2428 break; 2429 case 'x': 2430 cb.cb_explain = TRUE; 2431 break; 2432 case '?': 2433 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2434 optopt); 2435 usage(FALSE); 2436 } 2437 } 2438 2439 argc -= optind; 2440 argv += optind; 2441 2442 cb.cb_first = TRUE; 2443 2444 ret = for_each_pool(argc, argv, TRUE, status_callback, &cb); 2445 2446 if (argc == 0 && cb.cb_count == 0) 2447 (void) printf(gettext("no pools available\n")); 2448 else if (cb.cb_explain && cb.cb_first) { 2449 if (argc == 0) { 2450 (void) printf(gettext("all pools are healthy\n")); 2451 } else { 2452 int i; 2453 for (i = 0; i < argc; i++) 2454 (void) printf(gettext("pool '%s' is healthy\n"), 2455 argv[i]); 2456 } 2457 } 2458 2459 return (ret); 2460 } 2461 2462 int 2463 main(int argc, char **argv) 2464 { 2465 int ret; 2466 int i; 2467 char *cmdname; 2468 2469 (void) setlocale(LC_ALL, ""); 2470 (void) textdomain(TEXT_DOMAIN); 2471 2472 opterr = 0; 2473 2474 /* 2475 * Make sure the user has specified some command. 2476 */ 2477 if (argc < 2) { 2478 (void) fprintf(stderr, gettext("missing command\n")); 2479 usage(FALSE); 2480 } 2481 2482 cmdname = argv[1]; 2483 2484 /* 2485 * Special case '-?' 2486 */ 2487 if (strcmp(cmdname, "-?") == 0) 2488 usage(TRUE); 2489 2490 /* 2491 * Run the appropriate command. 2492 */ 2493 for (i = 0; i < NCOMMAND; i++) { 2494 if (command_table[i].name == NULL) 2495 continue; 2496 2497 if (strcmp(cmdname, command_table[i].name) == 0) { 2498 current_command = &command_table[i]; 2499 ret = command_table[i].func(argc - 1, argv + 1); 2500 break; 2501 } 2502 } 2503 2504 /* 2505 * 'freeze' is a vile debugging abomination, so we treat it as such. 2506 */ 2507 if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 2508 char buf[8192]; 2509 int fd = open("/dev/zpoolctl", O_RDWR); 2510 (void) strcpy((void *)buf, argv[2]); 2511 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 2512 } 2513 2514 if (i == NCOMMAND) { 2515 (void) fprintf(stderr, gettext("unrecognized " 2516 "command '%s'\n"), cmdname); 2517 usage(FALSE); 2518 } 2519 2520 /* 2521 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 2522 * for the purposes of running ::findleaks. 2523 */ 2524 if (getenv("ZFS_ABORT") != NULL) { 2525 (void) printf("dumping core by request\n"); 2526 abort(); 2527 } 2528 2529 return (ret); 2530 } 2531