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