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)) == 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 static int 1258 refresh_iostat(zpool_handle_t *zhp, void *data) 1259 { 1260 iostat_cbdata_t *cb = data; 1261 1262 /* 1263 * If the pool has disappeared, remove it from the list and continue. 1264 */ 1265 if (zpool_refresh_stats(zhp) != 0) 1266 pool_list_remove(cb->cb_list, zhp); 1267 1268 return (0); 1269 } 1270 1271 /* 1272 * Callback to print out the iostats for the given pool. 1273 */ 1274 int 1275 print_iostat(zpool_handle_t *zhp, void *data) 1276 { 1277 iostat_cbdata_t *cb = data; 1278 nvlist_t *oldconfig, *newconfig; 1279 nvlist_t *oldnvroot, *newnvroot; 1280 1281 newconfig = zpool_get_config(zhp, &oldconfig); 1282 1283 if (cb->cb_iteration == 1) 1284 oldconfig = NULL; 1285 1286 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 1287 &newnvroot) == 0); 1288 1289 if (oldconfig == NULL) 1290 oldnvroot = NULL; 1291 else 1292 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 1293 &oldnvroot) == 0); 1294 1295 /* 1296 * Print out the statistics for the pool. 1297 */ 1298 print_vdev_stats(zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 1299 1300 if (cb->cb_verbose) 1301 print_iostat_separator(cb); 1302 1303 return (0); 1304 } 1305 1306 int 1307 get_namewidth(zpool_handle_t *zhp, void *data) 1308 { 1309 iostat_cbdata_t *cb = data; 1310 nvlist_t *config, *nvroot; 1311 1312 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 1313 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1314 &nvroot) == 0); 1315 if (!cb->cb_verbose) 1316 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 1317 else 1318 cb->cb_namewidth = max_width(nvroot, 0, 0); 1319 } 1320 1321 /* 1322 * The width must fall into the range [10,38]. The upper limit is the 1323 * maximum we can have and still fit in 80 columns. 1324 */ 1325 if (cb->cb_namewidth < 10) 1326 cb->cb_namewidth = 10; 1327 if (cb->cb_namewidth > 38) 1328 cb->cb_namewidth = 38; 1329 1330 return (0); 1331 } 1332 1333 /* 1334 * zpool iostat [-v] [pool] ... [interval [count]] 1335 * 1336 * -v Display statistics for individual vdevs 1337 * 1338 * This command can be tricky because we want to be able to deal with pool 1339 * creation/destruction as well as vdev configuration changes. The bulk of this 1340 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 1341 * on pool_list_update() to detect the addition of new pools. Configuration 1342 * changes are all handled within libzfs. 1343 */ 1344 int 1345 zpool_do_iostat(int argc, char **argv) 1346 { 1347 int c; 1348 int ret; 1349 int npools; 1350 unsigned long interval = 0, count = 0; 1351 zpool_list_t *list; 1352 int verbose = FALSE; 1353 iostat_cbdata_t cb; 1354 1355 /* check options */ 1356 while ((c = getopt(argc, argv, "v")) != -1) { 1357 switch (c) { 1358 case 'v': 1359 verbose = TRUE; 1360 break; 1361 case '?': 1362 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1363 optopt); 1364 usage(FALSE); 1365 } 1366 } 1367 1368 argc -= optind; 1369 argv += optind; 1370 1371 /* 1372 * Determine if the last argument is an integer or a pool name 1373 */ 1374 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1375 char *end; 1376 1377 errno = 0; 1378 interval = strtoul(argv[argc - 1], &end, 10); 1379 1380 if (*end == '\0' && errno == 0) { 1381 if (interval == 0) { 1382 (void) fprintf(stderr, gettext("interval " 1383 "cannot be zero\n")); 1384 usage(FALSE); 1385 } 1386 1387 /* 1388 * Ignore the last parameter 1389 */ 1390 argc--; 1391 } else { 1392 /* 1393 * If this is not a valid number, just plow on. The 1394 * user will get a more informative error message later 1395 * on. 1396 */ 1397 interval = 0; 1398 } 1399 } 1400 1401 /* 1402 * If the last argument is also an integer, then we have both a count 1403 * and an integer. 1404 */ 1405 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1406 char *end; 1407 1408 errno = 0; 1409 count = interval; 1410 interval = strtoul(argv[argc - 1], &end, 10); 1411 1412 if (*end == '\0' && errno == 0) { 1413 if (interval == 0) { 1414 (void) fprintf(stderr, gettext("interval " 1415 "cannot be zero\n")); 1416 usage(FALSE); 1417 } 1418 1419 /* 1420 * Ignore the last parameter 1421 */ 1422 argc--; 1423 } else { 1424 interval = 0; 1425 } 1426 } 1427 1428 /* 1429 * Construct the list of all interesting pools. 1430 */ 1431 ret = 0; 1432 if ((list = pool_list_get(argc, argv, &ret)) == NULL) 1433 return (1); 1434 1435 if (pool_list_count(list) == 0 && argc != 0) 1436 return (1); 1437 1438 if (pool_list_count(list) == 0 && interval == 0) { 1439 (void) fprintf(stderr, gettext("no pools available\n")); 1440 return (1); 1441 } 1442 1443 /* 1444 * Enter the main iostat loop. 1445 */ 1446 cb.cb_list = list; 1447 cb.cb_verbose = verbose; 1448 cb.cb_iteration = 0; 1449 cb.cb_namewidth = 0; 1450 1451 for (;;) { 1452 pool_list_update(list); 1453 1454 if ((npools = pool_list_count(list)) == 0) 1455 break; 1456 1457 /* 1458 * Refresh all statistics. This is done as an explicit step 1459 * before calculating the maximum name width, so that any 1460 * configuration changes are properly accounted for. 1461 */ 1462 (void) pool_list_iter(list, FALSE, refresh_iostat, &cb); 1463 1464 /* 1465 * Iterate over all pools to determine the maximum width 1466 * for the pool / device name column across all pools. 1467 */ 1468 cb.cb_namewidth = 0; 1469 (void) pool_list_iter(list, FALSE, get_namewidth, &cb); 1470 1471 /* 1472 * If it's the first time, or verbose mode, print the header. 1473 */ 1474 if (++cb.cb_iteration == 1 || verbose) 1475 print_iostat_header(&cb); 1476 1477 (void) pool_list_iter(list, FALSE, print_iostat, &cb); 1478 1479 /* 1480 * If there's more than one pool, and we're not in verbose mode 1481 * (which prints a separator for us), then print a separator. 1482 */ 1483 if (npools > 1 && !verbose) 1484 print_iostat_separator(&cb); 1485 1486 if (verbose) 1487 (void) printf("\n"); 1488 1489 if (interval == 0) 1490 break; 1491 1492 if (count != 0 && --count == 0) 1493 break; 1494 1495 (void) sleep(interval); 1496 } 1497 1498 pool_list_free(list); 1499 1500 return (ret); 1501 } 1502 1503 typedef struct list_cbdata { 1504 int cb_scripted; 1505 int cb_first; 1506 int cb_fields[MAX_FIELDS]; 1507 int cb_fieldcount; 1508 } list_cbdata_t; 1509 1510 /* 1511 * Given a list of columns to display, output appropriate headers for each one. 1512 */ 1513 void 1514 print_header(int *fields, size_t count) 1515 { 1516 int i; 1517 column_def_t *col; 1518 const char *fmt; 1519 1520 for (i = 0; i < count; i++) { 1521 col = &column_table[fields[i]]; 1522 if (i != 0) 1523 (void) printf(" "); 1524 if (col->cd_justify == left_justify) 1525 fmt = "%-*s"; 1526 else 1527 fmt = "%*s"; 1528 1529 (void) printf(fmt, i == count - 1 ? strlen(col->cd_title) : 1530 col->cd_width, col->cd_title); 1531 } 1532 1533 (void) printf("\n"); 1534 } 1535 1536 int 1537 list_callback(zpool_handle_t *zhp, void *data) 1538 { 1539 list_cbdata_t *cbp = data; 1540 nvlist_t *config; 1541 int i; 1542 char buf[ZPOOL_MAXNAMELEN]; 1543 uint64_t total; 1544 uint64_t used; 1545 const char *fmt; 1546 column_def_t *col; 1547 1548 if (cbp->cb_first) { 1549 if (!cbp->cb_scripted) 1550 print_header(cbp->cb_fields, cbp->cb_fieldcount); 1551 cbp->cb_first = FALSE; 1552 } 1553 1554 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 1555 config = NULL; 1556 } else { 1557 config = zpool_get_config(zhp, NULL); 1558 total = zpool_get_space_total(zhp); 1559 used = zpool_get_space_used(zhp); 1560 } 1561 1562 for (i = 0; i < cbp->cb_fieldcount; i++) { 1563 if (i != 0) { 1564 if (cbp->cb_scripted) 1565 (void) printf("\t"); 1566 else 1567 (void) printf(" "); 1568 } 1569 1570 col = &column_table[cbp->cb_fields[i]]; 1571 1572 switch (cbp->cb_fields[i]) { 1573 case ZPOOL_FIELD_NAME: 1574 (void) strlcpy(buf, zpool_get_name(zhp), sizeof (buf)); 1575 break; 1576 1577 case ZPOOL_FIELD_SIZE: 1578 if (config == NULL) 1579 (void) strlcpy(buf, "-", sizeof (buf)); 1580 else 1581 zfs_nicenum(total, buf, sizeof (buf)); 1582 break; 1583 1584 case ZPOOL_FIELD_USED: 1585 if (config == NULL) 1586 (void) strlcpy(buf, "-", sizeof (buf)); 1587 else 1588 zfs_nicenum(used, buf, sizeof (buf)); 1589 break; 1590 1591 case ZPOOL_FIELD_AVAILABLE: 1592 if (config == NULL) 1593 (void) strlcpy(buf, "-", sizeof (buf)); 1594 else 1595 zfs_nicenum(total - used, buf, sizeof (buf)); 1596 break; 1597 1598 case ZPOOL_FIELD_CAPACITY: 1599 if (config == NULL) { 1600 (void) strlcpy(buf, "-", sizeof (buf)); 1601 } else { 1602 uint64_t capacity = (total == 0 ? 0 : 1603 (used * 100 / total)); 1604 (void) snprintf(buf, sizeof (buf), "%llu%%", 1605 capacity); 1606 } 1607 break; 1608 1609 case ZPOOL_FIELD_HEALTH: 1610 if (config == NULL) { 1611 (void) strlcpy(buf, "FAULTED", sizeof (buf)); 1612 } else { 1613 nvlist_t *nvroot; 1614 vdev_stat_t *vs; 1615 uint_t vsc; 1616 1617 verify(nvlist_lookup_nvlist(config, 1618 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 1619 verify(nvlist_lookup_uint64_array(nvroot, 1620 ZPOOL_CONFIG_STATS, (uint64_t **)&vs, 1621 &vsc) == 0); 1622 (void) strlcpy(buf, state_to_name(vs->vs_state), 1623 sizeof (buf)); 1624 } 1625 break; 1626 1627 case ZPOOL_FIELD_ROOT: 1628 if (config == NULL) 1629 (void) strlcpy(buf, "-", sizeof (buf)); 1630 else if (zpool_get_root(zhp, buf, sizeof (buf)) != 0) 1631 (void) strlcpy(buf, "-", sizeof (buf)); 1632 break; 1633 } 1634 1635 if (cbp->cb_scripted) 1636 (void) printf("%s", buf); 1637 else { 1638 if (col->cd_justify == left_justify) 1639 fmt = "%-*s"; 1640 else 1641 fmt = "%*s"; 1642 1643 (void) printf(fmt, i == cbp->cb_fieldcount - 1 ? 1644 strlen(buf) : col->cd_width, buf); 1645 } 1646 } 1647 1648 (void) printf("\n"); 1649 1650 return (0); 1651 } 1652 1653 /* 1654 * zpool list [-H] [-o field[,field]*] [pool] ... 1655 * 1656 * -H Scripted mode. Don't display headers, and separate fields by 1657 * a single tab. 1658 * -o List of fields to display. Defaults to all fields, or 1659 * "name,size,used,available,capacity,health,root" 1660 * 1661 * List all pools in the system, whether or not they're healthy. Output space 1662 * statistics for each one, as well as health status summary. 1663 */ 1664 int 1665 zpool_do_list(int argc, char **argv) 1666 { 1667 int c; 1668 int ret; 1669 list_cbdata_t cb = { 0 }; 1670 static char default_fields[] = 1671 "name,size,used,available,capacity,health,root"; 1672 char *fields = default_fields; 1673 char *value; 1674 1675 /* check options */ 1676 while ((c = getopt(argc, argv, ":Ho:")) != -1) { 1677 switch (c) { 1678 case 'H': 1679 cb.cb_scripted = TRUE; 1680 break; 1681 case 'o': 1682 fields = optarg; 1683 break; 1684 case ':': 1685 (void) fprintf(stderr, gettext("missing argument for " 1686 "'%c' option\n"), optopt); 1687 usage(FALSE); 1688 break; 1689 case '?': 1690 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1691 optopt); 1692 usage(FALSE); 1693 } 1694 } 1695 1696 argc -= optind; 1697 argv += optind; 1698 1699 while (*fields != '\0') { 1700 if (cb.cb_fieldcount == MAX_FIELDS) { 1701 (void) fprintf(stderr, gettext("too many " 1702 "properties given to -o option\n")); 1703 usage(FALSE); 1704 } 1705 1706 if ((cb.cb_fields[cb.cb_fieldcount] = getsubopt(&fields, 1707 column_subopts, &value)) == -1) { 1708 (void) fprintf(stderr, gettext("invalid property " 1709 "'%s'\n"), value); 1710 usage(FALSE); 1711 } 1712 1713 cb.cb_fieldcount++; 1714 } 1715 1716 1717 cb.cb_first = TRUE; 1718 1719 ret = for_each_pool(argc, argv, TRUE, list_callback, &cb); 1720 1721 if (argc == 0 && cb.cb_first) { 1722 (void) printf(gettext("no pools available\n")); 1723 return (0); 1724 } 1725 1726 return (ret); 1727 } 1728 1729 static nvlist_t * 1730 zpool_get_vdev_by_name(nvlist_t *nv, char *name) 1731 { 1732 nvlist_t **child; 1733 uint_t c, children; 1734 nvlist_t *match; 1735 char *path; 1736 1737 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1738 &child, &children) != 0) { 1739 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1740 if (strncmp(name, "/dev/dsk/", 9) == 0) 1741 name += 9; 1742 if (strncmp(path, "/dev/dsk/", 9) == 0) 1743 path += 9; 1744 if (strcmp(name, path) == 0) 1745 return (nv); 1746 return (NULL); 1747 } 1748 1749 for (c = 0; c < children; c++) 1750 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 1751 return (match); 1752 1753 return (NULL); 1754 } 1755 1756 static int 1757 zpool_do_attach_or_replace(int argc, char **argv, int replacing) 1758 { 1759 int force = FALSE; 1760 int c; 1761 nvlist_t *nvroot; 1762 char *poolname, *old_disk, *new_disk; 1763 zpool_handle_t *zhp; 1764 nvlist_t *config; 1765 1766 /* check options */ 1767 while ((c = getopt(argc, argv, "f")) != -1) { 1768 switch (c) { 1769 case 'f': 1770 force = TRUE; 1771 break; 1772 case '?': 1773 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1774 optopt); 1775 usage(FALSE); 1776 } 1777 } 1778 1779 argc -= optind; 1780 argv += optind; 1781 1782 /* get pool name and check number of arguments */ 1783 if (argc < 1) { 1784 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1785 usage(FALSE); 1786 } 1787 1788 poolname = argv[0]; 1789 1790 if (argc < 2) { 1791 (void) fprintf(stderr, 1792 gettext("missing <device> specification\n")); 1793 usage(FALSE); 1794 } 1795 1796 old_disk = argv[1]; 1797 1798 if (argc < 3) { 1799 if (!replacing) { 1800 (void) fprintf(stderr, 1801 gettext("missing <new_device> specification\n")); 1802 usage(FALSE); 1803 } 1804 new_disk = old_disk; 1805 argc -= 1; 1806 argv += 1; 1807 } else { 1808 new_disk = argv[2]; 1809 argc -= 2; 1810 argv += 2; 1811 } 1812 1813 if (argc > 1) { 1814 (void) fprintf(stderr, gettext("too many arguments\n")); 1815 usage(FALSE); 1816 } 1817 1818 if ((zhp = zpool_open(poolname)) == NULL) 1819 return (1); 1820 1821 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 1822 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 1823 poolname); 1824 zpool_close(zhp); 1825 return (1); 1826 } 1827 1828 nvroot = make_root_vdev(config, force, B_FALSE, argc, argv); 1829 if (nvroot == NULL) { 1830 zpool_close(zhp); 1831 return (1); 1832 } 1833 1834 return (zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing)); 1835 } 1836 1837 /* 1838 * zpool replace [-f] <pool> <device> <new_device> 1839 * 1840 * -f Force attach, even if <new_device> appears to be in use. 1841 * 1842 * Replace <device> with <new_device>. 1843 */ 1844 /* ARGSUSED */ 1845 int 1846 zpool_do_replace(int argc, char **argv) 1847 { 1848 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 1849 } 1850 1851 /* 1852 * zpool attach [-f] <pool> <device> <new_device> 1853 * 1854 * -f Force attach, even if <new_device> appears to be in use. 1855 * 1856 * Attach <new_device> to the mirror containing <device>. If <device> is not 1857 * part of a mirror, then <device> will be transformed into a mirror of 1858 * <device> and <new_device>. In either case, <new_device> will begin life 1859 * with a DTL of [0, now], and will immediately begin to resilver itself. 1860 */ 1861 int 1862 zpool_do_attach(int argc, char **argv) 1863 { 1864 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 1865 } 1866 1867 /* 1868 * zpool detach [-f] <pool> <device> 1869 * 1870 * -f Force detach of <device>, even if DTLs argue against it 1871 * (not supported yet) 1872 * 1873 * Detach a device from a mirror. The operation will be refused if <device> 1874 * is the last device in the mirror, or if the DTLs indicate that this device 1875 * has the only valid copy of some data. 1876 */ 1877 /* ARGSUSED */ 1878 int 1879 zpool_do_detach(int argc, char **argv) 1880 { 1881 int c; 1882 char *poolname, *path; 1883 zpool_handle_t *zhp; 1884 1885 /* check options */ 1886 while ((c = getopt(argc, argv, "f")) != -1) { 1887 switch (c) { 1888 case 'f': 1889 case '?': 1890 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1891 optopt); 1892 usage(FALSE); 1893 } 1894 } 1895 1896 argc -= optind; 1897 argv += optind; 1898 1899 /* get pool name and check number of arguments */ 1900 if (argc < 1) { 1901 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1902 usage(FALSE); 1903 } 1904 1905 if (argc < 2) { 1906 (void) fprintf(stderr, 1907 gettext("missing <device> specification\n")); 1908 usage(FALSE); 1909 } 1910 1911 poolname = argv[0]; 1912 path = argv[1]; 1913 1914 if ((zhp = zpool_open(poolname)) == NULL) 1915 return (1); 1916 1917 return (zpool_vdev_detach(zhp, path)); 1918 } 1919 1920 /* 1921 * zpool online [-t] <pool> <device> 1922 * 1923 * -t Only bring the device on-line temporarily. The online 1924 * state will not be persistent across reboots. 1925 */ 1926 /* ARGSUSED */ 1927 int 1928 zpool_do_online(int argc, char **argv) 1929 { 1930 int c, i; 1931 char *poolname; 1932 zpool_handle_t *zhp; 1933 int ret = 0; 1934 1935 /* check options */ 1936 while ((c = getopt(argc, argv, "t")) != -1) { 1937 switch (c) { 1938 case 't': 1939 case '?': 1940 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1941 optopt); 1942 usage(FALSE); 1943 } 1944 } 1945 1946 argc -= optind; 1947 argv += optind; 1948 1949 /* get pool name and check number of arguments */ 1950 if (argc < 1) { 1951 (void) fprintf(stderr, gettext("missing pool name\n")); 1952 usage(FALSE); 1953 } 1954 if (argc < 2) { 1955 (void) fprintf(stderr, gettext("missing device name\n")); 1956 usage(FALSE); 1957 } 1958 1959 poolname = argv[0]; 1960 1961 if ((zhp = zpool_open(poolname)) == NULL) 1962 return (1); 1963 1964 for (i = 1; i < argc; i++) 1965 if (zpool_vdev_online(zhp, argv[i]) == 0) 1966 (void) printf(gettext("Bringing device %s online\n"), 1967 argv[i]); 1968 else 1969 ret = 1; 1970 1971 return (ret); 1972 } 1973 1974 /* 1975 * zpool offline [-ft] <pool> <device> 1976 * 1977 * -f Force the device into the offline state, even if doing 1978 * so would appear to compromise pool availability. 1979 * (not supported yet) 1980 * 1981 * -t Only take the device off-line temporarily. The offline 1982 * state will not be persistent across reboots. 1983 * (not supported yet) 1984 */ 1985 /* ARGSUSED */ 1986 int 1987 zpool_do_offline(int argc, char **argv) 1988 { 1989 int c, i; 1990 char *poolname; 1991 zpool_handle_t *zhp; 1992 int ret = 0; 1993 1994 /* check options */ 1995 while ((c = getopt(argc, argv, "ft")) != -1) { 1996 switch (c) { 1997 case 'f': 1998 case 't': 1999 case '?': 2000 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2001 optopt); 2002 usage(FALSE); 2003 } 2004 } 2005 2006 argc -= optind; 2007 argv += optind; 2008 2009 /* get pool name and check number of arguments */ 2010 if (argc < 1) { 2011 (void) fprintf(stderr, gettext("missing pool name\n")); 2012 usage(FALSE); 2013 } 2014 if (argc < 2) { 2015 (void) fprintf(stderr, gettext("missing device name\n")); 2016 usage(FALSE); 2017 } 2018 2019 poolname = argv[0]; 2020 2021 if ((zhp = zpool_open(poolname)) == NULL) 2022 return (1); 2023 2024 for (i = 1; i < argc; i++) 2025 if (zpool_vdev_offline(zhp, argv[i]) == 0) 2026 (void) printf(gettext("Bringing device %s offline\n"), 2027 argv[i]); 2028 else 2029 ret = 1; 2030 2031 return (ret); 2032 } 2033 2034 typedef struct scrub_cbdata { 2035 int cb_type; 2036 } scrub_cbdata_t; 2037 2038 int 2039 scrub_callback(zpool_handle_t *zhp, void *data) 2040 { 2041 scrub_cbdata_t *cb = data; 2042 2043 return (zpool_scrub(zhp, cb->cb_type) != 0); 2044 } 2045 2046 /* 2047 * zpool scrub [-s] <pool> ... 2048 * 2049 * -s Stop. Stops any in-progress scrub. 2050 */ 2051 int 2052 zpool_do_scrub(int argc, char **argv) 2053 { 2054 int c; 2055 scrub_cbdata_t cb; 2056 2057 cb.cb_type = POOL_SCRUB_EVERYTHING; 2058 2059 /* check options */ 2060 while ((c = getopt(argc, argv, "s")) != -1) { 2061 switch (c) { 2062 case 's': 2063 cb.cb_type = POOL_SCRUB_NONE; 2064 break; 2065 case '?': 2066 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2067 optopt); 2068 usage(FALSE); 2069 } 2070 } 2071 2072 argc -= optind; 2073 argv += optind; 2074 2075 if (argc < 1) { 2076 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2077 usage(FALSE); 2078 } 2079 2080 return (for_each_pool(argc, argv, TRUE, scrub_callback, &cb)); 2081 } 2082 2083 typedef struct status_cbdata { 2084 int cb_verbose; 2085 int cb_explain; 2086 int cb_count; 2087 int cb_first; 2088 } status_cbdata_t; 2089 2090 /* 2091 * Print out detailed scrub status. 2092 */ 2093 void 2094 print_scrub_status(nvlist_t *nvroot) 2095 { 2096 vdev_stat_t *vs; 2097 uint_t vsc; 2098 time_t start, end, now; 2099 double fraction_done; 2100 uint64_t examined, total, minutes_left; 2101 char *scrub_type; 2102 2103 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 2104 (uint64_t **)&vs, &vsc) == 0); 2105 2106 /* 2107 * If there's never been a scrub, there's not much to say. 2108 */ 2109 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) { 2110 (void) printf(gettext("none requested\n")); 2111 return; 2112 } 2113 2114 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2115 "resilver" : "scrub"; 2116 2117 start = vs->vs_scrub_start; 2118 end = vs->vs_scrub_end; 2119 now = time(NULL); 2120 examined = vs->vs_scrub_examined; 2121 total = vs->vs_alloc; 2122 2123 if (end != 0) { 2124 (void) printf(gettext("%s %s with %llu errors on %s"), 2125 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped", 2126 (u_longlong_t)vs->vs_scrub_errors, ctime(&end)); 2127 return; 2128 } 2129 2130 if (examined == 0) 2131 examined = 1; 2132 if (examined > total) 2133 total = examined; 2134 2135 fraction_done = (double)examined / total; 2136 minutes_left = (uint64_t)((now - start) * 2137 (1 - fraction_done) / fraction_done / 60); 2138 2139 (void) printf(gettext("%s in progress, %.2f%% done, %lluh%um to go\n"), 2140 scrub_type, 100 * fraction_done, 2141 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60)); 2142 } 2143 2144 /* 2145 * Print out configuration state as requested by status_callback. 2146 */ 2147 void 2148 print_status_config(const char *name, nvlist_t *nv, int namewidth, int depth) 2149 { 2150 nvlist_t **child; 2151 uint_t c, children; 2152 vdev_stat_t *vs; 2153 char rbuf[6], wbuf[6], cbuf[6], repaired[6]; 2154 2155 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 2156 (uint64_t **)&vs, &c) == 0); 2157 2158 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2159 &child, &children) != 0) 2160 children = 0; 2161 2162 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 2163 name, state_to_name(vs->vs_state)); 2164 2165 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 2166 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 2167 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 2168 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 2169 2170 if (vs->vs_aux != 0) { 2171 (void) printf(" "); 2172 2173 switch (vs->vs_aux) { 2174 case VDEV_AUX_OPEN_FAILED: 2175 (void) printf(gettext("cannot open")); 2176 break; 2177 2178 case VDEV_AUX_BAD_GUID_SUM: 2179 (void) printf(gettext("missing device")); 2180 break; 2181 2182 case VDEV_AUX_NO_REPLICAS: 2183 (void) printf(gettext("insufficient replicas")); 2184 break; 2185 2186 default: 2187 (void) printf(gettext("corrupted data")); 2188 break; 2189 } 2190 } else if (vs->vs_scrub_repaired != 0 && children == 0) { 2191 /* 2192 * Report bytes resilvered/repaired on leaf devices. 2193 */ 2194 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); 2195 (void) printf(gettext(" %s %s"), repaired, 2196 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2197 "resilvered" : "repaired"); 2198 } 2199 2200 (void) printf("\n"); 2201 2202 for (c = 0; c < children; c++) 2203 print_status_config(vdev_get_name(child[c]), child[c], 2204 namewidth, depth + 2); 2205 } 2206 2207 /* 2208 * Display a summary of pool status. Displays a summary such as: 2209 * 2210 * pool: tank 2211 * status: DEGRADED 2212 * reason: One or more devices ... 2213 * see: http://www.sun.com/msg/ZFS-xxxx-01 2214 * config: 2215 * mirror DEGRADED 2216 * c1t0d0 OK 2217 * c2t0d0 FAULTED 2218 * 2219 * When given the '-v' option, we print out the complete config. If the '-e' 2220 * option is specified, then we print out error rate information as well. 2221 */ 2222 int 2223 status_callback(zpool_handle_t *zhp, void *data) 2224 { 2225 status_cbdata_t *cbp = data; 2226 nvlist_t *config, *nvroot; 2227 char *msgid; 2228 int reason; 2229 char *health; 2230 2231 config = zpool_get_config(zhp, NULL); 2232 reason = zpool_get_status(zhp, &msgid); 2233 2234 cbp->cb_count++; 2235 2236 /* 2237 * If we were given 'zpool status -x', only report those pools with 2238 * problems. 2239 */ 2240 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) 2241 return (0); 2242 2243 if (cbp->cb_first) 2244 cbp->cb_first = FALSE; 2245 else 2246 (void) printf("\n"); 2247 2248 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_HEALTH, 2249 &health) == 0); 2250 2251 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 2252 (void) printf(gettext(" state: %s\n"), health); 2253 2254 switch (reason) { 2255 case ZPOOL_STATUS_MISSING_DEV_R: 2256 (void) printf(gettext("status: One or more devices could not " 2257 "be opened. Sufficient replicas exist for\n\tthe pool to " 2258 "continue functioning in a degraded state.\n")); 2259 (void) printf(gettext("action: Attach the missing device and " 2260 "online it using 'zpool online'.\n")); 2261 break; 2262 2263 case ZPOOL_STATUS_MISSING_DEV_NR: 2264 (void) printf(gettext("status: One or more devices could not " 2265 "be opened. There are insufficient\n\treplicas for the " 2266 "pool to continue functioning.\n")); 2267 (void) printf(gettext("action: Attach the missing device and " 2268 "online it using 'zpool online'.\n")); 2269 break; 2270 2271 case ZPOOL_STATUS_CORRUPT_LABEL_R: 2272 (void) printf(gettext("status: One or more devices could not " 2273 "be used because the label is missing or\n\tinvalid. " 2274 "Sufficient replicas exist for the pool to continue\n\t" 2275 "functioning in a degraded state.\n")); 2276 (void) printf(gettext("action: Replace the device using " 2277 "'zpool replace'.\n")); 2278 break; 2279 2280 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 2281 (void) printf(gettext("status: One or more devices could not " 2282 "be used because the the label is missing \n\tor invalid. " 2283 "There are insufficient replicas for the pool to " 2284 "continue\n\tfunctioning.\n")); 2285 (void) printf(gettext("action: Destroy and re-create the pool " 2286 "from a backup source.\n")); 2287 break; 2288 2289 case ZPOOL_STATUS_FAILING_DEV: 2290 (void) printf(gettext("status: One or more devices has " 2291 "experienced an unrecoverable error. An\n\tattempt was " 2292 "made to correct the error. Applications are " 2293 "unaffected.\n")); 2294 (void) printf(gettext("action: Determine if the device needs " 2295 "to be replaced, and clear the errors\n\tusing " 2296 "'zpool online' or replace the device with 'zpool " 2297 "replace'.\n")); 2298 break; 2299 2300 case ZPOOL_STATUS_OFFLINE_DEV: 2301 (void) printf(gettext("status: One or more devices has " 2302 "been taken offline by the adminstrator.\n\tSufficient " 2303 "replicas exist for the pool to continue functioning in " 2304 "a\n\tdegraded state.\n")); 2305 (void) printf(gettext("action: Online the device using " 2306 "'zpool online' or replace the device with\n\t'zpool " 2307 "replace'.\n")); 2308 break; 2309 2310 case ZPOOL_STATUS_RESILVERING: 2311 (void) printf(gettext("status: One or more devices is " 2312 "currently being resilvered. The pool will\n\tcontinue " 2313 "to function, possibly in a degraded state.\n")); 2314 (void) printf(gettext("action: Wait for the resilver to " 2315 "complete.\n")); 2316 break; 2317 2318 default: 2319 /* 2320 * The remaining errors can't actually be generated, yet. 2321 */ 2322 assert(reason == ZPOOL_STATUS_OK); 2323 } 2324 2325 if (msgid != NULL) 2326 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 2327 msgid); 2328 2329 if (config != NULL) { 2330 int namewidth; 2331 2332 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2333 &nvroot) == 0); 2334 2335 (void) printf(gettext(" scrub: ")); 2336 print_scrub_status(nvroot); 2337 2338 namewidth = max_width(nvroot, 0, 0); 2339 if (namewidth < 10) 2340 namewidth = 10; 2341 2342 (void) printf(gettext("config:\n\n")); 2343 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 2344 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 2345 print_status_config(zpool_get_name(zhp), nvroot, namewidth, 0); 2346 } else { 2347 (void) printf(gettext("config: The configuration cannot be " 2348 "determined.\n")); 2349 } 2350 2351 return (0); 2352 } 2353 2354 /* 2355 * zpool status [-vx] [pool] ... 2356 * 2357 * -v Display complete error logs 2358 * -x Display only pools with potential problems 2359 * 2360 * Describes the health status of all pools or some subset. 2361 */ 2362 int 2363 zpool_do_status(int argc, char **argv) 2364 { 2365 int c; 2366 int ret; 2367 status_cbdata_t cb = { 0 }; 2368 2369 /* check options */ 2370 while ((c = getopt(argc, argv, "vx")) != -1) { 2371 switch (c) { 2372 case 'v': 2373 cb.cb_verbose = TRUE; 2374 break; 2375 case 'x': 2376 cb.cb_explain = TRUE; 2377 break; 2378 case '?': 2379 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2380 optopt); 2381 usage(FALSE); 2382 } 2383 } 2384 2385 argc -= optind; 2386 argv += optind; 2387 2388 cb.cb_first = TRUE; 2389 2390 ret = for_each_pool(argc, argv, TRUE, status_callback, &cb); 2391 2392 if (argc == 0 && cb.cb_count == 0) 2393 (void) printf(gettext("no pools available\n")); 2394 else if (cb.cb_explain && cb.cb_first) { 2395 if (argc == 0) { 2396 (void) printf(gettext("all pools are healthy\n")); 2397 } else { 2398 int i; 2399 for (i = 0; i < argc; i++) 2400 (void) printf(gettext("pool '%s' is healthy\n"), 2401 argv[i]); 2402 } 2403 } 2404 2405 return (ret); 2406 } 2407 2408 int 2409 main(int argc, char **argv) 2410 { 2411 int ret; 2412 int i; 2413 char *cmdname; 2414 2415 (void) setlocale(LC_ALL, ""); 2416 (void) textdomain(TEXT_DOMAIN); 2417 2418 opterr = 0; 2419 2420 /* 2421 * Make sure the user has specified some command. 2422 */ 2423 if (argc < 2) { 2424 (void) fprintf(stderr, gettext("missing command\n")); 2425 usage(FALSE); 2426 } 2427 2428 cmdname = argv[1]; 2429 2430 /* 2431 * Special case '-?' 2432 */ 2433 if (strcmp(cmdname, "-?") == 0) 2434 usage(TRUE); 2435 2436 /* 2437 * Run the appropriate command. 2438 */ 2439 for (i = 0; i < NCOMMAND; i++) { 2440 if (command_table[i].name == NULL) 2441 continue; 2442 2443 if (strcmp(cmdname, command_table[i].name) == 0) { 2444 current_command = &command_table[i]; 2445 ret = command_table[i].func(argc - 1, argv + 1); 2446 break; 2447 } 2448 } 2449 2450 /* 2451 * 'freeze' is a vile debugging abomination, so we treat it as such. 2452 */ 2453 if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 2454 char buf[8192]; 2455 int fd = open("/dev/zpoolctl", O_RDWR); 2456 (void) strcpy((void *)buf, argv[2]); 2457 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 2458 } 2459 2460 if (i == NCOMMAND) { 2461 (void) fprintf(stderr, gettext("unrecognized " 2462 "command '%s'\n"), cmdname); 2463 usage(FALSE); 2464 } 2465 2466 /* 2467 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 2468 * for the purposes of running ::findleaks. 2469 */ 2470 if (getenv("ZFS_ABORT") != NULL) { 2471 (void) printf("dumping core by request\n"); 2472 abort(); 2473 } 2474 2475 return (ret); 2476 } 2477