zpool_main.c revision 342941
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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2011, 2018 by Delphix. All rights reserved. 25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved. 26 * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved. 27 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved. 28 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>. 29 * Copyright 2016 Nexenta Systems, Inc. 30 * Copyright (c) 2017 Datto Inc. 31 */ 32 33#include <solaris.h> 34#include <assert.h> 35#include <ctype.h> 36#include <dirent.h> 37#include <errno.h> 38#include <fcntl.h> 39#include <getopt.h> 40#include <libgen.h> 41#include <libintl.h> 42#include <libuutil.h> 43#include <locale.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <strings.h> 48#include <unistd.h> 49#include <priv.h> 50#include <pwd.h> 51#include <zone.h> 52#include <sys/time.h> 53#include <zfs_prop.h> 54#include <sys/fs/zfs.h> 55#include <sys/stat.h> 56 57#include <libzfs.h> 58 59#include "zpool_util.h" 60#include "zfs_comutil.h" 61#include "zfeature_common.h" 62 63#include "statcommon.h" 64 65static int zpool_do_create(int, char **); 66static int zpool_do_destroy(int, char **); 67 68static int zpool_do_add(int, char **); 69static int zpool_do_remove(int, char **); 70static int zpool_do_labelclear(int, char **); 71 72static int zpool_do_checkpoint(int, char **); 73 74static int zpool_do_list(int, char **); 75static int zpool_do_iostat(int, char **); 76static int zpool_do_status(int, char **); 77 78static int zpool_do_online(int, char **); 79static int zpool_do_offline(int, char **); 80static int zpool_do_clear(int, char **); 81static int zpool_do_reopen(int, char **); 82 83static int zpool_do_reguid(int, char **); 84 85static int zpool_do_attach(int, char **); 86static int zpool_do_detach(int, char **); 87static int zpool_do_replace(int, char **); 88static int zpool_do_split(int, char **); 89 90static int zpool_do_initialize(int, char **); 91static int zpool_do_scrub(int, char **); 92 93static int zpool_do_import(int, char **); 94static int zpool_do_export(int, char **); 95 96static int zpool_do_upgrade(int, char **); 97 98static int zpool_do_history(int, char **); 99 100static int zpool_do_get(int, char **); 101static int zpool_do_set(int, char **); 102 103/* 104 * These libumem hooks provide a reasonable set of defaults for the allocator's 105 * debugging facilities. 106 */ 107 108#ifdef DEBUG 109const char * 110_umem_debug_init(void) 111{ 112 return ("default,verbose"); /* $UMEM_DEBUG setting */ 113} 114 115const char * 116_umem_logging_init(void) 117{ 118 return ("fail,contents"); /* $UMEM_LOGGING setting */ 119} 120#endif 121 122typedef enum { 123 HELP_ADD, 124 HELP_ATTACH, 125 HELP_CLEAR, 126 HELP_CREATE, 127 HELP_CHECKPOINT, 128 HELP_DESTROY, 129 HELP_DETACH, 130 HELP_EXPORT, 131 HELP_HISTORY, 132 HELP_IMPORT, 133 HELP_IOSTAT, 134 HELP_LABELCLEAR, 135 HELP_LIST, 136 HELP_OFFLINE, 137 HELP_ONLINE, 138 HELP_REPLACE, 139 HELP_REMOVE, 140 HELP_INITIALIZE, 141 HELP_SCRUB, 142 HELP_STATUS, 143 HELP_UPGRADE, 144 HELP_GET, 145 HELP_SET, 146 HELP_SPLIT, 147 HELP_REGUID, 148 HELP_REOPEN 149} zpool_help_t; 150 151 152typedef struct zpool_command { 153 const char *name; 154 int (*func)(int, char **); 155 zpool_help_t usage; 156} zpool_command_t; 157 158/* 159 * Master command table. Each ZFS command has a name, associated function, and 160 * usage message. The usage messages need to be internationalized, so we have 161 * to have a function to return the usage message based on a command index. 162 * 163 * These commands are organized according to how they are displayed in the usage 164 * message. An empty command (one with a NULL name) indicates an empty line in 165 * the generic usage message. 166 */ 167static zpool_command_t command_table[] = { 168 { "create", zpool_do_create, HELP_CREATE }, 169 { "destroy", zpool_do_destroy, HELP_DESTROY }, 170 { NULL }, 171 { "add", zpool_do_add, HELP_ADD }, 172 { "remove", zpool_do_remove, HELP_REMOVE }, 173 { NULL }, 174 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 175 { NULL }, 176 { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT }, 177 { NULL }, 178 { "list", zpool_do_list, HELP_LIST }, 179 { "iostat", zpool_do_iostat, HELP_IOSTAT }, 180 { "status", zpool_do_status, HELP_STATUS }, 181 { NULL }, 182 { "online", zpool_do_online, HELP_ONLINE }, 183 { "offline", zpool_do_offline, HELP_OFFLINE }, 184 { "clear", zpool_do_clear, HELP_CLEAR }, 185 { "reopen", zpool_do_reopen, HELP_REOPEN }, 186 { NULL }, 187 { "attach", zpool_do_attach, HELP_ATTACH }, 188 { "detach", zpool_do_detach, HELP_DETACH }, 189 { "replace", zpool_do_replace, HELP_REPLACE }, 190 { "split", zpool_do_split, HELP_SPLIT }, 191 { NULL }, 192 { "initialize", zpool_do_initialize, HELP_INITIALIZE }, 193 { "scrub", zpool_do_scrub, HELP_SCRUB }, 194 { NULL }, 195 { "import", zpool_do_import, HELP_IMPORT }, 196 { "export", zpool_do_export, HELP_EXPORT }, 197 { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 198 { "reguid", zpool_do_reguid, HELP_REGUID }, 199 { NULL }, 200 { "history", zpool_do_history, HELP_HISTORY }, 201 { "get", zpool_do_get, HELP_GET }, 202 { "set", zpool_do_set, HELP_SET }, 203}; 204 205#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 206 207static zpool_command_t *current_command; 208static char history_str[HIS_MAX_RECORD_LEN]; 209static boolean_t log_history = B_TRUE; 210static uint_t timestamp_fmt = NODATE; 211 212static const char * 213get_usage(zpool_help_t idx) 214{ 215 switch (idx) { 216 case HELP_ADD: 217 return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 218 case HELP_ATTACH: 219 return (gettext("\tattach [-f] <pool> <device> " 220 "<new-device>\n")); 221 case HELP_CLEAR: 222 return (gettext("\tclear [-nF] <pool> [device]\n")); 223 case HELP_CREATE: 224 return (gettext("\tcreate [-fnd] [-B] " 225 "[-o property=value] ... \n" 226 "\t [-O file-system-property=value] ...\n" 227 "\t [-m mountpoint] [-R root] [-t tempname] " 228 "<pool> <vdev> ...\n")); 229 case HELP_CHECKPOINT: 230 return (gettext("\tcheckpoint [--discard] <pool> ...\n")); 231 case HELP_DESTROY: 232 return (gettext("\tdestroy [-f] <pool>\n")); 233 case HELP_DETACH: 234 return (gettext("\tdetach <pool> <device>\n")); 235 case HELP_EXPORT: 236 return (gettext("\texport [-f] <pool> ...\n")); 237 case HELP_HISTORY: 238 return (gettext("\thistory [-il] [<pool>] ...\n")); 239 case HELP_IMPORT: 240 return (gettext("\timport [-d dir] [-D]\n" 241 "\timport [-o mntopts] [-o property=value] ... \n" 242 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 243 "[-R root] [-F [-n]] -a\n" 244 "\timport [-o mntopts] [-o property=value] ... \n" 245 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 246 "[-R root] [-F [-n]] [-t]\n" 247 "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n")); 248 case HELP_IOSTAT: 249 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval " 250 "[count]]\n")); 251 case HELP_LABELCLEAR: 252 return (gettext("\tlabelclear [-f] <vdev>\n")); 253 case HELP_LIST: 254 return (gettext("\tlist [-Hpv] [-o property[,...]] " 255 "[-T d|u] [pool] ... [interval [count]]\n")); 256 case HELP_OFFLINE: 257 return (gettext("\toffline [-t] <pool> <device> ...\n")); 258 case HELP_ONLINE: 259 return (gettext("\tonline [-e] <pool> <device> ...\n")); 260 case HELP_REPLACE: 261 return (gettext("\treplace [-f] <pool> <device> " 262 "[new-device]\n")); 263 case HELP_REMOVE: 264 return (gettext("\tremove [-nps] <pool> <device> ...\n")); 265 case HELP_REOPEN: 266 return (gettext("\treopen <pool>\n")); 267 case HELP_INITIALIZE: 268 return (gettext("\tinitialize [-cs] <pool> [<device> ...]\n")); 269 case HELP_SCRUB: 270 return (gettext("\tscrub [-s | -p] <pool> ...\n")); 271 case HELP_STATUS: 272 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval " 273 "[count]]\n")); 274 case HELP_UPGRADE: 275 return (gettext("\tupgrade [-v]\n" 276 "\tupgrade [-V version] <-a | pool ...>\n")); 277 case HELP_GET: 278 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] " 279 "<\"all\" | property[,...]> <pool> ...\n")); 280 case HELP_SET: 281 return (gettext("\tset <property=value> <pool> \n")); 282 case HELP_SPLIT: 283 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n" 284 "\t [-o property=value] <pool> <newpool> " 285 "[<device> ...]\n")); 286 case HELP_REGUID: 287 return (gettext("\treguid <pool>\n")); 288 } 289 290 abort(); 291 /* NOTREACHED */ 292} 293 294 295/* 296 * Callback routine that will print out a pool property value. 297 */ 298static int 299print_prop_cb(int prop, void *cb) 300{ 301 FILE *fp = cb; 302 303 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop)); 304 305 if (zpool_prop_readonly(prop)) 306 (void) fprintf(fp, " NO "); 307 else 308 (void) fprintf(fp, " YES "); 309 310 if (zpool_prop_values(prop) == NULL) 311 (void) fprintf(fp, "-\n"); 312 else 313 (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 314 315 return (ZPROP_CONT); 316} 317 318/* 319 * Display usage message. If we're inside a command, display only the usage for 320 * that command. Otherwise, iterate over the entire command table and display 321 * a complete usage message. 322 */ 323void 324usage(boolean_t requested) 325{ 326 FILE *fp = requested ? stdout : stderr; 327 328 if (current_command == NULL) { 329 int i; 330 331 (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 332 (void) fprintf(fp, 333 gettext("where 'command' is one of the following:\n\n")); 334 335 for (i = 0; i < NCOMMAND; i++) { 336 if (command_table[i].name == NULL) 337 (void) fprintf(fp, "\n"); 338 else 339 (void) fprintf(fp, "%s", 340 get_usage(command_table[i].usage)); 341 } 342 } else { 343 (void) fprintf(fp, gettext("usage:\n")); 344 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 345 } 346 347 if (current_command != NULL && 348 ((strcmp(current_command->name, "set") == 0) || 349 (strcmp(current_command->name, "get") == 0) || 350 (strcmp(current_command->name, "list") == 0))) { 351 352 (void) fprintf(fp, 353 gettext("\nthe following properties are supported:\n")); 354 355 (void) fprintf(fp, "\n\t%-15s %s %s\n\n", 356 "PROPERTY", "EDIT", "VALUES"); 357 358 /* Iterate over all properties */ 359 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 360 ZFS_TYPE_POOL); 361 362 (void) fprintf(fp, "\t%-15s ", "feature@..."); 363 (void) fprintf(fp, "YES disabled | enabled | active\n"); 364 365 (void) fprintf(fp, gettext("\nThe feature@ properties must be " 366 "appended with a feature name.\nSee zpool-features(7).\n")); 367 } 368 369 /* 370 * See comments at end of main(). 371 */ 372 if (getenv("ZFS_ABORT") != NULL) { 373 (void) printf("dumping core by request\n"); 374 abort(); 375 } 376 377 exit(requested ? 0 : 2); 378} 379 380void 381print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 382 boolean_t print_logs) 383{ 384 nvlist_t **child; 385 uint_t c, children; 386 char *vname; 387 388 if (name != NULL) 389 (void) printf("\t%*s%s\n", indent, "", name); 390 391 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 392 &child, &children) != 0) 393 return; 394 395 for (c = 0; c < children; c++) { 396 uint64_t is_log = B_FALSE; 397 398 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 399 &is_log); 400 if ((is_log && !print_logs) || (!is_log && print_logs)) 401 continue; 402 403 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 404 print_vdev_tree(zhp, vname, child[c], indent + 2, 405 B_FALSE); 406 free(vname); 407 } 408} 409 410static boolean_t 411prop_list_contains_feature(nvlist_t *proplist) 412{ 413 nvpair_t *nvp; 414 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 415 nvp = nvlist_next_nvpair(proplist, nvp)) { 416 if (zpool_prop_feature(nvpair_name(nvp))) 417 return (B_TRUE); 418 } 419 return (B_FALSE); 420} 421 422/* 423 * Add a property pair (name, string-value) into a property nvlist. 424 */ 425static int 426add_prop_list(const char *propname, char *propval, nvlist_t **props, 427 boolean_t poolprop) 428{ 429 zpool_prop_t prop = ZPROP_INVAL; 430 zfs_prop_t fprop; 431 nvlist_t *proplist; 432 const char *normnm; 433 char *strval; 434 435 if (*props == NULL && 436 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 437 (void) fprintf(stderr, 438 gettext("internal error: out of memory\n")); 439 return (1); 440 } 441 442 proplist = *props; 443 444 if (poolprop) { 445 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 446 447 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL && 448 !zpool_prop_feature(propname)) { 449 (void) fprintf(stderr, gettext("property '%s' is " 450 "not a valid pool property\n"), propname); 451 return (2); 452 } 453 454 /* 455 * feature@ properties and version should not be specified 456 * at the same time. 457 */ 458 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) && 459 nvlist_exists(proplist, vname)) || 460 (prop == ZPOOL_PROP_VERSION && 461 prop_list_contains_feature(proplist))) { 462 (void) fprintf(stderr, gettext("'feature@' and " 463 "'version' properties cannot be specified " 464 "together\n")); 465 return (2); 466 } 467 468 469 if (zpool_prop_feature(propname)) 470 normnm = propname; 471 else 472 normnm = zpool_prop_to_name(prop); 473 } else { 474 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 475 normnm = zfs_prop_to_name(fprop); 476 } else { 477 normnm = propname; 478 } 479 } 480 481 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 482 prop != ZPOOL_PROP_CACHEFILE) { 483 (void) fprintf(stderr, gettext("property '%s' " 484 "specified multiple times\n"), propname); 485 return (2); 486 } 487 488 if (nvlist_add_string(proplist, normnm, propval) != 0) { 489 (void) fprintf(stderr, gettext("internal " 490 "error: out of memory\n")); 491 return (1); 492 } 493 494 return (0); 495} 496 497/* 498 * Set a default property pair (name, string-value) in a property nvlist 499 */ 500static int 501add_prop_list_default(const char *propname, char *propval, nvlist_t **props, 502 boolean_t poolprop) 503{ 504 char *pval; 505 506 if (nvlist_lookup_string(*props, propname, &pval) == 0) 507 return (0); 508 509 return (add_prop_list(propname, propval, props, poolprop)); 510} 511 512/* 513 * zpool add [-fn] <pool> <vdev> ... 514 * 515 * -f Force addition of devices, even if they appear in use 516 * -n Do not add the devices, but display the resulting layout if 517 * they were to be added. 518 * 519 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 520 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 521 * libzfs. 522 */ 523int 524zpool_do_add(int argc, char **argv) 525{ 526 boolean_t force = B_FALSE; 527 boolean_t dryrun = B_FALSE; 528 int c; 529 nvlist_t *nvroot; 530 char *poolname; 531 zpool_boot_label_t boot_type; 532 uint64_t boot_size; 533 int ret; 534 zpool_handle_t *zhp; 535 nvlist_t *config; 536 537 /* check options */ 538 while ((c = getopt(argc, argv, "fn")) != -1) { 539 switch (c) { 540 case 'f': 541 force = B_TRUE; 542 break; 543 case 'n': 544 dryrun = B_TRUE; 545 break; 546 case '?': 547 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 548 optopt); 549 usage(B_FALSE); 550 } 551 } 552 553 argc -= optind; 554 argv += optind; 555 556 /* get pool name and check number of arguments */ 557 if (argc < 1) { 558 (void) fprintf(stderr, gettext("missing pool name argument\n")); 559 usage(B_FALSE); 560 } 561 if (argc < 2) { 562 (void) fprintf(stderr, gettext("missing vdev specification\n")); 563 usage(B_FALSE); 564 } 565 566 poolname = argv[0]; 567 568 argc--; 569 argv++; 570 571 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 572 return (1); 573 574 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 575 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 576 poolname); 577 zpool_close(zhp); 578 return (1); 579 } 580 581 if (zpool_is_bootable(zhp)) 582 boot_type = ZPOOL_COPY_BOOT_LABEL; 583 else 584 boot_type = ZPOOL_NO_BOOT_LABEL; 585 586 /* pass off to get_vdev_spec for processing */ 587 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 588 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun, 589 boot_type, boot_size, argc, argv); 590 if (nvroot == NULL) { 591 zpool_close(zhp); 592 return (1); 593 } 594 595 if (dryrun) { 596 nvlist_t *poolnvroot; 597 598 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 599 &poolnvroot) == 0); 600 601 (void) printf(gettext("would update '%s' to the following " 602 "configuration:\n"), zpool_get_name(zhp)); 603 604 /* print original main pool and new tree */ 605 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 606 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 607 608 /* Do the same for the logs */ 609 if (num_logs(poolnvroot) > 0) { 610 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 611 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 612 } else if (num_logs(nvroot) > 0) { 613 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 614 } 615 616 ret = 0; 617 } else { 618 ret = (zpool_add(zhp, nvroot) != 0); 619 } 620 621 nvlist_free(nvroot); 622 zpool_close(zhp); 623 624 return (ret); 625} 626 627/* 628 * zpool remove <pool> <vdev> ... 629 * 630 * Removes the given vdev from the pool. 631 */ 632int 633zpool_do_remove(int argc, char **argv) 634{ 635 char *poolname; 636 int i, ret = 0; 637 zpool_handle_t *zhp; 638 boolean_t stop = B_FALSE; 639 boolean_t noop = B_FALSE; 640 boolean_t parsable = B_FALSE; 641 char c; 642 643 /* check options */ 644 while ((c = getopt(argc, argv, "nps")) != -1) { 645 switch (c) { 646 case 'n': 647 noop = B_TRUE; 648 break; 649 case 'p': 650 parsable = B_TRUE; 651 break; 652 case 's': 653 stop = B_TRUE; 654 break; 655 case '?': 656 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 657 optopt); 658 usage(B_FALSE); 659 } 660 } 661 662 argc -= optind; 663 argv += optind; 664 665 /* get pool name and check number of arguments */ 666 if (argc < 1) { 667 (void) fprintf(stderr, gettext("missing pool name argument\n")); 668 usage(B_FALSE); 669 } 670 671 poolname = argv[0]; 672 673 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 674 return (1); 675 676 if (stop && noop) { 677 (void) fprintf(stderr, gettext("stop request ignored\n")); 678 return (0); 679 } 680 681 if (stop) { 682 if (argc > 1) { 683 (void) fprintf(stderr, gettext("too many arguments\n")); 684 usage(B_FALSE); 685 } 686 if (zpool_vdev_remove_cancel(zhp) != 0) 687 ret = 1; 688 } else { 689 if (argc < 2) { 690 (void) fprintf(stderr, gettext("missing device\n")); 691 usage(B_FALSE); 692 } 693 694 for (i = 1; i < argc; i++) { 695 if (noop) { 696 uint64_t size; 697 698 if (zpool_vdev_indirect_size(zhp, argv[i], 699 &size) != 0) { 700 ret = 1; 701 break; 702 } 703 if (parsable) { 704 (void) printf("%s %llu\n", 705 argv[i], size); 706 } else { 707 char valstr[32]; 708 zfs_nicenum(size, valstr, 709 sizeof (valstr)); 710 (void) printf("Memory that will be " 711 "used after removing %s: %s\n", 712 argv[i], valstr); 713 } 714 } else { 715 if (zpool_vdev_remove(zhp, argv[i]) != 0) 716 ret = 1; 717 } 718 } 719 } 720 721 return (ret); 722} 723 724/* 725 * zpool labelclear [-f] <vdev> 726 * 727 * -f Force clearing the label for the vdevs which are members of 728 * the exported or foreign pools. 729 * 730 * Verifies that the vdev is not active and zeros out the label information 731 * on the device. 732 */ 733int 734zpool_do_labelclear(int argc, char **argv) 735{ 736 char vdev[MAXPATHLEN]; 737 char *name = NULL; 738 struct stat st; 739 int c, fd, ret = 0; 740 nvlist_t *config; 741 pool_state_t state; 742 boolean_t inuse = B_FALSE; 743 boolean_t force = B_FALSE; 744 745 /* check options */ 746 while ((c = getopt(argc, argv, "f")) != -1) { 747 switch (c) { 748 case 'f': 749 force = B_TRUE; 750 break; 751 default: 752 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 753 optopt); 754 usage(B_FALSE); 755 } 756 } 757 758 argc -= optind; 759 argv += optind; 760 761 /* get vdev name */ 762 if (argc < 1) { 763 (void) fprintf(stderr, gettext("missing vdev name\n")); 764 usage(B_FALSE); 765 } 766 if (argc > 1) { 767 (void) fprintf(stderr, gettext("too many arguments\n")); 768 usage(B_FALSE); 769 } 770 771 /* 772 * Check if we were given absolute path and use it as is. 773 * Otherwise if the provided vdev name doesn't point to a file, 774 * try prepending dsk path and appending s0. 775 */ 776 (void) strlcpy(vdev, argv[0], sizeof (vdev)); 777 if (vdev[0] != '/' && stat(vdev, &st) != 0) { 778 char *s; 779 780 (void) snprintf(vdev, sizeof (vdev), "%s/%s", 781#ifdef illumos 782 ZFS_DISK_ROOT, argv[0]); 783 if ((s = strrchr(argv[0], 's')) == NULL || 784 !isdigit(*(s + 1))) 785 (void) strlcat(vdev, "s0", sizeof (vdev)); 786#else 787 "/dev", argv[0]); 788#endif 789 if (stat(vdev, &st) != 0) { 790 (void) fprintf(stderr, gettext( 791 "failed to find device %s, try specifying absolute " 792 "path instead\n"), argv[0]); 793 return (1); 794 } 795 } 796 797 if ((fd = open(vdev, O_RDWR)) < 0) { 798 (void) fprintf(stderr, gettext("failed to open %s: %s\n"), 799 vdev, strerror(errno)); 800 return (1); 801 } 802 803 if (zpool_read_label(fd, &config) != 0) { 804 (void) fprintf(stderr, 805 gettext("failed to read label from %s\n"), vdev); 806 return (1); 807 } 808 nvlist_free(config); 809 810 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); 811 if (ret != 0) { 812 (void) fprintf(stderr, 813 gettext("failed to check state for %s\n"), vdev); 814 return (1); 815 } 816 817 if (!inuse) 818 goto wipe_label; 819 820 switch (state) { 821 default: 822 case POOL_STATE_ACTIVE: 823 case POOL_STATE_SPARE: 824 case POOL_STATE_L2CACHE: 825 (void) fprintf(stderr, gettext( 826 "%s is a member (%s) of pool \"%s\"\n"), 827 vdev, zpool_pool_state_to_name(state), name); 828 ret = 1; 829 goto errout; 830 831 case POOL_STATE_EXPORTED: 832 if (force) 833 break; 834 (void) fprintf(stderr, gettext( 835 "use '-f' to override the following error:\n" 836 "%s is a member of exported pool \"%s\"\n"), 837 vdev, name); 838 ret = 1; 839 goto errout; 840 841 case POOL_STATE_POTENTIALLY_ACTIVE: 842 if (force) 843 break; 844 (void) fprintf(stderr, gettext( 845 "use '-f' to override the following error:\n" 846 "%s is a member of potentially active pool \"%s\"\n"), 847 vdev, name); 848 ret = 1; 849 goto errout; 850 851 case POOL_STATE_DESTROYED: 852 /* inuse should never be set for a destroyed pool */ 853 assert(0); 854 break; 855 } 856 857wipe_label: 858 ret = zpool_clear_label(fd); 859 if (ret != 0) { 860 (void) fprintf(stderr, 861 gettext("failed to clear label for %s\n"), vdev); 862 } 863 864errout: 865 free(name); 866 (void) close(fd); 867 868 return (ret); 869} 870 871/* 872 * zpool create [-fnd] [-B] [-o property=value] ... 873 * [-O file-system-property=value] ... 874 * [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ... 875 * 876 * -B Create boot partition. 877 * -f Force creation, even if devices appear in use 878 * -n Do not create the pool, but display the resulting layout if it 879 * were to be created. 880 * -R Create a pool under an alternate root 881 * -m Set default mountpoint for the root dataset. By default it's 882 * '/<pool>' 883 * -t Use the temporary name until the pool is exported. 884 * -o Set property=value. 885 * -d Don't automatically enable all supported pool features 886 * (individual features can be enabled with -o). 887 * -O Set fsproperty=value in the pool's root file system 888 * 889 * Creates the named pool according to the given vdev specification. The 890 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 891 * we get the nvlist back from get_vdev_spec(), we either print out the contents 892 * (if '-n' was specified), or pass it to libzfs to do the creation. 893 */ 894 895#define SYSTEM256 (256 * 1024 * 1024) 896int 897zpool_do_create(int argc, char **argv) 898{ 899 boolean_t force = B_FALSE; 900 boolean_t dryrun = B_FALSE; 901 boolean_t enable_all_pool_feat = B_TRUE; 902 zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL; 903 uint64_t boot_size = 0; 904 int c; 905 nvlist_t *nvroot = NULL; 906 char *poolname; 907 char *tname = NULL; 908 int ret = 1; 909 char *altroot = NULL; 910 char *mountpoint = NULL; 911 nvlist_t *fsprops = NULL; 912 nvlist_t *props = NULL; 913 char *propval; 914 915 /* check options */ 916 while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) { 917 switch (c) { 918 case 'f': 919 force = B_TRUE; 920 break; 921 case 'n': 922 dryrun = B_TRUE; 923 break; 924 case 'd': 925 enable_all_pool_feat = B_FALSE; 926 break; 927 case 'B': 928#ifdef illumos 929 /* 930 * We should create the system partition. 931 * Also make sure the size is set. 932 */ 933 boot_type = ZPOOL_CREATE_BOOT_LABEL; 934 if (boot_size == 0) 935 boot_size = SYSTEM256; 936 break; 937#else 938 (void) fprintf(stderr, 939 gettext("option '%c' is not supported\n"), 940 optopt); 941 goto badusage; 942#endif 943 case 'R': 944 altroot = optarg; 945 if (add_prop_list(zpool_prop_to_name( 946 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 947 goto errout; 948 if (add_prop_list_default(zpool_prop_to_name( 949 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 950 goto errout; 951 break; 952 case 'm': 953 /* Equivalent to -O mountpoint=optarg */ 954 mountpoint = optarg; 955 break; 956 case 'o': 957 if ((propval = strchr(optarg, '=')) == NULL) { 958 (void) fprintf(stderr, gettext("missing " 959 "'=' for -o option\n")); 960 goto errout; 961 } 962 *propval = '\0'; 963 propval++; 964 965 if (add_prop_list(optarg, propval, &props, B_TRUE)) 966 goto errout; 967 968 /* 969 * Get bootsize value for make_root_vdev(). 970 */ 971 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) { 972 if (zfs_nicestrtonum(g_zfs, propval, 973 &boot_size) < 0 || boot_size == 0) { 974 (void) fprintf(stderr, 975 gettext("bad boot partition size " 976 "'%s': %s\n"), propval, 977 libzfs_error_description(g_zfs)); 978 goto errout; 979 } 980 } 981 982 /* 983 * If the user is creating a pool that doesn't support 984 * feature flags, don't enable any features. 985 */ 986 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 987 char *end; 988 u_longlong_t ver; 989 990 ver = strtoull(propval, &end, 10); 991 if (*end == '\0' && 992 ver < SPA_VERSION_FEATURES) { 993 enable_all_pool_feat = B_FALSE; 994 } 995 } 996 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) 997 altroot = propval; 998 break; 999 case 'O': 1000 if ((propval = strchr(optarg, '=')) == NULL) { 1001 (void) fprintf(stderr, gettext("missing " 1002 "'=' for -O option\n")); 1003 goto errout; 1004 } 1005 *propval = '\0'; 1006 propval++; 1007 1008 /* 1009 * Mountpoints are checked and then added later. 1010 * Uniquely among properties, they can be specified 1011 * more than once, to avoid conflict with -m. 1012 */ 1013 if (0 == strcmp(optarg, 1014 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 1015 mountpoint = propval; 1016 } else if (add_prop_list(optarg, propval, &fsprops, 1017 B_FALSE)) { 1018 goto errout; 1019 } 1020 break; 1021 case 't': 1022 /* 1023 * Sanity check temporary pool name. 1024 */ 1025 if (strchr(optarg, '/') != NULL) { 1026 (void) fprintf(stderr, gettext("cannot create " 1027 "'%s': invalid character '/' in temporary " 1028 "name\n"), optarg); 1029 (void) fprintf(stderr, gettext("use 'zfs " 1030 "create' to create a dataset\n")); 1031 goto errout; 1032 } 1033 1034 if (add_prop_list(zpool_prop_to_name( 1035 ZPOOL_PROP_TNAME), optarg, &props, B_TRUE)) 1036 goto errout; 1037 if (add_prop_list_default(zpool_prop_to_name( 1038 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1039 goto errout; 1040 tname = optarg; 1041 break; 1042 case ':': 1043 (void) fprintf(stderr, gettext("missing argument for " 1044 "'%c' option\n"), optopt); 1045 goto badusage; 1046 case '?': 1047 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1048 optopt); 1049 goto badusage; 1050 } 1051 } 1052 1053 argc -= optind; 1054 argv += optind; 1055 1056 /* get pool name and check number of arguments */ 1057 if (argc < 1) { 1058 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1059 goto badusage; 1060 } 1061 if (argc < 2) { 1062 (void) fprintf(stderr, gettext("missing vdev specification\n")); 1063 goto badusage; 1064 } 1065 1066 poolname = argv[0]; 1067 1068 /* 1069 * As a special case, check for use of '/' in the name, and direct the 1070 * user to use 'zfs create' instead. 1071 */ 1072 if (strchr(poolname, '/') != NULL) { 1073 (void) fprintf(stderr, gettext("cannot create '%s': invalid " 1074 "character '/' in pool name\n"), poolname); 1075 (void) fprintf(stderr, gettext("use 'zfs create' to " 1076 "create a dataset\n")); 1077 goto errout; 1078 } 1079 1080 /* 1081 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used, 1082 * and not set otherwise. 1083 */ 1084 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) { 1085 const char *propname; 1086 char *strptr, *buf = NULL; 1087 int rv; 1088 1089 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 1090 if (nvlist_lookup_string(props, propname, &strptr) != 0) { 1091 (void) asprintf(&buf, "%" PRIu64, boot_size); 1092 if (buf == NULL) { 1093 (void) fprintf(stderr, 1094 gettext("internal error: out of memory\n")); 1095 goto errout; 1096 } 1097 rv = add_prop_list(propname, buf, &props, B_TRUE); 1098 free(buf); 1099 if (rv != 0) 1100 goto errout; 1101 } 1102 } else { 1103 const char *propname; 1104 char *strptr; 1105 1106 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 1107 if (nvlist_lookup_string(props, propname, &strptr) == 0) { 1108 (void) fprintf(stderr, gettext("error: setting boot " 1109 "partition size requires option '-B'\n")); 1110 goto errout; 1111 } 1112 } 1113 1114 /* pass off to get_vdev_spec for bulk processing */ 1115 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun, 1116 boot_type, boot_size, argc - 1, argv + 1); 1117 if (nvroot == NULL) 1118 goto errout; 1119 1120 /* make_root_vdev() allows 0 toplevel children if there are spares */ 1121 if (!zfs_allocatable_devs(nvroot)) { 1122 (void) fprintf(stderr, gettext("invalid vdev " 1123 "specification: at least one toplevel vdev must be " 1124 "specified\n")); 1125 goto errout; 1126 } 1127 1128 if (altroot != NULL && altroot[0] != '/') { 1129 (void) fprintf(stderr, gettext("invalid alternate root '%s': " 1130 "must be an absolute path\n"), altroot); 1131 goto errout; 1132 } 1133 1134 /* 1135 * Check the validity of the mountpoint and direct the user to use the 1136 * '-m' mountpoint option if it looks like its in use. 1137 * Ignore the checks if the '-f' option is given. 1138 */ 1139 if (!force && (mountpoint == NULL || 1140 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 1141 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) { 1142 char buf[MAXPATHLEN]; 1143 DIR *dirp; 1144 1145 if (mountpoint && mountpoint[0] != '/') { 1146 (void) fprintf(stderr, gettext("invalid mountpoint " 1147 "'%s': must be an absolute path, 'legacy', or " 1148 "'none'\n"), mountpoint); 1149 goto errout; 1150 } 1151 1152 if (mountpoint == NULL) { 1153 if (altroot != NULL) 1154 (void) snprintf(buf, sizeof (buf), "%s/%s", 1155 altroot, poolname); 1156 else 1157 (void) snprintf(buf, sizeof (buf), "/%s", 1158 poolname); 1159 } else { 1160 if (altroot != NULL) 1161 (void) snprintf(buf, sizeof (buf), "%s%s", 1162 altroot, mountpoint); 1163 else 1164 (void) snprintf(buf, sizeof (buf), "%s", 1165 mountpoint); 1166 } 1167 1168 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 1169 (void) fprintf(stderr, gettext("mountpoint '%s' : " 1170 "%s\n"), buf, strerror(errno)); 1171 (void) fprintf(stderr, gettext("use '-m' " 1172 "option to provide a different default\n")); 1173 goto errout; 1174 } else if (dirp) { 1175 int count = 0; 1176 1177 while (count < 3 && readdir(dirp) != NULL) 1178 count++; 1179 (void) closedir(dirp); 1180 1181 if (count > 2) { 1182 (void) fprintf(stderr, gettext("mountpoint " 1183 "'%s' exists and is not empty\n"), buf); 1184 (void) fprintf(stderr, gettext("use '-m' " 1185 "option to provide a " 1186 "different default\n")); 1187 goto errout; 1188 } 1189 } 1190 } 1191 1192 /* 1193 * Now that the mountpoint's validity has been checked, ensure that 1194 * the property is set appropriately prior to creating the pool. 1195 */ 1196 if (mountpoint != NULL) { 1197 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1198 mountpoint, &fsprops, B_FALSE); 1199 if (ret != 0) 1200 goto errout; 1201 } 1202 1203 ret = 1; 1204 if (dryrun) { 1205 /* 1206 * For a dry run invocation, print out a basic message and run 1207 * through all the vdevs in the list and print out in an 1208 * appropriate hierarchy. 1209 */ 1210 (void) printf(gettext("would create '%s' with the " 1211 "following layout:\n\n"), poolname); 1212 1213 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 1214 if (num_logs(nvroot) > 0) 1215 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 1216 1217 ret = 0; 1218 } else { 1219 /* 1220 * Hand off to libzfs. 1221 */ 1222 if (enable_all_pool_feat) { 1223 spa_feature_t i; 1224 for (i = 0; i < SPA_FEATURES; i++) { 1225 char propname[MAXPATHLEN]; 1226 zfeature_info_t *feat = &spa_feature_table[i]; 1227 1228 (void) snprintf(propname, sizeof (propname), 1229 "feature@%s", feat->fi_uname); 1230 1231 /* 1232 * Skip feature if user specified it manually 1233 * on the command line. 1234 */ 1235 if (nvlist_exists(props, propname)) 1236 continue; 1237 1238 ret = add_prop_list(propname, 1239 ZFS_FEATURE_ENABLED, &props, B_TRUE); 1240 if (ret != 0) 1241 goto errout; 1242 } 1243 } 1244 1245 ret = 1; 1246 if (zpool_create(g_zfs, poolname, 1247 nvroot, props, fsprops) == 0) { 1248 zfs_handle_t *pool = zfs_open(g_zfs, 1249 tname ? tname : poolname, ZFS_TYPE_FILESYSTEM); 1250 if (pool != NULL) { 1251 if (zfs_mount(pool, NULL, 0) == 0) 1252 ret = zfs_shareall(pool); 1253 zfs_close(pool); 1254 } 1255 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 1256 (void) fprintf(stderr, gettext("pool name may have " 1257 "been omitted\n")); 1258 } 1259 } 1260 1261errout: 1262 nvlist_free(nvroot); 1263 nvlist_free(fsprops); 1264 nvlist_free(props); 1265 return (ret); 1266badusage: 1267 nvlist_free(fsprops); 1268 nvlist_free(props); 1269 usage(B_FALSE); 1270 return (2); 1271} 1272 1273/* 1274 * zpool destroy <pool> 1275 * 1276 * -f Forcefully unmount any datasets 1277 * 1278 * Destroy the given pool. Automatically unmounts any datasets in the pool. 1279 */ 1280int 1281zpool_do_destroy(int argc, char **argv) 1282{ 1283 boolean_t force = B_FALSE; 1284 int c; 1285 char *pool; 1286 zpool_handle_t *zhp; 1287 int ret; 1288 1289 /* check options */ 1290 while ((c = getopt(argc, argv, "f")) != -1) { 1291 switch (c) { 1292 case 'f': 1293 force = B_TRUE; 1294 break; 1295 case '?': 1296 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1297 optopt); 1298 usage(B_FALSE); 1299 } 1300 } 1301 1302 argc -= optind; 1303 argv += optind; 1304 1305 /* check arguments */ 1306 if (argc < 1) { 1307 (void) fprintf(stderr, gettext("missing pool argument\n")); 1308 usage(B_FALSE); 1309 } 1310 if (argc > 1) { 1311 (void) fprintf(stderr, gettext("too many arguments\n")); 1312 usage(B_FALSE); 1313 } 1314 1315 pool = argv[0]; 1316 1317 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1318 /* 1319 * As a special case, check for use of '/' in the name, and 1320 * direct the user to use 'zfs destroy' instead. 1321 */ 1322 if (strchr(pool, '/') != NULL) 1323 (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1324 "destroy a dataset\n")); 1325 return (1); 1326 } 1327 1328 if (zpool_disable_datasets(zhp, force) != 0) { 1329 (void) fprintf(stderr, gettext("could not destroy '%s': " 1330 "could not unmount datasets\n"), zpool_get_name(zhp)); 1331 return (1); 1332 } 1333 1334 /* The history must be logged as part of the export */ 1335 log_history = B_FALSE; 1336 1337 ret = (zpool_destroy(zhp, history_str) != 0); 1338 1339 zpool_close(zhp); 1340 1341 return (ret); 1342} 1343 1344/* 1345 * zpool export [-f] <pool> ... 1346 * 1347 * -f Forcefully unmount datasets 1348 * 1349 * Export the given pools. By default, the command will attempt to cleanly 1350 * unmount any active datasets within the pool. If the '-f' flag is specified, 1351 * then the datasets will be forcefully unmounted. 1352 */ 1353int 1354zpool_do_export(int argc, char **argv) 1355{ 1356 boolean_t force = B_FALSE; 1357 boolean_t hardforce = B_FALSE; 1358 int c; 1359 zpool_handle_t *zhp; 1360 int ret; 1361 int i; 1362 1363 /* check options */ 1364 while ((c = getopt(argc, argv, "fF")) != -1) { 1365 switch (c) { 1366 case 'f': 1367 force = B_TRUE; 1368 break; 1369 case 'F': 1370 hardforce = B_TRUE; 1371 break; 1372 case '?': 1373 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1374 optopt); 1375 usage(B_FALSE); 1376 } 1377 } 1378 1379 argc -= optind; 1380 argv += optind; 1381 1382 /* check arguments */ 1383 if (argc < 1) { 1384 (void) fprintf(stderr, gettext("missing pool argument\n")); 1385 usage(B_FALSE); 1386 } 1387 1388 ret = 0; 1389 for (i = 0; i < argc; i++) { 1390 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 1391 ret = 1; 1392 continue; 1393 } 1394 1395 if (zpool_disable_datasets(zhp, force) != 0) { 1396 ret = 1; 1397 zpool_close(zhp); 1398 continue; 1399 } 1400 1401 /* The history must be logged as part of the export */ 1402 log_history = B_FALSE; 1403 1404 if (hardforce) { 1405 if (zpool_export_force(zhp, history_str) != 0) 1406 ret = 1; 1407 } else if (zpool_export(zhp, force, history_str) != 0) { 1408 ret = 1; 1409 } 1410 1411 zpool_close(zhp); 1412 } 1413 1414 return (ret); 1415} 1416 1417/* 1418 * Given a vdev configuration, determine the maximum width needed for the device 1419 * name column. 1420 */ 1421static int 1422max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 1423{ 1424 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE); 1425 nvlist_t **child; 1426 uint_t c, children; 1427 int ret; 1428 1429 if (strlen(name) + depth > max) 1430 max = strlen(name) + depth; 1431 1432 free(name); 1433 1434 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1435 &child, &children) == 0) { 1436 for (c = 0; c < children; c++) 1437 if ((ret = max_width(zhp, child[c], depth + 2, 1438 max)) > max) 1439 max = ret; 1440 } 1441 1442 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1443 &child, &children) == 0) { 1444 for (c = 0; c < children; c++) 1445 if ((ret = max_width(zhp, child[c], depth + 2, 1446 max)) > max) 1447 max = ret; 1448 } 1449 1450 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1451 &child, &children) == 0) { 1452 for (c = 0; c < children; c++) 1453 if ((ret = max_width(zhp, child[c], depth + 2, 1454 max)) > max) 1455 max = ret; 1456 } 1457 1458 1459 return (max); 1460} 1461 1462typedef struct spare_cbdata { 1463 uint64_t cb_guid; 1464 zpool_handle_t *cb_zhp; 1465} spare_cbdata_t; 1466 1467static boolean_t 1468find_vdev(nvlist_t *nv, uint64_t search) 1469{ 1470 uint64_t guid; 1471 nvlist_t **child; 1472 uint_t c, children; 1473 1474 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1475 search == guid) 1476 return (B_TRUE); 1477 1478 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1479 &child, &children) == 0) { 1480 for (c = 0; c < children; c++) 1481 if (find_vdev(child[c], search)) 1482 return (B_TRUE); 1483 } 1484 1485 return (B_FALSE); 1486} 1487 1488static int 1489find_spare(zpool_handle_t *zhp, void *data) 1490{ 1491 spare_cbdata_t *cbp = data; 1492 nvlist_t *config, *nvroot; 1493 1494 config = zpool_get_config(zhp, NULL); 1495 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1496 &nvroot) == 0); 1497 1498 if (find_vdev(nvroot, cbp->cb_guid)) { 1499 cbp->cb_zhp = zhp; 1500 return (1); 1501 } 1502 1503 zpool_close(zhp); 1504 return (0); 1505} 1506 1507/* 1508 * Print out configuration state as requested by status_callback. 1509 */ 1510void 1511print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 1512 int namewidth, int depth, boolean_t isspare) 1513{ 1514 nvlist_t **child; 1515 uint_t c, vsc, children; 1516 pool_scan_stat_t *ps = NULL; 1517 vdev_stat_t *vs; 1518 char rbuf[6], wbuf[6], cbuf[6]; 1519 char *vname; 1520 uint64_t notpresent; 1521 uint64_t ashift; 1522 spare_cbdata_t cb; 1523 const char *state; 1524 char *type; 1525 1526 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1527 &child, &children) != 0) 1528 children = 0; 1529 1530 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1531 (uint64_t **)&vs, &vsc) == 0); 1532 1533 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 1534 1535 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) 1536 return; 1537 1538 state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1539 if (isspare) { 1540 /* 1541 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1542 * online drives. 1543 */ 1544 if (vs->vs_aux == VDEV_AUX_SPARED) 1545 state = "INUSE"; 1546 else if (vs->vs_state == VDEV_STATE_HEALTHY) 1547 state = "AVAIL"; 1548 } 1549 1550 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 1551 name, state); 1552 1553 if (!isspare) { 1554 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1555 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1556 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1557 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1558 } 1559 1560 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1561 ¬present) == 0 || 1562 vs->vs_state <= VDEV_STATE_CANT_OPEN) { 1563 char *path; 1564 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) 1565 (void) printf(" was %s", path); 1566 } else if (vs->vs_aux != 0) { 1567 (void) printf(" "); 1568 1569 switch (vs->vs_aux) { 1570 case VDEV_AUX_OPEN_FAILED: 1571 (void) printf(gettext("cannot open")); 1572 break; 1573 1574 case VDEV_AUX_BAD_GUID_SUM: 1575 (void) printf(gettext("missing device")); 1576 break; 1577 1578 case VDEV_AUX_NO_REPLICAS: 1579 (void) printf(gettext("insufficient replicas")); 1580 break; 1581 1582 case VDEV_AUX_VERSION_NEWER: 1583 (void) printf(gettext("newer version")); 1584 break; 1585 1586 case VDEV_AUX_UNSUP_FEAT: 1587 (void) printf(gettext("unsupported feature(s)")); 1588 break; 1589 1590 case VDEV_AUX_ASHIFT_TOO_BIG: 1591 (void) printf(gettext("unsupported minimum blocksize")); 1592 break; 1593 1594 case VDEV_AUX_SPARED: 1595 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1596 &cb.cb_guid) == 0); 1597 if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 1598 if (strcmp(zpool_get_name(cb.cb_zhp), 1599 zpool_get_name(zhp)) == 0) 1600 (void) printf(gettext("currently in " 1601 "use")); 1602 else 1603 (void) printf(gettext("in use by " 1604 "pool '%s'"), 1605 zpool_get_name(cb.cb_zhp)); 1606 zpool_close(cb.cb_zhp); 1607 } else { 1608 (void) printf(gettext("currently in use")); 1609 } 1610 break; 1611 1612 case VDEV_AUX_ERR_EXCEEDED: 1613 (void) printf(gettext("too many errors")); 1614 break; 1615 1616 case VDEV_AUX_IO_FAILURE: 1617 (void) printf(gettext("experienced I/O failures")); 1618 break; 1619 1620 case VDEV_AUX_BAD_LOG: 1621 (void) printf(gettext("bad intent log")); 1622 break; 1623 1624 case VDEV_AUX_EXTERNAL: 1625 (void) printf(gettext("external device fault")); 1626 break; 1627 1628 case VDEV_AUX_SPLIT_POOL: 1629 (void) printf(gettext("split into new pool")); 1630 break; 1631 1632 case VDEV_AUX_CHILDREN_OFFLINE: 1633 (void) printf(gettext("all children offline")); 1634 break; 1635 1636 default: 1637 (void) printf(gettext("corrupted data")); 1638 break; 1639 } 1640 } else if (children == 0 && !isspare && 1641 VDEV_STAT_VALID(vs_physical_ashift, vsc) && 1642 vs->vs_configured_ashift < vs->vs_physical_ashift) { 1643 (void) printf( 1644 gettext(" block size: %dB configured, %dB native"), 1645 1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift); 1646 } 1647 1648 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS, 1649 (uint64_t **)&ps, &c); 1650 1651 if (ps != NULL && ps->pss_state == DSS_SCANNING && 1652 vs->vs_scan_processed != 0 && children == 0) { 1653 (void) printf(gettext(" (%s)"), 1654 (ps->pss_func == POOL_SCAN_RESILVER) ? 1655 "resilvering" : "repairing"); 1656 } 1657 1658 if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE || 1659 vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED || 1660 vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) && 1661 !vs->vs_scan_removing) { 1662 char zbuf[1024]; 1663 char tbuf[256]; 1664 struct tm zaction_ts; 1665 1666 time_t t = vs->vs_initialize_action_time; 1667 int initialize_pct = 100; 1668 if (vs->vs_initialize_state != VDEV_INITIALIZE_COMPLETE) { 1669 initialize_pct = (vs->vs_initialize_bytes_done * 100 / 1670 (vs->vs_initialize_bytes_est + 1)); 1671 } 1672 1673 (void) localtime_r(&t, &zaction_ts); 1674 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); 1675 1676 switch (vs->vs_initialize_state) { 1677 case VDEV_INITIALIZE_SUSPENDED: 1678 (void) snprintf(zbuf, sizeof (zbuf), 1679 ", suspended, started at %s", tbuf); 1680 break; 1681 case VDEV_INITIALIZE_ACTIVE: 1682 (void) snprintf(zbuf, sizeof (zbuf), 1683 ", started at %s", tbuf); 1684 break; 1685 case VDEV_INITIALIZE_COMPLETE: 1686 (void) snprintf(zbuf, sizeof (zbuf), 1687 ", completed at %s", tbuf); 1688 break; 1689 } 1690 1691 (void) printf(gettext(" (%d%% initialized%s)"), 1692 initialize_pct, zbuf); 1693 } 1694 1695 (void) printf("\n"); 1696 1697 for (c = 0; c < children; c++) { 1698 uint64_t islog = B_FALSE, ishole = B_FALSE; 1699 1700 /* Don't print logs or holes here */ 1701 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1702 &islog); 1703 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 1704 &ishole); 1705 if (islog || ishole) 1706 continue; 1707 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1708 print_status_config(zhp, vname, child[c], 1709 namewidth, depth + 2, isspare); 1710 free(vname); 1711 } 1712} 1713 1714 1715/* 1716 * Print the configuration of an exported pool. Iterate over all vdevs in the 1717 * pool, printing out the name and status for each one. 1718 */ 1719void 1720print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) 1721{ 1722 nvlist_t **child; 1723 uint_t c, children; 1724 vdev_stat_t *vs; 1725 char *type, *vname; 1726 1727 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 1728 if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 1729 strcmp(type, VDEV_TYPE_HOLE) == 0) 1730 return; 1731 1732 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1733 (uint64_t **)&vs, &c) == 0); 1734 1735 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 1736 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1737 1738 if (vs->vs_aux != 0) { 1739 (void) printf(" "); 1740 1741 switch (vs->vs_aux) { 1742 case VDEV_AUX_OPEN_FAILED: 1743 (void) printf(gettext("cannot open")); 1744 break; 1745 1746 case VDEV_AUX_BAD_GUID_SUM: 1747 (void) printf(gettext("missing device")); 1748 break; 1749 1750 case VDEV_AUX_NO_REPLICAS: 1751 (void) printf(gettext("insufficient replicas")); 1752 break; 1753 1754 case VDEV_AUX_VERSION_NEWER: 1755 (void) printf(gettext("newer version")); 1756 break; 1757 1758 case VDEV_AUX_UNSUP_FEAT: 1759 (void) printf(gettext("unsupported feature(s)")); 1760 break; 1761 1762 case VDEV_AUX_ERR_EXCEEDED: 1763 (void) printf(gettext("too many errors")); 1764 break; 1765 1766 case VDEV_AUX_CHILDREN_OFFLINE: 1767 (void) printf(gettext("all children offline")); 1768 break; 1769 1770 default: 1771 (void) printf(gettext("corrupted data")); 1772 break; 1773 } 1774 } 1775 (void) printf("\n"); 1776 1777 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1778 &child, &children) != 0) 1779 return; 1780 1781 for (c = 0; c < children; c++) { 1782 uint64_t is_log = B_FALSE; 1783 1784 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1785 &is_log); 1786 if (is_log) 1787 continue; 1788 1789 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE); 1790 print_import_config(vname, child[c], namewidth, depth + 2); 1791 free(vname); 1792 } 1793 1794 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1795 &child, &children) == 0) { 1796 (void) printf(gettext("\tcache\n")); 1797 for (c = 0; c < children; c++) { 1798 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1799 (void) printf("\t %s\n", vname); 1800 free(vname); 1801 } 1802 } 1803 1804 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1805 &child, &children) == 0) { 1806 (void) printf(gettext("\tspares\n")); 1807 for (c = 0; c < children; c++) { 1808 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1809 (void) printf("\t %s\n", vname); 1810 free(vname); 1811 } 1812 } 1813} 1814 1815/* 1816 * Print log vdevs. 1817 * Logs are recorded as top level vdevs in the main pool child array 1818 * but with "is_log" set to 1. We use either print_status_config() or 1819 * print_import_config() to print the top level logs then any log 1820 * children (eg mirrored slogs) are printed recursively - which 1821 * works because only the top level vdev is marked "is_log" 1822 */ 1823static void 1824print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) 1825{ 1826 uint_t c, children; 1827 nvlist_t **child; 1828 1829 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1830 &children) != 0) 1831 return; 1832 1833 (void) printf(gettext("\tlogs\n")); 1834 1835 for (c = 0; c < children; c++) { 1836 uint64_t is_log = B_FALSE; 1837 char *name; 1838 1839 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1840 &is_log); 1841 if (!is_log) 1842 continue; 1843 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1844 if (verbose) 1845 print_status_config(zhp, name, child[c], namewidth, 1846 2, B_FALSE); 1847 else 1848 print_import_config(name, child[c], namewidth, 2); 1849 free(name); 1850 } 1851} 1852 1853/* 1854 * Display the status for the given pool. 1855 */ 1856static void 1857show_import(nvlist_t *config) 1858{ 1859 uint64_t pool_state; 1860 vdev_stat_t *vs; 1861 char *name; 1862 uint64_t guid; 1863 char *msgid; 1864 nvlist_t *nvroot; 1865 int reason; 1866 const char *health; 1867 uint_t vsc; 1868 int namewidth; 1869 char *comment; 1870 1871 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1872 &name) == 0); 1873 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1874 &guid) == 0); 1875 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1876 &pool_state) == 0); 1877 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1878 &nvroot) == 0); 1879 1880 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 1881 (uint64_t **)&vs, &vsc) == 0); 1882 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1883 1884 reason = zpool_import_status(config, &msgid); 1885 1886 (void) printf(gettext(" pool: %s\n"), name); 1887 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 1888 (void) printf(gettext(" state: %s"), health); 1889 if (pool_state == POOL_STATE_DESTROYED) 1890 (void) printf(gettext(" (DESTROYED)")); 1891 (void) printf("\n"); 1892 1893 switch (reason) { 1894 case ZPOOL_STATUS_MISSING_DEV_R: 1895 case ZPOOL_STATUS_MISSING_DEV_NR: 1896 case ZPOOL_STATUS_BAD_GUID_SUM: 1897 (void) printf(gettext(" status: One or more devices are " 1898 "missing from the system.\n")); 1899 break; 1900 1901 case ZPOOL_STATUS_CORRUPT_LABEL_R: 1902 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 1903 (void) printf(gettext(" status: One or more devices contains " 1904 "corrupted data.\n")); 1905 break; 1906 1907 case ZPOOL_STATUS_CORRUPT_DATA: 1908 (void) printf( 1909 gettext(" status: The pool data is corrupted.\n")); 1910 break; 1911 1912 case ZPOOL_STATUS_OFFLINE_DEV: 1913 (void) printf(gettext(" status: One or more devices " 1914 "are offlined.\n")); 1915 break; 1916 1917 case ZPOOL_STATUS_CORRUPT_POOL: 1918 (void) printf(gettext(" status: The pool metadata is " 1919 "corrupted.\n")); 1920 break; 1921 1922 case ZPOOL_STATUS_VERSION_OLDER: 1923 (void) printf(gettext(" status: The pool is formatted using a " 1924 "legacy on-disk version.\n")); 1925 break; 1926 1927 case ZPOOL_STATUS_VERSION_NEWER: 1928 (void) printf(gettext(" status: The pool is formatted using an " 1929 "incompatible version.\n")); 1930 break; 1931 1932 case ZPOOL_STATUS_FEAT_DISABLED: 1933 (void) printf(gettext(" status: Some supported features are " 1934 "not enabled on the pool.\n")); 1935 break; 1936 1937 case ZPOOL_STATUS_UNSUP_FEAT_READ: 1938 (void) printf(gettext("status: The pool uses the following " 1939 "feature(s) not supported on this system:\n")); 1940 zpool_print_unsup_feat(config); 1941 break; 1942 1943 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1944 (void) printf(gettext("status: The pool can only be accessed " 1945 "in read-only mode on this system. It\n\tcannot be " 1946 "accessed in read-write mode because it uses the " 1947 "following\n\tfeature(s) not supported on this system:\n")); 1948 zpool_print_unsup_feat(config); 1949 break; 1950 1951 case ZPOOL_STATUS_HOSTID_MISMATCH: 1952 (void) printf(gettext(" status: The pool was last accessed by " 1953 "another system.\n")); 1954 break; 1955 1956 case ZPOOL_STATUS_FAULTED_DEV_R: 1957 case ZPOOL_STATUS_FAULTED_DEV_NR: 1958 (void) printf(gettext(" status: One or more devices are " 1959 "faulted.\n")); 1960 break; 1961 1962 case ZPOOL_STATUS_BAD_LOG: 1963 (void) printf(gettext(" status: An intent log record cannot be " 1964 "read.\n")); 1965 break; 1966 1967 case ZPOOL_STATUS_RESILVERING: 1968 (void) printf(gettext(" status: One or more devices were being " 1969 "resilvered.\n")); 1970 break; 1971 1972 case ZPOOL_STATUS_NON_NATIVE_ASHIFT: 1973 (void) printf(gettext("status: One or more devices were " 1974 "configured to use a non-native block size.\n" 1975 "\tExpect reduced performance.\n")); 1976 break; 1977 1978 default: 1979 /* 1980 * No other status can be seen when importing pools. 1981 */ 1982 assert(reason == ZPOOL_STATUS_OK); 1983 } 1984 1985 /* 1986 * Print out an action according to the overall state of the pool. 1987 */ 1988 if (vs->vs_state == VDEV_STATE_HEALTHY) { 1989 if (reason == ZPOOL_STATUS_VERSION_OLDER || 1990 reason == ZPOOL_STATUS_FEAT_DISABLED) { 1991 (void) printf(gettext(" action: The pool can be " 1992 "imported using its name or numeric identifier, " 1993 "though\n\tsome features will not be available " 1994 "without an explicit 'zpool upgrade'.\n")); 1995 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 1996 (void) printf(gettext(" action: The pool can be " 1997 "imported using its name or numeric " 1998 "identifier and\n\tthe '-f' flag.\n")); 1999 } else { 2000 (void) printf(gettext(" action: The pool can be " 2001 "imported using its name or numeric " 2002 "identifier.\n")); 2003 } 2004 } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 2005 (void) printf(gettext(" action: The pool can be imported " 2006 "despite missing or damaged devices. The\n\tfault " 2007 "tolerance of the pool may be compromised if imported.\n")); 2008 } else { 2009 switch (reason) { 2010 case ZPOOL_STATUS_VERSION_NEWER: 2011 (void) printf(gettext(" action: The pool cannot be " 2012 "imported. Access the pool on a system running " 2013 "newer\n\tsoftware, or recreate the pool from " 2014 "backup.\n")); 2015 break; 2016 case ZPOOL_STATUS_UNSUP_FEAT_READ: 2017 (void) printf(gettext("action: The pool cannot be " 2018 "imported. Access the pool on a system that " 2019 "supports\n\tthe required feature(s), or recreate " 2020 "the pool from backup.\n")); 2021 break; 2022 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2023 (void) printf(gettext("action: The pool cannot be " 2024 "imported in read-write mode. Import the pool " 2025 "with\n" 2026 "\t\"-o readonly=on\", access the pool on a system " 2027 "that supports the\n\trequired feature(s), or " 2028 "recreate the pool from backup.\n")); 2029 break; 2030 case ZPOOL_STATUS_MISSING_DEV_R: 2031 case ZPOOL_STATUS_MISSING_DEV_NR: 2032 case ZPOOL_STATUS_BAD_GUID_SUM: 2033 (void) printf(gettext(" action: The pool cannot be " 2034 "imported. Attach the missing\n\tdevices and try " 2035 "again.\n")); 2036 break; 2037 default: 2038 (void) printf(gettext(" action: The pool cannot be " 2039 "imported due to damaged devices or data.\n")); 2040 } 2041 } 2042 2043 /* Print the comment attached to the pool. */ 2044 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 2045 (void) printf(gettext("comment: %s\n"), comment); 2046 2047 /* 2048 * If the state is "closed" or "can't open", and the aux state 2049 * is "corrupt data": 2050 */ 2051 if (((vs->vs_state == VDEV_STATE_CLOSED) || 2052 (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 2053 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 2054 if (pool_state == POOL_STATE_DESTROYED) 2055 (void) printf(gettext("\tThe pool was destroyed, " 2056 "but can be imported using the '-Df' flags.\n")); 2057 else if (pool_state != POOL_STATE_EXPORTED) 2058 (void) printf(gettext("\tThe pool may be active on " 2059 "another system, but can be imported using\n\t" 2060 "the '-f' flag.\n")); 2061 } 2062 2063 if (msgid != NULL) 2064 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 2065 msgid); 2066 2067 (void) printf(gettext(" config:\n\n")); 2068 2069 namewidth = max_width(NULL, nvroot, 0, 0); 2070 if (namewidth < 10) 2071 namewidth = 10; 2072 2073 print_import_config(name, nvroot, namewidth, 0); 2074 if (num_logs(nvroot) > 0) 2075 print_logs(NULL, nvroot, namewidth, B_FALSE); 2076 2077 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 2078 (void) printf(gettext("\n\tAdditional devices are known to " 2079 "be part of this pool, though their\n\texact " 2080 "configuration cannot be determined.\n")); 2081 } 2082} 2083 2084/* 2085 * Perform the import for the given configuration. This passes the heavy 2086 * lifting off to zpool_import_props(), and then mounts the datasets contained 2087 * within the pool. 2088 */ 2089static int 2090do_import(nvlist_t *config, const char *newname, const char *mntopts, 2091 nvlist_t *props, int flags) 2092{ 2093 zpool_handle_t *zhp; 2094 char *name; 2095 uint64_t state; 2096 uint64_t version; 2097 2098 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 2099 &name) == 0); 2100 2101 verify(nvlist_lookup_uint64(config, 2102 ZPOOL_CONFIG_POOL_STATE, &state) == 0); 2103 verify(nvlist_lookup_uint64(config, 2104 ZPOOL_CONFIG_VERSION, &version) == 0); 2105 if (!SPA_VERSION_IS_SUPPORTED(version)) { 2106 (void) fprintf(stderr, gettext("cannot import '%s': pool " 2107 "is formatted using an unsupported ZFS version\n"), name); 2108 return (1); 2109 } else if (state != POOL_STATE_EXPORTED && 2110 !(flags & ZFS_IMPORT_ANY_HOST)) { 2111 uint64_t hostid; 2112 2113 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 2114 &hostid) == 0) { 2115 if ((unsigned long)hostid != gethostid()) { 2116 char *hostname; 2117 uint64_t timestamp; 2118 time_t t; 2119 2120 verify(nvlist_lookup_string(config, 2121 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 2122 verify(nvlist_lookup_uint64(config, 2123 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 2124 t = timestamp; 2125 (void) fprintf(stderr, gettext("cannot import " 2126 "'%s': pool may be in use from other " 2127 "system, it was last accessed by %s " 2128 "(hostid: 0x%lx) on %s"), name, hostname, 2129 (unsigned long)hostid, 2130 asctime(localtime(&t))); 2131 (void) fprintf(stderr, gettext("use '-f' to " 2132 "import anyway\n")); 2133 return (1); 2134 } 2135 } else { 2136 (void) fprintf(stderr, gettext("cannot import '%s': " 2137 "pool may be in use from other system\n"), name); 2138 (void) fprintf(stderr, gettext("use '-f' to import " 2139 "anyway\n")); 2140 return (1); 2141 } 2142 } 2143 2144 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 2145 return (1); 2146 2147 if (newname != NULL) 2148 name = (char *)newname; 2149 2150 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 2151 return (1); 2152 2153 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 2154 !(flags & ZFS_IMPORT_ONLY) && 2155 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 2156 zpool_close(zhp); 2157 return (1); 2158 } 2159 2160 zpool_close(zhp); 2161 return (0); 2162} 2163 2164/* 2165 * zpool checkpoint <pool> 2166 * checkpoint --discard <pool> 2167 * 2168 * -d Discard the checkpoint from a checkpointed 2169 * --discard pool. 2170 * 2171 * Checkpoints the specified pool, by taking a "snapshot" of its 2172 * current state. A pool can only have one checkpoint at a time. 2173 */ 2174int 2175zpool_do_checkpoint(int argc, char **argv) 2176{ 2177 boolean_t discard; 2178 char *pool; 2179 zpool_handle_t *zhp; 2180 int c, err; 2181 2182 struct option long_options[] = { 2183 {"discard", no_argument, NULL, 'd'}, 2184 {0, 0, 0, 0} 2185 }; 2186 2187 discard = B_FALSE; 2188 while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) { 2189 switch (c) { 2190 case 'd': 2191 discard = B_TRUE; 2192 break; 2193 case '?': 2194 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2195 optopt); 2196 usage(B_FALSE); 2197 } 2198 } 2199 2200 argc -= optind; 2201 argv += optind; 2202 2203 if (argc < 1) { 2204 (void) fprintf(stderr, gettext("missing pool argument\n")); 2205 usage(B_FALSE); 2206 } 2207 2208 if (argc > 1) { 2209 (void) fprintf(stderr, gettext("too many arguments\n")); 2210 usage(B_FALSE); 2211 } 2212 2213 pool = argv[0]; 2214 2215 if ((zhp = zpool_open(g_zfs, pool)) == NULL) { 2216 /* As a special case, check for use of '/' in the name */ 2217 if (strchr(pool, '/') != NULL) 2218 (void) fprintf(stderr, gettext("'zpool checkpoint' " 2219 "doesn't work on datasets. To save the state " 2220 "of a dataset from a specific point in time " 2221 "please use 'zfs snapshot'\n")); 2222 return (1); 2223 } 2224 2225 if (discard) 2226 err = (zpool_discard_checkpoint(zhp) != 0); 2227 else 2228 err = (zpool_checkpoint(zhp) != 0); 2229 2230 zpool_close(zhp); 2231 2232 return (err); 2233} 2234 2235#define CHECKPOINT_OPT 1024 2236 2237/* 2238 * zpool import [-d dir] [-D] 2239 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 2240 * [-d dir | -c cachefile] [-f] -a 2241 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 2242 * [-d dir | -c cachefile] [-f] [-n] [-F] [-t] 2243 * <pool | id> [newpool] 2244 * 2245 * -c Read pool information from a cachefile instead of searching 2246 * devices. 2247 * 2248 * -d Scan in a specific directory, other than /dev/dsk. More than 2249 * one directory can be specified using multiple '-d' options. 2250 * 2251 * -D Scan for previously destroyed pools or import all or only 2252 * specified destroyed pools. 2253 * 2254 * -R Temporarily import the pool, with all mountpoints relative to 2255 * the given root. The pool will remain exported when the machine 2256 * is rebooted. 2257 * 2258 * -V Import even in the presence of faulted vdevs. This is an 2259 * intentionally undocumented option for testing purposes, and 2260 * treats the pool configuration as complete, leaving any bad 2261 * vdevs in the FAULTED state. In other words, it does verbatim 2262 * import. 2263 * 2264 * -f Force import, even if it appears that the pool is active. 2265 * 2266 * -F Attempt rewind if necessary. 2267 * 2268 * -n See if rewind would work, but don't actually rewind. 2269 * 2270 * -N Import the pool but don't mount datasets. 2271 * 2272 * -t Use newpool as a temporary pool name instead of renaming 2273 * the pool. 2274 * 2275 * -T Specify a starting txg to use for import. This option is 2276 * intentionally undocumented option for testing purposes. 2277 * 2278 * -a Import all pools found. 2279 * 2280 * -o Set property=value and/or temporary mount options (without '='). 2281 * 2282 * --rewind-to-checkpoint 2283 * Import the pool and revert back to the checkpoint. 2284 * 2285 * The import command scans for pools to import, and import pools based on pool 2286 * name and GUID. The pool can also be renamed as part of the import process. 2287 */ 2288int 2289zpool_do_import(int argc, char **argv) 2290{ 2291 char **searchdirs = NULL; 2292 int nsearch = 0; 2293 int c; 2294 int err = 0; 2295 nvlist_t *pools = NULL; 2296 boolean_t do_all = B_FALSE; 2297 boolean_t do_destroyed = B_FALSE; 2298 char *mntopts = NULL; 2299 nvpair_t *elem; 2300 nvlist_t *config; 2301 uint64_t searchguid = 0; 2302 char *searchname = NULL; 2303 char *propval; 2304 nvlist_t *found_config; 2305 nvlist_t *policy = NULL; 2306 nvlist_t *props = NULL; 2307 boolean_t first; 2308 int flags = ZFS_IMPORT_NORMAL; 2309 uint32_t rewind_policy = ZPOOL_NO_REWIND; 2310 boolean_t dryrun = B_FALSE; 2311 boolean_t do_rewind = B_FALSE; 2312 boolean_t xtreme_rewind = B_FALSE; 2313 uint64_t pool_state, txg = -1ULL; 2314 char *cachefile = NULL; 2315 importargs_t idata = { 0 }; 2316 char *endptr; 2317 2318 2319 struct option long_options[] = { 2320 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT}, 2321 {0, 0, 0, 0} 2322 }; 2323 2324 /* check options */ 2325 while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:tT:VX", 2326 long_options, NULL)) != -1) { 2327 switch (c) { 2328 case 'a': 2329 do_all = B_TRUE; 2330 break; 2331 case 'c': 2332 cachefile = optarg; 2333 break; 2334 case 'd': 2335 if (searchdirs == NULL) { 2336 searchdirs = safe_malloc(sizeof (char *)); 2337 } else { 2338 char **tmp = safe_malloc((nsearch + 1) * 2339 sizeof (char *)); 2340 bcopy(searchdirs, tmp, nsearch * 2341 sizeof (char *)); 2342 free(searchdirs); 2343 searchdirs = tmp; 2344 } 2345 searchdirs[nsearch++] = optarg; 2346 break; 2347 case 'D': 2348 do_destroyed = B_TRUE; 2349 break; 2350 case 'f': 2351 flags |= ZFS_IMPORT_ANY_HOST; 2352 break; 2353 case 'F': 2354 do_rewind = B_TRUE; 2355 break; 2356 case 'm': 2357 flags |= ZFS_IMPORT_MISSING_LOG; 2358 break; 2359 case 'n': 2360 dryrun = B_TRUE; 2361 break; 2362 case 'N': 2363 flags |= ZFS_IMPORT_ONLY; 2364 break; 2365 case 'o': 2366 if ((propval = strchr(optarg, '=')) != NULL) { 2367 *propval = '\0'; 2368 propval++; 2369 if (add_prop_list(optarg, propval, 2370 &props, B_TRUE)) 2371 goto error; 2372 } else { 2373 mntopts = optarg; 2374 } 2375 break; 2376 case 'R': 2377 if (add_prop_list(zpool_prop_to_name( 2378 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 2379 goto error; 2380 if (add_prop_list_default(zpool_prop_to_name( 2381 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2382 goto error; 2383 break; 2384 case 't': 2385 flags |= ZFS_IMPORT_TEMP_NAME; 2386 if (add_prop_list_default(zpool_prop_to_name( 2387 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2388 goto error; 2389 break; 2390 case 'T': 2391 errno = 0; 2392 txg = strtoull(optarg, &endptr, 0); 2393 if (errno != 0 || *endptr != '\0') { 2394 (void) fprintf(stderr, 2395 gettext("invalid txg value\n")); 2396 usage(B_FALSE); 2397 } 2398 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 2399 break; 2400 case 'V': 2401 flags |= ZFS_IMPORT_VERBATIM; 2402 break; 2403 case 'X': 2404 xtreme_rewind = B_TRUE; 2405 break; 2406 case CHECKPOINT_OPT: 2407 flags |= ZFS_IMPORT_CHECKPOINT; 2408 break; 2409 case ':': 2410 (void) fprintf(stderr, gettext("missing argument for " 2411 "'%c' option\n"), optopt); 2412 usage(B_FALSE); 2413 break; 2414 case '?': 2415 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2416 optopt); 2417 usage(B_FALSE); 2418 } 2419 } 2420 2421 argc -= optind; 2422 argv += optind; 2423 2424 if (cachefile && nsearch != 0) { 2425 (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 2426 usage(B_FALSE); 2427 } 2428 2429 if ((dryrun || xtreme_rewind) && !do_rewind) { 2430 (void) fprintf(stderr, 2431 gettext("-n or -X only meaningful with -F\n")); 2432 usage(B_FALSE); 2433 } 2434 if (dryrun) 2435 rewind_policy = ZPOOL_TRY_REWIND; 2436 else if (do_rewind) 2437 rewind_policy = ZPOOL_DO_REWIND; 2438 if (xtreme_rewind) 2439 rewind_policy |= ZPOOL_EXTREME_REWIND; 2440 2441 /* In the future, we can capture further policy and include it here */ 2442 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 2443 nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 || 2444 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 2445 rewind_policy) != 0) 2446 goto error; 2447 2448 if (searchdirs == NULL) { 2449 searchdirs = safe_malloc(sizeof (char *)); 2450 searchdirs[0] = "/dev"; 2451 nsearch = 1; 2452 } 2453 2454 /* check argument count */ 2455 if (do_all) { 2456 if (argc != 0) { 2457 (void) fprintf(stderr, gettext("too many arguments\n")); 2458 usage(B_FALSE); 2459 } 2460 } else { 2461 if (argc > 2) { 2462 (void) fprintf(stderr, gettext("too many arguments\n")); 2463 usage(B_FALSE); 2464 } 2465 2466 /* 2467 * Check for the SYS_CONFIG privilege. We do this explicitly 2468 * here because otherwise any attempt to discover pools will 2469 * silently fail. 2470 */ 2471 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 2472 (void) fprintf(stderr, gettext("cannot " 2473 "discover pools: permission denied\n")); 2474 free(searchdirs); 2475 nvlist_free(policy); 2476 return (1); 2477 } 2478 } 2479 2480 /* 2481 * Depending on the arguments given, we do one of the following: 2482 * 2483 * <none> Iterate through all pools and display information about 2484 * each one. 2485 * 2486 * -a Iterate through all pools and try to import each one. 2487 * 2488 * <id> Find the pool that corresponds to the given GUID/pool 2489 * name and import that one. 2490 * 2491 * -D Above options applies only to destroyed pools. 2492 */ 2493 if (argc != 0) { 2494 char *endptr; 2495 2496 errno = 0; 2497 searchguid = strtoull(argv[0], &endptr, 10); 2498 if (errno != 0 || *endptr != '\0') { 2499 searchname = argv[0]; 2500 searchguid = 0; 2501 } 2502 found_config = NULL; 2503 2504 /* 2505 * User specified a name or guid. Ensure it's unique. 2506 */ 2507 idata.unique = B_TRUE; 2508 } 2509 2510 2511 idata.path = searchdirs; 2512 idata.paths = nsearch; 2513 idata.poolname = searchname; 2514 idata.guid = searchguid; 2515 idata.cachefile = cachefile; 2516 idata.policy = policy; 2517 2518 pools = zpool_search_import(g_zfs, &idata); 2519 2520 if (pools != NULL && idata.exists && 2521 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 2522 (void) fprintf(stderr, gettext("cannot import '%s': " 2523 "a pool with that name already exists\n"), 2524 argv[0]); 2525 (void) fprintf(stderr, gettext("use the form 'zpool import " 2526 "[-t] <pool | id> <newpool>' to give it a new temporary " 2527 "or permanent name\n")); 2528 err = 1; 2529 } else if (pools == NULL && idata.exists) { 2530 (void) fprintf(stderr, gettext("cannot import '%s': " 2531 "a pool with that name is already created/imported,\n"), 2532 argv[0]); 2533 (void) fprintf(stderr, gettext("and no additional pools " 2534 "with that name were found\n")); 2535 err = 1; 2536 } else if (pools == NULL) { 2537 if (argc != 0) { 2538 (void) fprintf(stderr, gettext("cannot import '%s': " 2539 "no such pool available\n"), argv[0]); 2540 } 2541 err = 1; 2542 } 2543 2544 if (err == 1) { 2545 free(searchdirs); 2546 nvlist_free(policy); 2547 return (1); 2548 } 2549 2550 /* 2551 * At this point we have a list of import candidate configs. Even if 2552 * we were searching by pool name or guid, we still need to 2553 * post-process the list to deal with pool state and possible 2554 * duplicate names. 2555 */ 2556 err = 0; 2557 elem = NULL; 2558 first = B_TRUE; 2559 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 2560 2561 verify(nvpair_value_nvlist(elem, &config) == 0); 2562 2563 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 2564 &pool_state) == 0); 2565 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 2566 continue; 2567 if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 2568 continue; 2569 2570 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, 2571 policy) == 0); 2572 2573 if (argc == 0) { 2574 if (first) 2575 first = B_FALSE; 2576 else if (!do_all) 2577 (void) printf("\n"); 2578 2579 if (do_all) { 2580 err |= do_import(config, NULL, mntopts, 2581 props, flags); 2582 } else { 2583 show_import(config); 2584 } 2585 } else if (searchname != NULL) { 2586 char *name; 2587 2588 /* 2589 * We are searching for a pool based on name. 2590 */ 2591 verify(nvlist_lookup_string(config, 2592 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 2593 2594 if (strcmp(name, searchname) == 0) { 2595 if (found_config != NULL) { 2596 (void) fprintf(stderr, gettext( 2597 "cannot import '%s': more than " 2598 "one matching pool\n"), searchname); 2599 (void) fprintf(stderr, gettext( 2600 "import by numeric ID instead\n")); 2601 err = B_TRUE; 2602 } 2603 found_config = config; 2604 } 2605 } else { 2606 uint64_t guid; 2607 2608 /* 2609 * Search for a pool by guid. 2610 */ 2611 verify(nvlist_lookup_uint64(config, 2612 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 2613 2614 if (guid == searchguid) 2615 found_config = config; 2616 } 2617 } 2618 2619 /* 2620 * If we were searching for a specific pool, verify that we found a 2621 * pool, and then do the import. 2622 */ 2623 if (argc != 0 && err == 0) { 2624 if (found_config == NULL) { 2625 (void) fprintf(stderr, gettext("cannot import '%s': " 2626 "no such pool available\n"), argv[0]); 2627 err = B_TRUE; 2628 } else { 2629 err |= do_import(found_config, argc == 1 ? NULL : 2630 argv[1], mntopts, props, flags); 2631 } 2632 } 2633 2634 /* 2635 * If we were just looking for pools, report an error if none were 2636 * found. 2637 */ 2638 if (argc == 0 && first) 2639 (void) fprintf(stderr, 2640 gettext("no pools available to import\n")); 2641 2642error: 2643 nvlist_free(props); 2644 nvlist_free(pools); 2645 nvlist_free(policy); 2646 free(searchdirs); 2647 2648 return (err ? 1 : 0); 2649} 2650 2651typedef struct iostat_cbdata { 2652 boolean_t cb_verbose; 2653 int cb_namewidth; 2654 int cb_iteration; 2655 zpool_list_t *cb_list; 2656} iostat_cbdata_t; 2657 2658static void 2659print_iostat_separator(iostat_cbdata_t *cb) 2660{ 2661 int i = 0; 2662 2663 for (i = 0; i < cb->cb_namewidth; i++) 2664 (void) printf("-"); 2665 (void) printf(" ----- ----- ----- ----- ----- -----\n"); 2666} 2667 2668static void 2669print_iostat_header(iostat_cbdata_t *cb) 2670{ 2671 (void) printf("%*s capacity operations bandwidth\n", 2672 cb->cb_namewidth, ""); 2673 (void) printf("%-*s alloc free read write read write\n", 2674 cb->cb_namewidth, "pool"); 2675 print_iostat_separator(cb); 2676} 2677 2678/* 2679 * Display a single statistic. 2680 */ 2681static void 2682print_one_stat(uint64_t value) 2683{ 2684 char buf[64]; 2685 2686 zfs_nicenum(value, buf, sizeof (buf)); 2687 (void) printf(" %5s", buf); 2688} 2689 2690/* 2691 * Print out all the statistics for the given vdev. This can either be the 2692 * toplevel configuration, or called recursively. If 'name' is NULL, then this 2693 * is a verbose output, and we don't want to display the toplevel pool stats. 2694 */ 2695void 2696print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 2697 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 2698{ 2699 nvlist_t **oldchild, **newchild; 2700 uint_t c, children; 2701 vdev_stat_t *oldvs, *newvs; 2702 vdev_stat_t zerovs = { 0 }; 2703 uint64_t tdelta; 2704 double scale; 2705 char *vname; 2706 2707 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 2708 return; 2709 2710 if (oldnv != NULL) { 2711 verify(nvlist_lookup_uint64_array(oldnv, 2712 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 2713 } else { 2714 oldvs = &zerovs; 2715 } 2716 2717 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 2718 (uint64_t **)&newvs, &c) == 0); 2719 2720 if (strlen(name) + depth > cb->cb_namewidth) 2721 (void) printf("%*s%s", depth, "", name); 2722 else 2723 (void) printf("%*s%s%*s", depth, "", name, 2724 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 2725 2726 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 2727 2728 if (tdelta == 0) 2729 scale = 1.0; 2730 else 2731 scale = (double)NANOSEC / tdelta; 2732 2733 /* only toplevel vdevs have capacity stats */ 2734 if (newvs->vs_space == 0) { 2735 (void) printf(" - -"); 2736 } else { 2737 print_one_stat(newvs->vs_alloc); 2738 print_one_stat(newvs->vs_space - newvs->vs_alloc); 2739 } 2740 2741 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 2742 oldvs->vs_ops[ZIO_TYPE_READ]))); 2743 2744 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 2745 oldvs->vs_ops[ZIO_TYPE_WRITE]))); 2746 2747 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 2748 oldvs->vs_bytes[ZIO_TYPE_READ]))); 2749 2750 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 2751 oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 2752 2753 (void) printf("\n"); 2754 2755 if (!cb->cb_verbose) 2756 return; 2757 2758 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 2759 &newchild, &children) != 0) 2760 return; 2761 2762 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 2763 &oldchild, &c) != 0) 2764 return; 2765 2766 for (c = 0; c < children; c++) { 2767 uint64_t ishole = B_FALSE, islog = B_FALSE; 2768 2769 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 2770 &ishole); 2771 2772 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 2773 &islog); 2774 2775 if (ishole || islog) 2776 continue; 2777 2778 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE); 2779 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2780 newchild[c], cb, depth + 2); 2781 free(vname); 2782 } 2783 2784 /* 2785 * Log device section 2786 */ 2787 2788 if (num_logs(newnv) > 0) { 2789 (void) printf("%-*s - - - - - " 2790 "-\n", cb->cb_namewidth, "logs"); 2791 2792 for (c = 0; c < children; c++) { 2793 uint64_t islog = B_FALSE; 2794 (void) nvlist_lookup_uint64(newchild[c], 2795 ZPOOL_CONFIG_IS_LOG, &islog); 2796 2797 if (islog) { 2798 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2799 B_FALSE); 2800 print_vdev_stats(zhp, vname, oldnv ? 2801 oldchild[c] : NULL, newchild[c], 2802 cb, depth + 2); 2803 free(vname); 2804 } 2805 } 2806 2807 } 2808 2809 /* 2810 * Include level 2 ARC devices in iostat output 2811 */ 2812 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 2813 &newchild, &children) != 0) 2814 return; 2815 2816 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 2817 &oldchild, &c) != 0) 2818 return; 2819 2820 if (children > 0) { 2821 (void) printf("%-*s - - - - - " 2822 "-\n", cb->cb_namewidth, "cache"); 2823 for (c = 0; c < children; c++) { 2824 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2825 B_FALSE); 2826 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2827 newchild[c], cb, depth + 2); 2828 free(vname); 2829 } 2830 } 2831} 2832 2833static int 2834refresh_iostat(zpool_handle_t *zhp, void *data) 2835{ 2836 iostat_cbdata_t *cb = data; 2837 boolean_t missing; 2838 2839 /* 2840 * If the pool has disappeared, remove it from the list and continue. 2841 */ 2842 if (zpool_refresh_stats(zhp, &missing) != 0) 2843 return (-1); 2844 2845 if (missing) 2846 pool_list_remove(cb->cb_list, zhp); 2847 2848 return (0); 2849} 2850 2851/* 2852 * Callback to print out the iostats for the given pool. 2853 */ 2854int 2855print_iostat(zpool_handle_t *zhp, void *data) 2856{ 2857 iostat_cbdata_t *cb = data; 2858 nvlist_t *oldconfig, *newconfig; 2859 nvlist_t *oldnvroot, *newnvroot; 2860 2861 newconfig = zpool_get_config(zhp, &oldconfig); 2862 2863 if (cb->cb_iteration == 1) 2864 oldconfig = NULL; 2865 2866 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 2867 &newnvroot) == 0); 2868 2869 if (oldconfig == NULL) 2870 oldnvroot = NULL; 2871 else 2872 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 2873 &oldnvroot) == 0); 2874 2875 /* 2876 * Print out the statistics for the pool. 2877 */ 2878 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 2879 2880 if (cb->cb_verbose) 2881 print_iostat_separator(cb); 2882 2883 return (0); 2884} 2885 2886int 2887get_namewidth(zpool_handle_t *zhp, void *data) 2888{ 2889 iostat_cbdata_t *cb = data; 2890 nvlist_t *config, *nvroot; 2891 2892 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 2893 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2894 &nvroot) == 0); 2895 if (!cb->cb_verbose) 2896 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 2897 else 2898 cb->cb_namewidth = max_width(zhp, nvroot, 0, 2899 cb->cb_namewidth); 2900 } 2901 2902 /* 2903 * The width must fall into the range [10,38]. The upper limit is the 2904 * maximum we can have and still fit in 80 columns. 2905 */ 2906 if (cb->cb_namewidth < 10) 2907 cb->cb_namewidth = 10; 2908 if (cb->cb_namewidth > 38) 2909 cb->cb_namewidth = 38; 2910 2911 return (0); 2912} 2913 2914/* 2915 * Parse the input string, get the 'interval' and 'count' value if there is one. 2916 */ 2917static void 2918get_interval_count(int *argcp, char **argv, unsigned long *iv, 2919 unsigned long *cnt) 2920{ 2921 unsigned long interval = 0, count = 0; 2922 int argc = *argcp, errno; 2923 2924 /* 2925 * Determine if the last argument is an integer or a pool name 2926 */ 2927 if (argc > 0 && isdigit(argv[argc - 1][0])) { 2928 char *end; 2929 2930 errno = 0; 2931 interval = strtoul(argv[argc - 1], &end, 10); 2932 2933 if (*end == '\0' && errno == 0) { 2934 if (interval == 0) { 2935 (void) fprintf(stderr, gettext("interval " 2936 "cannot be zero\n")); 2937 usage(B_FALSE); 2938 } 2939 /* 2940 * Ignore the last parameter 2941 */ 2942 argc--; 2943 } else { 2944 /* 2945 * If this is not a valid number, just plow on. The 2946 * user will get a more informative error message later 2947 * on. 2948 */ 2949 interval = 0; 2950 } 2951 } 2952 2953 /* 2954 * If the last argument is also an integer, then we have both a count 2955 * and an interval. 2956 */ 2957 if (argc > 0 && isdigit(argv[argc - 1][0])) { 2958 char *end; 2959 2960 errno = 0; 2961 count = interval; 2962 interval = strtoul(argv[argc - 1], &end, 10); 2963 2964 if (*end == '\0' && errno == 0) { 2965 if (interval == 0) { 2966 (void) fprintf(stderr, gettext("interval " 2967 "cannot be zero\n")); 2968 usage(B_FALSE); 2969 } 2970 2971 /* 2972 * Ignore the last parameter 2973 */ 2974 argc--; 2975 } else { 2976 interval = 0; 2977 } 2978 } 2979 2980 *iv = interval; 2981 *cnt = count; 2982 *argcp = argc; 2983} 2984 2985static void 2986get_timestamp_arg(char c) 2987{ 2988 if (c == 'u') 2989 timestamp_fmt = UDATE; 2990 else if (c == 'd') 2991 timestamp_fmt = DDATE; 2992 else 2993 usage(B_FALSE); 2994} 2995 2996/* 2997 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]] 2998 * 2999 * -v Display statistics for individual vdevs 3000 * -T Display a timestamp in date(1) or Unix format 3001 * 3002 * This command can be tricky because we want to be able to deal with pool 3003 * creation/destruction as well as vdev configuration changes. The bulk of this 3004 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 3005 * on pool_list_update() to detect the addition of new pools. Configuration 3006 * changes are all handled within libzfs. 3007 */ 3008int 3009zpool_do_iostat(int argc, char **argv) 3010{ 3011 int c; 3012 int ret; 3013 int npools; 3014 unsigned long interval = 0, count = 0; 3015 zpool_list_t *list; 3016 boolean_t verbose = B_FALSE; 3017 iostat_cbdata_t cb; 3018 3019 /* check options */ 3020 while ((c = getopt(argc, argv, "T:v")) != -1) { 3021 switch (c) { 3022 case 'T': 3023 get_timestamp_arg(*optarg); 3024 break; 3025 case 'v': 3026 verbose = B_TRUE; 3027 break; 3028 case '?': 3029 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3030 optopt); 3031 usage(B_FALSE); 3032 } 3033 } 3034 3035 argc -= optind; 3036 argv += optind; 3037 3038 get_interval_count(&argc, argv, &interval, &count); 3039 3040 /* 3041 * Construct the list of all interesting pools. 3042 */ 3043 ret = 0; 3044 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 3045 return (1); 3046 3047 if (pool_list_count(list) == 0 && argc != 0) { 3048 pool_list_free(list); 3049 return (1); 3050 } 3051 3052 if (pool_list_count(list) == 0 && interval == 0) { 3053 pool_list_free(list); 3054 (void) fprintf(stderr, gettext("no pools available\n")); 3055 return (1); 3056 } 3057 3058 /* 3059 * Enter the main iostat loop. 3060 */ 3061 cb.cb_list = list; 3062 cb.cb_verbose = verbose; 3063 cb.cb_iteration = 0; 3064 cb.cb_namewidth = 0; 3065 3066 for (;;) { 3067 pool_list_update(list); 3068 3069 if ((npools = pool_list_count(list)) == 0) 3070 break; 3071 3072 /* 3073 * Refresh all statistics. This is done as an explicit step 3074 * before calculating the maximum name width, so that any 3075 * configuration changes are properly accounted for. 3076 */ 3077 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 3078 3079 /* 3080 * Iterate over all pools to determine the maximum width 3081 * for the pool / device name column across all pools. 3082 */ 3083 cb.cb_namewidth = 0; 3084 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3085 3086 if (timestamp_fmt != NODATE) 3087 print_timestamp(timestamp_fmt); 3088 3089 /* 3090 * If it's the first time, or verbose mode, print the header. 3091 */ 3092 if (++cb.cb_iteration == 1 || verbose) 3093 print_iostat_header(&cb); 3094 3095 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 3096 3097 /* 3098 * If there's more than one pool, and we're not in verbose mode 3099 * (which prints a separator for us), then print a separator. 3100 */ 3101 if (npools > 1 && !verbose) 3102 print_iostat_separator(&cb); 3103 3104 if (verbose) 3105 (void) printf("\n"); 3106 3107 /* 3108 * Flush the output so that redirection to a file isn't buffered 3109 * indefinitely. 3110 */ 3111 (void) fflush(stdout); 3112 3113 if (interval == 0) 3114 break; 3115 3116 if (count != 0 && --count == 0) 3117 break; 3118 3119 (void) sleep(interval); 3120 } 3121 3122 pool_list_free(list); 3123 3124 return (ret); 3125} 3126 3127typedef struct list_cbdata { 3128 boolean_t cb_verbose; 3129 int cb_namewidth; 3130 boolean_t cb_scripted; 3131 zprop_list_t *cb_proplist; 3132 boolean_t cb_literal; 3133} list_cbdata_t; 3134 3135/* 3136 * Given a list of columns to display, output appropriate headers for each one. 3137 */ 3138static void 3139print_header(list_cbdata_t *cb) 3140{ 3141 zprop_list_t *pl = cb->cb_proplist; 3142 char headerbuf[ZPOOL_MAXPROPLEN]; 3143 const char *header; 3144 boolean_t first = B_TRUE; 3145 boolean_t right_justify; 3146 size_t width = 0; 3147 3148 for (; pl != NULL; pl = pl->pl_next) { 3149 width = pl->pl_width; 3150 if (first && cb->cb_verbose) { 3151 /* 3152 * Reset the width to accommodate the verbose listing 3153 * of devices. 3154 */ 3155 width = cb->cb_namewidth; 3156 } 3157 3158 if (!first) 3159 (void) printf(" "); 3160 else 3161 first = B_FALSE; 3162 3163 right_justify = B_FALSE; 3164 if (pl->pl_prop != ZPROP_INVAL) { 3165 header = zpool_prop_column_name(pl->pl_prop); 3166 right_justify = zpool_prop_align_right(pl->pl_prop); 3167 } else { 3168 int i; 3169 3170 for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 3171 headerbuf[i] = toupper(pl->pl_user_prop[i]); 3172 headerbuf[i] = '\0'; 3173 header = headerbuf; 3174 } 3175 3176 if (pl->pl_next == NULL && !right_justify) 3177 (void) printf("%s", header); 3178 else if (right_justify) 3179 (void) printf("%*s", width, header); 3180 else 3181 (void) printf("%-*s", width, header); 3182 3183 } 3184 3185 (void) printf("\n"); 3186} 3187 3188/* 3189 * Given a pool and a list of properties, print out all the properties according 3190 * to the described layout. 3191 */ 3192static void 3193print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 3194{ 3195 zprop_list_t *pl = cb->cb_proplist; 3196 boolean_t first = B_TRUE; 3197 char property[ZPOOL_MAXPROPLEN]; 3198 char *propstr; 3199 boolean_t right_justify; 3200 size_t width; 3201 3202 for (; pl != NULL; pl = pl->pl_next) { 3203 3204 width = pl->pl_width; 3205 if (first && cb->cb_verbose) { 3206 /* 3207 * Reset the width to accommodate the verbose listing 3208 * of devices. 3209 */ 3210 width = cb->cb_namewidth; 3211 } 3212 3213 if (!first) { 3214 if (cb->cb_scripted) 3215 (void) printf("\t"); 3216 else 3217 (void) printf(" "); 3218 } else { 3219 first = B_FALSE; 3220 } 3221 3222 right_justify = B_FALSE; 3223 if (pl->pl_prop != ZPROP_INVAL) { 3224 if (zpool_get_prop(zhp, pl->pl_prop, property, 3225 sizeof (property), NULL, cb->cb_literal) != 0) 3226 propstr = "-"; 3227 else 3228 propstr = property; 3229 3230 right_justify = zpool_prop_align_right(pl->pl_prop); 3231 } else if ((zpool_prop_feature(pl->pl_user_prop) || 3232 zpool_prop_unsupported(pl->pl_user_prop)) && 3233 zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 3234 sizeof (property)) == 0) { 3235 propstr = property; 3236 } else { 3237 propstr = "-"; 3238 } 3239 3240 3241 /* 3242 * If this is being called in scripted mode, or if this is the 3243 * last column and it is left-justified, don't include a width 3244 * format specifier. 3245 */ 3246 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 3247 (void) printf("%s", propstr); 3248 else if (right_justify) 3249 (void) printf("%*s", width, propstr); 3250 else 3251 (void) printf("%-*s", width, propstr); 3252 } 3253 3254 (void) printf("\n"); 3255} 3256 3257static void 3258print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted, 3259 boolean_t valid) 3260{ 3261 char propval[64]; 3262 boolean_t fixed; 3263 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 3264 3265 switch (prop) { 3266 case ZPOOL_PROP_EXPANDSZ: 3267 case ZPOOL_PROP_CHECKPOINT: 3268 if (value == 0) 3269 (void) strlcpy(propval, "-", sizeof (propval)); 3270 else 3271 zfs_nicenum(value, propval, sizeof (propval)); 3272 break; 3273 case ZPOOL_PROP_FRAGMENTATION: 3274 if (value == ZFS_FRAG_INVALID) { 3275 (void) strlcpy(propval, "-", sizeof (propval)); 3276 } else { 3277 (void) snprintf(propval, sizeof (propval), "%llu%%", 3278 value); 3279 } 3280 break; 3281 case ZPOOL_PROP_CAPACITY: 3282 (void) snprintf(propval, sizeof (propval), "%llu%%", value); 3283 break; 3284 default: 3285 zfs_nicenum(value, propval, sizeof (propval)); 3286 } 3287 3288 if (!valid) 3289 (void) strlcpy(propval, "-", sizeof (propval)); 3290 3291 if (scripted) 3292 (void) printf("\t%s", propval); 3293 else 3294 (void) printf(" %*s", width, propval); 3295} 3296 3297void 3298print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 3299 list_cbdata_t *cb, int depth) 3300{ 3301 nvlist_t **child; 3302 vdev_stat_t *vs; 3303 uint_t c, children; 3304 char *vname; 3305 boolean_t scripted = cb->cb_scripted; 3306 uint64_t islog = B_FALSE; 3307 boolean_t haslog = B_FALSE; 3308 char *dashes = "%-*s - - - - - -\n"; 3309 3310 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 3311 (uint64_t **)&vs, &c) == 0); 3312 3313 if (name != NULL) { 3314 boolean_t toplevel = (vs->vs_space != 0); 3315 uint64_t cap; 3316 3317 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 3318 return; 3319 3320 if (scripted) 3321 (void) printf("\t%s", name); 3322 else if (strlen(name) + depth > cb->cb_namewidth) 3323 (void) printf("%*s%s", depth, "", name); 3324 else 3325 (void) printf("%*s%s%*s", depth, "", name, 3326 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 3327 3328 /* 3329 * Print the properties for the individual vdevs. Some 3330 * properties are only applicable to toplevel vdevs. The 3331 * 'toplevel' boolean value is passed to the print_one_column() 3332 * to indicate that the value is valid. 3333 */ 3334 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted, 3335 toplevel); 3336 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted, 3337 toplevel); 3338 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc, 3339 scripted, toplevel); 3340 print_one_column(ZPOOL_PROP_CHECKPOINT, 3341 vs->vs_checkpoint_space, scripted, toplevel); 3342 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted, 3343 B_TRUE); 3344 print_one_column(ZPOOL_PROP_FRAGMENTATION, 3345 vs->vs_fragmentation, scripted, 3346 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel)); 3347 cap = (vs->vs_space == 0) ? 0 : 3348 (vs->vs_alloc * 100 / vs->vs_space); 3349 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel); 3350 (void) printf("\n"); 3351 } 3352 3353 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 3354 &child, &children) != 0) 3355 return; 3356 3357 for (c = 0; c < children; c++) { 3358 uint64_t ishole = B_FALSE; 3359 3360 if (nvlist_lookup_uint64(child[c], 3361 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 3362 continue; 3363 3364 if (nvlist_lookup_uint64(child[c], 3365 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) { 3366 haslog = B_TRUE; 3367 continue; 3368 } 3369 3370 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3371 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3372 free(vname); 3373 } 3374 3375 if (haslog == B_TRUE) { 3376 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3377 (void) printf(dashes, cb->cb_namewidth, "log"); 3378 for (c = 0; c < children; c++) { 3379 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 3380 &islog) != 0 || !islog) 3381 continue; 3382 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3383 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3384 free(vname); 3385 } 3386 } 3387 3388 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 3389 &child, &children) == 0 && children > 0) { 3390 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3391 (void) printf(dashes, cb->cb_namewidth, "cache"); 3392 for (c = 0; c < children; c++) { 3393 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3394 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3395 free(vname); 3396 } 3397 } 3398 3399 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, 3400 &children) == 0 && children > 0) { 3401 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3402 (void) printf(dashes, cb->cb_namewidth, "spare"); 3403 for (c = 0; c < children; c++) { 3404 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3405 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3406 free(vname); 3407 } 3408 } 3409} 3410 3411 3412/* 3413 * Generic callback function to list a pool. 3414 */ 3415int 3416list_callback(zpool_handle_t *zhp, void *data) 3417{ 3418 list_cbdata_t *cbp = data; 3419 nvlist_t *config; 3420 nvlist_t *nvroot; 3421 3422 config = zpool_get_config(zhp, NULL); 3423 3424 print_pool(zhp, cbp); 3425 if (!cbp->cb_verbose) 3426 return (0); 3427 3428 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 3429 &nvroot) == 0); 3430 print_list_stats(zhp, NULL, nvroot, cbp, 0); 3431 3432 return (0); 3433} 3434 3435/* 3436 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 3437 * 3438 * -H Scripted mode. Don't display headers, and separate properties 3439 * by a single tab. 3440 * -o List of properties to display. Defaults to 3441 * "name,size,allocated,free,expandsize,fragmentation,capacity," 3442 * "dedupratio,health,altroot" 3443 * -p Diplay values in parsable (exact) format. 3444 * -T Display a timestamp in date(1) or Unix format 3445 * 3446 * List all pools in the system, whether or not they're healthy. Output space 3447 * statistics for each one, as well as health status summary. 3448 */ 3449int 3450zpool_do_list(int argc, char **argv) 3451{ 3452 int c; 3453 int ret; 3454 list_cbdata_t cb = { 0 }; 3455 static char default_props[] = 3456 "name,size,allocated,free,checkpoint,expandsize,fragmentation," 3457 "capacity,dedupratio,health,altroot"; 3458 char *props = default_props; 3459 unsigned long interval = 0, count = 0; 3460 zpool_list_t *list; 3461 boolean_t first = B_TRUE; 3462 3463 /* check options */ 3464 while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) { 3465 switch (c) { 3466 case 'H': 3467 cb.cb_scripted = B_TRUE; 3468 break; 3469 case 'o': 3470 props = optarg; 3471 break; 3472 case 'p': 3473 cb.cb_literal = B_TRUE; 3474 break; 3475 case 'T': 3476 get_timestamp_arg(*optarg); 3477 break; 3478 case 'v': 3479 cb.cb_verbose = B_TRUE; 3480 break; 3481 case ':': 3482 (void) fprintf(stderr, gettext("missing argument for " 3483 "'%c' option\n"), optopt); 3484 usage(B_FALSE); 3485 break; 3486 case '?': 3487 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3488 optopt); 3489 usage(B_FALSE); 3490 } 3491 } 3492 3493 argc -= optind; 3494 argv += optind; 3495 3496 get_interval_count(&argc, argv, &interval, &count); 3497 3498 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 3499 usage(B_FALSE); 3500 3501 for (;;) { 3502 if ((list = pool_list_get(argc, argv, &cb.cb_proplist, 3503 &ret)) == NULL) 3504 return (1); 3505 3506 if (pool_list_count(list) == 0) 3507 break; 3508 3509 cb.cb_namewidth = 0; 3510 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3511 3512 if (timestamp_fmt != NODATE) 3513 print_timestamp(timestamp_fmt); 3514 3515 if (!cb.cb_scripted && (first || cb.cb_verbose)) { 3516 print_header(&cb); 3517 first = B_FALSE; 3518 } 3519 ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 3520 3521 if (interval == 0) 3522 break; 3523 3524 if (count != 0 && --count == 0) 3525 break; 3526 3527 pool_list_free(list); 3528 (void) sleep(interval); 3529 } 3530 3531 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 3532 (void) printf(gettext("no pools available\n")); 3533 ret = 0; 3534 } 3535 3536 pool_list_free(list); 3537 zprop_free_list(cb.cb_proplist); 3538 return (ret); 3539} 3540 3541static int 3542zpool_do_attach_or_replace(int argc, char **argv, int replacing) 3543{ 3544 boolean_t force = B_FALSE; 3545 int c; 3546 nvlist_t *nvroot; 3547 char *poolname, *old_disk, *new_disk; 3548 zpool_handle_t *zhp; 3549 zpool_boot_label_t boot_type; 3550 uint64_t boot_size; 3551 int ret; 3552 3553 /* check options */ 3554 while ((c = getopt(argc, argv, "f")) != -1) { 3555 switch (c) { 3556 case 'f': 3557 force = B_TRUE; 3558 break; 3559 case '?': 3560 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3561 optopt); 3562 usage(B_FALSE); 3563 } 3564 } 3565 3566 argc -= optind; 3567 argv += optind; 3568 3569 /* get pool name and check number of arguments */ 3570 if (argc < 1) { 3571 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3572 usage(B_FALSE); 3573 } 3574 3575 poolname = argv[0]; 3576 3577 if (argc < 2) { 3578 (void) fprintf(stderr, 3579 gettext("missing <device> specification\n")); 3580 usage(B_FALSE); 3581 } 3582 3583 old_disk = argv[1]; 3584 3585 if (argc < 3) { 3586 if (!replacing) { 3587 (void) fprintf(stderr, 3588 gettext("missing <new_device> specification\n")); 3589 usage(B_FALSE); 3590 } 3591 new_disk = old_disk; 3592 argc -= 1; 3593 argv += 1; 3594 } else { 3595 new_disk = argv[2]; 3596 argc -= 2; 3597 argv += 2; 3598 } 3599 3600 if (argc > 1) { 3601 (void) fprintf(stderr, gettext("too many arguments\n")); 3602 usage(B_FALSE); 3603 } 3604 3605 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3606 return (1); 3607 3608 if (zpool_get_config(zhp, NULL) == NULL) { 3609 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 3610 poolname); 3611 zpool_close(zhp); 3612 return (1); 3613 } 3614 3615 if (zpool_is_bootable(zhp)) 3616 boot_type = ZPOOL_COPY_BOOT_LABEL; 3617 else 3618 boot_type = ZPOOL_NO_BOOT_LABEL; 3619 3620 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 3621 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE, 3622 boot_type, boot_size, argc, argv); 3623 if (nvroot == NULL) { 3624 zpool_close(zhp); 3625 return (1); 3626 } 3627 3628 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 3629 3630 nvlist_free(nvroot); 3631 zpool_close(zhp); 3632 3633 return (ret); 3634} 3635 3636/* 3637 * zpool replace [-f] <pool> <device> <new_device> 3638 * 3639 * -f Force attach, even if <new_device> appears to be in use. 3640 * 3641 * Replace <device> with <new_device>. 3642 */ 3643/* ARGSUSED */ 3644int 3645zpool_do_replace(int argc, char **argv) 3646{ 3647 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 3648} 3649 3650/* 3651 * zpool attach [-f] <pool> <device> <new_device> 3652 * 3653 * -f Force attach, even if <new_device> appears to be in use. 3654 * 3655 * Attach <new_device> to the mirror containing <device>. If <device> is not 3656 * part of a mirror, then <device> will be transformed into a mirror of 3657 * <device> and <new_device>. In either case, <new_device> will begin life 3658 * with a DTL of [0, now], and will immediately begin to resilver itself. 3659 */ 3660int 3661zpool_do_attach(int argc, char **argv) 3662{ 3663 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 3664} 3665 3666/* 3667 * zpool detach [-f] <pool> <device> 3668 * 3669 * -f Force detach of <device>, even if DTLs argue against it 3670 * (not supported yet) 3671 * 3672 * Detach a device from a mirror. The operation will be refused if <device> 3673 * is the last device in the mirror, or if the DTLs indicate that this device 3674 * has the only valid copy of some data. 3675 */ 3676/* ARGSUSED */ 3677int 3678zpool_do_detach(int argc, char **argv) 3679{ 3680 int c; 3681 char *poolname, *path; 3682 zpool_handle_t *zhp; 3683 int ret; 3684 3685 /* check options */ 3686 while ((c = getopt(argc, argv, "f")) != -1) { 3687 switch (c) { 3688 case 'f': 3689 case '?': 3690 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3691 optopt); 3692 usage(B_FALSE); 3693 } 3694 } 3695 3696 argc -= optind; 3697 argv += optind; 3698 3699 /* get pool name and check number of arguments */ 3700 if (argc < 1) { 3701 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3702 usage(B_FALSE); 3703 } 3704 3705 if (argc < 2) { 3706 (void) fprintf(stderr, 3707 gettext("missing <device> specification\n")); 3708 usage(B_FALSE); 3709 } 3710 3711 poolname = argv[0]; 3712 path = argv[1]; 3713 3714 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3715 return (1); 3716 3717 ret = zpool_vdev_detach(zhp, path); 3718 3719 zpool_close(zhp); 3720 3721 return (ret); 3722} 3723 3724/* 3725 * zpool split [-n] [-o prop=val] ... 3726 * [-o mntopt] ... 3727 * [-R altroot] <pool> <newpool> [<device> ...] 3728 * 3729 * -n Do not split the pool, but display the resulting layout if 3730 * it were to be split. 3731 * -o Set property=value, or set mount options. 3732 * -R Mount the split-off pool under an alternate root. 3733 * 3734 * Splits the named pool and gives it the new pool name. Devices to be split 3735 * off may be listed, provided that no more than one device is specified 3736 * per top-level vdev mirror. The newly split pool is left in an exported 3737 * state unless -R is specified. 3738 * 3739 * Restrictions: the top-level of the pool pool must only be made up of 3740 * mirrors; all devices in the pool must be healthy; no device may be 3741 * undergoing a resilvering operation. 3742 */ 3743int 3744zpool_do_split(int argc, char **argv) 3745{ 3746 char *srcpool, *newpool, *propval; 3747 char *mntopts = NULL; 3748 splitflags_t flags; 3749 int c, ret = 0; 3750 zpool_handle_t *zhp; 3751 nvlist_t *config, *props = NULL; 3752 3753 flags.dryrun = B_FALSE; 3754 flags.import = B_FALSE; 3755 3756 /* check options */ 3757 while ((c = getopt(argc, argv, ":R:no:")) != -1) { 3758 switch (c) { 3759 case 'R': 3760 flags.import = B_TRUE; 3761 if (add_prop_list( 3762 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 3763 &props, B_TRUE) != 0) { 3764 nvlist_free(props); 3765 usage(B_FALSE); 3766 } 3767 break; 3768 case 'n': 3769 flags.dryrun = B_TRUE; 3770 break; 3771 case 'o': 3772 if ((propval = strchr(optarg, '=')) != NULL) { 3773 *propval = '\0'; 3774 propval++; 3775 if (add_prop_list(optarg, propval, 3776 &props, B_TRUE) != 0) { 3777 nvlist_free(props); 3778 usage(B_FALSE); 3779 } 3780 } else { 3781 mntopts = optarg; 3782 } 3783 break; 3784 case ':': 3785 (void) fprintf(stderr, gettext("missing argument for " 3786 "'%c' option\n"), optopt); 3787 usage(B_FALSE); 3788 break; 3789 case '?': 3790 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3791 optopt); 3792 usage(B_FALSE); 3793 break; 3794 } 3795 } 3796 3797 if (!flags.import && mntopts != NULL) { 3798 (void) fprintf(stderr, gettext("setting mntopts is only " 3799 "valid when importing the pool\n")); 3800 usage(B_FALSE); 3801 } 3802 3803 argc -= optind; 3804 argv += optind; 3805 3806 if (argc < 1) { 3807 (void) fprintf(stderr, gettext("Missing pool name\n")); 3808 usage(B_FALSE); 3809 } 3810 if (argc < 2) { 3811 (void) fprintf(stderr, gettext("Missing new pool name\n")); 3812 usage(B_FALSE); 3813 } 3814 3815 srcpool = argv[0]; 3816 newpool = argv[1]; 3817 3818 argc -= 2; 3819 argv += 2; 3820 3821 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) 3822 return (1); 3823 3824 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 3825 if (config == NULL) { 3826 ret = 1; 3827 } else { 3828 if (flags.dryrun) { 3829 (void) printf(gettext("would create '%s' with the " 3830 "following layout:\n\n"), newpool); 3831 print_vdev_tree(NULL, newpool, config, 0, B_FALSE); 3832 } 3833 nvlist_free(config); 3834 } 3835 3836 zpool_close(zhp); 3837 3838 if (ret != 0 || flags.dryrun || !flags.import) 3839 return (ret); 3840 3841 /* 3842 * The split was successful. Now we need to open the new 3843 * pool and import it. 3844 */ 3845 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) 3846 return (1); 3847 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 3848 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 3849 ret = 1; 3850 (void) fprintf(stderr, gettext("Split was successful, but " 3851 "the datasets could not all be mounted\n")); 3852 (void) fprintf(stderr, gettext("Try doing '%s' with a " 3853 "different altroot\n"), "zpool import"); 3854 } 3855 zpool_close(zhp); 3856 3857 return (ret); 3858} 3859 3860 3861 3862/* 3863 * zpool online <pool> <device> ... 3864 */ 3865int 3866zpool_do_online(int argc, char **argv) 3867{ 3868 int c, i; 3869 char *poolname; 3870 zpool_handle_t *zhp; 3871 int ret = 0; 3872 vdev_state_t newstate; 3873 int flags = 0; 3874 3875 /* check options */ 3876 while ((c = getopt(argc, argv, "et")) != -1) { 3877 switch (c) { 3878 case 'e': 3879 flags |= ZFS_ONLINE_EXPAND; 3880 break; 3881 case 't': 3882 case '?': 3883 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3884 optopt); 3885 usage(B_FALSE); 3886 } 3887 } 3888 3889 argc -= optind; 3890 argv += optind; 3891 3892 /* get pool name and check number of arguments */ 3893 if (argc < 1) { 3894 (void) fprintf(stderr, gettext("missing pool name\n")); 3895 usage(B_FALSE); 3896 } 3897 if (argc < 2) { 3898 (void) fprintf(stderr, gettext("missing device name\n")); 3899 usage(B_FALSE); 3900 } 3901 3902 poolname = argv[0]; 3903 3904 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3905 return (1); 3906 3907 for (i = 1; i < argc; i++) { 3908 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 3909 if (newstate != VDEV_STATE_HEALTHY) { 3910 (void) printf(gettext("warning: device '%s' " 3911 "onlined, but remains in faulted state\n"), 3912 argv[i]); 3913 if (newstate == VDEV_STATE_FAULTED) 3914 (void) printf(gettext("use 'zpool " 3915 "clear' to restore a faulted " 3916 "device\n")); 3917 else 3918 (void) printf(gettext("use 'zpool " 3919 "replace' to replace devices " 3920 "that are no longer present\n")); 3921 } 3922 } else { 3923 ret = 1; 3924 } 3925 } 3926 3927 zpool_close(zhp); 3928 3929 return (ret); 3930} 3931 3932/* 3933 * zpool offline [-ft] <pool> <device> ... 3934 * 3935 * -f Force the device into the offline state, even if doing 3936 * so would appear to compromise pool availability. 3937 * (not supported yet) 3938 * 3939 * -t Only take the device off-line temporarily. The offline 3940 * state will not be persistent across reboots. 3941 */ 3942/* ARGSUSED */ 3943int 3944zpool_do_offline(int argc, char **argv) 3945{ 3946 int c, i; 3947 char *poolname; 3948 zpool_handle_t *zhp; 3949 int ret = 0; 3950 boolean_t istmp = B_FALSE; 3951 3952 /* check options */ 3953 while ((c = getopt(argc, argv, "ft")) != -1) { 3954 switch (c) { 3955 case 't': 3956 istmp = B_TRUE; 3957 break; 3958 case 'f': 3959 case '?': 3960 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3961 optopt); 3962 usage(B_FALSE); 3963 } 3964 } 3965 3966 argc -= optind; 3967 argv += optind; 3968 3969 /* get pool name and check number of arguments */ 3970 if (argc < 1) { 3971 (void) fprintf(stderr, gettext("missing pool name\n")); 3972 usage(B_FALSE); 3973 } 3974 if (argc < 2) { 3975 (void) fprintf(stderr, gettext("missing device name\n")); 3976 usage(B_FALSE); 3977 } 3978 3979 poolname = argv[0]; 3980 3981 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3982 return (1); 3983 3984 for (i = 1; i < argc; i++) { 3985 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 3986 ret = 1; 3987 } 3988 3989 zpool_close(zhp); 3990 3991 return (ret); 3992} 3993 3994/* 3995 * zpool clear <pool> [device] 3996 * 3997 * Clear all errors associated with a pool or a particular device. 3998 */ 3999int 4000zpool_do_clear(int argc, char **argv) 4001{ 4002 int c; 4003 int ret = 0; 4004 boolean_t dryrun = B_FALSE; 4005 boolean_t do_rewind = B_FALSE; 4006 boolean_t xtreme_rewind = B_FALSE; 4007 uint32_t rewind_policy = ZPOOL_NO_REWIND; 4008 nvlist_t *policy = NULL; 4009 zpool_handle_t *zhp; 4010 char *pool, *device; 4011 4012 /* check options */ 4013 while ((c = getopt(argc, argv, "FnX")) != -1) { 4014 switch (c) { 4015 case 'F': 4016 do_rewind = B_TRUE; 4017 break; 4018 case 'n': 4019 dryrun = B_TRUE; 4020 break; 4021 case 'X': 4022 xtreme_rewind = B_TRUE; 4023 break; 4024 case '?': 4025 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4026 optopt); 4027 usage(B_FALSE); 4028 } 4029 } 4030 4031 argc -= optind; 4032 argv += optind; 4033 4034 if (argc < 1) { 4035 (void) fprintf(stderr, gettext("missing pool name\n")); 4036 usage(B_FALSE); 4037 } 4038 4039 if (argc > 2) { 4040 (void) fprintf(stderr, gettext("too many arguments\n")); 4041 usage(B_FALSE); 4042 } 4043 4044 if ((dryrun || xtreme_rewind) && !do_rewind) { 4045 (void) fprintf(stderr, 4046 gettext("-n or -X only meaningful with -F\n")); 4047 usage(B_FALSE); 4048 } 4049 if (dryrun) 4050 rewind_policy = ZPOOL_TRY_REWIND; 4051 else if (do_rewind) 4052 rewind_policy = ZPOOL_DO_REWIND; 4053 if (xtreme_rewind) 4054 rewind_policy |= ZPOOL_EXTREME_REWIND; 4055 4056 /* In future, further rewind policy choices can be passed along here */ 4057 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 4058 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 4059 rewind_policy) != 0) { 4060 return (1); 4061 } 4062 4063 pool = argv[0]; 4064 device = argc == 2 ? argv[1] : NULL; 4065 4066 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 4067 nvlist_free(policy); 4068 return (1); 4069 } 4070 4071 if (zpool_clear(zhp, device, policy) != 0) 4072 ret = 1; 4073 4074 zpool_close(zhp); 4075 4076 nvlist_free(policy); 4077 4078 return (ret); 4079} 4080 4081/* 4082 * zpool reguid <pool> 4083 */ 4084int 4085zpool_do_reguid(int argc, char **argv) 4086{ 4087 int c; 4088 char *poolname; 4089 zpool_handle_t *zhp; 4090 int ret = 0; 4091 4092 /* check options */ 4093 while ((c = getopt(argc, argv, "")) != -1) { 4094 switch (c) { 4095 case '?': 4096 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4097 optopt); 4098 usage(B_FALSE); 4099 } 4100 } 4101 4102 argc -= optind; 4103 argv += optind; 4104 4105 /* get pool name and check number of arguments */ 4106 if (argc < 1) { 4107 (void) fprintf(stderr, gettext("missing pool name\n")); 4108 usage(B_FALSE); 4109 } 4110 4111 if (argc > 1) { 4112 (void) fprintf(stderr, gettext("too many arguments\n")); 4113 usage(B_FALSE); 4114 } 4115 4116 poolname = argv[0]; 4117 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4118 return (1); 4119 4120 ret = zpool_reguid(zhp); 4121 4122 zpool_close(zhp); 4123 return (ret); 4124} 4125 4126 4127/* 4128 * zpool reopen <pool> 4129 * 4130 * Reopen the pool so that the kernel can update the sizes of all vdevs. 4131 */ 4132int 4133zpool_do_reopen(int argc, char **argv) 4134{ 4135 int c; 4136 int ret = 0; 4137 zpool_handle_t *zhp; 4138 char *pool; 4139 4140 /* check options */ 4141 while ((c = getopt(argc, argv, "")) != -1) { 4142 switch (c) { 4143 case '?': 4144 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4145 optopt); 4146 usage(B_FALSE); 4147 } 4148 } 4149 4150 argc--; 4151 argv++; 4152 4153 if (argc < 1) { 4154 (void) fprintf(stderr, gettext("missing pool name\n")); 4155 usage(B_FALSE); 4156 } 4157 4158 if (argc > 1) { 4159 (void) fprintf(stderr, gettext("too many arguments\n")); 4160 usage(B_FALSE); 4161 } 4162 4163 pool = argv[0]; 4164 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 4165 return (1); 4166 4167 ret = zpool_reopen(zhp); 4168 zpool_close(zhp); 4169 return (ret); 4170} 4171 4172typedef struct scrub_cbdata { 4173 int cb_type; 4174 int cb_argc; 4175 char **cb_argv; 4176 pool_scrub_cmd_t cb_scrub_cmd; 4177} scrub_cbdata_t; 4178 4179static boolean_t 4180zpool_has_checkpoint(zpool_handle_t *zhp) 4181{ 4182 nvlist_t *config, *nvroot; 4183 4184 config = zpool_get_config(zhp, NULL); 4185 4186 if (config != NULL) { 4187 pool_checkpoint_stat_t *pcs = NULL; 4188 uint_t c; 4189 4190 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 4191 (void) nvlist_lookup_uint64_array(nvroot, 4192 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 4193 4194 if (pcs == NULL || pcs->pcs_state == CS_NONE) 4195 return (B_FALSE); 4196 4197 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS || 4198 pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 4199 return (B_TRUE); 4200 } 4201 4202 return (B_FALSE); 4203} 4204 4205int 4206scrub_callback(zpool_handle_t *zhp, void *data) 4207{ 4208 scrub_cbdata_t *cb = data; 4209 int err; 4210 4211 /* 4212 * Ignore faulted pools. 4213 */ 4214 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 4215 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 4216 "currently unavailable\n"), zpool_get_name(zhp)); 4217 return (1); 4218 } 4219 4220 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd); 4221 4222 if (err == 0 && zpool_has_checkpoint(zhp) && 4223 cb->cb_type == POOL_SCAN_SCRUB) { 4224 (void) printf(gettext("warning: will not scrub state that " 4225 "belongs to the checkpoint of pool '%s'\n"), 4226 zpool_get_name(zhp)); 4227 } 4228 4229 return (err != 0); 4230} 4231 4232/* 4233 * zpool scrub [-s | -p] <pool> ... 4234 * 4235 * -s Stop. Stops any in-progress scrub. 4236 * -p Pause. Pause in-progress scrub. 4237 */ 4238int 4239zpool_do_scrub(int argc, char **argv) 4240{ 4241 int c; 4242 scrub_cbdata_t cb; 4243 4244 cb.cb_type = POOL_SCAN_SCRUB; 4245 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 4246 4247 /* check options */ 4248 while ((c = getopt(argc, argv, "sp")) != -1) { 4249 switch (c) { 4250 case 's': 4251 cb.cb_type = POOL_SCAN_NONE; 4252 break; 4253 case 'p': 4254 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE; 4255 break; 4256 case '?': 4257 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4258 optopt); 4259 usage(B_FALSE); 4260 } 4261 } 4262 4263 if (cb.cb_type == POOL_SCAN_NONE && 4264 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) { 4265 (void) fprintf(stderr, gettext("invalid option combination: " 4266 "-s and -p are mutually exclusive\n")); 4267 usage(B_FALSE); 4268 } 4269 4270 cb.cb_argc = argc; 4271 cb.cb_argv = argv; 4272 argc -= optind; 4273 argv += optind; 4274 4275 if (argc < 1) { 4276 (void) fprintf(stderr, gettext("missing pool name argument\n")); 4277 usage(B_FALSE); 4278 } 4279 4280 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 4281} 4282 4283static void 4284zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res) 4285{ 4286 uint_t children = 0; 4287 nvlist_t **child; 4288 uint_t i; 4289 4290 (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 4291 &child, &children); 4292 4293 if (children == 0) { 4294 char *path = zpool_vdev_name(g_zfs, zhp, nvroot, B_FALSE); 4295 fnvlist_add_boolean(res, path); 4296 free(path); 4297 return; 4298 } 4299 4300 for (i = 0; i < children; i++) { 4301 zpool_collect_leaves(zhp, child[i], res); 4302 } 4303} 4304 4305/* 4306 * zpool initialize [-cs] <pool> [<vdev> ...] 4307 * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool 4308 * if none specified. 4309 * 4310 * -c Cancel. Ends active initializing. 4311 * -s Suspend. Initializing can then be restarted with no flags. 4312 */ 4313int 4314zpool_do_initialize(int argc, char **argv) 4315{ 4316 int c; 4317 char *poolname; 4318 zpool_handle_t *zhp; 4319 nvlist_t *vdevs; 4320 int err = 0; 4321 4322 struct option long_options[] = { 4323 {"cancel", no_argument, NULL, 'c'}, 4324 {"suspend", no_argument, NULL, 's'}, 4325 {0, 0, 0, 0} 4326 }; 4327 4328 pool_initialize_func_t cmd_type = POOL_INITIALIZE_DO; 4329 while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) { 4330 switch (c) { 4331 case 'c': 4332 if (cmd_type != POOL_INITIALIZE_DO) { 4333 (void) fprintf(stderr, gettext("-c cannot be " 4334 "combined with other options\n")); 4335 usage(B_FALSE); 4336 } 4337 cmd_type = POOL_INITIALIZE_CANCEL; 4338 break; 4339 case 's': 4340 if (cmd_type != POOL_INITIALIZE_DO) { 4341 (void) fprintf(stderr, gettext("-s cannot be " 4342 "combined with other options\n")); 4343 usage(B_FALSE); 4344 } 4345 cmd_type = POOL_INITIALIZE_SUSPEND; 4346 break; 4347 case '?': 4348 if (optopt != 0) { 4349 (void) fprintf(stderr, 4350 gettext("invalid option '%c'\n"), optopt); 4351 } else { 4352 (void) fprintf(stderr, 4353 gettext("invalid option '%s'\n"), 4354 argv[optind - 1]); 4355 } 4356 usage(B_FALSE); 4357 } 4358 } 4359 4360 argc -= optind; 4361 argv += optind; 4362 4363 if (argc < 1) { 4364 (void) fprintf(stderr, gettext("missing pool name argument\n")); 4365 usage(B_FALSE); 4366 return (-1); 4367 } 4368 4369 poolname = argv[0]; 4370 zhp = zpool_open(g_zfs, poolname); 4371 if (zhp == NULL) 4372 return (-1); 4373 4374 vdevs = fnvlist_alloc(); 4375 if (argc == 1) { 4376 /* no individual leaf vdevs specified, so add them all */ 4377 nvlist_t *config = zpool_get_config(zhp, NULL); 4378 nvlist_t *nvroot = fnvlist_lookup_nvlist(config, 4379 ZPOOL_CONFIG_VDEV_TREE); 4380 zpool_collect_leaves(zhp, nvroot, vdevs); 4381 } else { 4382 int i; 4383 for (i = 1; i < argc; i++) { 4384 fnvlist_add_boolean(vdevs, argv[i]); 4385 } 4386 } 4387 4388 err = zpool_initialize(zhp, cmd_type, vdevs); 4389 4390 fnvlist_free(vdevs); 4391 zpool_close(zhp); 4392 4393 return (err); 4394} 4395 4396typedef struct status_cbdata { 4397 int cb_count; 4398 boolean_t cb_allpools; 4399 boolean_t cb_verbose; 4400 boolean_t cb_explain; 4401 boolean_t cb_first; 4402 boolean_t cb_dedup_stats; 4403} status_cbdata_t; 4404 4405/* 4406 * Print out detailed scrub status. 4407 */ 4408static void 4409print_scan_status(pool_scan_stat_t *ps) 4410{ 4411 time_t start, end, pause; 4412 uint64_t total_secs_left; 4413 uint64_t elapsed, secs_left, mins_left, hours_left, days_left; 4414 uint64_t pass_scanned, scanned, pass_issued, issued, total; 4415 uint_t scan_rate, issue_rate; 4416 double fraction_done; 4417 char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7]; 4418 char srate_buf[7], irate_buf[7]; 4419 4420 (void) printf(gettext(" scan: ")); 4421 4422 /* If there's never been a scan, there's not much to say. */ 4423 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 4424 ps->pss_func >= POOL_SCAN_FUNCS) { 4425 (void) printf(gettext("none requested\n")); 4426 return; 4427 } 4428 4429 start = ps->pss_start_time; 4430 end = ps->pss_end_time; 4431 pause = ps->pss_pass_scrub_pause; 4432 4433 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); 4434 4435 assert(ps->pss_func == POOL_SCAN_SCRUB || 4436 ps->pss_func == POOL_SCAN_RESILVER); 4437 4438 /* Scan is finished or canceled. */ 4439 if (ps->pss_state == DSS_FINISHED) { 4440 total_secs_left = end - start; 4441 days_left = total_secs_left / 60 / 60 / 24; 4442 hours_left = (total_secs_left / 60 / 60) % 24; 4443 mins_left = (total_secs_left / 60) % 60; 4444 secs_left = (total_secs_left % 60); 4445 4446 if (ps->pss_func == POOL_SCAN_SCRUB) { 4447 (void) printf(gettext("scrub repaired %s " 4448 "in %llu days %02llu:%02llu:%02llu " 4449 "with %llu errors on %s"), processed_buf, 4450 (u_longlong_t)days_left, (u_longlong_t)hours_left, 4451 (u_longlong_t)mins_left, (u_longlong_t)secs_left, 4452 (u_longlong_t)ps->pss_errors, ctime(&end)); 4453 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4454 (void) printf(gettext("resilvered %s " 4455 "in %llu days %02llu:%02llu:%02llu " 4456 "with %llu errors on %s"), processed_buf, 4457 (u_longlong_t)days_left, (u_longlong_t)hours_left, 4458 (u_longlong_t)mins_left, (u_longlong_t)secs_left, 4459 (u_longlong_t)ps->pss_errors, ctime(&end)); 4460 4461 } 4462 4463 return; 4464 } else if (ps->pss_state == DSS_CANCELED) { 4465 if (ps->pss_func == POOL_SCAN_SCRUB) { 4466 (void) printf(gettext("scrub canceled on %s"), 4467 ctime(&end)); 4468 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4469 (void) printf(gettext("resilver canceled on %s"), 4470 ctime(&end)); 4471 } 4472 return; 4473 } 4474 4475 assert(ps->pss_state == DSS_SCANNING); 4476 4477 /* Scan is in progress. Resilvers can't be paused. */ 4478 if (ps->pss_func == POOL_SCAN_SCRUB) { 4479 if (pause == 0) { 4480 (void) printf(gettext("scrub in progress since %s"), 4481 ctime(&start)); 4482 } else { 4483 (void) printf(gettext("scrub paused since %s"), 4484 ctime(&pause)); 4485 (void) printf(gettext("\tscrub started on %s"), 4486 ctime(&start)); 4487 } 4488 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4489 (void) printf(gettext("resilver in progress since %s"), 4490 ctime(&start)); 4491 } 4492 4493 scanned = ps->pss_examined; 4494 pass_scanned = ps->pss_pass_exam; 4495 issued = ps->pss_issued; 4496 pass_issued = ps->pss_pass_issued; 4497 total = ps->pss_to_examine; 4498 4499 /* we are only done with a block once we have issued the IO for it */ 4500 fraction_done = (double)issued / total; 4501 4502 /* elapsed time for this pass, rounding up to 1 if it's 0 */ 4503 elapsed = time(NULL) - ps->pss_pass_start; 4504 elapsed -= ps->pss_pass_scrub_spent_paused; 4505 elapsed = (elapsed != 0) ? elapsed : 1; 4506 4507 scan_rate = pass_scanned / elapsed; 4508 issue_rate = pass_issued / elapsed; 4509 total_secs_left = (issue_rate != 0) ? 4510 ((total - issued) / issue_rate) : UINT64_MAX; 4511 4512 days_left = total_secs_left / 60 / 60 / 24; 4513 hours_left = (total_secs_left / 60 / 60) % 24; 4514 mins_left = (total_secs_left / 60) % 60; 4515 secs_left = (total_secs_left % 60); 4516 4517 /* format all of the numbers we will be reporting */ 4518 zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf)); 4519 zfs_nicenum(issued, issued_buf, sizeof (issued_buf)); 4520 zfs_nicenum(total, total_buf, sizeof (total_buf)); 4521 zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf)); 4522 zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf)); 4523 4524 /* doo not print estimated time if we have a paused scrub */ 4525 if (pause == 0) { 4526 (void) printf(gettext("\t%s scanned at %s/s, " 4527 "%s issued at %s/s, %s total\n"), 4528 scanned_buf, srate_buf, issued_buf, irate_buf, total_buf); 4529 } else { 4530 (void) printf(gettext("\t%s scanned, %s issued, %s total\n"), 4531 scanned_buf, issued_buf, total_buf); 4532 } 4533 4534 if (ps->pss_func == POOL_SCAN_RESILVER) { 4535 (void) printf(gettext("\t%s resilvered, %.2f%% done"), 4536 processed_buf, 100 * fraction_done); 4537 } else if (ps->pss_func == POOL_SCAN_SCRUB) { 4538 (void) printf(gettext("\t%s repaired, %.2f%% done"), 4539 processed_buf, 100 * fraction_done); 4540 } 4541 4542 if (pause == 0) { 4543 if (issue_rate >= 10 * 1024 * 1024) { 4544 (void) printf(gettext(", %llu days " 4545 "%02llu:%02llu:%02llu to go\n"), 4546 (u_longlong_t)days_left, (u_longlong_t)hours_left, 4547 (u_longlong_t)mins_left, (u_longlong_t)secs_left); 4548 } else { 4549 (void) printf(gettext(", no estimated " 4550 "completion time\n")); 4551 } 4552 } else { 4553 (void) printf(gettext("\n")); 4554 } 4555} 4556 4557/* 4558 * As we don't scrub checkpointed blocks, we want to warn the 4559 * user that we skipped scanning some blocks if a checkpoint exists 4560 * or existed at any time during the scan. 4561 */ 4562static void 4563print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs) 4564{ 4565 if (ps == NULL || pcs == NULL) 4566 return; 4567 4568 if (pcs->pcs_state == CS_NONE || 4569 pcs->pcs_state == CS_CHECKPOINT_DISCARDING) 4570 return; 4571 4572 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS); 4573 4574 if (ps->pss_state == DSS_NONE) 4575 return; 4576 4577 if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) && 4578 ps->pss_end_time < pcs->pcs_start_time) 4579 return; 4580 4581 if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) { 4582 (void) printf(gettext(" scan warning: skipped blocks " 4583 "that are only referenced by the checkpoint.\n")); 4584 } else { 4585 assert(ps->pss_state == DSS_SCANNING); 4586 (void) printf(gettext(" scan warning: skipping blocks " 4587 "that are only referenced by the checkpoint.\n")); 4588 } 4589} 4590 4591/* 4592 * Print out detailed removal status. 4593 */ 4594static void 4595print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) 4596{ 4597 char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 4598 time_t start, end; 4599 nvlist_t *config, *nvroot; 4600 nvlist_t **child; 4601 uint_t children; 4602 char *vdev_name; 4603 4604 if (prs == NULL || prs->prs_state == DSS_NONE) 4605 return; 4606 4607 /* 4608 * Determine name of vdev. 4609 */ 4610 config = zpool_get_config(zhp, NULL); 4611 nvroot = fnvlist_lookup_nvlist(config, 4612 ZPOOL_CONFIG_VDEV_TREE); 4613 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 4614 &child, &children) == 0); 4615 assert(prs->prs_removing_vdev < children); 4616 vdev_name = zpool_vdev_name(g_zfs, zhp, 4617 child[prs->prs_removing_vdev], B_TRUE); 4618 4619 (void) printf(gettext("remove: ")); 4620 4621 start = prs->prs_start_time; 4622 end = prs->prs_end_time; 4623 zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf)); 4624 4625 /* 4626 * Removal is finished or canceled. 4627 */ 4628 if (prs->prs_state == DSS_FINISHED) { 4629 uint64_t minutes_taken = (end - start) / 60; 4630 4631 (void) printf(gettext("Removal of vdev %llu copied %s " 4632 "in %lluh%um, completed on %s"), 4633 (longlong_t)prs->prs_removing_vdev, 4634 copied_buf, 4635 (u_longlong_t)(minutes_taken / 60), 4636 (uint_t)(minutes_taken % 60), 4637 ctime((time_t *)&end)); 4638 } else if (prs->prs_state == DSS_CANCELED) { 4639 (void) printf(gettext("Removal of %s canceled on %s"), 4640 vdev_name, ctime(&end)); 4641 } else { 4642 uint64_t copied, total, elapsed, mins_left, hours_left; 4643 double fraction_done; 4644 uint_t rate; 4645 4646 assert(prs->prs_state == DSS_SCANNING); 4647 4648 /* 4649 * Removal is in progress. 4650 */ 4651 (void) printf(gettext( 4652 "Evacuation of %s in progress since %s"), 4653 vdev_name, ctime(&start)); 4654 4655 copied = prs->prs_copied > 0 ? prs->prs_copied : 1; 4656 total = prs->prs_to_copy; 4657 fraction_done = (double)copied / total; 4658 4659 /* elapsed time for this pass */ 4660 elapsed = time(NULL) - prs->prs_start_time; 4661 elapsed = elapsed > 0 ? elapsed : 1; 4662 rate = copied / elapsed; 4663 rate = rate > 0 ? rate : 1; 4664 mins_left = ((total - copied) / rate) / 60; 4665 hours_left = mins_left / 60; 4666 4667 zfs_nicenum(copied, examined_buf, sizeof (examined_buf)); 4668 zfs_nicenum(total, total_buf, sizeof (total_buf)); 4669 zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 4670 4671 /* 4672 * do not print estimated time if hours_left is more than 4673 * 30 days 4674 */ 4675 (void) printf(gettext(" %s copied out of %s at %s/s, " 4676 "%.2f%% done"), 4677 examined_buf, total_buf, rate_buf, 100 * fraction_done); 4678 if (hours_left < (30 * 24)) { 4679 (void) printf(gettext(", %lluh%um to go\n"), 4680 (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 4681 } else { 4682 (void) printf(gettext( 4683 ", (copy is slow, no estimated time)\n")); 4684 } 4685 } 4686 4687 if (prs->prs_mapping_memory > 0) { 4688 char mem_buf[7]; 4689 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf)); 4690 (void) printf(gettext(" %s memory used for " 4691 "removed device mappings\n"), 4692 mem_buf); 4693 } 4694} 4695 4696static void 4697print_checkpoint_status(pool_checkpoint_stat_t *pcs) 4698{ 4699 time_t start; 4700 char space_buf[7]; 4701 4702 if (pcs == NULL || pcs->pcs_state == CS_NONE) 4703 return; 4704 4705 (void) printf(gettext("checkpoint: ")); 4706 4707 start = pcs->pcs_start_time; 4708 zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf)); 4709 4710 if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) { 4711 char *date = ctime(&start); 4712 4713 /* 4714 * ctime() adds a newline at the end of the generated 4715 * string, thus the weird format specifier and the 4716 * strlen() call used to chop it off from the output. 4717 */ 4718 (void) printf(gettext("created %.*s, consumes %s\n"), 4719 strlen(date) - 1, date, space_buf); 4720 return; 4721 } 4722 4723 assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 4724 4725 (void) printf(gettext("discarding, %s remaining.\n"), 4726 space_buf); 4727} 4728 4729static void 4730print_error_log(zpool_handle_t *zhp) 4731{ 4732 nvlist_t *nverrlist = NULL; 4733 nvpair_t *elem; 4734 char *pathname; 4735 size_t len = MAXPATHLEN * 2; 4736 4737 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 4738 (void) printf("errors: List of errors unavailable " 4739 "(insufficient privileges)\n"); 4740 return; 4741 } 4742 4743 (void) printf("errors: Permanent errors have been " 4744 "detected in the following files:\n\n"); 4745 4746 pathname = safe_malloc(len); 4747 elem = NULL; 4748 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 4749 nvlist_t *nv; 4750 uint64_t dsobj, obj; 4751 4752 verify(nvpair_value_nvlist(elem, &nv) == 0); 4753 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 4754 &dsobj) == 0); 4755 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 4756 &obj) == 0); 4757 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 4758 (void) printf("%7s %s\n", "", pathname); 4759 } 4760 free(pathname); 4761 nvlist_free(nverrlist); 4762} 4763 4764static void 4765print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 4766 int namewidth) 4767{ 4768 uint_t i; 4769 char *name; 4770 4771 if (nspares == 0) 4772 return; 4773 4774 (void) printf(gettext("\tspares\n")); 4775 4776 for (i = 0; i < nspares; i++) { 4777 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE); 4778 print_status_config(zhp, name, spares[i], 4779 namewidth, 2, B_TRUE); 4780 free(name); 4781 } 4782} 4783 4784static void 4785print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, 4786 int namewidth) 4787{ 4788 uint_t i; 4789 char *name; 4790 4791 if (nl2cache == 0) 4792 return; 4793 4794 (void) printf(gettext("\tcache\n")); 4795 4796 for (i = 0; i < nl2cache; i++) { 4797 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE); 4798 print_status_config(zhp, name, l2cache[i], 4799 namewidth, 2, B_FALSE); 4800 free(name); 4801 } 4802} 4803 4804static void 4805print_dedup_stats(nvlist_t *config) 4806{ 4807 ddt_histogram_t *ddh; 4808 ddt_stat_t *dds; 4809 ddt_object_t *ddo; 4810 uint_t c; 4811 4812 /* 4813 * If the pool was faulted then we may not have been able to 4814 * obtain the config. Otherwise, if we have anything in the dedup 4815 * table continue processing the stats. 4816 */ 4817 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 4818 (uint64_t **)&ddo, &c) != 0) 4819 return; 4820 4821 (void) printf("\n"); 4822 (void) printf(gettext(" dedup: ")); 4823 if (ddo->ddo_count == 0) { 4824 (void) printf(gettext("no DDT entries\n")); 4825 return; 4826 } 4827 4828 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", 4829 (u_longlong_t)ddo->ddo_count, 4830 (u_longlong_t)ddo->ddo_dspace, 4831 (u_longlong_t)ddo->ddo_mspace); 4832 4833 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 4834 (uint64_t **)&dds, &c) == 0); 4835 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 4836 (uint64_t **)&ddh, &c) == 0); 4837 zpool_dump_ddt(dds, ddh); 4838} 4839 4840/* 4841 * Display a summary of pool status. Displays a summary such as: 4842 * 4843 * pool: tank 4844 * status: DEGRADED 4845 * reason: One or more devices ... 4846 * see: http://illumos.org/msg/ZFS-xxxx-01 4847 * config: 4848 * mirror DEGRADED 4849 * c1t0d0 OK 4850 * c2t0d0 UNAVAIL 4851 * 4852 * When given the '-v' option, we print out the complete config. If the '-e' 4853 * option is specified, then we print out error rate information as well. 4854 */ 4855int 4856status_callback(zpool_handle_t *zhp, void *data) 4857{ 4858 status_cbdata_t *cbp = data; 4859 nvlist_t *config, *nvroot; 4860 char *msgid; 4861 int reason; 4862 const char *health; 4863 uint_t c; 4864 vdev_stat_t *vs; 4865 4866 config = zpool_get_config(zhp, NULL); 4867 reason = zpool_get_status(zhp, &msgid); 4868 4869 cbp->cb_count++; 4870 4871 /* 4872 * If we were given 'zpool status -x', only report those pools with 4873 * problems. 4874 */ 4875 if (cbp->cb_explain && 4876 (reason == ZPOOL_STATUS_OK || 4877 reason == ZPOOL_STATUS_VERSION_OLDER || 4878 reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT || 4879 reason == ZPOOL_STATUS_FEAT_DISABLED)) { 4880 if (!cbp->cb_allpools) { 4881 (void) printf(gettext("pool '%s' is healthy\n"), 4882 zpool_get_name(zhp)); 4883 if (cbp->cb_first) 4884 cbp->cb_first = B_FALSE; 4885 } 4886 return (0); 4887 } 4888 4889 if (cbp->cb_first) 4890 cbp->cb_first = B_FALSE; 4891 else 4892 (void) printf("\n"); 4893 4894 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 4895 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 4896 (uint64_t **)&vs, &c) == 0); 4897 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 4898 4899 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 4900 (void) printf(gettext(" state: %s\n"), health); 4901 4902 switch (reason) { 4903 case ZPOOL_STATUS_MISSING_DEV_R: 4904 (void) printf(gettext("status: One or more devices could not " 4905 "be opened. Sufficient replicas exist for\n\tthe pool to " 4906 "continue functioning in a degraded state.\n")); 4907 (void) printf(gettext("action: Attach the missing device and " 4908 "online it using 'zpool online'.\n")); 4909 break; 4910 4911 case ZPOOL_STATUS_MISSING_DEV_NR: 4912 (void) printf(gettext("status: One or more devices could not " 4913 "be opened. There are insufficient\n\treplicas for the " 4914 "pool to continue functioning.\n")); 4915 (void) printf(gettext("action: Attach the missing device and " 4916 "online it using 'zpool online'.\n")); 4917 break; 4918 4919 case ZPOOL_STATUS_CORRUPT_LABEL_R: 4920 (void) printf(gettext("status: One or more devices could not " 4921 "be used because the label is missing or\n\tinvalid. " 4922 "Sufficient replicas exist for the pool to continue\n\t" 4923 "functioning in a degraded state.\n")); 4924 (void) printf(gettext("action: Replace the device using " 4925 "'zpool replace'.\n")); 4926 break; 4927 4928 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 4929 (void) printf(gettext("status: One or more devices could not " 4930 "be used because the label is missing \n\tor invalid. " 4931 "There are insufficient replicas for the pool to " 4932 "continue\n\tfunctioning.\n")); 4933 zpool_explain_recover(zpool_get_handle(zhp), 4934 zpool_get_name(zhp), reason, config); 4935 break; 4936 4937 case ZPOOL_STATUS_FAILING_DEV: 4938 (void) printf(gettext("status: One or more devices has " 4939 "experienced an unrecoverable error. An\n\tattempt was " 4940 "made to correct the error. Applications are " 4941 "unaffected.\n")); 4942 (void) printf(gettext("action: Determine if the device needs " 4943 "to be replaced, and clear the errors\n\tusing " 4944 "'zpool clear' or replace the device with 'zpool " 4945 "replace'.\n")); 4946 break; 4947 4948 case ZPOOL_STATUS_OFFLINE_DEV: 4949 (void) printf(gettext("status: One or more devices has " 4950 "been taken offline by the administrator.\n\tSufficient " 4951 "replicas exist for the pool to continue functioning in " 4952 "a\n\tdegraded state.\n")); 4953 (void) printf(gettext("action: Online the device using " 4954 "'zpool online' or replace the device with\n\t'zpool " 4955 "replace'.\n")); 4956 break; 4957 4958 case ZPOOL_STATUS_REMOVED_DEV: 4959 (void) printf(gettext("status: One or more devices has " 4960 "been removed by the administrator.\n\tSufficient " 4961 "replicas exist for the pool to continue functioning in " 4962 "a\n\tdegraded state.\n")); 4963 (void) printf(gettext("action: Online the device using " 4964 "'zpool online' or replace the device with\n\t'zpool " 4965 "replace'.\n")); 4966 break; 4967 4968 case ZPOOL_STATUS_RESILVERING: 4969 (void) printf(gettext("status: One or more devices is " 4970 "currently being resilvered. The pool will\n\tcontinue " 4971 "to function, possibly in a degraded state.\n")); 4972 (void) printf(gettext("action: Wait for the resilver to " 4973 "complete.\n")); 4974 break; 4975 4976 case ZPOOL_STATUS_CORRUPT_DATA: 4977 (void) printf(gettext("status: One or more devices has " 4978 "experienced an error resulting in data\n\tcorruption. " 4979 "Applications may be affected.\n")); 4980 (void) printf(gettext("action: Restore the file in question " 4981 "if possible. Otherwise restore the\n\tentire pool from " 4982 "backup.\n")); 4983 break; 4984 4985 case ZPOOL_STATUS_CORRUPT_POOL: 4986 (void) printf(gettext("status: The pool metadata is corrupted " 4987 "and the pool cannot be opened.\n")); 4988 zpool_explain_recover(zpool_get_handle(zhp), 4989 zpool_get_name(zhp), reason, config); 4990 break; 4991 4992 case ZPOOL_STATUS_VERSION_OLDER: 4993 (void) printf(gettext("status: The pool is formatted using a " 4994 "legacy on-disk format. The pool can\n\tstill be used, " 4995 "but some features are unavailable.\n")); 4996 (void) printf(gettext("action: Upgrade the pool using 'zpool " 4997 "upgrade'. Once this is done, the\n\tpool will no longer " 4998 "be accessible on software that does not support feature\n" 4999 "\tflags.\n")); 5000 break; 5001 5002 case ZPOOL_STATUS_VERSION_NEWER: 5003 (void) printf(gettext("status: The pool has been upgraded to a " 5004 "newer, incompatible on-disk version.\n\tThe pool cannot " 5005 "be accessed on this system.\n")); 5006 (void) printf(gettext("action: Access the pool from a system " 5007 "running more recent software, or\n\trestore the pool from " 5008 "backup.\n")); 5009 break; 5010 5011 case ZPOOL_STATUS_FEAT_DISABLED: 5012 (void) printf(gettext("status: Some supported features are not " 5013 "enabled on the pool. The pool can\n\tstill be used, but " 5014 "some features are unavailable.\n")); 5015 (void) printf(gettext("action: Enable all features using " 5016 "'zpool upgrade'. Once this is done,\n\tthe pool may no " 5017 "longer be accessible by software that does not support\n\t" 5018 "the features. See zpool-features(7) for details.\n")); 5019 break; 5020 5021 case ZPOOL_STATUS_UNSUP_FEAT_READ: 5022 (void) printf(gettext("status: The pool cannot be accessed on " 5023 "this system because it uses the\n\tfollowing feature(s) " 5024 "not supported on this system:\n")); 5025 zpool_print_unsup_feat(config); 5026 (void) printf("\n"); 5027 (void) printf(gettext("action: Access the pool from a system " 5028 "that supports the required feature(s),\n\tor restore the " 5029 "pool from backup.\n")); 5030 break; 5031 5032 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 5033 (void) printf(gettext("status: The pool can only be accessed " 5034 "in read-only mode on this system. It\n\tcannot be " 5035 "accessed in read-write mode because it uses the " 5036 "following\n\tfeature(s) not supported on this system:\n")); 5037 zpool_print_unsup_feat(config); 5038 (void) printf("\n"); 5039 (void) printf(gettext("action: The pool cannot be accessed in " 5040 "read-write mode. Import the pool with\n" 5041 "\t\"-o readonly=on\", access the pool from a system that " 5042 "supports the\n\trequired feature(s), or restore the " 5043 "pool from backup.\n")); 5044 break; 5045 5046 case ZPOOL_STATUS_FAULTED_DEV_R: 5047 (void) printf(gettext("status: One or more devices are " 5048 "faulted in response to persistent errors.\n\tSufficient " 5049 "replicas exist for the pool to continue functioning " 5050 "in a\n\tdegraded state.\n")); 5051 (void) printf(gettext("action: Replace the faulted device, " 5052 "or use 'zpool clear' to mark the device\n\trepaired.\n")); 5053 break; 5054 5055 case ZPOOL_STATUS_FAULTED_DEV_NR: 5056 (void) printf(gettext("status: One or more devices are " 5057 "faulted in response to persistent errors. There are " 5058 "insufficient replicas for the pool to\n\tcontinue " 5059 "functioning.\n")); 5060 (void) printf(gettext("action: Destroy and re-create the pool " 5061 "from a backup source. Manually marking the device\n" 5062 "\trepaired using 'zpool clear' may allow some data " 5063 "to be recovered.\n")); 5064 break; 5065 5066 case ZPOOL_STATUS_IO_FAILURE_WAIT: 5067 case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 5068 (void) printf(gettext("status: One or more devices are " 5069 "faulted in response to IO failures.\n")); 5070 (void) printf(gettext("action: Make sure the affected devices " 5071 "are connected, then run 'zpool clear'.\n")); 5072 break; 5073 5074 case ZPOOL_STATUS_BAD_LOG: 5075 (void) printf(gettext("status: An intent log record " 5076 "could not be read.\n" 5077 "\tWaiting for adminstrator intervention to fix the " 5078 "faulted pool.\n")); 5079 (void) printf(gettext("action: Either restore the affected " 5080 "device(s) and run 'zpool online',\n" 5081 "\tor ignore the intent log records by running " 5082 "'zpool clear'.\n")); 5083 break; 5084 5085 case ZPOOL_STATUS_NON_NATIVE_ASHIFT: 5086 (void) printf(gettext("status: One or more devices are " 5087 "configured to use a non-native block size.\n" 5088 "\tExpect reduced performance.\n")); 5089 (void) printf(gettext("action: Replace affected devices with " 5090 "devices that support the\n\tconfigured block size, or " 5091 "migrate data to a properly configured\n\tpool.\n")); 5092 break; 5093 5094 default: 5095 /* 5096 * The remaining errors can't actually be generated, yet. 5097 */ 5098 assert(reason == ZPOOL_STATUS_OK); 5099 } 5100 5101 if (msgid != NULL) 5102 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 5103 msgid); 5104 5105 if (config != NULL) { 5106 int namewidth; 5107 uint64_t nerr; 5108 nvlist_t **spares, **l2cache; 5109 uint_t nspares, nl2cache; 5110 pool_checkpoint_stat_t *pcs = NULL; 5111 pool_scan_stat_t *ps = NULL; 5112 pool_removal_stat_t *prs = NULL; 5113 5114 (void) nvlist_lookup_uint64_array(nvroot, 5115 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 5116 (void) nvlist_lookup_uint64_array(nvroot, 5117 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); 5118 (void) nvlist_lookup_uint64_array(nvroot, 5119 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c); 5120 5121 print_scan_status(ps); 5122 print_checkpoint_scan_warning(ps, pcs); 5123 print_removal_status(zhp, prs); 5124 print_checkpoint_status(pcs); 5125 5126 namewidth = max_width(zhp, nvroot, 0, 0); 5127 if (namewidth < 10) 5128 namewidth = 10; 5129 5130 (void) printf(gettext("config:\n\n")); 5131 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 5132 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 5133 print_status_config(zhp, zpool_get_name(zhp), nvroot, 5134 namewidth, 0, B_FALSE); 5135 5136 if (num_logs(nvroot) > 0) 5137 print_logs(zhp, nvroot, namewidth, B_TRUE); 5138 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 5139 &l2cache, &nl2cache) == 0) 5140 print_l2cache(zhp, l2cache, nl2cache, namewidth); 5141 5142 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 5143 &spares, &nspares) == 0) 5144 print_spares(zhp, spares, nspares, namewidth); 5145 5146 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 5147 &nerr) == 0) { 5148 nvlist_t *nverrlist = NULL; 5149 5150 /* 5151 * If the approximate error count is small, get a 5152 * precise count by fetching the entire log and 5153 * uniquifying the results. 5154 */ 5155 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 5156 zpool_get_errlog(zhp, &nverrlist) == 0) { 5157 nvpair_t *elem; 5158 5159 elem = NULL; 5160 nerr = 0; 5161 while ((elem = nvlist_next_nvpair(nverrlist, 5162 elem)) != NULL) { 5163 nerr++; 5164 } 5165 } 5166 nvlist_free(nverrlist); 5167 5168 (void) printf("\n"); 5169 5170 if (nerr == 0) 5171 (void) printf(gettext("errors: No known data " 5172 "errors\n")); 5173 else if (!cbp->cb_verbose) 5174 (void) printf(gettext("errors: %llu data " 5175 "errors, use '-v' for a list\n"), 5176 (u_longlong_t)nerr); 5177 else 5178 print_error_log(zhp); 5179 } 5180 5181 if (cbp->cb_dedup_stats) 5182 print_dedup_stats(config); 5183 } else { 5184 (void) printf(gettext("config: The configuration cannot be " 5185 "determined.\n")); 5186 } 5187 5188 return (0); 5189} 5190 5191/* 5192 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]] 5193 * 5194 * -v Display complete error logs 5195 * -x Display only pools with potential problems 5196 * -D Display dedup status (undocumented) 5197 * -T Display a timestamp in date(1) or Unix format 5198 * 5199 * Describes the health status of all pools or some subset. 5200 */ 5201int 5202zpool_do_status(int argc, char **argv) 5203{ 5204 int c; 5205 int ret; 5206 unsigned long interval = 0, count = 0; 5207 status_cbdata_t cb = { 0 }; 5208 5209 /* check options */ 5210 while ((c = getopt(argc, argv, "vxDT:")) != -1) { 5211 switch (c) { 5212 case 'v': 5213 cb.cb_verbose = B_TRUE; 5214 break; 5215 case 'x': 5216 cb.cb_explain = B_TRUE; 5217 break; 5218 case 'D': 5219 cb.cb_dedup_stats = B_TRUE; 5220 break; 5221 case 'T': 5222 get_timestamp_arg(*optarg); 5223 break; 5224 case '?': 5225 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5226 optopt); 5227 usage(B_FALSE); 5228 } 5229 } 5230 5231 argc -= optind; 5232 argv += optind; 5233 5234 get_interval_count(&argc, argv, &interval, &count); 5235 5236 if (argc == 0) 5237 cb.cb_allpools = B_TRUE; 5238 5239 cb.cb_first = B_TRUE; 5240 5241 for (;;) { 5242 if (timestamp_fmt != NODATE) 5243 print_timestamp(timestamp_fmt); 5244 5245 ret = for_each_pool(argc, argv, B_TRUE, NULL, 5246 status_callback, &cb); 5247 5248 if (argc == 0 && cb.cb_count == 0) 5249 (void) printf(gettext("no pools available\n")); 5250 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 5251 (void) printf(gettext("all pools are healthy\n")); 5252 5253 if (ret != 0) 5254 return (ret); 5255 5256 if (interval == 0) 5257 break; 5258 5259 if (count != 0 && --count == 0) 5260 break; 5261 5262 (void) sleep(interval); 5263 } 5264 5265 return (0); 5266} 5267 5268typedef struct upgrade_cbdata { 5269 boolean_t cb_first; 5270 boolean_t cb_unavail; 5271 char cb_poolname[ZFS_MAX_DATASET_NAME_LEN]; 5272 int cb_argc; 5273 uint64_t cb_version; 5274 char **cb_argv; 5275} upgrade_cbdata_t; 5276 5277#ifdef __FreeBSD__ 5278static int 5279is_root_pool(zpool_handle_t *zhp) 5280{ 5281 static struct statfs sfs; 5282 static char *poolname = NULL; 5283 static boolean_t stated = B_FALSE; 5284 char *slash; 5285 5286 if (!stated) { 5287 stated = B_TRUE; 5288 if (statfs("/", &sfs) == -1) { 5289 (void) fprintf(stderr, 5290 "Unable to stat root file system: %s.\n", 5291 strerror(errno)); 5292 return (0); 5293 } 5294 if (strcmp(sfs.f_fstypename, "zfs") != 0) 5295 return (0); 5296 poolname = sfs.f_mntfromname; 5297 if ((slash = strchr(poolname, '/')) != NULL) 5298 *slash = '\0'; 5299 } 5300 return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0); 5301} 5302 5303static void 5304root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size) 5305{ 5306 5307 if (poolname[0] == '\0' && is_root_pool(zhp)) 5308 (void) strlcpy(poolname, zpool_get_name(zhp), size); 5309} 5310#endif /* FreeBSD */ 5311 5312static int 5313upgrade_version(zpool_handle_t *zhp, uint64_t version) 5314{ 5315 int ret; 5316 nvlist_t *config; 5317 uint64_t oldversion; 5318 5319 config = zpool_get_config(zhp, NULL); 5320 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5321 &oldversion) == 0); 5322 5323 assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 5324 assert(oldversion < version); 5325 5326 ret = zpool_upgrade(zhp, version); 5327 if (ret != 0) 5328 return (ret); 5329 5330 if (version >= SPA_VERSION_FEATURES) { 5331 (void) printf(gettext("Successfully upgraded " 5332 "'%s' from version %llu to feature flags.\n"), 5333 zpool_get_name(zhp), oldversion); 5334 } else { 5335 (void) printf(gettext("Successfully upgraded " 5336 "'%s' from version %llu to version %llu.\n"), 5337 zpool_get_name(zhp), oldversion, version); 5338 } 5339 5340 return (0); 5341} 5342 5343static int 5344upgrade_enable_all(zpool_handle_t *zhp, int *countp) 5345{ 5346 int i, ret, count; 5347 boolean_t firstff = B_TRUE; 5348 nvlist_t *enabled = zpool_get_features(zhp); 5349 5350 count = 0; 5351 for (i = 0; i < SPA_FEATURES; i++) { 5352 const char *fname = spa_feature_table[i].fi_uname; 5353 const char *fguid = spa_feature_table[i].fi_guid; 5354 if (!nvlist_exists(enabled, fguid)) { 5355 char *propname; 5356 verify(-1 != asprintf(&propname, "feature@%s", fname)); 5357 ret = zpool_set_prop(zhp, propname, 5358 ZFS_FEATURE_ENABLED); 5359 if (ret != 0) { 5360 free(propname); 5361 return (ret); 5362 } 5363 count++; 5364 5365 if (firstff) { 5366 (void) printf(gettext("Enabled the " 5367 "following features on '%s':\n"), 5368 zpool_get_name(zhp)); 5369 firstff = B_FALSE; 5370 } 5371 (void) printf(gettext(" %s\n"), fname); 5372 free(propname); 5373 } 5374 } 5375 5376 if (countp != NULL) 5377 *countp = count; 5378 return (0); 5379} 5380 5381static int 5382upgrade_cb(zpool_handle_t *zhp, void *arg) 5383{ 5384 upgrade_cbdata_t *cbp = arg; 5385 nvlist_t *config; 5386 uint64_t version; 5387 boolean_t printnl = B_FALSE; 5388 int ret; 5389 5390 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5391 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is " 5392 "currently unavailable.\n\n"), zpool_get_name(zhp)); 5393 cbp->cb_unavail = B_TRUE; 5394 /* Allow iteration to continue. */ 5395 return (0); 5396 } 5397 5398 config = zpool_get_config(zhp, NULL); 5399 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5400 &version) == 0); 5401 5402 assert(SPA_VERSION_IS_SUPPORTED(version)); 5403 5404 if (version < cbp->cb_version) { 5405 cbp->cb_first = B_FALSE; 5406 ret = upgrade_version(zhp, cbp->cb_version); 5407 if (ret != 0) 5408 return (ret); 5409#ifdef __FreeBSD__ 5410 root_pool_upgrade_check(zhp, cbp->cb_poolname, 5411 sizeof(cbp->cb_poolname)); 5412#endif /* __FreeBSD__ */ 5413 printnl = B_TRUE; 5414 5415#ifdef illumos 5416 /* 5417 * If they did "zpool upgrade -a", then we could 5418 * be doing ioctls to different pools. We need 5419 * to log this history once to each pool, and bypass 5420 * the normal history logging that happens in main(). 5421 */ 5422 (void) zpool_log_history(g_zfs, history_str); 5423 log_history = B_FALSE; 5424#endif 5425 } 5426 5427 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 5428 int count; 5429 ret = upgrade_enable_all(zhp, &count); 5430 if (ret != 0) 5431 return (ret); 5432 5433 if (count > 0) { 5434 cbp->cb_first = B_FALSE; 5435 printnl = B_TRUE; 5436#ifdef __FreeBSD__ 5437 root_pool_upgrade_check(zhp, cbp->cb_poolname, 5438 sizeof(cbp->cb_poolname)); 5439#endif /* __FreeBSD__ */ 5440 /* 5441 * If they did "zpool upgrade -a", then we could 5442 * be doing ioctls to different pools. We need 5443 * to log this history once to each pool, and bypass 5444 * the normal history logging that happens in main(). 5445 */ 5446 (void) zpool_log_history(g_zfs, history_str); 5447 log_history = B_FALSE; 5448 } 5449 } 5450 5451 if (printnl) { 5452 (void) printf(gettext("\n")); 5453 } 5454 5455 return (0); 5456} 5457 5458static int 5459upgrade_list_unavail(zpool_handle_t *zhp, void *arg) 5460{ 5461 upgrade_cbdata_t *cbp = arg; 5462 5463 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5464 if (cbp->cb_first) { 5465 (void) fprintf(stderr, gettext("The following pools " 5466 "are unavailable and cannot be upgraded as this " 5467 "time.\n\n")); 5468 (void) fprintf(stderr, gettext("POOL\n")); 5469 (void) fprintf(stderr, gettext("------------\n")); 5470 cbp->cb_first = B_FALSE; 5471 } 5472 (void) printf(gettext("%s\n"), zpool_get_name(zhp)); 5473 cbp->cb_unavail = B_TRUE; 5474 } 5475 return (0); 5476} 5477 5478static int 5479upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 5480{ 5481 upgrade_cbdata_t *cbp = arg; 5482 nvlist_t *config; 5483 uint64_t version; 5484 5485 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5486 /* 5487 * This will have been reported by upgrade_list_unavail so 5488 * just allow iteration to continue. 5489 */ 5490 cbp->cb_unavail = B_TRUE; 5491 return (0); 5492 } 5493 5494 config = zpool_get_config(zhp, NULL); 5495 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5496 &version) == 0); 5497 5498 assert(SPA_VERSION_IS_SUPPORTED(version)); 5499 5500 if (version < SPA_VERSION_FEATURES) { 5501 if (cbp->cb_first) { 5502 (void) printf(gettext("The following pools are " 5503 "formatted with legacy version numbers and can\n" 5504 "be upgraded to use feature flags. After " 5505 "being upgraded, these pools\nwill no " 5506 "longer be accessible by software that does not " 5507 "support feature\nflags.\n\n")); 5508 (void) printf(gettext("VER POOL\n")); 5509 (void) printf(gettext("--- ------------\n")); 5510 cbp->cb_first = B_FALSE; 5511 } 5512 5513 (void) printf("%2llu %s\n", (u_longlong_t)version, 5514 zpool_get_name(zhp)); 5515 } 5516 5517 return (0); 5518} 5519 5520static int 5521upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 5522{ 5523 upgrade_cbdata_t *cbp = arg; 5524 nvlist_t *config; 5525 uint64_t version; 5526 5527 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5528 /* 5529 * This will have been reported by upgrade_list_unavail so 5530 * just allow iteration to continue. 5531 */ 5532 cbp->cb_unavail = B_TRUE; 5533 return (0); 5534 } 5535 5536 config = zpool_get_config(zhp, NULL); 5537 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5538 &version) == 0); 5539 5540 if (version >= SPA_VERSION_FEATURES) { 5541 int i; 5542 boolean_t poolfirst = B_TRUE; 5543 nvlist_t *enabled = zpool_get_features(zhp); 5544 5545 for (i = 0; i < SPA_FEATURES; i++) { 5546 const char *fguid = spa_feature_table[i].fi_guid; 5547 const char *fname = spa_feature_table[i].fi_uname; 5548 if (!nvlist_exists(enabled, fguid)) { 5549 if (cbp->cb_first) { 5550 (void) printf(gettext("\nSome " 5551 "supported features are not " 5552 "enabled on the following pools. " 5553 "Once a\nfeature is enabled the " 5554 "pool may become incompatible with " 5555 "software\nthat does not support " 5556 "the feature. See " 5557 "zpool-features(7) for " 5558 "details.\n\n")); 5559 (void) printf(gettext("POOL " 5560 "FEATURE\n")); 5561 (void) printf(gettext("------" 5562 "---------\n")); 5563 cbp->cb_first = B_FALSE; 5564 } 5565 5566 if (poolfirst) { 5567 (void) printf(gettext("%s\n"), 5568 zpool_get_name(zhp)); 5569 poolfirst = B_FALSE; 5570 } 5571 5572 (void) printf(gettext(" %s\n"), fname); 5573 } 5574 } 5575 } 5576 5577 return (0); 5578} 5579 5580/* ARGSUSED */ 5581static int 5582upgrade_one(zpool_handle_t *zhp, void *data) 5583{ 5584 boolean_t printnl = B_FALSE; 5585 upgrade_cbdata_t *cbp = data; 5586 uint64_t cur_version; 5587 int ret; 5588 5589 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5590 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is " 5591 "is currently unavailable.\n\n"), zpool_get_name(zhp)); 5592 cbp->cb_unavail = B_TRUE; 5593 return (1); 5594 } 5595 5596 if (strcmp("log", zpool_get_name(zhp)) == 0) { 5597 (void) printf(gettext("'log' is now a reserved word\n" 5598 "Pool 'log' must be renamed using export and import" 5599 " to upgrade.\n\n")); 5600 return (1); 5601 } 5602 5603 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 5604 if (cur_version > cbp->cb_version) { 5605 (void) printf(gettext("Pool '%s' is already formatted " 5606 "using more current version '%llu'.\n\n"), 5607 zpool_get_name(zhp), cur_version); 5608 return (0); 5609 } 5610 5611 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 5612 (void) printf(gettext("Pool '%s' is already formatted " 5613 "using version %llu.\n\n"), zpool_get_name(zhp), 5614 cbp->cb_version); 5615 return (0); 5616 } 5617 5618 if (cur_version != cbp->cb_version) { 5619 printnl = B_TRUE; 5620 ret = upgrade_version(zhp, cbp->cb_version); 5621 if (ret != 0) 5622 return (ret); 5623#ifdef __FreeBSD__ 5624 root_pool_upgrade_check(zhp, cbp->cb_poolname, 5625 sizeof(cbp->cb_poolname)); 5626#endif /* __FreeBSD__ */ 5627 } 5628 5629 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 5630 int count = 0; 5631 ret = upgrade_enable_all(zhp, &count); 5632 if (ret != 0) 5633 return (ret); 5634 5635 if (count != 0) { 5636 printnl = B_TRUE; 5637#ifdef __FreeBSD__ 5638 root_pool_upgrade_check(zhp, cbp->cb_poolname, 5639 sizeof(cbp->cb_poolname)); 5640#endif /* __FreeBSD __*/ 5641 } else if (cur_version == SPA_VERSION) { 5642 (void) printf(gettext("Pool '%s' already has all " 5643 "supported features enabled.\n\n"), 5644 zpool_get_name(zhp)); 5645 } 5646 } 5647 5648 if (printnl) { 5649 (void) printf(gettext("\n")); 5650 } 5651 5652 return (0); 5653} 5654 5655/* 5656 * zpool upgrade 5657 * zpool upgrade -v 5658 * zpool upgrade [-V version] <-a | pool ...> 5659 * 5660 * With no arguments, display downrev'd ZFS pool available for upgrade. 5661 * Individual pools can be upgraded by specifying the pool, and '-a' will 5662 * upgrade all pools. 5663 */ 5664int 5665zpool_do_upgrade(int argc, char **argv) 5666{ 5667 int c; 5668 upgrade_cbdata_t cb = { 0 }; 5669 int ret = 0; 5670 boolean_t showversions = B_FALSE; 5671 boolean_t upgradeall = B_FALSE; 5672 char *end; 5673 5674 5675 /* check options */ 5676 while ((c = getopt(argc, argv, ":avV:")) != -1) { 5677 switch (c) { 5678 case 'a': 5679 upgradeall = B_TRUE; 5680 break; 5681 case 'v': 5682 showversions = B_TRUE; 5683 break; 5684 case 'V': 5685 cb.cb_version = strtoll(optarg, &end, 10); 5686 if (*end != '\0' || 5687 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 5688 (void) fprintf(stderr, 5689 gettext("invalid version '%s'\n"), optarg); 5690 usage(B_FALSE); 5691 } 5692 break; 5693 case ':': 5694 (void) fprintf(stderr, gettext("missing argument for " 5695 "'%c' option\n"), optopt); 5696 usage(B_FALSE); 5697 break; 5698 case '?': 5699 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5700 optopt); 5701 usage(B_FALSE); 5702 } 5703 } 5704 5705 cb.cb_argc = argc; 5706 cb.cb_argv = argv; 5707 argc -= optind; 5708 argv += optind; 5709 5710 if (cb.cb_version == 0) { 5711 cb.cb_version = SPA_VERSION; 5712 } else if (!upgradeall && argc == 0) { 5713 (void) fprintf(stderr, gettext("-V option is " 5714 "incompatible with other arguments\n")); 5715 usage(B_FALSE); 5716 } 5717 5718 if (showversions) { 5719 if (upgradeall || argc != 0) { 5720 (void) fprintf(stderr, gettext("-v option is " 5721 "incompatible with other arguments\n")); 5722 usage(B_FALSE); 5723 } 5724 } else if (upgradeall) { 5725 if (argc != 0) { 5726 (void) fprintf(stderr, gettext("-a option should not " 5727 "be used along with a pool name\n")); 5728 usage(B_FALSE); 5729 } 5730 } 5731 5732 (void) printf(gettext("This system supports ZFS pool feature " 5733 "flags.\n\n")); 5734 if (showversions) { 5735 int i; 5736 5737 (void) printf(gettext("The following features are " 5738 "supported:\n\n")); 5739 (void) printf(gettext("FEAT DESCRIPTION\n")); 5740 (void) printf("----------------------------------------------" 5741 "---------------\n"); 5742 for (i = 0; i < SPA_FEATURES; i++) { 5743 zfeature_info_t *fi = &spa_feature_table[i]; 5744 const char *ro = 5745 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 5746 " (read-only compatible)" : ""; 5747 5748 (void) printf("%-37s%s\n", fi->fi_uname, ro); 5749 (void) printf(" %s\n", fi->fi_desc); 5750 } 5751 (void) printf("\n"); 5752 5753 (void) printf(gettext("The following legacy versions are also " 5754 "supported:\n\n")); 5755 (void) printf(gettext("VER DESCRIPTION\n")); 5756 (void) printf("--- -----------------------------------------" 5757 "---------------\n"); 5758 (void) printf(gettext(" 1 Initial ZFS version\n")); 5759 (void) printf(gettext(" 2 Ditto blocks " 5760 "(replicated metadata)\n")); 5761 (void) printf(gettext(" 3 Hot spares and double parity " 5762 "RAID-Z\n")); 5763 (void) printf(gettext(" 4 zpool history\n")); 5764 (void) printf(gettext(" 5 Compression using the gzip " 5765 "algorithm\n")); 5766 (void) printf(gettext(" 6 bootfs pool property\n")); 5767 (void) printf(gettext(" 7 Separate intent log devices\n")); 5768 (void) printf(gettext(" 8 Delegated administration\n")); 5769 (void) printf(gettext(" 9 refquota and refreservation " 5770 "properties\n")); 5771 (void) printf(gettext(" 10 Cache devices\n")); 5772 (void) printf(gettext(" 11 Improved scrub performance\n")); 5773 (void) printf(gettext(" 12 Snapshot properties\n")); 5774 (void) printf(gettext(" 13 snapused property\n")); 5775 (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 5776 (void) printf(gettext(" 15 user/group space accounting\n")); 5777 (void) printf(gettext(" 16 stmf property support\n")); 5778 (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 5779 (void) printf(gettext(" 18 Snapshot user holds\n")); 5780 (void) printf(gettext(" 19 Log device removal\n")); 5781 (void) printf(gettext(" 20 Compression using zle " 5782 "(zero-length encoding)\n")); 5783 (void) printf(gettext(" 21 Deduplication\n")); 5784 (void) printf(gettext(" 22 Received properties\n")); 5785 (void) printf(gettext(" 23 Slim ZIL\n")); 5786 (void) printf(gettext(" 24 System attributes\n")); 5787 (void) printf(gettext(" 25 Improved scrub stats\n")); 5788 (void) printf(gettext(" 26 Improved snapshot deletion " 5789 "performance\n")); 5790 (void) printf(gettext(" 27 Improved snapshot creation " 5791 "performance\n")); 5792 (void) printf(gettext(" 28 Multiple vdev replacements\n")); 5793 (void) printf(gettext("\nFor more information on a particular " 5794 "version, including supported releases,\n")); 5795 (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 5796 } else if (argc == 0 && upgradeall) { 5797 cb.cb_first = B_TRUE; 5798 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 5799 if (ret == 0 && cb.cb_first) { 5800 if (cb.cb_version == SPA_VERSION) { 5801 (void) printf(gettext("All %spools are already " 5802 "formatted using feature flags.\n\n"), 5803 cb.cb_unavail ? gettext("available ") : ""); 5804 (void) printf(gettext("Every %sfeature flags " 5805 "pool already has all supported features " 5806 "enabled.\n"), 5807 cb.cb_unavail ? gettext("available ") : ""); 5808 } else { 5809 (void) printf(gettext("All pools are already " 5810 "formatted with version %llu or higher.\n"), 5811 cb.cb_version); 5812 } 5813 } 5814 } else if (argc == 0) { 5815 cb.cb_first = B_TRUE; 5816 ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb); 5817 assert(ret == 0); 5818 5819 if (!cb.cb_first) { 5820 (void) fprintf(stderr, "\n"); 5821 } 5822 5823 cb.cb_first = B_TRUE; 5824 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 5825 assert(ret == 0); 5826 5827 if (cb.cb_first) { 5828 (void) printf(gettext("All %spools are formatted using " 5829 "feature flags.\n\n"), cb.cb_unavail ? 5830 gettext("available ") : ""); 5831 } else { 5832 (void) printf(gettext("\nUse 'zpool upgrade -v' " 5833 "for a list of available legacy versions.\n")); 5834 } 5835 5836 cb.cb_first = B_TRUE; 5837 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 5838 assert(ret == 0); 5839 5840 if (cb.cb_first) { 5841 (void) printf(gettext("Every %sfeature flags pool has " 5842 "all supported features enabled.\n"), 5843 cb.cb_unavail ? gettext("available ") : ""); 5844 } else { 5845 (void) printf(gettext("\n")); 5846 } 5847 } else { 5848 ret = for_each_pool(argc, argv, B_TRUE, NULL, 5849 upgrade_one, &cb); 5850 } 5851 5852 if (cb.cb_poolname[0] != '\0') { 5853 (void) printf( 5854 "If you boot from pool '%s', don't forget to update boot code.\n" 5855 "Assuming you use GPT partitioning and da0 is your boot disk\n" 5856 "the following command will do it:\n" 5857 "\n" 5858 "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n", 5859 cb.cb_poolname); 5860 } 5861 5862 return (ret); 5863} 5864 5865typedef struct hist_cbdata { 5866 boolean_t first; 5867 boolean_t longfmt; 5868 boolean_t internal; 5869} hist_cbdata_t; 5870 5871/* 5872 * Print out the command history for a specific pool. 5873 */ 5874static int 5875get_history_one(zpool_handle_t *zhp, void *data) 5876{ 5877 nvlist_t *nvhis; 5878 nvlist_t **records; 5879 uint_t numrecords; 5880 int ret, i; 5881 hist_cbdata_t *cb = (hist_cbdata_t *)data; 5882 5883 cb->first = B_FALSE; 5884 5885 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 5886 5887 if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 5888 return (ret); 5889 5890 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 5891 &records, &numrecords) == 0); 5892 for (i = 0; i < numrecords; i++) { 5893 nvlist_t *rec = records[i]; 5894 char tbuf[30] = ""; 5895 5896 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 5897 time_t tsec; 5898 struct tm t; 5899 5900 tsec = fnvlist_lookup_uint64(records[i], 5901 ZPOOL_HIST_TIME); 5902 (void) localtime_r(&tsec, &t); 5903 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 5904 } 5905 5906 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 5907 (void) printf("%s %s", tbuf, 5908 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 5909 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 5910 int ievent = 5911 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 5912 if (!cb->internal) 5913 continue; 5914 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 5915 (void) printf("%s unrecognized record:\n", 5916 tbuf); 5917 dump_nvlist(rec, 4); 5918 continue; 5919 } 5920 (void) printf("%s [internal %s txg:%lld] %s", tbuf, 5921 zfs_history_event_names[ievent], 5922 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 5923 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 5924 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 5925 if (!cb->internal) 5926 continue; 5927 (void) printf("%s [txg:%lld] %s", tbuf, 5928 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 5929 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 5930 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 5931 (void) printf(" %s (%llu)", 5932 fnvlist_lookup_string(rec, 5933 ZPOOL_HIST_DSNAME), 5934 fnvlist_lookup_uint64(rec, 5935 ZPOOL_HIST_DSID)); 5936 } 5937 (void) printf(" %s", fnvlist_lookup_string(rec, 5938 ZPOOL_HIST_INT_STR)); 5939 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 5940 if (!cb->internal) 5941 continue; 5942 (void) printf("%s ioctl %s\n", tbuf, 5943 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 5944 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 5945 (void) printf(" input:\n"); 5946 dump_nvlist(fnvlist_lookup_nvlist(rec, 5947 ZPOOL_HIST_INPUT_NVL), 8); 5948 } 5949 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 5950 (void) printf(" output:\n"); 5951 dump_nvlist(fnvlist_lookup_nvlist(rec, 5952 ZPOOL_HIST_OUTPUT_NVL), 8); 5953 } 5954 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) { 5955 (void) printf(" errno: %lld\n", 5956 fnvlist_lookup_int64(rec, 5957 ZPOOL_HIST_ERRNO)); 5958 } 5959 } else { 5960 if (!cb->internal) 5961 continue; 5962 (void) printf("%s unrecognized record:\n", tbuf); 5963 dump_nvlist(rec, 4); 5964 } 5965 5966 if (!cb->longfmt) { 5967 (void) printf("\n"); 5968 continue; 5969 } 5970 (void) printf(" ["); 5971 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 5972 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 5973 struct passwd *pwd = getpwuid(who); 5974 (void) printf("user %d ", (int)who); 5975 if (pwd != NULL) 5976 (void) printf("(%s) ", pwd->pw_name); 5977 } 5978 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 5979 (void) printf("on %s", 5980 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 5981 } 5982 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 5983 (void) printf(":%s", 5984 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 5985 } 5986 (void) printf("]"); 5987 (void) printf("\n"); 5988 } 5989 (void) printf("\n"); 5990 nvlist_free(nvhis); 5991 5992 return (ret); 5993} 5994 5995/* 5996 * zpool history <pool> 5997 * 5998 * Displays the history of commands that modified pools. 5999 */ 6000int 6001zpool_do_history(int argc, char **argv) 6002{ 6003 hist_cbdata_t cbdata = { 0 }; 6004 int ret; 6005 int c; 6006 6007 cbdata.first = B_TRUE; 6008 /* check options */ 6009 while ((c = getopt(argc, argv, "li")) != -1) { 6010 switch (c) { 6011 case 'l': 6012 cbdata.longfmt = B_TRUE; 6013 break; 6014 case 'i': 6015 cbdata.internal = B_TRUE; 6016 break; 6017 case '?': 6018 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6019 optopt); 6020 usage(B_FALSE); 6021 } 6022 } 6023 argc -= optind; 6024 argv += optind; 6025 6026 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 6027 &cbdata); 6028 6029 if (argc == 0 && cbdata.first == B_TRUE) { 6030 (void) printf(gettext("no pools available\n")); 6031 return (0); 6032 } 6033 6034 return (ret); 6035} 6036 6037static int 6038get_callback(zpool_handle_t *zhp, void *data) 6039{ 6040 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 6041 char value[MAXNAMELEN]; 6042 zprop_source_t srctype; 6043 zprop_list_t *pl; 6044 6045 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 6046 6047 /* 6048 * Skip the special fake placeholder. This will also skip 6049 * over the name property when 'all' is specified. 6050 */ 6051 if (pl->pl_prop == ZPOOL_PROP_NAME && 6052 pl == cbp->cb_proplist) 6053 continue; 6054 6055 if (pl->pl_prop == ZPROP_INVAL && 6056 (zpool_prop_feature(pl->pl_user_prop) || 6057 zpool_prop_unsupported(pl->pl_user_prop))) { 6058 srctype = ZPROP_SRC_LOCAL; 6059 6060 if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 6061 value, sizeof (value)) == 0) { 6062 zprop_print_one_property(zpool_get_name(zhp), 6063 cbp, pl->pl_user_prop, value, srctype, 6064 NULL, NULL); 6065 } 6066 } else { 6067 if (zpool_get_prop(zhp, pl->pl_prop, value, 6068 sizeof (value), &srctype, cbp->cb_literal) != 0) 6069 continue; 6070 6071 zprop_print_one_property(zpool_get_name(zhp), cbp, 6072 zpool_prop_to_name(pl->pl_prop), value, srctype, 6073 NULL, NULL); 6074 } 6075 } 6076 return (0); 6077} 6078 6079/* 6080 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ... 6081 * 6082 * -H Scripted mode. Don't display headers, and separate properties 6083 * by a single tab. 6084 * -o List of columns to display. Defaults to 6085 * "name,property,value,source". 6086 * -p Diplay values in parsable (exact) format. 6087 * 6088 * Get properties of pools in the system. Output space statistics 6089 * for each one as well as other attributes. 6090 */ 6091int 6092zpool_do_get(int argc, char **argv) 6093{ 6094 zprop_get_cbdata_t cb = { 0 }; 6095 zprop_list_t fake_name = { 0 }; 6096 int ret; 6097 int c, i; 6098 char *value; 6099 6100 cb.cb_first = B_TRUE; 6101 6102 /* 6103 * Set up default columns and sources. 6104 */ 6105 cb.cb_sources = ZPROP_SRC_ALL; 6106 cb.cb_columns[0] = GET_COL_NAME; 6107 cb.cb_columns[1] = GET_COL_PROPERTY; 6108 cb.cb_columns[2] = GET_COL_VALUE; 6109 cb.cb_columns[3] = GET_COL_SOURCE; 6110 cb.cb_type = ZFS_TYPE_POOL; 6111 6112 /* check options */ 6113 while ((c = getopt(argc, argv, ":Hpo:")) != -1) { 6114 switch (c) { 6115 case 'p': 6116 cb.cb_literal = B_TRUE; 6117 break; 6118 case 'H': 6119 cb.cb_scripted = B_TRUE; 6120 break; 6121 case 'o': 6122 bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 6123 i = 0; 6124 while (*optarg != '\0') { 6125 static char *col_subopts[] = 6126 { "name", "property", "value", "source", 6127 "all", NULL }; 6128 6129 if (i == ZFS_GET_NCOLS) { 6130 (void) fprintf(stderr, gettext("too " 6131 "many fields given to -o " 6132 "option\n")); 6133 usage(B_FALSE); 6134 } 6135 6136 switch (getsubopt(&optarg, col_subopts, 6137 &value)) { 6138 case 0: 6139 cb.cb_columns[i++] = GET_COL_NAME; 6140 break; 6141 case 1: 6142 cb.cb_columns[i++] = GET_COL_PROPERTY; 6143 break; 6144 case 2: 6145 cb.cb_columns[i++] = GET_COL_VALUE; 6146 break; 6147 case 3: 6148 cb.cb_columns[i++] = GET_COL_SOURCE; 6149 break; 6150 case 4: 6151 if (i > 0) { 6152 (void) fprintf(stderr, 6153 gettext("\"all\" conflicts " 6154 "with specific fields " 6155 "given to -o option\n")); 6156 usage(B_FALSE); 6157 } 6158 cb.cb_columns[0] = GET_COL_NAME; 6159 cb.cb_columns[1] = GET_COL_PROPERTY; 6160 cb.cb_columns[2] = GET_COL_VALUE; 6161 cb.cb_columns[3] = GET_COL_SOURCE; 6162 i = ZFS_GET_NCOLS; 6163 break; 6164 default: 6165 (void) fprintf(stderr, 6166 gettext("invalid column name " 6167 "'%s'\n"), suboptarg); 6168 usage(B_FALSE); 6169 } 6170 } 6171 break; 6172 case '?': 6173 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6174 optopt); 6175 usage(B_FALSE); 6176 } 6177 } 6178 6179 argc -= optind; 6180 argv += optind; 6181 6182 if (argc < 1) { 6183 (void) fprintf(stderr, gettext("missing property " 6184 "argument\n")); 6185 usage(B_FALSE); 6186 } 6187 6188 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, 6189 ZFS_TYPE_POOL) != 0) 6190 usage(B_FALSE); 6191 6192 argc--; 6193 argv++; 6194 6195 if (cb.cb_proplist != NULL) { 6196 fake_name.pl_prop = ZPOOL_PROP_NAME; 6197 fake_name.pl_width = strlen(gettext("NAME")); 6198 fake_name.pl_next = cb.cb_proplist; 6199 cb.cb_proplist = &fake_name; 6200 } 6201 6202 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 6203 get_callback, &cb); 6204 6205 if (cb.cb_proplist == &fake_name) 6206 zprop_free_list(fake_name.pl_next); 6207 else 6208 zprop_free_list(cb.cb_proplist); 6209 6210 return (ret); 6211} 6212 6213typedef struct set_cbdata { 6214 char *cb_propname; 6215 char *cb_value; 6216 boolean_t cb_any_successful; 6217} set_cbdata_t; 6218 6219int 6220set_callback(zpool_handle_t *zhp, void *data) 6221{ 6222 int error; 6223 set_cbdata_t *cb = (set_cbdata_t *)data; 6224 6225 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 6226 6227 if (!error) 6228 cb->cb_any_successful = B_TRUE; 6229 6230 return (error); 6231} 6232 6233int 6234zpool_do_set(int argc, char **argv) 6235{ 6236 set_cbdata_t cb = { 0 }; 6237 int error; 6238 6239 if (argc > 1 && argv[1][0] == '-') { 6240 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6241 argv[1][1]); 6242 usage(B_FALSE); 6243 } 6244 6245 if (argc < 2) { 6246 (void) fprintf(stderr, gettext("missing property=value " 6247 "argument\n")); 6248 usage(B_FALSE); 6249 } 6250 6251 if (argc < 3) { 6252 (void) fprintf(stderr, gettext("missing pool name\n")); 6253 usage(B_FALSE); 6254 } 6255 6256 if (argc > 3) { 6257 (void) fprintf(stderr, gettext("too many pool names\n")); 6258 usage(B_FALSE); 6259 } 6260 6261 cb.cb_propname = argv[1]; 6262 cb.cb_value = strchr(cb.cb_propname, '='); 6263 if (cb.cb_value == NULL) { 6264 (void) fprintf(stderr, gettext("missing value in " 6265 "property=value argument\n")); 6266 usage(B_FALSE); 6267 } 6268 6269 *(cb.cb_value) = '\0'; 6270 cb.cb_value++; 6271 6272 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 6273 set_callback, &cb); 6274 6275 return (error); 6276} 6277 6278static int 6279find_command_idx(char *command, int *idx) 6280{ 6281 int i; 6282 6283 for (i = 0; i < NCOMMAND; i++) { 6284 if (command_table[i].name == NULL) 6285 continue; 6286 6287 if (strcmp(command, command_table[i].name) == 0) { 6288 *idx = i; 6289 return (0); 6290 } 6291 } 6292 return (1); 6293} 6294 6295int 6296main(int argc, char **argv) 6297{ 6298 int ret = 0; 6299 int i; 6300 char *cmdname; 6301 6302 (void) setlocale(LC_ALL, ""); 6303 (void) textdomain(TEXT_DOMAIN); 6304 6305 if ((g_zfs = libzfs_init()) == NULL) { 6306 (void) fprintf(stderr, gettext("internal error: failed to " 6307 "initialize ZFS library\n")); 6308 return (1); 6309 } 6310 6311 libzfs_print_on_error(g_zfs, B_TRUE); 6312 6313 opterr = 0; 6314 6315 /* 6316 * Make sure the user has specified some command. 6317 */ 6318 if (argc < 2) { 6319 (void) fprintf(stderr, gettext("missing command\n")); 6320 usage(B_FALSE); 6321 } 6322 6323 cmdname = argv[1]; 6324 6325 /* 6326 * Special case '-?' 6327 */ 6328 if (strcmp(cmdname, "-?") == 0) 6329 usage(B_TRUE); 6330 6331 zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 6332 6333 /* 6334 * Run the appropriate command. 6335 */ 6336 if (find_command_idx(cmdname, &i) == 0) { 6337 current_command = &command_table[i]; 6338 ret = command_table[i].func(argc - 1, argv + 1); 6339 } else if (strchr(cmdname, '=')) { 6340 verify(find_command_idx("set", &i) == 0); 6341 current_command = &command_table[i]; 6342 ret = command_table[i].func(argc, argv); 6343 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 6344 /* 6345 * 'freeze' is a vile debugging abomination, so we treat 6346 * it as such. 6347 */ 6348 zfs_cmd_t zc = { 0 }; 6349 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name)); 6350 return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc)); 6351 } else { 6352 (void) fprintf(stderr, gettext("unrecognized " 6353 "command '%s'\n"), cmdname); 6354 usage(B_FALSE); 6355 } 6356 6357 if (ret == 0 && log_history) 6358 (void) zpool_log_history(g_zfs, history_str); 6359 6360 libzfs_fini(g_zfs); 6361 6362 /* 6363 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 6364 * for the purposes of running ::findleaks. 6365 */ 6366 if (getenv("ZFS_ABORT") != NULL) { 6367 (void) printf("dumping core by request\n"); 6368 abort(); 6369 } 6370 6371 return (ret); 6372} 6373