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