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