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