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]\n" 171 "\timport [-d dir] [-f] [-o opts] [-R root] -a\n" 172 "\timport [-d dir] [-f] [-o opts] [-R root ] <pool | id> " 173 "[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\n", health); 853 854 switch (reason) { 855 case ZPOOL_STATUS_MISSING_DEV_R: 856 case ZPOOL_STATUS_MISSING_DEV_NR: 857 case ZPOOL_STATUS_BAD_GUID_SUM: 858 (void) printf(gettext("status: One or more devices are missing " 859 "from the system.\n")); 860 break; 861 862 case ZPOOL_STATUS_CORRUPT_LABEL_R: 863 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 864 (void) printf(gettext("status: One or more devices contains " 865 "corrupted data.\n")); 866 break; 867 868 case ZPOOL_STATUS_CORRUPT_DATA: 869 (void) printf(gettext("status: The pool data is corrupted.\n")); 870 break; 871 872 case ZPOOL_STATUS_OFFLINE_DEV: 873 (void) printf(gettext("status: One or more devices " 874 "are offlined.\n")); 875 break; 876 877 case ZPOOL_STATUS_CORRUPT_POOL: 878 (void) printf(gettext("status: The pool metadata is " 879 "corrupted.\n")); 880 break; 881 882 default: 883 /* 884 * No other status can be seen when importing pools. 885 */ 886 assert(reason == ZPOOL_STATUS_OK); 887 } 888 889 /* 890 * Print out an action according to the overall state of the pool. 891 */ 892 if (strcmp(health, gettext("ONLINE")) == 0) { 893 (void) printf(gettext("action: The pool can be imported" 894 " using its name or numeric identifier.")); 895 if (pool_state != POOL_STATE_EXPORTED) 896 (void) printf(gettext(" The\n\tpool may be active on " 897 "on another system, but can be imported using\n\t" 898 "the '-f' flag.\n")); 899 else 900 (void) printf("\n"); 901 } else if (strcmp(health, gettext("DEGRADED")) == 0) { 902 (void) printf(gettext("action: The pool can be imported " 903 "despite missing or damaged devices. The\n\tfault " 904 "tolerance of the pool may be compromised if imported.")); 905 if (pool_state != POOL_STATE_EXPORTED) 906 (void) printf(gettext(" The\n\tpool may be active on " 907 "on another system, but can be imported using\n\t" 908 "the '-f' flag.\n")); 909 else 910 (void) printf("\n"); 911 } else { 912 if (reason == ZPOOL_STATUS_MISSING_DEV_R || 913 reason == ZPOOL_STATUS_MISSING_DEV_NR || 914 reason == ZPOOL_STATUS_BAD_GUID_SUM) 915 (void) printf(gettext("action: The pool cannot be " 916 "imported. Attach the missing\n\tdevices and try " 917 "again.\n")); 918 else 919 (void) printf(gettext("action: The pool cannot be " 920 "imported due to damaged devices or data.\n")); 921 } 922 923 if (msgid != NULL) 924 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 925 msgid); 926 927 (void) printf(gettext("config:\n\n")); 928 929 namewidth = max_width(NULL, nvroot, 0, 0); 930 if (namewidth < 10) 931 namewidth = 10; 932 print_import_config(name, nvroot, namewidth, 0); 933 934 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 935 (void) printf("\n\tAdditional devices are known to " 936 "be part of this pool, though their\n\texact " 937 "configuration cannot be determined.\n"); 938 } 939 } 940 941 /* 942 * Perform the import for the given configuration. This passes the heavy 943 * lifting off to zpool_import(), and then mounts the datasets contained within 944 * the pool. 945 */ 946 static int 947 do_import(nvlist_t *config, const char *newname, const char *mntopts, 948 const char *altroot, int force) 949 { 950 zpool_handle_t *zhp; 951 char *name; 952 uint64_t state; 953 954 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 955 &name) == 0); 956 957 verify(nvlist_lookup_uint64(config, 958 ZPOOL_CONFIG_POOL_STATE, &state) == 0); 959 if (state != POOL_STATE_EXPORTED && !force) { 960 (void) fprintf(stderr, gettext("cannot import '%s': pool " 961 "may be in use from other system\n"), name); 962 (void) fprintf(stderr, gettext("use '-f' to import anyway\n")); 963 return (1); 964 } 965 966 if (zpool_import(config, newname, altroot) != 0) 967 return (1); 968 969 if (newname != NULL) 970 name = (char *)newname; 971 972 verify((zhp = zpool_open(name)) != NULL); 973 974 if (mount_share_datasets(zhp, mntopts) != 0) { 975 zpool_close(zhp); 976 return (1); 977 } 978 979 zpool_close(zhp); 980 return (0); 981 } 982 983 /* 984 * zpool import [-d dir] 985 * import [-R root] [-d dir] [-f] -a 986 * import [-R root] [-d dir] [-f] <pool | id> [newpool] 987 * 988 * -d Scan in a specific directory, other than /dev/dsk. More than 989 * one directory can be specified using multiple '-d' options. 990 * 991 * -R Temporarily import the pool, with all mountpoints relative to 992 * the given root. The pool will remain exported when the machine 993 * is rebooted. 994 * 995 * -f Force import, even if it appears that the pool is active. 996 * 997 * -a Import all pools found. 998 * 999 * The import command scans for pools to import, and import pools based on pool 1000 * name and GUID. The pool can also be renamed as part of the import process. 1001 */ 1002 int 1003 zpool_do_import(int argc, char **argv) 1004 { 1005 char **searchdirs = NULL; 1006 int nsearch = 0; 1007 int c; 1008 int err; 1009 nvlist_t *pools; 1010 int do_all = FALSE; 1011 char *altroot = NULL; 1012 char *mntopts = NULL; 1013 int do_force = FALSE; 1014 nvpair_t *elem; 1015 nvlist_t *config; 1016 uint64_t searchguid; 1017 char *searchname; 1018 nvlist_t *found_config; 1019 int first; 1020 1021 /* check options */ 1022 while ((c = getopt(argc, argv, ":fd:R:ao:")) != -1) { 1023 switch (c) { 1024 case 'a': 1025 do_all = TRUE; 1026 break; 1027 case 'd': 1028 if (searchdirs == NULL) { 1029 searchdirs = safe_malloc(sizeof (char *)); 1030 } else { 1031 char **tmp = safe_malloc((nsearch + 1) * 1032 sizeof (char *)); 1033 bcopy(searchdirs, tmp, nsearch * 1034 sizeof (char *)); 1035 free(searchdirs); 1036 searchdirs = tmp; 1037 } 1038 searchdirs[nsearch++] = optarg; 1039 break; 1040 case 'f': 1041 do_force = TRUE; 1042 break; 1043 case 'o': 1044 mntopts = optarg; 1045 break; 1046 case 'R': 1047 altroot = optarg; 1048 break; 1049 case ':': 1050 (void) fprintf(stderr, gettext("missing argument for " 1051 "'%c' option\n"), optopt); 1052 usage(FALSE); 1053 break; 1054 case '?': 1055 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1056 optopt); 1057 usage(FALSE); 1058 } 1059 } 1060 1061 argc -= optind; 1062 argv += optind; 1063 1064 if (searchdirs == NULL) { 1065 searchdirs = safe_malloc(sizeof (char *)); 1066 searchdirs[0] = "/dev/dsk"; 1067 nsearch = 1; 1068 } 1069 1070 /* check argument count */ 1071 if (do_all) { 1072 if (argc != 0) { 1073 (void) fprintf(stderr, gettext("too many arguments\n")); 1074 usage(FALSE); 1075 } 1076 } else { 1077 if (argc > 2) { 1078 (void) fprintf(stderr, gettext("too many arguments\n")); 1079 usage(FALSE); 1080 } 1081 1082 /* 1083 * Check for the SYS_CONFIG privilege. We do this explicitly 1084 * here because otherwise any attempt to discover pools will 1085 * silently fail. 1086 */ 1087 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 1088 (void) fprintf(stderr, gettext("cannot " 1089 "discover pools: permission denied\n")); 1090 return (1); 1091 } 1092 } 1093 1094 if ((pools = zpool_find_import(nsearch, searchdirs)) == NULL) 1095 return (1); 1096 1097 /* 1098 * We now have a list of all available pools in the given directories. 1099 * Depending on the arguments given, we do one of the following: 1100 * 1101 * <none> Iterate through all pools and display information about 1102 * each one. 1103 * 1104 * -a Iterate through all pools and try to import each one. 1105 * 1106 * <id> Find the pool that corresponds to the given GUID/pool 1107 * name and import that one. 1108 */ 1109 if (argc != 0) { 1110 char *endptr; 1111 1112 errno = 0; 1113 searchguid = strtoull(argv[0], &endptr, 10); 1114 if (errno != 0 || *endptr != '\0') 1115 searchname = argv[0]; 1116 else 1117 searchname = NULL; 1118 found_config = NULL; 1119 } 1120 1121 err = 0; 1122 elem = NULL; 1123 first = TRUE; 1124 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 1125 1126 verify(nvpair_value_nvlist(elem, &config) == 0); 1127 1128 if (argc == 0) { 1129 if (first) 1130 first = FALSE; 1131 else 1132 (void) printf("\n"); 1133 1134 if (do_all) 1135 err |= do_import(config, NULL, mntopts, 1136 altroot, do_force); 1137 else 1138 show_import(config); 1139 } else if (searchname != NULL) { 1140 char *name; 1141 1142 /* 1143 * We are searching for a pool based on name. 1144 */ 1145 verify(nvlist_lookup_string(config, 1146 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 1147 1148 if (strcmp(name, searchname) == 0) { 1149 if (found_config != NULL) { 1150 (void) fprintf(stderr, gettext( 1151 "cannot import '%s': more than " 1152 "one matching pool\n"), searchname); 1153 (void) fprintf(stderr, gettext( 1154 "import by numeric ID instead\n")); 1155 err = TRUE; 1156 } 1157 found_config = config; 1158 } 1159 } else { 1160 uint64_t guid; 1161 1162 /* 1163 * Search for a pool by guid. 1164 */ 1165 verify(nvlist_lookup_uint64(config, 1166 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 1167 1168 if (guid == searchguid) 1169 found_config = config; 1170 } 1171 } 1172 1173 /* 1174 * If we were searching for a specific pool, verify that we found a 1175 * pool, and then do the import. 1176 */ 1177 if (argc != 0 && err == 0) { 1178 if (found_config == NULL) { 1179 (void) fprintf(stderr, gettext("cannot import '%s': " 1180 "no such pool available\n"), argv[0]); 1181 err = TRUE; 1182 } else { 1183 err |= do_import(found_config, argc == 1 ? NULL : 1184 argv[1], mntopts, altroot, do_force); 1185 } 1186 } 1187 1188 /* 1189 * If we were just looking for pools, report an error if none were 1190 * found. 1191 */ 1192 if (argc == 0 && first) 1193 (void) fprintf(stderr, 1194 gettext("no pools available to import\n")); 1195 1196 nvlist_free(pools); 1197 1198 return (err ? 1 : 0); 1199 } 1200 1201 typedef struct iostat_cbdata { 1202 zpool_list_t *cb_list; 1203 int cb_verbose; 1204 int cb_iteration; 1205 int cb_namewidth; 1206 } iostat_cbdata_t; 1207 1208 static void 1209 print_iostat_separator(iostat_cbdata_t *cb) 1210 { 1211 int i = 0; 1212 1213 for (i = 0; i < cb->cb_namewidth; i++) 1214 (void) printf("-"); 1215 (void) printf(" ----- ----- ----- ----- ----- -----\n"); 1216 } 1217 1218 static void 1219 print_iostat_header(iostat_cbdata_t *cb) 1220 { 1221 (void) printf("%*s capacity operations bandwidth\n", 1222 cb->cb_namewidth, ""); 1223 (void) printf("%-*s used avail read write read write\n", 1224 cb->cb_namewidth, "pool"); 1225 print_iostat_separator(cb); 1226 } 1227 1228 /* 1229 * Display a single statistic. 1230 */ 1231 void 1232 print_one_stat(uint64_t value) 1233 { 1234 char buf[64]; 1235 1236 zfs_nicenum(value, buf, sizeof (buf)); 1237 (void) printf(" %5s", buf); 1238 } 1239 1240 /* 1241 * Print out all the statistics for the given vdev. This can either be the 1242 * toplevel configuration, or called recursively. If 'name' is NULL, then this 1243 * is a verbose output, and we don't want to display the toplevel pool stats. 1244 */ 1245 void 1246 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 1247 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 1248 { 1249 nvlist_t **oldchild, **newchild; 1250 uint_t c, children; 1251 vdev_stat_t *oldvs, *newvs; 1252 vdev_stat_t zerovs = { 0 }; 1253 uint64_t tdelta; 1254 double scale; 1255 char *vname; 1256 1257 if (oldnv != NULL) { 1258 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS, 1259 (uint64_t **)&oldvs, &c) == 0); 1260 } else { 1261 oldvs = &zerovs; 1262 } 1263 1264 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS, 1265 (uint64_t **)&newvs, &c) == 0); 1266 1267 if (strlen(name) + depth > cb->cb_namewidth) 1268 (void) printf("%*s%s", depth, "", name); 1269 else 1270 (void) printf("%*s%s%*s", depth, "", name, 1271 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 1272 1273 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 1274 1275 if (tdelta == 0) 1276 scale = 1.0; 1277 else 1278 scale = (double)NANOSEC / tdelta; 1279 1280 /* only toplevel vdevs have capacity stats */ 1281 if (newvs->vs_space == 0) { 1282 (void) printf(" - -"); 1283 } else { 1284 print_one_stat(newvs->vs_alloc); 1285 print_one_stat(newvs->vs_space - newvs->vs_alloc); 1286 } 1287 1288 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 1289 oldvs->vs_ops[ZIO_TYPE_READ]))); 1290 1291 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 1292 oldvs->vs_ops[ZIO_TYPE_WRITE]))); 1293 1294 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 1295 oldvs->vs_bytes[ZIO_TYPE_READ]))); 1296 1297 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 1298 oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 1299 1300 (void) printf("\n"); 1301 1302 if (!cb->cb_verbose) 1303 return; 1304 1305 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 1306 &newchild, &children) != 0) 1307 return; 1308 1309 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 1310 &oldchild, &c) != 0) 1311 return; 1312 1313 for (c = 0; c < children; c++) { 1314 vname = zpool_vdev_name(zhp, newchild[c]); 1315 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 1316 newchild[c], cb, depth + 2); 1317 free(vname); 1318 } 1319 } 1320 1321 static int 1322 refresh_iostat(zpool_handle_t *zhp, void *data) 1323 { 1324 iostat_cbdata_t *cb = data; 1325 1326 /* 1327 * If the pool has disappeared, remove it from the list and continue. 1328 */ 1329 if (zpool_refresh_stats(zhp) != 0) 1330 pool_list_remove(cb->cb_list, zhp); 1331 1332 return (0); 1333 } 1334 1335 /* 1336 * Callback to print out the iostats for the given pool. 1337 */ 1338 int 1339 print_iostat(zpool_handle_t *zhp, void *data) 1340 { 1341 iostat_cbdata_t *cb = data; 1342 nvlist_t *oldconfig, *newconfig; 1343 nvlist_t *oldnvroot, *newnvroot; 1344 1345 newconfig = zpool_get_config(zhp, &oldconfig); 1346 1347 if (cb->cb_iteration == 1) 1348 oldconfig = NULL; 1349 1350 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 1351 &newnvroot) == 0); 1352 1353 if (oldconfig == NULL) 1354 oldnvroot = NULL; 1355 else 1356 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 1357 &oldnvroot) == 0); 1358 1359 /* 1360 * Print out the statistics for the pool. 1361 */ 1362 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 1363 1364 if (cb->cb_verbose) 1365 print_iostat_separator(cb); 1366 1367 return (0); 1368 } 1369 1370 int 1371 get_namewidth(zpool_handle_t *zhp, void *data) 1372 { 1373 iostat_cbdata_t *cb = data; 1374 nvlist_t *config, *nvroot; 1375 1376 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 1377 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1378 &nvroot) == 0); 1379 if (!cb->cb_verbose) 1380 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 1381 else 1382 cb->cb_namewidth = max_width(zhp, nvroot, 0, 0); 1383 } 1384 1385 /* 1386 * The width must fall into the range [10,38]. The upper limit is the 1387 * maximum we can have and still fit in 80 columns. 1388 */ 1389 if (cb->cb_namewidth < 10) 1390 cb->cb_namewidth = 10; 1391 if (cb->cb_namewidth > 38) 1392 cb->cb_namewidth = 38; 1393 1394 return (0); 1395 } 1396 1397 /* 1398 * zpool iostat [-v] [pool] ... [interval [count]] 1399 * 1400 * -v Display statistics for individual vdevs 1401 * 1402 * This command can be tricky because we want to be able to deal with pool 1403 * creation/destruction as well as vdev configuration changes. The bulk of this 1404 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 1405 * on pool_list_update() to detect the addition of new pools. Configuration 1406 * changes are all handled within libzfs. 1407 */ 1408 int 1409 zpool_do_iostat(int argc, char **argv) 1410 { 1411 int c; 1412 int ret; 1413 int npools; 1414 unsigned long interval = 0, count = 0; 1415 zpool_list_t *list; 1416 int verbose = FALSE; 1417 iostat_cbdata_t cb; 1418 1419 /* check options */ 1420 while ((c = getopt(argc, argv, "v")) != -1) { 1421 switch (c) { 1422 case 'v': 1423 verbose = TRUE; 1424 break; 1425 case '?': 1426 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1427 optopt); 1428 usage(FALSE); 1429 } 1430 } 1431 1432 argc -= optind; 1433 argv += optind; 1434 1435 /* 1436 * Determine if the last argument is an integer or a pool name 1437 */ 1438 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1439 char *end; 1440 1441 errno = 0; 1442 interval = strtoul(argv[argc - 1], &end, 10); 1443 1444 if (*end == '\0' && errno == 0) { 1445 if (interval == 0) { 1446 (void) fprintf(stderr, gettext("interval " 1447 "cannot be zero\n")); 1448 usage(FALSE); 1449 } 1450 1451 /* 1452 * Ignore the last parameter 1453 */ 1454 argc--; 1455 } else { 1456 /* 1457 * If this is not a valid number, just plow on. The 1458 * user will get a more informative error message later 1459 * on. 1460 */ 1461 interval = 0; 1462 } 1463 } 1464 1465 /* 1466 * If the last argument is also an integer, then we have both a count 1467 * and an integer. 1468 */ 1469 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1470 char *end; 1471 1472 errno = 0; 1473 count = interval; 1474 interval = strtoul(argv[argc - 1], &end, 10); 1475 1476 if (*end == '\0' && errno == 0) { 1477 if (interval == 0) { 1478 (void) fprintf(stderr, gettext("interval " 1479 "cannot be zero\n")); 1480 usage(FALSE); 1481 } 1482 1483 /* 1484 * Ignore the last parameter 1485 */ 1486 argc--; 1487 } else { 1488 interval = 0; 1489 } 1490 } 1491 1492 /* 1493 * Construct the list of all interesting pools. 1494 */ 1495 ret = 0; 1496 if ((list = pool_list_get(argc, argv, &ret)) == NULL) 1497 return (1); 1498 1499 if (pool_list_count(list) == 0 && argc != 0) 1500 return (1); 1501 1502 if (pool_list_count(list) == 0 && interval == 0) { 1503 (void) fprintf(stderr, gettext("no pools available\n")); 1504 return (1); 1505 } 1506 1507 /* 1508 * Enter the main iostat loop. 1509 */ 1510 cb.cb_list = list; 1511 cb.cb_verbose = verbose; 1512 cb.cb_iteration = 0; 1513 cb.cb_namewidth = 0; 1514 1515 for (;;) { 1516 pool_list_update(list); 1517 1518 if ((npools = pool_list_count(list)) == 0) 1519 break; 1520 1521 /* 1522 * Refresh all statistics. This is done as an explicit step 1523 * before calculating the maximum name width, so that any 1524 * configuration changes are properly accounted for. 1525 */ 1526 (void) pool_list_iter(list, FALSE, refresh_iostat, &cb); 1527 1528 /* 1529 * Iterate over all pools to determine the maximum width 1530 * for the pool / device name column across all pools. 1531 */ 1532 cb.cb_namewidth = 0; 1533 (void) pool_list_iter(list, FALSE, get_namewidth, &cb); 1534 1535 /* 1536 * If it's the first time, or verbose mode, print the header. 1537 */ 1538 if (++cb.cb_iteration == 1 || verbose) 1539 print_iostat_header(&cb); 1540 1541 (void) pool_list_iter(list, FALSE, print_iostat, &cb); 1542 1543 /* 1544 * If there's more than one pool, and we're not in verbose mode 1545 * (which prints a separator for us), then print a separator. 1546 */ 1547 if (npools > 1 && !verbose) 1548 print_iostat_separator(&cb); 1549 1550 if (verbose) 1551 (void) printf("\n"); 1552 1553 if (interval == 0) 1554 break; 1555 1556 if (count != 0 && --count == 0) 1557 break; 1558 1559 (void) sleep(interval); 1560 } 1561 1562 pool_list_free(list); 1563 1564 return (ret); 1565 } 1566 1567 typedef struct list_cbdata { 1568 int cb_scripted; 1569 int cb_first; 1570 int cb_fields[MAX_FIELDS]; 1571 int cb_fieldcount; 1572 } list_cbdata_t; 1573 1574 /* 1575 * Given a list of columns to display, output appropriate headers for each one. 1576 */ 1577 void 1578 print_header(int *fields, size_t count) 1579 { 1580 int i; 1581 column_def_t *col; 1582 const char *fmt; 1583 1584 for (i = 0; i < count; i++) { 1585 col = &column_table[fields[i]]; 1586 if (i != 0) 1587 (void) printf(" "); 1588 if (col->cd_justify == left_justify) 1589 fmt = "%-*s"; 1590 else 1591 fmt = "%*s"; 1592 1593 (void) printf(fmt, i == count - 1 ? strlen(col->cd_title) : 1594 col->cd_width, col->cd_title); 1595 } 1596 1597 (void) printf("\n"); 1598 } 1599 1600 int 1601 list_callback(zpool_handle_t *zhp, void *data) 1602 { 1603 list_cbdata_t *cbp = data; 1604 nvlist_t *config; 1605 int i; 1606 char buf[ZPOOL_MAXNAMELEN]; 1607 uint64_t total; 1608 uint64_t used; 1609 const char *fmt; 1610 column_def_t *col; 1611 1612 if (cbp->cb_first) { 1613 if (!cbp->cb_scripted) 1614 print_header(cbp->cb_fields, cbp->cb_fieldcount); 1615 cbp->cb_first = FALSE; 1616 } 1617 1618 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 1619 config = NULL; 1620 } else { 1621 config = zpool_get_config(zhp, NULL); 1622 total = zpool_get_space_total(zhp); 1623 used = zpool_get_space_used(zhp); 1624 } 1625 1626 for (i = 0; i < cbp->cb_fieldcount; i++) { 1627 if (i != 0) { 1628 if (cbp->cb_scripted) 1629 (void) printf("\t"); 1630 else 1631 (void) printf(" "); 1632 } 1633 1634 col = &column_table[cbp->cb_fields[i]]; 1635 1636 switch (cbp->cb_fields[i]) { 1637 case ZPOOL_FIELD_NAME: 1638 (void) strlcpy(buf, zpool_get_name(zhp), sizeof (buf)); 1639 break; 1640 1641 case ZPOOL_FIELD_SIZE: 1642 if (config == NULL) 1643 (void) strlcpy(buf, "-", sizeof (buf)); 1644 else 1645 zfs_nicenum(total, buf, sizeof (buf)); 1646 break; 1647 1648 case ZPOOL_FIELD_USED: 1649 if (config == NULL) 1650 (void) strlcpy(buf, "-", sizeof (buf)); 1651 else 1652 zfs_nicenum(used, buf, sizeof (buf)); 1653 break; 1654 1655 case ZPOOL_FIELD_AVAILABLE: 1656 if (config == NULL) 1657 (void) strlcpy(buf, "-", sizeof (buf)); 1658 else 1659 zfs_nicenum(total - used, buf, sizeof (buf)); 1660 break; 1661 1662 case ZPOOL_FIELD_CAPACITY: 1663 if (config == NULL) { 1664 (void) strlcpy(buf, "-", sizeof (buf)); 1665 } else { 1666 uint64_t capacity = (total == 0 ? 0 : 1667 (used * 100 / total)); 1668 (void) snprintf(buf, sizeof (buf), "%llu%%", 1669 capacity); 1670 } 1671 break; 1672 1673 case ZPOOL_FIELD_HEALTH: 1674 if (config == NULL) { 1675 (void) strlcpy(buf, "FAULTED", sizeof (buf)); 1676 } else { 1677 nvlist_t *nvroot; 1678 vdev_stat_t *vs; 1679 uint_t vsc; 1680 1681 verify(nvlist_lookup_nvlist(config, 1682 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 1683 verify(nvlist_lookup_uint64_array(nvroot, 1684 ZPOOL_CONFIG_STATS, (uint64_t **)&vs, 1685 &vsc) == 0); 1686 (void) strlcpy(buf, state_to_name(vs), 1687 sizeof (buf)); 1688 } 1689 break; 1690 1691 case ZPOOL_FIELD_ROOT: 1692 if (config == NULL) 1693 (void) strlcpy(buf, "-", sizeof (buf)); 1694 else if (zpool_get_root(zhp, buf, sizeof (buf)) != 0) 1695 (void) strlcpy(buf, "-", sizeof (buf)); 1696 break; 1697 } 1698 1699 if (cbp->cb_scripted) 1700 (void) printf("%s", buf); 1701 else { 1702 if (col->cd_justify == left_justify) 1703 fmt = "%-*s"; 1704 else 1705 fmt = "%*s"; 1706 1707 (void) printf(fmt, i == cbp->cb_fieldcount - 1 ? 1708 strlen(buf) : col->cd_width, buf); 1709 } 1710 } 1711 1712 (void) printf("\n"); 1713 1714 return (0); 1715 } 1716 1717 /* 1718 * zpool list [-H] [-o field[,field]*] [pool] ... 1719 * 1720 * -H Scripted mode. Don't display headers, and separate fields by 1721 * a single tab. 1722 * -o List of fields to display. Defaults to all fields, or 1723 * "name,size,used,available,capacity,health,root" 1724 * 1725 * List all pools in the system, whether or not they're healthy. Output space 1726 * statistics for each one, as well as health status summary. 1727 */ 1728 int 1729 zpool_do_list(int argc, char **argv) 1730 { 1731 int c; 1732 int ret; 1733 list_cbdata_t cb = { 0 }; 1734 static char default_fields[] = 1735 "name,size,used,available,capacity,health,root"; 1736 char *fields = default_fields; 1737 char *value; 1738 1739 /* check options */ 1740 while ((c = getopt(argc, argv, ":Ho:")) != -1) { 1741 switch (c) { 1742 case 'H': 1743 cb.cb_scripted = TRUE; 1744 break; 1745 case 'o': 1746 fields = optarg; 1747 break; 1748 case ':': 1749 (void) fprintf(stderr, gettext("missing argument for " 1750 "'%c' option\n"), optopt); 1751 usage(FALSE); 1752 break; 1753 case '?': 1754 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1755 optopt); 1756 usage(FALSE); 1757 } 1758 } 1759 1760 argc -= optind; 1761 argv += optind; 1762 1763 while (*fields != '\0') { 1764 if (cb.cb_fieldcount == MAX_FIELDS) { 1765 (void) fprintf(stderr, gettext("too many " 1766 "properties given to -o option\n")); 1767 usage(FALSE); 1768 } 1769 1770 if ((cb.cb_fields[cb.cb_fieldcount] = getsubopt(&fields, 1771 column_subopts, &value)) == -1) { 1772 (void) fprintf(stderr, gettext("invalid property " 1773 "'%s'\n"), value); 1774 usage(FALSE); 1775 } 1776 1777 cb.cb_fieldcount++; 1778 } 1779 1780 1781 cb.cb_first = TRUE; 1782 1783 ret = for_each_pool(argc, argv, TRUE, list_callback, &cb); 1784 1785 if (argc == 0 && cb.cb_first) { 1786 (void) printf(gettext("no pools available\n")); 1787 return (0); 1788 } 1789 1790 return (ret); 1791 } 1792 1793 static nvlist_t * 1794 zpool_get_vdev_by_name(nvlist_t *nv, char *name) 1795 { 1796 nvlist_t **child; 1797 uint_t c, children; 1798 nvlist_t *match; 1799 char *path; 1800 1801 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1802 &child, &children) != 0) { 1803 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1804 if (strncmp(name, "/dev/dsk/", 9) == 0) 1805 name += 9; 1806 if (strncmp(path, "/dev/dsk/", 9) == 0) 1807 path += 9; 1808 if (strcmp(name, path) == 0) 1809 return (nv); 1810 return (NULL); 1811 } 1812 1813 for (c = 0; c < children; c++) 1814 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 1815 return (match); 1816 1817 return (NULL); 1818 } 1819 1820 static int 1821 zpool_do_attach_or_replace(int argc, char **argv, int replacing) 1822 { 1823 int force = FALSE; 1824 int c; 1825 nvlist_t *nvroot; 1826 char *poolname, *old_disk, *new_disk; 1827 zpool_handle_t *zhp; 1828 nvlist_t *config; 1829 1830 /* check options */ 1831 while ((c = getopt(argc, argv, "f")) != -1) { 1832 switch (c) { 1833 case 'f': 1834 force = TRUE; 1835 break; 1836 case '?': 1837 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1838 optopt); 1839 usage(FALSE); 1840 } 1841 } 1842 1843 argc -= optind; 1844 argv += optind; 1845 1846 /* get pool name and check number of arguments */ 1847 if (argc < 1) { 1848 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1849 usage(FALSE); 1850 } 1851 1852 poolname = argv[0]; 1853 1854 if (argc < 2) { 1855 (void) fprintf(stderr, 1856 gettext("missing <device> specification\n")); 1857 usage(FALSE); 1858 } 1859 1860 old_disk = argv[1]; 1861 1862 if (argc < 3) { 1863 if (!replacing) { 1864 (void) fprintf(stderr, 1865 gettext("missing <new_device> specification\n")); 1866 usage(FALSE); 1867 } 1868 new_disk = old_disk; 1869 argc -= 1; 1870 argv += 1; 1871 } else { 1872 new_disk = argv[2]; 1873 argc -= 2; 1874 argv += 2; 1875 } 1876 1877 if (argc > 1) { 1878 (void) fprintf(stderr, gettext("too many arguments\n")); 1879 usage(FALSE); 1880 } 1881 1882 if ((zhp = zpool_open(poolname)) == NULL) 1883 return (1); 1884 1885 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 1886 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 1887 poolname); 1888 zpool_close(zhp); 1889 return (1); 1890 } 1891 1892 nvroot = make_root_vdev(config, force, B_FALSE, argc, argv); 1893 if (nvroot == NULL) { 1894 zpool_close(zhp); 1895 return (1); 1896 } 1897 1898 return (zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing)); 1899 } 1900 1901 /* 1902 * zpool replace [-f] <pool> <device> <new_device> 1903 * 1904 * -f Force attach, even if <new_device> appears to be in use. 1905 * 1906 * Replace <device> with <new_device>. 1907 */ 1908 /* ARGSUSED */ 1909 int 1910 zpool_do_replace(int argc, char **argv) 1911 { 1912 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 1913 } 1914 1915 /* 1916 * zpool attach [-f] <pool> <device> <new_device> 1917 * 1918 * -f Force attach, even if <new_device> appears to be in use. 1919 * 1920 * Attach <new_device> to the mirror containing <device>. If <device> is not 1921 * part of a mirror, then <device> will be transformed into a mirror of 1922 * <device> and <new_device>. In either case, <new_device> will begin life 1923 * with a DTL of [0, now], and will immediately begin to resilver itself. 1924 */ 1925 int 1926 zpool_do_attach(int argc, char **argv) 1927 { 1928 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 1929 } 1930 1931 /* 1932 * zpool detach [-f] <pool> <device> 1933 * 1934 * -f Force detach of <device>, even if DTLs argue against it 1935 * (not supported yet) 1936 * 1937 * Detach a device from a mirror. The operation will be refused if <device> 1938 * is the last device in the mirror, or if the DTLs indicate that this device 1939 * has the only valid copy of some data. 1940 */ 1941 /* ARGSUSED */ 1942 int 1943 zpool_do_detach(int argc, char **argv) 1944 { 1945 int c; 1946 char *poolname, *path; 1947 zpool_handle_t *zhp; 1948 1949 /* check options */ 1950 while ((c = getopt(argc, argv, "f")) != -1) { 1951 switch (c) { 1952 case 'f': 1953 case '?': 1954 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1955 optopt); 1956 usage(FALSE); 1957 } 1958 } 1959 1960 argc -= optind; 1961 argv += optind; 1962 1963 /* get pool name and check number of arguments */ 1964 if (argc < 1) { 1965 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1966 usage(FALSE); 1967 } 1968 1969 if (argc < 2) { 1970 (void) fprintf(stderr, 1971 gettext("missing <device> specification\n")); 1972 usage(FALSE); 1973 } 1974 1975 poolname = argv[0]; 1976 path = argv[1]; 1977 1978 if ((zhp = zpool_open(poolname)) == NULL) 1979 return (1); 1980 1981 return (zpool_vdev_detach(zhp, path)); 1982 } 1983 1984 /* 1985 * zpool online <pool> <device> ... 1986 */ 1987 /* ARGSUSED */ 1988 int 1989 zpool_do_online(int argc, char **argv) 1990 { 1991 int c, i; 1992 char *poolname; 1993 zpool_handle_t *zhp; 1994 int ret = 0; 1995 1996 /* check options */ 1997 while ((c = getopt(argc, argv, "t")) != -1) { 1998 switch (c) { 1999 case 't': 2000 case '?': 2001 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2002 optopt); 2003 usage(FALSE); 2004 } 2005 } 2006 2007 argc -= optind; 2008 argv += optind; 2009 2010 /* get pool name and check number of arguments */ 2011 if (argc < 1) { 2012 (void) fprintf(stderr, gettext("missing pool name\n")); 2013 usage(FALSE); 2014 } 2015 if (argc < 2) { 2016 (void) fprintf(stderr, gettext("missing device name\n")); 2017 usage(FALSE); 2018 } 2019 2020 poolname = argv[0]; 2021 2022 if ((zhp = zpool_open(poolname)) == NULL) 2023 return (1); 2024 2025 for (i = 1; i < argc; i++) 2026 if (zpool_vdev_online(zhp, argv[i]) == 0) 2027 (void) printf(gettext("Bringing device %s online\n"), 2028 argv[i]); 2029 else 2030 ret = 1; 2031 2032 return (ret); 2033 } 2034 2035 /* 2036 * zpool offline [-ft] <pool> <device> ... 2037 * 2038 * -f Force the device into the offline state, even if doing 2039 * so would appear to compromise pool availability. 2040 * (not supported yet) 2041 * 2042 * -t Only take the device off-line temporarily. The offline 2043 * state will not be persistent across reboots. 2044 */ 2045 /* ARGSUSED */ 2046 int 2047 zpool_do_offline(int argc, char **argv) 2048 { 2049 int c, i; 2050 char *poolname; 2051 zpool_handle_t *zhp; 2052 int ret = 0, istmp = FALSE; 2053 2054 /* check options */ 2055 while ((c = getopt(argc, argv, "ft")) != -1) { 2056 switch (c) { 2057 case 't': 2058 istmp = TRUE; 2059 break; 2060 case 'f': 2061 case '?': 2062 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2063 optopt); 2064 usage(FALSE); 2065 } 2066 } 2067 2068 argc -= optind; 2069 argv += optind; 2070 2071 /* get pool name and check number of arguments */ 2072 if (argc < 1) { 2073 (void) fprintf(stderr, gettext("missing pool name\n")); 2074 usage(FALSE); 2075 } 2076 if (argc < 2) { 2077 (void) fprintf(stderr, gettext("missing device name\n")); 2078 usage(FALSE); 2079 } 2080 2081 poolname = argv[0]; 2082 2083 if ((zhp = zpool_open(poolname)) == NULL) 2084 return (1); 2085 2086 for (i = 1; i < argc; i++) 2087 if (zpool_vdev_offline(zhp, argv[i], istmp) == 0) 2088 (void) printf(gettext("Bringing device %s offline\n"), 2089 argv[i]); 2090 else 2091 ret = 1; 2092 2093 return (ret); 2094 } 2095 2096 /* 2097 * zpool clear <pool> [device] 2098 * 2099 * Clear all errors associated with a pool or a particular device. 2100 */ 2101 int 2102 zpool_do_clear(int argc, char **argv) 2103 { 2104 int ret = 0; 2105 zpool_handle_t *zhp; 2106 char *pool, *device; 2107 2108 if (argc < 2) { 2109 (void) fprintf(stderr, gettext("missing pool name\n")); 2110 usage(FALSE); 2111 } 2112 2113 if (argc > 3) { 2114 (void) fprintf(stderr, gettext("too many arguments\n")); 2115 usage(FALSE); 2116 } 2117 2118 pool = argv[1]; 2119 device = argc == 3 ? argv[2] : NULL; 2120 2121 if ((zhp = zpool_open(pool)) == NULL) 2122 return (1); 2123 2124 if (zpool_clear(zhp, device) != 0) 2125 ret = 1; 2126 2127 zpool_close(zhp); 2128 2129 return (ret); 2130 } 2131 2132 typedef struct scrub_cbdata { 2133 int cb_type; 2134 } scrub_cbdata_t; 2135 2136 int 2137 scrub_callback(zpool_handle_t *zhp, void *data) 2138 { 2139 scrub_cbdata_t *cb = data; 2140 2141 /* 2142 * Ignore faulted pools. 2143 */ 2144 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 2145 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 2146 "currently unavailable\n"), zpool_get_name(zhp)); 2147 return (1); 2148 } 2149 2150 return (zpool_scrub(zhp, cb->cb_type) != 0); 2151 } 2152 2153 /* 2154 * zpool scrub [-s] <pool> ... 2155 * 2156 * -s Stop. Stops any in-progress scrub. 2157 */ 2158 int 2159 zpool_do_scrub(int argc, char **argv) 2160 { 2161 int c; 2162 scrub_cbdata_t cb; 2163 2164 cb.cb_type = POOL_SCRUB_EVERYTHING; 2165 2166 /* check options */ 2167 while ((c = getopt(argc, argv, "s")) != -1) { 2168 switch (c) { 2169 case 's': 2170 cb.cb_type = POOL_SCRUB_NONE; 2171 break; 2172 case '?': 2173 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2174 optopt); 2175 usage(FALSE); 2176 } 2177 } 2178 2179 argc -= optind; 2180 argv += optind; 2181 2182 if (argc < 1) { 2183 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2184 usage(FALSE); 2185 } 2186 2187 return (for_each_pool(argc, argv, TRUE, scrub_callback, &cb)); 2188 } 2189 2190 typedef struct status_cbdata { 2191 int cb_verbose; 2192 int cb_explain; 2193 int cb_count; 2194 int cb_first; 2195 } status_cbdata_t; 2196 2197 /* 2198 * Print out detailed scrub status. 2199 */ 2200 void 2201 print_scrub_status(nvlist_t *nvroot) 2202 { 2203 vdev_stat_t *vs; 2204 uint_t vsc; 2205 time_t start, end, now; 2206 double fraction_done; 2207 uint64_t examined, total, minutes_left; 2208 char *scrub_type; 2209 2210 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 2211 (uint64_t **)&vs, &vsc) == 0); 2212 2213 /* 2214 * If there's never been a scrub, there's not much to say. 2215 */ 2216 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) { 2217 (void) printf(gettext("none requested\n")); 2218 return; 2219 } 2220 2221 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2222 "resilver" : "scrub"; 2223 2224 start = vs->vs_scrub_start; 2225 end = vs->vs_scrub_end; 2226 now = time(NULL); 2227 examined = vs->vs_scrub_examined; 2228 total = vs->vs_alloc; 2229 2230 if (end != 0) { 2231 (void) printf(gettext("%s %s with %llu errors on %s"), 2232 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped", 2233 (u_longlong_t)vs->vs_scrub_errors, ctime(&end)); 2234 return; 2235 } 2236 2237 if (examined == 0) 2238 examined = 1; 2239 if (examined > total) 2240 total = examined; 2241 2242 fraction_done = (double)examined / total; 2243 minutes_left = (uint64_t)((now - start) * 2244 (1 - fraction_done) / fraction_done / 60); 2245 2246 (void) printf(gettext("%s in progress, %.2f%% done, %lluh%um to go\n"), 2247 scrub_type, 100 * fraction_done, 2248 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60)); 2249 } 2250 2251 /* 2252 * Print out configuration state as requested by status_callback. 2253 */ 2254 void 2255 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 2256 int namewidth, int depth) 2257 { 2258 nvlist_t **child; 2259 uint_t c, children; 2260 vdev_stat_t *vs; 2261 char rbuf[6], wbuf[6], cbuf[6], repaired[7]; 2262 char *vname; 2263 uint64_t notpresent; 2264 2265 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 2266 (uint64_t **)&vs, &c) == 0); 2267 2268 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2269 &child, &children) != 0) 2270 children = 0; 2271 2272 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 2273 name, state_to_name(vs)); 2274 2275 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 2276 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 2277 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 2278 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 2279 2280 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 2281 ¬present) == 0) { 2282 char *path; 2283 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2284 (void) printf(" was %s\n", path); 2285 } else if (vs->vs_aux != 0) { 2286 (void) printf(" "); 2287 2288 switch (vs->vs_aux) { 2289 case VDEV_AUX_OPEN_FAILED: 2290 (void) printf(gettext("cannot open")); 2291 break; 2292 2293 case VDEV_AUX_BAD_GUID_SUM: 2294 (void) printf(gettext("missing device")); 2295 break; 2296 2297 case VDEV_AUX_NO_REPLICAS: 2298 (void) printf(gettext("insufficient replicas")); 2299 break; 2300 2301 default: 2302 (void) printf(gettext("corrupted data")); 2303 break; 2304 } 2305 } else if (vs->vs_scrub_repaired != 0 && children == 0) { 2306 /* 2307 * Report bytes resilvered/repaired on leaf devices. 2308 */ 2309 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); 2310 (void) printf(gettext(" %s %s"), repaired, 2311 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2312 "resilvered" : "repaired"); 2313 } 2314 2315 (void) printf("\n"); 2316 2317 for (c = 0; c < children; c++) { 2318 vname = zpool_vdev_name(zhp, child[c]); 2319 print_status_config(zhp, vname, child[c], 2320 namewidth, depth + 2); 2321 free(vname); 2322 } 2323 } 2324 2325 static void 2326 print_error_log(zpool_handle_t *zhp) 2327 { 2328 nvlist_t **log; 2329 size_t nelem; 2330 size_t maxdsname = sizeof ("DATASET") - 1; 2331 size_t maxobjname = sizeof ("OBJECT") - 1; 2332 int i; 2333 nvlist_t *nv; 2334 size_t len; 2335 char *dsname, *objname, *range; 2336 2337 if (zpool_get_errlog(zhp, &log, &nelem) != 0) { 2338 (void) printf("errors: List of errors unavailable " 2339 "(insufficient privileges)\n"); 2340 return; 2341 } 2342 2343 for (i = 0; i < nelem; i++) { 2344 nv = log[i]; 2345 2346 verify(nvlist_lookup_string(nv, ZPOOL_ERR_DATASET, 2347 &dsname) == 0); 2348 len = strlen(dsname); 2349 if (len > maxdsname) 2350 maxdsname = len; 2351 2352 verify(nvlist_lookup_string(nv, ZPOOL_ERR_OBJECT, 2353 &objname) == 0); 2354 len = strlen(objname); 2355 if (len > maxobjname) 2356 maxobjname = len; 2357 } 2358 2359 (void) printf("errors: The following persistent errors have been " 2360 "detected:\n\n"); 2361 (void) printf("%8s %-*s %-*s %s\n", "", maxdsname, "DATASET", 2362 maxobjname, "OBJECT", "RANGE"); 2363 2364 for (i = 0; i < nelem; i++) { 2365 nv = log[i]; 2366 2367 verify(nvlist_lookup_string(nv, ZPOOL_ERR_DATASET, 2368 &dsname) == 0); 2369 verify(nvlist_lookup_string(nv, ZPOOL_ERR_OBJECT, 2370 &objname) == 0); 2371 verify(nvlist_lookup_string(nv, ZPOOL_ERR_RANGE, 2372 &range) == 0); 2373 2374 (void) printf("%8s %-*s %-*s %s\n", "", maxdsname, 2375 dsname, maxobjname, objname, range); 2376 } 2377 } 2378 2379 /* 2380 * Display a summary of pool status. Displays a summary such as: 2381 * 2382 * pool: tank 2383 * status: DEGRADED 2384 * reason: One or more devices ... 2385 * see: http://www.sun.com/msg/ZFS-xxxx-01 2386 * config: 2387 * mirror DEGRADED 2388 * c1t0d0 OK 2389 * c2t0d0 UNAVAIL 2390 * 2391 * When given the '-v' option, we print out the complete config. If the '-e' 2392 * option is specified, then we print out error rate information as well. 2393 */ 2394 int 2395 status_callback(zpool_handle_t *zhp, void *data) 2396 { 2397 status_cbdata_t *cbp = data; 2398 nvlist_t *config, *nvroot; 2399 char *msgid; 2400 int reason; 2401 char *health; 2402 2403 config = zpool_get_config(zhp, NULL); 2404 reason = zpool_get_status(zhp, &msgid); 2405 2406 cbp->cb_count++; 2407 2408 /* 2409 * If we were given 'zpool status -x', only report those pools with 2410 * problems. 2411 */ 2412 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) 2413 return (0); 2414 2415 if (cbp->cb_first) 2416 cbp->cb_first = FALSE; 2417 else 2418 (void) printf("\n"); 2419 2420 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_HEALTH, 2421 &health) == 0); 2422 2423 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 2424 (void) printf(gettext(" state: %s\n"), health); 2425 2426 switch (reason) { 2427 case ZPOOL_STATUS_MISSING_DEV_R: 2428 (void) printf(gettext("status: One or more devices could not " 2429 "be opened. Sufficient replicas exist for\n\tthe pool to " 2430 "continue functioning in a degraded state.\n")); 2431 (void) printf(gettext("action: Attach the missing device and " 2432 "online it using 'zpool online'.\n")); 2433 break; 2434 2435 case ZPOOL_STATUS_MISSING_DEV_NR: 2436 (void) printf(gettext("status: One or more devices could not " 2437 "be opened. There are insufficient\n\treplicas for the " 2438 "pool to continue functioning.\n")); 2439 (void) printf(gettext("action: Attach the missing device and " 2440 "online it using 'zpool online'.\n")); 2441 break; 2442 2443 case ZPOOL_STATUS_CORRUPT_LABEL_R: 2444 (void) printf(gettext("status: One or more devices could not " 2445 "be used because the label is missing or\n\tinvalid. " 2446 "Sufficient replicas exist for the pool to continue\n\t" 2447 "functioning in a degraded state.\n")); 2448 (void) printf(gettext("action: Replace the device using " 2449 "'zpool replace'.\n")); 2450 break; 2451 2452 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 2453 (void) printf(gettext("status: One or more devices could not " 2454 "be used because the the label is missing \n\tor invalid. " 2455 "There are insufficient replicas for the pool to " 2456 "continue\n\tfunctioning.\n")); 2457 (void) printf(gettext("action: Destroy and re-create the pool " 2458 "from a backup source.\n")); 2459 break; 2460 2461 case ZPOOL_STATUS_FAILING_DEV: 2462 (void) printf(gettext("status: One or more devices has " 2463 "experienced an unrecoverable error. An\n\tattempt was " 2464 "made to correct the error. Applications are " 2465 "unaffected.\n")); 2466 (void) printf(gettext("action: Determine if the device needs " 2467 "to be replaced, and clear the errors\n\tusing " 2468 "'zpool clear' or replace the device with 'zpool " 2469 "replace'.\n")); 2470 break; 2471 2472 case ZPOOL_STATUS_OFFLINE_DEV: 2473 (void) printf(gettext("status: One or more devices has " 2474 "been taken offline by the adminstrator.\n\tSufficient " 2475 "replicas exist for the pool to continue functioning in " 2476 "a\n\tdegraded state.\n")); 2477 (void) printf(gettext("action: Online the device using " 2478 "'zpool online' or replace the device with\n\t'zpool " 2479 "replace'.\n")); 2480 break; 2481 2482 case ZPOOL_STATUS_RESILVERING: 2483 (void) printf(gettext("status: One or more devices is " 2484 "currently being resilvered. The pool will\n\tcontinue " 2485 "to function, possibly in a degraded state.\n")); 2486 (void) printf(gettext("action: Wait for the resilver to " 2487 "complete.\n")); 2488 break; 2489 2490 case ZPOOL_STATUS_CORRUPT_DATA: 2491 (void) printf(gettext("status: One or more devices has " 2492 "experienced an error resulting in data\n\tcorruption. " 2493 "Applications may be affected.\n")); 2494 (void) printf(gettext("action: Restore the file in question " 2495 "if possible. Otherwise restore the\n\tentire pool from " 2496 "backup.\n")); 2497 break; 2498 2499 case ZPOOL_STATUS_CORRUPT_POOL: 2500 (void) printf(gettext("status: The pool metadata is corrupted " 2501 "and the pool cannot be opened.\n")); 2502 (void) printf(gettext("action: Destroy and re-create the pool " 2503 "from a backup source.\n")); 2504 break; 2505 2506 default: 2507 /* 2508 * The remaining errors can't actually be generated, yet. 2509 */ 2510 assert(reason == ZPOOL_STATUS_OK); 2511 } 2512 2513 if (msgid != NULL) 2514 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 2515 msgid); 2516 2517 if (config != NULL) { 2518 int namewidth; 2519 uint64_t nerr; 2520 size_t realerr; 2521 2522 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2523 &nvroot) == 0); 2524 2525 (void) printf(gettext(" scrub: ")); 2526 print_scrub_status(nvroot); 2527 2528 namewidth = max_width(zhp, nvroot, 0, 0); 2529 if (namewidth < 10) 2530 namewidth = 10; 2531 2532 (void) printf(gettext("config:\n\n")); 2533 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 2534 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 2535 print_status_config(zhp, zpool_get_name(zhp), nvroot, 2536 namewidth, 0); 2537 2538 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 2539 &nerr) == 0) { 2540 /* 2541 * If the approximate error count is small, get a 2542 * precise count by fetching the entire log and 2543 * uniquifying the results. 2544 */ 2545 if (nerr < 100 && !cbp->cb_verbose && 2546 zpool_get_errlog(zhp, NULL, &realerr) == 0) 2547 nerr = realerr; 2548 2549 (void) printf("\n"); 2550 if (nerr == 0) 2551 (void) printf(gettext("errors: No known data " 2552 "errors\n")); 2553 else if (!cbp->cb_verbose) 2554 (void) printf(gettext("errors: %d data errors, " 2555 "use '-v' for a list\n"), nerr); 2556 else 2557 print_error_log(zhp); 2558 } 2559 } else { 2560 (void) printf(gettext("config: The configuration cannot be " 2561 "determined.\n")); 2562 } 2563 2564 return (0); 2565 } 2566 2567 /* 2568 * zpool status [-vx] [pool] ... 2569 * 2570 * -v Display complete error logs 2571 * -x Display only pools with potential problems 2572 * 2573 * Describes the health status of all pools or some subset. 2574 */ 2575 int 2576 zpool_do_status(int argc, char **argv) 2577 { 2578 int c; 2579 int ret; 2580 status_cbdata_t cb = { 0 }; 2581 2582 /* check options */ 2583 while ((c = getopt(argc, argv, "vx")) != -1) { 2584 switch (c) { 2585 case 'v': 2586 cb.cb_verbose = TRUE; 2587 break; 2588 case 'x': 2589 cb.cb_explain = TRUE; 2590 break; 2591 case '?': 2592 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2593 optopt); 2594 usage(FALSE); 2595 } 2596 } 2597 2598 argc -= optind; 2599 argv += optind; 2600 2601 cb.cb_first = TRUE; 2602 2603 ret = for_each_pool(argc, argv, TRUE, status_callback, &cb); 2604 2605 if (argc == 0 && cb.cb_count == 0) 2606 (void) printf(gettext("no pools available\n")); 2607 else if (cb.cb_explain && cb.cb_first) { 2608 if (argc == 0) { 2609 (void) printf(gettext("all pools are healthy\n")); 2610 } else { 2611 int i; 2612 for (i = 0; i < argc; i++) 2613 (void) printf(gettext("pool '%s' is healthy\n"), 2614 argv[i]); 2615 } 2616 } 2617 2618 return (ret); 2619 } 2620 2621 int 2622 main(int argc, char **argv) 2623 { 2624 int ret; 2625 int i; 2626 char *cmdname; 2627 2628 (void) setlocale(LC_ALL, ""); 2629 (void) textdomain(TEXT_DOMAIN); 2630 2631 opterr = 0; 2632 2633 /* 2634 * Make sure the user has specified some command. 2635 */ 2636 if (argc < 2) { 2637 (void) fprintf(stderr, gettext("missing command\n")); 2638 usage(FALSE); 2639 } 2640 2641 cmdname = argv[1]; 2642 2643 /* 2644 * Special case '-?' 2645 */ 2646 if (strcmp(cmdname, "-?") == 0) 2647 usage(TRUE); 2648 2649 /* 2650 * Run the appropriate command. 2651 */ 2652 for (i = 0; i < NCOMMAND; i++) { 2653 if (command_table[i].name == NULL) 2654 continue; 2655 2656 if (strcmp(cmdname, command_table[i].name) == 0) { 2657 current_command = &command_table[i]; 2658 ret = command_table[i].func(argc - 1, argv + 1); 2659 break; 2660 } 2661 } 2662 2663 /* 2664 * 'freeze' is a vile debugging abomination, so we treat it as such. 2665 */ 2666 if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 2667 char buf[16384]; 2668 int fd = open(ZFS_DEV, O_RDWR); 2669 (void) strcpy((void *)buf, argv[2]); 2670 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 2671 } 2672 2673 if (i == NCOMMAND) { 2674 (void) fprintf(stderr, gettext("unrecognized " 2675 "command '%s'\n"), cmdname); 2676 usage(FALSE); 2677 } 2678 2679 /* 2680 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 2681 * for the purposes of running ::findleaks. 2682 */ 2683 if (getenv("ZFS_ABORT") != NULL) { 2684 (void) printf("dumping core by request\n"); 2685 abort(); 2686 } 2687 2688 return (ret); 2689 } 2690