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_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_nfs(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_disable_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_disable_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_enable_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 /* 1747 * Flush the output so that redirection to a file isn't buffered 1748 * indefinitely. 1749 */ 1750 (void) fflush(stdout); 1751 1752 if (interval == 0) 1753 break; 1754 1755 if (count != 0 && --count == 0) 1756 break; 1757 1758 (void) sleep(interval); 1759 } 1760 1761 pool_list_free(list); 1762 1763 return (ret); 1764 } 1765 1766 typedef struct list_cbdata { 1767 boolean_t cb_scripted; 1768 boolean_t cb_first; 1769 int cb_fields[MAX_FIELDS]; 1770 int cb_fieldcount; 1771 } list_cbdata_t; 1772 1773 /* 1774 * Given a list of columns to display, output appropriate headers for each one. 1775 */ 1776 void 1777 print_header(int *fields, size_t count) 1778 { 1779 int i; 1780 column_def_t *col; 1781 const char *fmt; 1782 1783 for (i = 0; i < count; i++) { 1784 col = &column_table[fields[i]]; 1785 if (i != 0) 1786 (void) printf(" "); 1787 if (col->cd_justify == left_justify) 1788 fmt = "%-*s"; 1789 else 1790 fmt = "%*s"; 1791 1792 (void) printf(fmt, i == count - 1 ? strlen(col->cd_title) : 1793 col->cd_width, col->cd_title); 1794 } 1795 1796 (void) printf("\n"); 1797 } 1798 1799 int 1800 list_callback(zpool_handle_t *zhp, void *data) 1801 { 1802 list_cbdata_t *cbp = data; 1803 nvlist_t *config; 1804 int i; 1805 char buf[ZPOOL_MAXNAMELEN]; 1806 uint64_t total; 1807 uint64_t used; 1808 const char *fmt; 1809 column_def_t *col; 1810 1811 if (cbp->cb_first) { 1812 if (!cbp->cb_scripted) 1813 print_header(cbp->cb_fields, cbp->cb_fieldcount); 1814 cbp->cb_first = B_FALSE; 1815 } 1816 1817 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 1818 config = NULL; 1819 } else { 1820 config = zpool_get_config(zhp, NULL); 1821 total = zpool_get_space_total(zhp); 1822 used = zpool_get_space_used(zhp); 1823 } 1824 1825 for (i = 0; i < cbp->cb_fieldcount; i++) { 1826 if (i != 0) { 1827 if (cbp->cb_scripted) 1828 (void) printf("\t"); 1829 else 1830 (void) printf(" "); 1831 } 1832 1833 col = &column_table[cbp->cb_fields[i]]; 1834 1835 switch (cbp->cb_fields[i]) { 1836 case ZPOOL_FIELD_NAME: 1837 (void) strlcpy(buf, zpool_get_name(zhp), sizeof (buf)); 1838 break; 1839 1840 case ZPOOL_FIELD_SIZE: 1841 if (config == NULL) 1842 (void) strlcpy(buf, "-", sizeof (buf)); 1843 else 1844 zfs_nicenum(total, buf, sizeof (buf)); 1845 break; 1846 1847 case ZPOOL_FIELD_USED: 1848 if (config == NULL) 1849 (void) strlcpy(buf, "-", sizeof (buf)); 1850 else 1851 zfs_nicenum(used, buf, sizeof (buf)); 1852 break; 1853 1854 case ZPOOL_FIELD_AVAILABLE: 1855 if (config == NULL) 1856 (void) strlcpy(buf, "-", sizeof (buf)); 1857 else 1858 zfs_nicenum(total - used, buf, sizeof (buf)); 1859 break; 1860 1861 case ZPOOL_FIELD_CAPACITY: 1862 if (config == NULL) { 1863 (void) strlcpy(buf, "-", sizeof (buf)); 1864 } else { 1865 uint64_t capacity = (total == 0 ? 0 : 1866 (used * 100 / total)); 1867 (void) snprintf(buf, sizeof (buf), "%llu%%", 1868 (u_longlong_t)capacity); 1869 } 1870 break; 1871 1872 case ZPOOL_FIELD_HEALTH: 1873 if (config == NULL) { 1874 (void) strlcpy(buf, "FAULTED", sizeof (buf)); 1875 } else { 1876 nvlist_t *nvroot; 1877 vdev_stat_t *vs; 1878 uint_t vsc; 1879 1880 verify(nvlist_lookup_nvlist(config, 1881 ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 1882 verify(nvlist_lookup_uint64_array(nvroot, 1883 ZPOOL_CONFIG_STATS, (uint64_t **)&vs, 1884 &vsc) == 0); 1885 (void) strlcpy(buf, state_to_name(vs), 1886 sizeof (buf)); 1887 } 1888 break; 1889 1890 case ZPOOL_FIELD_ROOT: 1891 if (config == NULL) 1892 (void) strlcpy(buf, "-", sizeof (buf)); 1893 else if (zpool_get_root(zhp, buf, sizeof (buf)) != 0) 1894 (void) strlcpy(buf, "-", sizeof (buf)); 1895 break; 1896 } 1897 1898 if (cbp->cb_scripted) 1899 (void) printf("%s", buf); 1900 else { 1901 if (col->cd_justify == left_justify) 1902 fmt = "%-*s"; 1903 else 1904 fmt = "%*s"; 1905 1906 (void) printf(fmt, i == cbp->cb_fieldcount - 1 ? 1907 strlen(buf) : col->cd_width, buf); 1908 } 1909 } 1910 1911 (void) printf("\n"); 1912 1913 return (0); 1914 } 1915 1916 /* 1917 * zpool list [-H] [-o field[,field]*] [pool] ... 1918 * 1919 * -H Scripted mode. Don't display headers, and separate fields by 1920 * a single tab. 1921 * -o List of fields to display. Defaults to all fields, or 1922 * "name,size,used,available,capacity,health,root" 1923 * 1924 * List all pools in the system, whether or not they're healthy. Output space 1925 * statistics for each one, as well as health status summary. 1926 */ 1927 int 1928 zpool_do_list(int argc, char **argv) 1929 { 1930 int c; 1931 int ret; 1932 list_cbdata_t cb = { 0 }; 1933 static char default_fields[] = 1934 "name,size,used,available,capacity,health,root"; 1935 char *fields = default_fields; 1936 char *value; 1937 1938 /* check options */ 1939 while ((c = getopt(argc, argv, ":Ho:")) != -1) { 1940 switch (c) { 1941 case 'H': 1942 cb.cb_scripted = B_TRUE; 1943 break; 1944 case 'o': 1945 fields = optarg; 1946 break; 1947 case ':': 1948 (void) fprintf(stderr, gettext("missing argument for " 1949 "'%c' option\n"), optopt); 1950 usage(B_FALSE); 1951 break; 1952 case '?': 1953 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1954 optopt); 1955 usage(B_FALSE); 1956 } 1957 } 1958 1959 argc -= optind; 1960 argv += optind; 1961 1962 while (*fields != '\0') { 1963 if (cb.cb_fieldcount == MAX_FIELDS) { 1964 (void) fprintf(stderr, gettext("too many " 1965 "properties given to -o option\n")); 1966 usage(B_FALSE); 1967 } 1968 1969 if ((cb.cb_fields[cb.cb_fieldcount] = getsubopt(&fields, 1970 column_subopts, &value)) == -1) { 1971 (void) fprintf(stderr, gettext("invalid property " 1972 "'%s'\n"), value); 1973 usage(B_FALSE); 1974 } 1975 1976 cb.cb_fieldcount++; 1977 } 1978 1979 1980 cb.cb_first = B_TRUE; 1981 1982 ret = for_each_pool(argc, argv, B_TRUE, list_callback, &cb); 1983 1984 if (argc == 0 && cb.cb_first) { 1985 (void) printf(gettext("no pools available\n")); 1986 return (0); 1987 } 1988 1989 return (ret); 1990 } 1991 1992 static nvlist_t * 1993 zpool_get_vdev_by_name(nvlist_t *nv, char *name) 1994 { 1995 nvlist_t **child; 1996 uint_t c, children; 1997 nvlist_t *match; 1998 char *path; 1999 2000 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2001 &child, &children) != 0) { 2002 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2003 if (strncmp(name, "/dev/dsk/", 9) == 0) 2004 name += 9; 2005 if (strncmp(path, "/dev/dsk/", 9) == 0) 2006 path += 9; 2007 if (strcmp(name, path) == 0) 2008 return (nv); 2009 return (NULL); 2010 } 2011 2012 for (c = 0; c < children; c++) 2013 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 2014 return (match); 2015 2016 return (NULL); 2017 } 2018 2019 static int 2020 zpool_do_attach_or_replace(int argc, char **argv, int replacing) 2021 { 2022 boolean_t force = B_FALSE; 2023 int c; 2024 nvlist_t *nvroot; 2025 char *poolname, *old_disk, *new_disk; 2026 zpool_handle_t *zhp; 2027 nvlist_t *config; 2028 int ret; 2029 int log_argc; 2030 char **log_argv; 2031 2032 /* check options */ 2033 while ((c = getopt(argc, argv, "f")) != -1) { 2034 switch (c) { 2035 case 'f': 2036 force = B_TRUE; 2037 break; 2038 case '?': 2039 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2040 optopt); 2041 usage(B_FALSE); 2042 } 2043 } 2044 2045 log_argc = argc; 2046 log_argv = argv; 2047 argc -= optind; 2048 argv += optind; 2049 2050 /* get pool name and check number of arguments */ 2051 if (argc < 1) { 2052 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2053 usage(B_FALSE); 2054 } 2055 2056 poolname = argv[0]; 2057 2058 if (argc < 2) { 2059 (void) fprintf(stderr, 2060 gettext("missing <device> specification\n")); 2061 usage(B_FALSE); 2062 } 2063 2064 old_disk = argv[1]; 2065 2066 if (argc < 3) { 2067 if (!replacing) { 2068 (void) fprintf(stderr, 2069 gettext("missing <new_device> specification\n")); 2070 usage(B_FALSE); 2071 } 2072 new_disk = old_disk; 2073 argc -= 1; 2074 argv += 1; 2075 } else { 2076 new_disk = argv[2]; 2077 argc -= 2; 2078 argv += 2; 2079 } 2080 2081 if (argc > 1) { 2082 (void) fprintf(stderr, gettext("too many arguments\n")); 2083 usage(B_FALSE); 2084 } 2085 2086 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2087 return (1); 2088 2089 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 2090 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 2091 poolname); 2092 zpool_close(zhp); 2093 return (1); 2094 } 2095 2096 nvroot = make_root_vdev(config, force, B_FALSE, replacing, argc, argv); 2097 if (nvroot == NULL) { 2098 zpool_close(zhp); 2099 return (1); 2100 } 2101 2102 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 2103 2104 if (!ret) { 2105 zpool_log_history(g_zfs, log_argc, log_argv, poolname, B_TRUE, 2106 B_FALSE); 2107 } 2108 2109 nvlist_free(nvroot); 2110 zpool_close(zhp); 2111 2112 return (ret); 2113 } 2114 2115 /* 2116 * zpool replace [-f] <pool> <device> <new_device> 2117 * 2118 * -f Force attach, even if <new_device> appears to be in use. 2119 * 2120 * Replace <device> with <new_device>. 2121 */ 2122 /* ARGSUSED */ 2123 int 2124 zpool_do_replace(int argc, char **argv) 2125 { 2126 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 2127 } 2128 2129 /* 2130 * zpool attach [-f] <pool> <device> <new_device> 2131 * 2132 * -f Force attach, even if <new_device> appears to be in use. 2133 * 2134 * Attach <new_device> to the mirror containing <device>. If <device> is not 2135 * part of a mirror, then <device> will be transformed into a mirror of 2136 * <device> and <new_device>. In either case, <new_device> will begin life 2137 * with a DTL of [0, now], and will immediately begin to resilver itself. 2138 */ 2139 int 2140 zpool_do_attach(int argc, char **argv) 2141 { 2142 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 2143 } 2144 2145 /* 2146 * zpool detach [-f] <pool> <device> 2147 * 2148 * -f Force detach of <device>, even if DTLs argue against it 2149 * (not supported yet) 2150 * 2151 * Detach a device from a mirror. The operation will be refused if <device> 2152 * is the last device in the mirror, or if the DTLs indicate that this device 2153 * has the only valid copy of some data. 2154 */ 2155 /* ARGSUSED */ 2156 int 2157 zpool_do_detach(int argc, char **argv) 2158 { 2159 int c; 2160 char *poolname, *path; 2161 zpool_handle_t *zhp; 2162 int ret; 2163 2164 /* check options */ 2165 while ((c = getopt(argc, argv, "f")) != -1) { 2166 switch (c) { 2167 case 'f': 2168 case '?': 2169 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2170 optopt); 2171 usage(B_FALSE); 2172 } 2173 } 2174 2175 argc -= optind; 2176 argv += optind; 2177 2178 /* get pool name and check number of arguments */ 2179 if (argc < 1) { 2180 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2181 usage(B_FALSE); 2182 } 2183 2184 if (argc < 2) { 2185 (void) fprintf(stderr, 2186 gettext("missing <device> specification\n")); 2187 usage(B_FALSE); 2188 } 2189 2190 poolname = argv[0]; 2191 path = argv[1]; 2192 2193 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2194 return (1); 2195 2196 ret = zpool_vdev_detach(zhp, path); 2197 2198 if (!ret) { 2199 zpool_log_history(g_zfs, argc + optind, argv - optind, poolname, 2200 B_TRUE, B_FALSE); 2201 } 2202 zpool_close(zhp); 2203 2204 return (ret); 2205 } 2206 2207 /* 2208 * zpool online <pool> <device> ... 2209 */ 2210 /* ARGSUSED */ 2211 int 2212 zpool_do_online(int argc, char **argv) 2213 { 2214 int c, i; 2215 char *poolname; 2216 zpool_handle_t *zhp; 2217 int ret = 0; 2218 2219 /* check options */ 2220 while ((c = getopt(argc, argv, "t")) != -1) { 2221 switch (c) { 2222 case 't': 2223 case '?': 2224 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2225 optopt); 2226 usage(B_FALSE); 2227 } 2228 } 2229 2230 argc -= optind; 2231 argv += optind; 2232 2233 /* get pool name and check number of arguments */ 2234 if (argc < 1) { 2235 (void) fprintf(stderr, gettext("missing pool name\n")); 2236 usage(B_FALSE); 2237 } 2238 if (argc < 2) { 2239 (void) fprintf(stderr, gettext("missing device name\n")); 2240 usage(B_FALSE); 2241 } 2242 2243 poolname = argv[0]; 2244 2245 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2246 return (1); 2247 2248 for (i = 1; i < argc; i++) 2249 if (zpool_vdev_online(zhp, argv[i]) == 0) 2250 (void) printf(gettext("Bringing device %s online\n"), 2251 argv[i]); 2252 else 2253 ret = 1; 2254 2255 if (!ret) { 2256 zpool_log_history(g_zfs, argc + optind, argv - optind, poolname, 2257 B_TRUE, B_FALSE); 2258 } 2259 zpool_close(zhp); 2260 2261 return (ret); 2262 } 2263 2264 /* 2265 * zpool offline [-ft] <pool> <device> ... 2266 * 2267 * -f Force the device into the offline state, even if doing 2268 * so would appear to compromise pool availability. 2269 * (not supported yet) 2270 * 2271 * -t Only take the device off-line temporarily. The offline 2272 * state will not be persistent across reboots. 2273 */ 2274 /* ARGSUSED */ 2275 int 2276 zpool_do_offline(int argc, char **argv) 2277 { 2278 int c, i; 2279 char *poolname; 2280 zpool_handle_t *zhp; 2281 int ret = 0; 2282 boolean_t istmp = B_FALSE; 2283 2284 /* check options */ 2285 while ((c = getopt(argc, argv, "ft")) != -1) { 2286 switch (c) { 2287 case 't': 2288 istmp = B_TRUE; 2289 break; 2290 case 'f': 2291 case '?': 2292 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2293 optopt); 2294 usage(B_FALSE); 2295 } 2296 } 2297 2298 argc -= optind; 2299 argv += optind; 2300 2301 /* get pool name and check number of arguments */ 2302 if (argc < 1) { 2303 (void) fprintf(stderr, gettext("missing pool name\n")); 2304 usage(B_FALSE); 2305 } 2306 if (argc < 2) { 2307 (void) fprintf(stderr, gettext("missing device name\n")); 2308 usage(B_FALSE); 2309 } 2310 2311 poolname = argv[0]; 2312 2313 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2314 return (1); 2315 2316 for (i = 1; i < argc; i++) 2317 if (zpool_vdev_offline(zhp, argv[i], istmp) == 0) 2318 (void) printf(gettext("Bringing device %s offline\n"), 2319 argv[i]); 2320 else 2321 ret = 1; 2322 2323 if (!ret) { 2324 zpool_log_history(g_zfs, argc + optind, argv - optind, poolname, 2325 B_TRUE, B_FALSE); 2326 } 2327 zpool_close(zhp); 2328 2329 return (ret); 2330 } 2331 2332 /* 2333 * zpool clear <pool> [device] 2334 * 2335 * Clear all errors associated with a pool or a particular device. 2336 */ 2337 int 2338 zpool_do_clear(int argc, char **argv) 2339 { 2340 int ret = 0; 2341 zpool_handle_t *zhp; 2342 char *pool, *device; 2343 2344 if (argc < 2) { 2345 (void) fprintf(stderr, gettext("missing pool name\n")); 2346 usage(B_FALSE); 2347 } 2348 2349 if (argc > 3) { 2350 (void) fprintf(stderr, gettext("too many arguments\n")); 2351 usage(B_FALSE); 2352 } 2353 2354 pool = argv[1]; 2355 device = argc == 3 ? argv[2] : NULL; 2356 2357 if ((zhp = zpool_open(g_zfs, pool)) == NULL) 2358 return (1); 2359 2360 if (zpool_clear(zhp, device) != 0) 2361 ret = 1; 2362 2363 if (!ret) 2364 zpool_log_history(g_zfs, argc, argv, pool, B_TRUE, B_FALSE); 2365 zpool_close(zhp); 2366 2367 return (ret); 2368 } 2369 2370 typedef struct scrub_cbdata { 2371 int cb_type; 2372 int cb_argc; 2373 char **cb_argv; 2374 } scrub_cbdata_t; 2375 2376 int 2377 scrub_callback(zpool_handle_t *zhp, void *data) 2378 { 2379 scrub_cbdata_t *cb = data; 2380 int err; 2381 2382 /* 2383 * Ignore faulted pools. 2384 */ 2385 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 2386 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 2387 "currently unavailable\n"), zpool_get_name(zhp)); 2388 return (1); 2389 } 2390 2391 err = zpool_scrub(zhp, cb->cb_type); 2392 2393 if (!err) { 2394 zpool_log_history(g_zfs, cb->cb_argc, cb->cb_argv, 2395 zpool_get_name(zhp), B_TRUE, B_FALSE); 2396 } 2397 2398 return (err != 0); 2399 } 2400 2401 /* 2402 * zpool scrub [-s] <pool> ... 2403 * 2404 * -s Stop. Stops any in-progress scrub. 2405 */ 2406 int 2407 zpool_do_scrub(int argc, char **argv) 2408 { 2409 int c; 2410 scrub_cbdata_t cb; 2411 2412 cb.cb_type = POOL_SCRUB_EVERYTHING; 2413 2414 /* check options */ 2415 while ((c = getopt(argc, argv, "s")) != -1) { 2416 switch (c) { 2417 case 's': 2418 cb.cb_type = POOL_SCRUB_NONE; 2419 break; 2420 case '?': 2421 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2422 optopt); 2423 usage(B_FALSE); 2424 } 2425 } 2426 2427 cb.cb_argc = argc; 2428 cb.cb_argv = argv; 2429 argc -= optind; 2430 argv += optind; 2431 2432 if (argc < 1) { 2433 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2434 usage(B_FALSE); 2435 } 2436 2437 return (for_each_pool(argc, argv, B_TRUE, scrub_callback, &cb)); 2438 } 2439 2440 typedef struct status_cbdata { 2441 int cb_count; 2442 boolean_t cb_allpools; 2443 boolean_t cb_verbose; 2444 boolean_t cb_explain; 2445 boolean_t cb_first; 2446 } status_cbdata_t; 2447 2448 /* 2449 * Print out detailed scrub status. 2450 */ 2451 void 2452 print_scrub_status(nvlist_t *nvroot) 2453 { 2454 vdev_stat_t *vs; 2455 uint_t vsc; 2456 time_t start, end, now; 2457 double fraction_done; 2458 uint64_t examined, total, minutes_left; 2459 char *scrub_type; 2460 2461 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 2462 (uint64_t **)&vs, &vsc) == 0); 2463 2464 /* 2465 * If there's never been a scrub, there's not much to say. 2466 */ 2467 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) { 2468 (void) printf(gettext("none requested\n")); 2469 return; 2470 } 2471 2472 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2473 "resilver" : "scrub"; 2474 2475 start = vs->vs_scrub_start; 2476 end = vs->vs_scrub_end; 2477 now = time(NULL); 2478 examined = vs->vs_scrub_examined; 2479 total = vs->vs_alloc; 2480 2481 if (end != 0) { 2482 (void) printf(gettext("%s %s with %llu errors on %s"), 2483 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped", 2484 (u_longlong_t)vs->vs_scrub_errors, ctime(&end)); 2485 return; 2486 } 2487 2488 if (examined == 0) 2489 examined = 1; 2490 if (examined > total) 2491 total = examined; 2492 2493 fraction_done = (double)examined / total; 2494 minutes_left = (uint64_t)((now - start) * 2495 (1 - fraction_done) / fraction_done / 60); 2496 2497 (void) printf(gettext("%s in progress, %.2f%% done, %lluh%um to go\n"), 2498 scrub_type, 100 * fraction_done, 2499 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60)); 2500 } 2501 2502 typedef struct spare_cbdata { 2503 uint64_t cb_guid; 2504 zpool_handle_t *cb_zhp; 2505 } spare_cbdata_t; 2506 2507 static boolean_t 2508 find_vdev(nvlist_t *nv, uint64_t search) 2509 { 2510 uint64_t guid; 2511 nvlist_t **child; 2512 uint_t c, children; 2513 2514 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 2515 search == guid) 2516 return (B_TRUE); 2517 2518 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2519 &child, &children) == 0) { 2520 for (c = 0; c < children; c++) 2521 if (find_vdev(child[c], search)) 2522 return (B_TRUE); 2523 } 2524 2525 return (B_FALSE); 2526 } 2527 2528 static int 2529 find_spare(zpool_handle_t *zhp, void *data) 2530 { 2531 spare_cbdata_t *cbp = data; 2532 nvlist_t *config, *nvroot; 2533 2534 config = zpool_get_config(zhp, NULL); 2535 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2536 &nvroot) == 0); 2537 2538 if (find_vdev(nvroot, cbp->cb_guid)) { 2539 cbp->cb_zhp = zhp; 2540 return (1); 2541 } 2542 2543 zpool_close(zhp); 2544 return (0); 2545 } 2546 2547 /* 2548 * Print out configuration state as requested by status_callback. 2549 */ 2550 void 2551 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 2552 int namewidth, int depth, boolean_t isspare) 2553 { 2554 nvlist_t **child; 2555 uint_t c, children; 2556 vdev_stat_t *vs; 2557 char rbuf[6], wbuf[6], cbuf[6], repaired[7]; 2558 char *vname; 2559 uint64_t notpresent; 2560 spare_cbdata_t cb; 2561 const char *state; 2562 2563 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 2564 (uint64_t **)&vs, &c) == 0); 2565 2566 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2567 &child, &children) != 0) 2568 children = 0; 2569 2570 state = state_to_name(vs); 2571 if (isspare) { 2572 /* 2573 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 2574 * online drives. 2575 */ 2576 if (vs->vs_aux == VDEV_AUX_SPARED) 2577 state = "INUSE"; 2578 else if (vs->vs_state == VDEV_STATE_HEALTHY) 2579 state = "AVAIL"; 2580 } 2581 2582 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 2583 name, state); 2584 2585 if (!isspare) { 2586 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 2587 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 2588 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 2589 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 2590 } 2591 2592 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 2593 ¬present) == 0) { 2594 char *path; 2595 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2596 (void) printf(" was %s", path); 2597 } else if (vs->vs_aux != 0) { 2598 (void) printf(" "); 2599 2600 switch (vs->vs_aux) { 2601 case VDEV_AUX_OPEN_FAILED: 2602 (void) printf(gettext("cannot open")); 2603 break; 2604 2605 case VDEV_AUX_BAD_GUID_SUM: 2606 (void) printf(gettext("missing device")); 2607 break; 2608 2609 case VDEV_AUX_NO_REPLICAS: 2610 (void) printf(gettext("insufficient replicas")); 2611 break; 2612 2613 case VDEV_AUX_VERSION_NEWER: 2614 (void) printf(gettext("newer version")); 2615 break; 2616 2617 case VDEV_AUX_SPARED: 2618 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 2619 &cb.cb_guid) == 0); 2620 if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 2621 if (strcmp(zpool_get_name(cb.cb_zhp), 2622 zpool_get_name(zhp)) == 0) 2623 (void) printf(gettext("currently in " 2624 "use")); 2625 else 2626 (void) printf(gettext("in use by " 2627 "pool '%s'"), 2628 zpool_get_name(cb.cb_zhp)); 2629 zpool_close(cb.cb_zhp); 2630 } else { 2631 (void) printf(gettext("currently in use")); 2632 } 2633 break; 2634 2635 default: 2636 (void) printf(gettext("corrupted data")); 2637 break; 2638 } 2639 } else if (vs->vs_scrub_repaired != 0 && children == 0) { 2640 /* 2641 * Report bytes resilvered/repaired on leaf devices. 2642 */ 2643 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); 2644 (void) printf(gettext(" %s %s"), repaired, 2645 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2646 "resilvered" : "repaired"); 2647 } 2648 2649 (void) printf("\n"); 2650 2651 for (c = 0; c < children; c++) { 2652 vname = zpool_vdev_name(g_zfs, zhp, child[c]); 2653 print_status_config(zhp, vname, child[c], 2654 namewidth, depth + 2, isspare); 2655 free(vname); 2656 } 2657 } 2658 2659 static void 2660 print_error_log(zpool_handle_t *zhp) 2661 { 2662 nvlist_t *nverrlist; 2663 nvpair_t *elem; 2664 char *pathname; 2665 size_t len = MAXPATHLEN * 2; 2666 2667 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 2668 (void) printf("errors: List of errors unavailable " 2669 "(insufficient privileges)\n"); 2670 return; 2671 } 2672 2673 (void) printf("errors: Permanent errors have been " 2674 "detected in the following files:\n\n"); 2675 2676 pathname = safe_malloc(len); 2677 elem = NULL; 2678 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 2679 nvlist_t *nv; 2680 uint64_t dsobj, obj; 2681 2682 verify(nvpair_value_nvlist(elem, &nv) == 0); 2683 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 2684 &dsobj) == 0); 2685 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 2686 &obj) == 0); 2687 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 2688 (void) printf("%7s %s\n", "", pathname); 2689 } 2690 free(pathname); 2691 nvlist_free(nverrlist); 2692 } 2693 2694 static void 2695 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 2696 int namewidth) 2697 { 2698 uint_t i; 2699 char *name; 2700 2701 if (nspares == 0) 2702 return; 2703 2704 (void) printf(gettext("\tspares\n")); 2705 2706 for (i = 0; i < nspares; i++) { 2707 name = zpool_vdev_name(g_zfs, zhp, spares[i]); 2708 print_status_config(zhp, name, spares[i], 2709 namewidth, 2, B_TRUE); 2710 free(name); 2711 } 2712 } 2713 2714 /* 2715 * Display a summary of pool status. Displays a summary such as: 2716 * 2717 * pool: tank 2718 * status: DEGRADED 2719 * reason: One or more devices ... 2720 * see: http://www.sun.com/msg/ZFS-xxxx-01 2721 * config: 2722 * mirror DEGRADED 2723 * c1t0d0 OK 2724 * c2t0d0 UNAVAIL 2725 * 2726 * When given the '-v' option, we print out the complete config. If the '-e' 2727 * option is specified, then we print out error rate information as well. 2728 */ 2729 int 2730 status_callback(zpool_handle_t *zhp, void *data) 2731 { 2732 status_cbdata_t *cbp = data; 2733 nvlist_t *config, *nvroot; 2734 char *msgid; 2735 int reason; 2736 char *health; 2737 2738 config = zpool_get_config(zhp, NULL); 2739 reason = zpool_get_status(zhp, &msgid); 2740 2741 cbp->cb_count++; 2742 2743 /* 2744 * If we were given 'zpool status -x', only report those pools with 2745 * problems. 2746 */ 2747 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) { 2748 if (!cbp->cb_allpools) { 2749 (void) printf(gettext("pool '%s' is healthy\n"), 2750 zpool_get_name(zhp)); 2751 if (cbp->cb_first) 2752 cbp->cb_first = B_FALSE; 2753 } 2754 return (0); 2755 } 2756 2757 if (cbp->cb_first) 2758 cbp->cb_first = B_FALSE; 2759 else 2760 (void) printf("\n"); 2761 2762 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_HEALTH, 2763 &health) == 0); 2764 2765 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 2766 (void) printf(gettext(" state: %s\n"), health); 2767 2768 switch (reason) { 2769 case ZPOOL_STATUS_MISSING_DEV_R: 2770 (void) printf(gettext("status: One or more devices could not " 2771 "be opened. Sufficient replicas exist for\n\tthe pool to " 2772 "continue functioning in a degraded state.\n")); 2773 (void) printf(gettext("action: Attach the missing device and " 2774 "online it using 'zpool online'.\n")); 2775 break; 2776 2777 case ZPOOL_STATUS_MISSING_DEV_NR: 2778 (void) printf(gettext("status: One or more devices could not " 2779 "be opened. There are insufficient\n\treplicas for the " 2780 "pool to continue functioning.\n")); 2781 (void) printf(gettext("action: Attach the missing device and " 2782 "online it using 'zpool online'.\n")); 2783 break; 2784 2785 case ZPOOL_STATUS_CORRUPT_LABEL_R: 2786 (void) printf(gettext("status: One or more devices could not " 2787 "be used because the label is missing or\n\tinvalid. " 2788 "Sufficient replicas exist for the pool to continue\n\t" 2789 "functioning in a degraded state.\n")); 2790 (void) printf(gettext("action: Replace the device using " 2791 "'zpool replace'.\n")); 2792 break; 2793 2794 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 2795 (void) printf(gettext("status: One or more devices could not " 2796 "be used because the the label is missing \n\tor invalid. " 2797 "There are insufficient replicas for the pool to " 2798 "continue\n\tfunctioning.\n")); 2799 (void) printf(gettext("action: Destroy and re-create the pool " 2800 "from a backup source.\n")); 2801 break; 2802 2803 case ZPOOL_STATUS_FAILING_DEV: 2804 (void) printf(gettext("status: One or more devices has " 2805 "experienced an unrecoverable error. An\n\tattempt was " 2806 "made to correct the error. Applications are " 2807 "unaffected.\n")); 2808 (void) printf(gettext("action: Determine if the device needs " 2809 "to be replaced, and clear the errors\n\tusing " 2810 "'zpool clear' or replace the device with 'zpool " 2811 "replace'.\n")); 2812 break; 2813 2814 case ZPOOL_STATUS_OFFLINE_DEV: 2815 (void) printf(gettext("status: One or more devices has " 2816 "been taken offline by the administrator.\n\tSufficient " 2817 "replicas exist for the pool to continue functioning in " 2818 "a\n\tdegraded state.\n")); 2819 (void) printf(gettext("action: Online the device using " 2820 "'zpool online' or replace the device with\n\t'zpool " 2821 "replace'.\n")); 2822 break; 2823 2824 case ZPOOL_STATUS_RESILVERING: 2825 (void) printf(gettext("status: One or more devices is " 2826 "currently being resilvered. The pool will\n\tcontinue " 2827 "to function, possibly in a degraded state.\n")); 2828 (void) printf(gettext("action: Wait for the resilver to " 2829 "complete.\n")); 2830 break; 2831 2832 case ZPOOL_STATUS_CORRUPT_DATA: 2833 (void) printf(gettext("status: One or more devices has " 2834 "experienced an error resulting in data\n\tcorruption. " 2835 "Applications may be affected.\n")); 2836 (void) printf(gettext("action: Restore the file in question " 2837 "if possible. Otherwise restore the\n\tentire pool from " 2838 "backup.\n")); 2839 break; 2840 2841 case ZPOOL_STATUS_CORRUPT_POOL: 2842 (void) printf(gettext("status: The pool metadata is corrupted " 2843 "and the pool cannot be opened.\n")); 2844 (void) printf(gettext("action: Destroy and re-create the pool " 2845 "from a backup source.\n")); 2846 break; 2847 2848 case ZPOOL_STATUS_VERSION_OLDER: 2849 (void) printf(gettext("status: The pool is formatted using an " 2850 "older on-disk format. The pool can\n\tstill be used, but " 2851 "some features are unavailable.\n")); 2852 (void) printf(gettext("action: Upgrade the pool using 'zpool " 2853 "upgrade'. Once this is done, the\n\tpool will no longer " 2854 "be accessible on older software versions.\n")); 2855 break; 2856 2857 case ZPOOL_STATUS_VERSION_NEWER: 2858 (void) printf(gettext("status: The pool has been upgraded to a " 2859 "newer, incompatible on-disk version.\n\tThe pool cannot " 2860 "be accessed on this system.\n")); 2861 (void) printf(gettext("action: Access the pool from a system " 2862 "running more recent software, or\n\trestore the pool from " 2863 "backup.\n")); 2864 break; 2865 2866 default: 2867 /* 2868 * The remaining errors can't actually be generated, yet. 2869 */ 2870 assert(reason == ZPOOL_STATUS_OK); 2871 } 2872 2873 if (msgid != NULL) 2874 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 2875 msgid); 2876 2877 if (config != NULL) { 2878 int namewidth; 2879 uint64_t nerr; 2880 nvlist_t **spares; 2881 uint_t nspares; 2882 2883 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2884 &nvroot) == 0); 2885 2886 (void) printf(gettext(" scrub: ")); 2887 print_scrub_status(nvroot); 2888 2889 namewidth = max_width(zhp, nvroot, 0, 0); 2890 if (namewidth < 10) 2891 namewidth = 10; 2892 2893 (void) printf(gettext("config:\n\n")); 2894 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 2895 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 2896 print_status_config(zhp, zpool_get_name(zhp), nvroot, 2897 namewidth, 0, B_FALSE); 2898 2899 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 2900 &spares, &nspares) == 0) 2901 print_spares(zhp, spares, nspares, namewidth); 2902 2903 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 2904 &nerr) == 0) { 2905 nvlist_t *nverrlist = NULL; 2906 2907 /* 2908 * If the approximate error count is small, get a 2909 * precise count by fetching the entire log and 2910 * uniquifying the results. 2911 */ 2912 if (nerr < 100 && !cbp->cb_verbose && 2913 zpool_get_errlog(zhp, &nverrlist) == 0) { 2914 nvpair_t *elem; 2915 2916 elem = NULL; 2917 nerr = 0; 2918 while ((elem = nvlist_next_nvpair(nverrlist, 2919 elem)) != NULL) { 2920 nerr++; 2921 } 2922 } 2923 nvlist_free(nverrlist); 2924 2925 (void) printf("\n"); 2926 2927 if (nerr == 0) 2928 (void) printf(gettext("errors: No known data " 2929 "errors\n")); 2930 else if (!cbp->cb_verbose) 2931 (void) printf(gettext("errors: %llu data " 2932 "errors, use '-v' for a list\n"), 2933 (u_longlong_t)nerr); 2934 else 2935 print_error_log(zhp); 2936 } 2937 } else { 2938 (void) printf(gettext("config: The configuration cannot be " 2939 "determined.\n")); 2940 } 2941 2942 return (0); 2943 } 2944 2945 /* 2946 * zpool status [-vx] [pool] ... 2947 * 2948 * -v Display complete error logs 2949 * -x Display only pools with potential problems 2950 * 2951 * Describes the health status of all pools or some subset. 2952 */ 2953 int 2954 zpool_do_status(int argc, char **argv) 2955 { 2956 int c; 2957 int ret; 2958 status_cbdata_t cb = { 0 }; 2959 2960 /* check options */ 2961 while ((c = getopt(argc, argv, "vx")) != -1) { 2962 switch (c) { 2963 case 'v': 2964 cb.cb_verbose = B_TRUE; 2965 break; 2966 case 'x': 2967 cb.cb_explain = B_TRUE; 2968 break; 2969 case '?': 2970 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2971 optopt); 2972 usage(B_FALSE); 2973 } 2974 } 2975 2976 argc -= optind; 2977 argv += optind; 2978 2979 cb.cb_first = B_TRUE; 2980 2981 if (argc == 0) 2982 cb.cb_allpools = B_TRUE; 2983 2984 ret = for_each_pool(argc, argv, B_TRUE, status_callback, &cb); 2985 2986 if (argc == 0 && cb.cb_count == 0) 2987 (void) printf(gettext("no pools available\n")); 2988 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 2989 (void) printf(gettext("all pools are healthy\n")); 2990 2991 return (ret); 2992 } 2993 2994 typedef struct upgrade_cbdata { 2995 int cb_all; 2996 int cb_first; 2997 int cb_newer; 2998 int cb_argc; 2999 char **cb_argv; 3000 } upgrade_cbdata_t; 3001 3002 static int 3003 upgrade_cb(zpool_handle_t *zhp, void *arg) 3004 { 3005 upgrade_cbdata_t *cbp = arg; 3006 nvlist_t *config; 3007 uint64_t version; 3008 int ret = 0; 3009 3010 config = zpool_get_config(zhp, NULL); 3011 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 3012 &version) == 0); 3013 3014 if (!cbp->cb_newer && version < ZFS_VERSION) { 3015 if (!cbp->cb_all) { 3016 if (cbp->cb_first) { 3017 (void) printf(gettext("The following pools are " 3018 "out of date, and can be upgraded. After " 3019 "being\nupgraded, these pools will no " 3020 "longer be accessible by older software " 3021 "versions.\n\n")); 3022 (void) printf(gettext("VER POOL\n")); 3023 (void) printf(gettext("--- ------------\n")); 3024 cbp->cb_first = B_FALSE; 3025 } 3026 3027 (void) printf("%2llu %s\n", (u_longlong_t)version, 3028 zpool_get_name(zhp)); 3029 } else { 3030 cbp->cb_first = B_FALSE; 3031 ret = zpool_upgrade(zhp); 3032 if (!ret) { 3033 zpool_log_history(g_zfs, cbp->cb_argc, 3034 cbp->cb_argv, zpool_get_name(zhp), B_TRUE, 3035 B_FALSE); 3036 (void) printf(gettext("Successfully upgraded " 3037 "'%s'\n"), zpool_get_name(zhp)); 3038 } 3039 } 3040 } else if (cbp->cb_newer && version > ZFS_VERSION) { 3041 assert(!cbp->cb_all); 3042 3043 if (cbp->cb_first) { 3044 (void) printf(gettext("The following pools are " 3045 "formatted using a newer software version and\n" 3046 "cannot be accessed on the current system.\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 } 3055 3056 zpool_close(zhp); 3057 return (ret); 3058 } 3059 3060 /* ARGSUSED */ 3061 static int 3062 upgrade_one(zpool_handle_t *zhp, void *data) 3063 { 3064 nvlist_t *config; 3065 uint64_t version; 3066 int ret; 3067 upgrade_cbdata_t *cbp = data; 3068 3069 config = zpool_get_config(zhp, NULL); 3070 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 3071 &version) == 0); 3072 3073 if (version == ZFS_VERSION) { 3074 (void) printf(gettext("Pool '%s' is already formatted " 3075 "using the current version.\n"), zpool_get_name(zhp)); 3076 return (0); 3077 } 3078 3079 ret = zpool_upgrade(zhp); 3080 3081 if (!ret) { 3082 zpool_log_history(g_zfs, cbp->cb_argc, cbp->cb_argv, 3083 zpool_get_name(zhp), B_TRUE, B_FALSE); 3084 (void) printf(gettext("Successfully upgraded '%s' " 3085 "from version %llu to version %llu\n"), zpool_get_name(zhp), 3086 (u_longlong_t)version, (u_longlong_t)ZFS_VERSION); 3087 } 3088 3089 return (ret != 0); 3090 } 3091 3092 /* 3093 * zpool upgrade 3094 * zpool upgrade -v 3095 * zpool upgrade <-a | pool> 3096 * 3097 * With no arguments, display downrev'd ZFS pool available for upgrade. 3098 * Individual pools can be upgraded by specifying the pool, and '-a' will 3099 * upgrade all pools. 3100 */ 3101 int 3102 zpool_do_upgrade(int argc, char **argv) 3103 { 3104 int c; 3105 upgrade_cbdata_t cb = { 0 }; 3106 int ret = 0; 3107 boolean_t showversions = B_FALSE; 3108 3109 /* check options */ 3110 while ((c = getopt(argc, argv, "av")) != -1) { 3111 switch (c) { 3112 case 'a': 3113 cb.cb_all = B_TRUE; 3114 break; 3115 case 'v': 3116 showversions = B_TRUE; 3117 break; 3118 case '?': 3119 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3120 optopt); 3121 usage(B_FALSE); 3122 } 3123 } 3124 3125 cb.cb_argc = argc; 3126 cb.cb_argv = argv; 3127 argc -= optind; 3128 argv += optind; 3129 3130 if (showversions) { 3131 if (cb.cb_all || argc != 0) { 3132 (void) fprintf(stderr, gettext("-v option is " 3133 "incompatible with other arguments\n")); 3134 usage(B_FALSE); 3135 } 3136 } else if (cb.cb_all) { 3137 if (argc != 0) { 3138 (void) fprintf(stderr, gettext("-a option is " 3139 "incompatible with other arguments\n")); 3140 usage(B_FALSE); 3141 } 3142 } 3143 3144 (void) printf(gettext("This system is currently running ZFS version " 3145 "%llu.\n\n"), ZFS_VERSION); 3146 cb.cb_first = B_TRUE; 3147 if (showversions) { 3148 (void) printf(gettext("The following versions are " 3149 "supported:\n\n")); 3150 (void) printf(gettext("VER DESCRIPTION\n")); 3151 (void) printf("--- -----------------------------------------" 3152 "---------------\n"); 3153 (void) printf(gettext(" 1 Initial ZFS version\n")); 3154 (void) printf(gettext(" 2 Ditto blocks " 3155 "(replicated metadata)\n")); 3156 (void) printf(gettext(" 3 Hot spares and double parity " 3157 "RAID-Z\n")); 3158 (void) printf(gettext("\nFor more information on a particular " 3159 "version, including supported releases, see:\n\n")); 3160 (void) printf("http://www.opensolaris.org/os/community/zfs/" 3161 "version/N\n\n"); 3162 (void) printf(gettext("Where 'N' is the version number.\n")); 3163 } else if (argc == 0) { 3164 int notfound; 3165 3166 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 3167 notfound = cb.cb_first; 3168 3169 if (!cb.cb_all && ret == 0) { 3170 if (!cb.cb_first) 3171 (void) printf("\n"); 3172 cb.cb_first = B_TRUE; 3173 cb.cb_newer = B_TRUE; 3174 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 3175 if (!cb.cb_first) { 3176 notfound = B_FALSE; 3177 (void) printf("\n"); 3178 } 3179 } 3180 3181 if (ret == 0) { 3182 if (notfound) 3183 (void) printf(gettext("All pools are formatted " 3184 "using this version.\n")); 3185 else if (!cb.cb_all) 3186 (void) printf(gettext("Use 'zpool upgrade -v' " 3187 "for a list of available versions and " 3188 "their associated\nfeatures.\n")); 3189 } 3190 } else { 3191 ret = for_each_pool(argc, argv, B_FALSE, upgrade_one, &cb); 3192 } 3193 3194 return (ret); 3195 } 3196 3197 /* 3198 * Print out the command history for a specific pool. 3199 */ 3200 static int 3201 get_history_one(zpool_handle_t *zhp, void *data) 3202 { 3203 nvlist_t *nvhis; 3204 nvlist_t **records; 3205 uint_t numrecords; 3206 char *cmdstr; 3207 uint64_t dst_time; 3208 time_t tsec; 3209 struct tm t; 3210 char tbuf[30]; 3211 int ret, i; 3212 3213 *(boolean_t *)data = B_FALSE; 3214 3215 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 3216 3217 if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 3218 return (ret); 3219 3220 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 3221 &records, &numrecords) == 0); 3222 for (i = 0; i < numrecords; i++) { 3223 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME, 3224 &dst_time) == 0) { 3225 verify(nvlist_lookup_string(records[i], ZPOOL_HIST_CMD, 3226 &cmdstr) == 0); 3227 tsec = dst_time; 3228 (void) localtime_r(&tsec, &t); 3229 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 3230 (void) printf("%s %s\n", tbuf, cmdstr); 3231 } 3232 } 3233 (void) printf("\n"); 3234 nvlist_free(nvhis); 3235 3236 return (ret); 3237 } 3238 3239 /* 3240 * zpool history <pool> 3241 * 3242 * Displays the history of commands that modified pools. 3243 */ 3244 int 3245 zpool_do_history(int argc, char **argv) 3246 { 3247 boolean_t first = B_TRUE; 3248 int ret; 3249 3250 argc -= optind; 3251 argv += optind; 3252 3253 ret = for_each_pool(argc, argv, B_FALSE, get_history_one, &first); 3254 3255 if (argc == 0 && first == B_TRUE) { 3256 (void) printf(gettext("no pools available\n")); 3257 return (0); 3258 } 3259 3260 return (ret); 3261 } 3262 3263 int 3264 main(int argc, char **argv) 3265 { 3266 int ret; 3267 int i; 3268 char *cmdname; 3269 3270 (void) setlocale(LC_ALL, ""); 3271 (void) textdomain(TEXT_DOMAIN); 3272 3273 if ((g_zfs = libzfs_init()) == NULL) { 3274 (void) fprintf(stderr, gettext("internal error: failed to " 3275 "initialize ZFS library\n")); 3276 return (1); 3277 } 3278 3279 libzfs_print_on_error(g_zfs, B_TRUE); 3280 3281 opterr = 0; 3282 3283 /* 3284 * Make sure the user has specified some command. 3285 */ 3286 if (argc < 2) { 3287 (void) fprintf(stderr, gettext("missing command\n")); 3288 usage(B_FALSE); 3289 } 3290 3291 cmdname = argv[1]; 3292 3293 /* 3294 * Special case '-?' 3295 */ 3296 if (strcmp(cmdname, "-?") == 0) 3297 usage(B_TRUE); 3298 3299 /* 3300 * Run the appropriate command. 3301 */ 3302 for (i = 0; i < NCOMMAND; i++) { 3303 if (command_table[i].name == NULL) 3304 continue; 3305 3306 if (strcmp(cmdname, command_table[i].name) == 0) { 3307 current_command = &command_table[i]; 3308 ret = command_table[i].func(argc - 1, argv + 1); 3309 break; 3310 } 3311 } 3312 3313 /* 3314 * 'freeze' is a vile debugging abomination, so we treat it as such. 3315 */ 3316 if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 3317 char buf[16384]; 3318 int fd = open(ZFS_DEV, O_RDWR); 3319 (void) strcpy((void *)buf, argv[2]); 3320 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 3321 } 3322 3323 if (i == NCOMMAND) { 3324 (void) fprintf(stderr, gettext("unrecognized " 3325 "command '%s'\n"), cmdname); 3326 usage(B_FALSE); 3327 } 3328 3329 libzfs_fini(g_zfs); 3330 3331 /* 3332 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 3333 * for the purposes of running ::findleaks. 3334 */ 3335 if (getenv("ZFS_ABORT") != NULL) { 3336 (void) printf("dumping core by request\n"); 3337 abort(); 3338 } 3339 3340 return (ret); 3341 } 3342