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