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