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