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