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