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