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