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