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