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