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