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