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  * Copyright (c) 2017, Intel Corporation.
  31  * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
  32  * Copyright 2020 Joyent, Inc.
  33  * Copyright (c) 2012 by Cyril Plisko. All rights reserved.
  34  * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
  35  */
  36 
  37 #include <assert.h>
  38 #include <ctype.h>
  39 #include <dirent.h>
  40 #include <errno.h>
  41 #include <fcntl.h>
  42 #include <getopt.h>
  43 #include <libgen.h>
  44 #include <libintl.h>
  45 #include <libuutil.h>
  46 #include <locale.h>
  47 #include <stdio.h>
  48 #include <stdlib.h>
  49 #include <string.h>
  50 #include <strings.h>
  51 #include <unistd.h>
  52 #include <priv.h>
  53 #include <pwd.h>
  54 #include <zone.h>
  55 #include <zfs_prop.h>
  56 #include <sys/fs/zfs.h>
  57 #include <sys/stat.h>
  58 #include <sys/debug.h>
  59 #include <math.h>
  60 #include <sys/sysmacros.h>
  61 #include <sys/termios.h>
  62 
  63 #include <libzfs.h>
  64 #include <libzutil.h>
  65 
  66 #include "zpool_util.h"
  67 #include "zfs_comutil.h"
  68 #include "zfeature_common.h"
  69 
  70 #include "statcommon.h"
  71 
  72 static int zpool_do_create(int, char **);
  73 static int zpool_do_destroy(int, char **);
  74 
  75 static int zpool_do_add(int, char **);
  76 static int zpool_do_remove(int, char **);
  77 static int zpool_do_labelclear(int, char **);
  78 
  79 static int zpool_do_checkpoint(int, char **);
  80 
  81 static int zpool_do_list(int, char **);
  82 static int zpool_do_iostat(int, char **);
  83 static int zpool_do_status(int, char **);
  84 
  85 static int zpool_do_online(int, char **);
  86 static int zpool_do_offline(int, char **);
  87 static int zpool_do_clear(int, char **);
  88 static int zpool_do_reopen(int, char **);
  89 
  90 static int zpool_do_reguid(int, char **);
  91 
  92 static int zpool_do_attach(int, char **);
  93 static int zpool_do_detach(int, char **);
  94 static int zpool_do_replace(int, char **);
  95 static int zpool_do_split(int, char **);
  96 
  97 static int zpool_do_initialize(int, char **);
  98 static int zpool_do_scrub(int, char **);
  99 static int zpool_do_resilver(int, char **);
 100 static int zpool_do_trim(int, char **);
 101 
 102 static int zpool_do_import(int, char **);
 103 static int zpool_do_export(int, char **);
 104 
 105 static int zpool_do_upgrade(int, char **);
 106 
 107 static int zpool_do_history(int, char **);
 108 
 109 static int zpool_do_get(int, char **);
 110 static int zpool_do_set(int, char **);
 111 
 112 static int zpool_do_sync(int, char **);
 113 
 114 /*
 115  * These libumem hooks provide a reasonable set of defaults for the allocator's
 116  * debugging facilities.
 117  */
 118 
 119 #ifdef DEBUG
 120 const char *
 121 _umem_debug_init(void)
 122 {
 123         return ("default,verbose"); /* $UMEM_DEBUG setting */
 124 }
 125 
 126 const char *
 127 _umem_logging_init(void)
 128 {
 129         return ("fail,contents"); /* $UMEM_LOGGING setting */
 130 }
 131 #endif
 132 
 133 typedef enum {
 134         HELP_ADD,
 135         HELP_ATTACH,
 136         HELP_CLEAR,
 137         HELP_CREATE,
 138         HELP_CHECKPOINT,
 139         HELP_DESTROY,
 140         HELP_DETACH,
 141         HELP_EXPORT,
 142         HELP_HISTORY,
 143         HELP_IMPORT,
 144         HELP_IOSTAT,
 145         HELP_LABELCLEAR,
 146         HELP_LIST,
 147         HELP_OFFLINE,
 148         HELP_ONLINE,
 149         HELP_REPLACE,
 150         HELP_REMOVE,
 151         HELP_INITIALIZE,
 152         HELP_SCRUB,
 153         HELP_RESILVER,
 154         HELP_TRIM,
 155         HELP_STATUS,
 156         HELP_UPGRADE,
 157         HELP_GET,
 158         HELP_SET,
 159         HELP_SPLIT,
 160         HELP_SYNC,
 161         HELP_REGUID,
 162         HELP_REOPEN
 163 } zpool_help_t;
 164 
 165 
 166 /*
 167  * Flags for stats to display with "zpool iostats"
 168  */
 169 enum iostat_type {
 170         IOS_DEFAULT = 0,
 171         IOS_LATENCY = 1,
 172         IOS_QUEUES = 2,
 173         IOS_L_HISTO = 3,
 174         IOS_RQ_HISTO = 4,
 175         IOS_COUNT,      /* always last element */
 176 };
 177 
 178 /* iostat_type entries as bitmasks */
 179 #define IOS_DEFAULT_M   (1ULL << IOS_DEFAULT)
 180 #define IOS_LATENCY_M   (1ULL << IOS_LATENCY)
 181 #define IOS_QUEUES_M    (1ULL << IOS_QUEUES)
 182 #define IOS_L_HISTO_M   (1ULL << IOS_L_HISTO)
 183 #define IOS_RQ_HISTO_M  (1ULL << IOS_RQ_HISTO)
 184 
 185 /* Mask of all the histo bits */
 186 #define IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M)
 187 
 188 /*
 189  * Lookup table for iostat flags to nvlist names.  Basically a list
 190  * of all the nvlists a flag requires.  Also specifies the order in
 191  * which data gets printed in zpool iostat.
 192  */
 193 static const char *vsx_type_to_nvlist[IOS_COUNT][13] = {
 194         [IOS_L_HISTO] = {
 195             ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
 196             ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
 197             ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
 198             ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
 199             ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
 200             ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
 201             ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
 202             ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
 203             ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
 204             ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
 205             NULL},
 206         [IOS_LATENCY] = {
 207             ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
 208             ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
 209             ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
 210             ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
 211             ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
 212             NULL},
 213         [IOS_QUEUES] = {
 214             ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
 215             ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
 216             ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
 217             ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
 218             ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
 219             ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
 220             NULL},
 221         [IOS_RQ_HISTO] = {
 222             ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
 223             ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
 224             ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO,
 225             ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO,
 226             ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO,
 227             ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO,
 228             ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO,
 229             ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO,
 230             ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO,
 231             ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO,
 232             ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO,
 233             ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO,
 234             NULL},
 235 };
 236 
 237 
 238 /*
 239  * Given a cb->cb_flags with a histogram bit set, return the iostat_type.
 240  * Right now, only one histo bit is ever set at one time, so we can
 241  * just do a highbit64(a)
 242  */
 243 #define IOS_HISTO_IDX(a)        (highbit64(a & IOS_ANYHISTO_M) - 1)
 244 
 245 typedef struct zpool_command {
 246         const char      *name;
 247         int             (*func)(int, char **);
 248         zpool_help_t    usage;
 249 } zpool_command_t;
 250 
 251 /*
 252  * Master command table.  Each ZFS command has a name, associated function, and
 253  * usage message.  The usage messages need to be internationalized, so we have
 254  * to have a function to return the usage message based on a command index.
 255  *
 256  * These commands are organized according to how they are displayed in the usage
 257  * message.  An empty command (one with a NULL name) indicates an empty line in
 258  * the generic usage message.
 259  */
 260 static zpool_command_t command_table[] = {
 261         { "create",     zpool_do_create,        HELP_CREATE             },
 262         { "destroy",    zpool_do_destroy,       HELP_DESTROY            },
 263         { NULL },
 264         { "add",        zpool_do_add,           HELP_ADD                },
 265         { "remove",     zpool_do_remove,        HELP_REMOVE             },
 266         { NULL },
 267         { "labelclear", zpool_do_labelclear,    HELP_LABELCLEAR         },
 268         { NULL },
 269         { "checkpoint", zpool_do_checkpoint,    HELP_CHECKPOINT         },
 270         { NULL },
 271         { "list",       zpool_do_list,          HELP_LIST               },
 272         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
 273         { "status",     zpool_do_status,        HELP_STATUS             },
 274         { NULL },
 275         { "online",     zpool_do_online,        HELP_ONLINE             },
 276         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
 277         { "clear",      zpool_do_clear,         HELP_CLEAR              },
 278         { "reopen",     zpool_do_reopen,        HELP_REOPEN             },
 279         { NULL },
 280         { "attach",     zpool_do_attach,        HELP_ATTACH             },
 281         { "detach",     zpool_do_detach,        HELP_DETACH             },
 282         { "replace",    zpool_do_replace,       HELP_REPLACE            },
 283         { "split",      zpool_do_split,         HELP_SPLIT              },
 284         { NULL },
 285         { "initialize", zpool_do_initialize,    HELP_INITIALIZE         },
 286         { "resilver",   zpool_do_resilver,      HELP_RESILVER           },
 287         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
 288         { "trim",       zpool_do_trim,          HELP_TRIM               },
 289         { NULL },
 290         { "import",     zpool_do_import,        HELP_IMPORT             },
 291         { "export",     zpool_do_export,        HELP_EXPORT             },
 292         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 293         { "reguid",     zpool_do_reguid,        HELP_REGUID             },
 294         { NULL },
 295         { "history",    zpool_do_history,       HELP_HISTORY            },
 296         { "get",        zpool_do_get,           HELP_GET                },
 297         { "set",        zpool_do_set,           HELP_SET                },
 298         { "sync",       zpool_do_sync,          HELP_SYNC               },
 299 };
 300 
 301 #define NCOMMAND        (ARRAY_SIZE(command_table))
 302 
 303 #define VDEV_ALLOC_CLASS_LOGS   "logs"
 304 
 305 static zpool_command_t *current_command;
 306 static char history_str[HIS_MAX_RECORD_LEN];
 307 static boolean_t log_history = B_TRUE;
 308 static uint_t timestamp_fmt = NODATE;
 309 
 310 static const char *
 311 get_usage(zpool_help_t idx)
 312 {
 313         switch (idx) {
 314         case HELP_ADD:
 315                 return (gettext("\tadd [-fgLnP] [-o property=value] "
 316                     "<pool> <vdev> ...\n"));
 317         case HELP_ATTACH:
 318                 return (gettext("\tattach [-f] [-o property=value] "
 319                     "<pool> <device> <new-device>\n"));
 320         case HELP_CLEAR:
 321                 return (gettext("\tclear [-nF] <pool> [device]\n"));
 322         case HELP_CREATE:
 323                 return (gettext("\tcreate [-fnd] [-B] "
 324                     "[-o property=value] ... \n"
 325                     "\t    [-O file-system-property=value] ...\n"
 326                     "\t    [-m mountpoint] [-R root] [-t tempname] "
 327                     "<pool> <vdev> ...\n"));
 328         case HELP_CHECKPOINT:
 329                 return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
 330         case HELP_DESTROY:
 331                 return (gettext("\tdestroy [-f] <pool>\n"));
 332         case HELP_DETACH:
 333                 return (gettext("\tdetach <pool> <device>\n"));
 334         case HELP_EXPORT:
 335                 return (gettext("\texport [-f] <pool> ...\n"));
 336         case HELP_HISTORY:
 337                 return (gettext("\thistory [-il] [<pool>] ...\n"));
 338         case HELP_IMPORT:
 339                 return (gettext("\timport [-d dir] [-D]\n"
 340                     "\timport [-d dir | -c cachefile] [-F [-n]] [-l] "
 341                     "<pool | id>\n"
 342                     "\timport [-o mntopts] [-o property=value] ... \n"
 343                     "\t    [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
 344                     "[-R root] [-F [-n]] -a\n"
 345                     "\timport [-o mntopts] [-o property=value] ... \n"
 346                     "\t    [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
 347                     "[-R root] [-F [-n]] [-t]\n"
 348                     "\t    [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
 349         case HELP_IOSTAT:
 350                 return (gettext("\tiostat "
 351                     "[[-lq]|[-rw]] [-T d | u] [-ghHLpPvy]\n"
 352                     "\t    [[pool] ...]|[pool vdev ...]|[vdev ...]]"
 353                     " [[-n] interval [count]]\n"));
 354         case HELP_LABELCLEAR:
 355                 return (gettext("\tlabelclear [-f] <vdev>\n"));
 356         case HELP_LIST:
 357                 return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
 358                     "[-T d|u] [pool] ... [interval [count]]\n"));
 359         case HELP_OFFLINE:
 360                 return (gettext("\toffline [-t] <pool> <device> ...\n"));
 361         case HELP_ONLINE:
 362                 return (gettext("\tonline <pool> <device> ...\n"));
 363         case HELP_REPLACE:
 364                 return (gettext("\treplace [-f] <pool> <device> "
 365                     "[new-device]\n"));
 366         case HELP_REMOVE:
 367                 return (gettext("\tremove [-nps] <pool> <device> ...\n"));
 368         case HELP_REOPEN:
 369                 return (gettext("\treopen <pool>\n"));
 370         case HELP_INITIALIZE:
 371                 return (gettext("\tinitialize [-c | -s] <pool> "
 372                     "[<device> ...]\n"));
 373         case HELP_SCRUB:
 374                 return (gettext("\tscrub [-s | -p] <pool> ...\n"));
 375         case HELP_RESILVER:
 376                 return (gettext("\tresilver <pool> ...\n"));
 377         case HELP_TRIM:
 378                 return (gettext("\ttrim [-d] [-r <rate>] [-c | -s] <pool> "
 379                     "[<device> ...]\n"));
 380         case HELP_STATUS:
 381                 return (gettext("\tstatus "
 382                     "[-igLpPsvxD] [-T d|u] [pool] ... "
 383                     "[interval [count]]\n"));
 384         case HELP_UPGRADE:
 385                 return (gettext("\tupgrade\n"
 386                     "\tupgrade -v\n"
 387                     "\tupgrade [-V version] <-a | pool ...>\n"));
 388         case HELP_GET:
 389                 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
 390                     "<\"all\" | property[,...]> <pool> ...\n"));
 391         case HELP_SET:
 392                 return (gettext("\tset <property=value> <pool> \n"));
 393         case HELP_SPLIT:
 394                 return (gettext("\tsplit [-gLlnP] [-R altroot] [-o mntopts]\n"
 395                     "\t    [-o property=value] <pool> <newpool> "
 396                     "[<device> ...]\n"));
 397         case HELP_REGUID:
 398                 return (gettext("\treguid <pool>\n"));
 399         case HELP_SYNC:
 400                 return (gettext("\tsync [pool] ...\n"));
 401         }
 402 
 403         abort();
 404         /* NOTREACHED */
 405 }
 406 
 407 static void
 408 zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
 409 {
 410         uint_t children = 0;
 411         nvlist_t **child;
 412         uint_t i;
 413 
 414         (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
 415             &child, &children);
 416 
 417         if (children == 0) {
 418                 char *path = zpool_vdev_name(g_zfs, zhp, nvroot, 0);
 419 
 420                 if (strcmp(path, VDEV_TYPE_INDIRECT) != 0)
 421                         fnvlist_add_boolean(res, path);
 422 
 423                 free(path);
 424                 return;
 425         }
 426 
 427         for (i = 0; i < children; i++) {
 428                 zpool_collect_leaves(zhp, child[i], res);
 429         }
 430 }
 431 
 432 /*
 433  * Callback routine that will print out a pool property value.
 434  */
 435 static int
 436 print_prop_cb(int prop, void *cb)
 437 {
 438         FILE *fp = cb;
 439 
 440         (void) fprintf(fp, "\t%-19s  ", zpool_prop_to_name(prop));
 441 
 442         if (zpool_prop_readonly(prop))
 443                 (void) fprintf(fp, "  NO   ");
 444         else
 445                 (void) fprintf(fp, " YES   ");
 446 
 447         if (zpool_prop_values(prop) == NULL)
 448                 (void) fprintf(fp, "-\n");
 449         else
 450                 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
 451 
 452         return (ZPROP_CONT);
 453 }
 454 
 455 /*
 456  * Display usage message.  If we're inside a command, display only the usage for
 457  * that command.  Otherwise, iterate over the entire command table and display
 458  * a complete usage message.
 459  */
 460 void
 461 usage(boolean_t requested)
 462 {
 463         FILE *fp = requested ? stdout : stderr;
 464 
 465         if (current_command == NULL) {
 466                 int i;
 467 
 468                 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
 469                 (void) fprintf(fp,
 470                     gettext("where 'command' is one of the following:\n\n"));
 471 
 472                 for (i = 0; i < NCOMMAND; i++) {
 473                         if (command_table[i].name == NULL)
 474                                 (void) fprintf(fp, "\n");
 475                         else
 476                                 (void) fprintf(fp, "%s",
 477                                     get_usage(command_table[i].usage));
 478                 }
 479         } else {
 480                 (void) fprintf(fp, gettext("usage:\n"));
 481                 (void) fprintf(fp, "%s", get_usage(current_command->usage));
 482         }
 483 
 484         if (current_command != NULL &&
 485             ((strcmp(current_command->name, "set") == 0) ||
 486             (strcmp(current_command->name, "get") == 0) ||
 487             (strcmp(current_command->name, "list") == 0))) {
 488 
 489                 (void) fprintf(fp,
 490                     gettext("\nthe following properties are supported:\n"));
 491 
 492                 (void) fprintf(fp, "\n\t%-19s  %s   %s\n\n",
 493                     "PROPERTY", "EDIT", "VALUES");
 494 
 495                 /* Iterate over all properties */
 496                 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
 497                     ZFS_TYPE_POOL);
 498 
 499                 (void) fprintf(fp, "\t%-19s   ", "feature@...");
 500                 (void) fprintf(fp, "YES   disabled | enabled | active\n");
 501 
 502                 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
 503                     "appended with a feature name.\nSee zpool-features(5).\n"));
 504         }
 505 
 506         /*
 507          * See comments at end of main().
 508          */
 509         if (getenv("ZFS_ABORT") != NULL) {
 510                 (void) printf("dumping core by request\n");
 511                 abort();
 512         }
 513 
 514         exit(requested ? 0 : 2);
 515 }
 516 
 517 /*
 518  * print a pool vdev config for dry runs
 519  */
 520 static void
 521 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
 522     const char *match, int name_flags)
 523 {
 524         nvlist_t **child;
 525         uint_t c, children;
 526         char *vname;
 527         boolean_t printed = B_FALSE;
 528 
 529         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
 530             &child, &children) != 0) {
 531                 if (name != NULL)
 532                         (void) printf("\t%*s%s\n", indent, "", name);
 533                 return;
 534         }
 535 
 536         for (c = 0; c < children; c++) {
 537                 uint64_t is_log = B_FALSE;
 538                 char *class = "";
 539 
 540                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
 541                     &is_log);
 542                 if (is_log)
 543                         class = VDEV_ALLOC_BIAS_LOG;
 544                 (void) nvlist_lookup_string(child[c],
 545                     ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
 546                 if (strcmp(match, class) != 0)
 547                         continue;
 548 
 549                 if (!printed && name != NULL) {
 550                         (void) printf("\t%*s%s\n", indent, "", name);
 551                         printed = B_TRUE;
 552                 }
 553                 vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
 554                 print_vdev_tree(zhp, vname, child[c], indent + 2, "",
 555                     name_flags);
 556                 free(vname);
 557         }
 558 }
 559 
 560 static boolean_t
 561 prop_list_contains_feature(nvlist_t *proplist)
 562 {
 563         nvpair_t *nvp;
 564         for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
 565             nvp = nvlist_next_nvpair(proplist, nvp)) {
 566                 if (zpool_prop_feature(nvpair_name(nvp)))
 567                         return (B_TRUE);
 568         }
 569         return (B_FALSE);
 570 }
 571 
 572 /*
 573  * Add a property pair (name, string-value) into a property nvlist.
 574  */
 575 static int
 576 add_prop_list(const char *propname, char *propval, nvlist_t **props,
 577     boolean_t poolprop)
 578 {
 579         zpool_prop_t prop = ZPOOL_PROP_INVAL;
 580         zfs_prop_t fprop;
 581         nvlist_t *proplist;
 582         const char *normnm;
 583         char *strval;
 584 
 585         if (*props == NULL &&
 586             nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
 587                 (void) fprintf(stderr,
 588                     gettext("internal error: out of memory\n"));
 589                 return (1);
 590         }
 591 
 592         proplist = *props;
 593 
 594         if (poolprop) {
 595                 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
 596 
 597                 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
 598                     !zpool_prop_feature(propname)) {
 599                         (void) fprintf(stderr, gettext("property '%s' is "
 600                             "not a valid pool property\n"), propname);
 601                         return (2);
 602                 }
 603 
 604                 /*
 605                  * feature@ properties and version should not be specified
 606                  * at the same time.
 607                  */
 608                 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
 609                     nvlist_exists(proplist, vname)) ||
 610                     (prop == ZPOOL_PROP_VERSION &&
 611                     prop_list_contains_feature(proplist))) {
 612                         (void) fprintf(stderr, gettext("'feature@' and "
 613                             "'version' properties cannot be specified "
 614                             "together\n"));
 615                         return (2);
 616                 }
 617 
 618 
 619                 if (zpool_prop_feature(propname))
 620                         normnm = propname;
 621                 else
 622                         normnm = zpool_prop_to_name(prop);
 623         } else {
 624                 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
 625                         normnm = zfs_prop_to_name(fprop);
 626                 } else {
 627                         normnm = propname;
 628                 }
 629         }
 630 
 631         if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
 632             prop != ZPOOL_PROP_CACHEFILE) {
 633                 (void) fprintf(stderr, gettext("property '%s' "
 634                     "specified multiple times\n"), propname);
 635                 return (2);
 636         }
 637 
 638         if (nvlist_add_string(proplist, normnm, propval) != 0) {
 639                 (void) fprintf(stderr, gettext("internal "
 640                     "error: out of memory\n"));
 641                 return (1);
 642         }
 643 
 644         return (0);
 645 }
 646 
 647 /*
 648  * Set a default property pair (name, string-value) in a property nvlist
 649  */
 650 static int
 651 add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
 652     boolean_t poolprop)
 653 {
 654         char *pval;
 655 
 656         if (nvlist_lookup_string(*props, propname, &pval) == 0)
 657                 return (0);
 658 
 659         return (add_prop_list(propname, propval, props, poolprop));
 660 }
 661 
 662 /*
 663  * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
 664  *
 665  *      -f      Force addition of devices, even if they appear in use
 666  *      -g      Display guid for individual vdev name.
 667  *      -L      Follow links when resolving vdev path name.
 668  *      -n      Do not add the devices, but display the resulting layout if
 669  *              they were to be added.
 670  *      -P      Display full path for vdev name.
 671  *      -o      Set property=value.
 672  *
 673  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
 674  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
 675  * libzfs.
 676  */
 677 int
 678 zpool_do_add(int argc, char **argv)
 679 {
 680         boolean_t force = B_FALSE;
 681         boolean_t dryrun = B_FALSE;
 682         int name_flags = 0;
 683         int c;
 684         nvlist_t *nvroot;
 685         char *poolname;
 686         zpool_boot_label_t boot_type;
 687         uint64_t boot_size;
 688         int ret;
 689         zpool_handle_t *zhp;
 690         nvlist_t *config;
 691         nvlist_t *props = NULL;
 692         char *propval;
 693 
 694         /* check options */
 695         while ((c = getopt(argc, argv, "fgLnPo:")) != -1) {
 696                 switch (c) {
 697                 case 'f':
 698                         force = B_TRUE;
 699                         break;
 700                 case 'g':
 701                         name_flags |= VDEV_NAME_GUID;
 702                         break;
 703                 case 'L':
 704                         name_flags |= VDEV_NAME_FOLLOW_LINKS;
 705                         break;
 706                 case 'n':
 707                         dryrun = B_TRUE;
 708                         break;
 709                 case 'P':
 710                         name_flags |= VDEV_NAME_PATH;
 711                         break;
 712                 case 'o':
 713                         if ((propval = strchr(optarg, '=')) == NULL) {
 714                                 (void) fprintf(stderr, gettext("missing "
 715                                     "'=' for -o option\n"));
 716                                 usage(B_FALSE);
 717                         }
 718                         *propval = '\0';
 719                         propval++;
 720 
 721                         if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
 722                             (add_prop_list(optarg, propval, &props, B_TRUE)))
 723                                 usage(B_FALSE);
 724                         break;
 725                 case '?':
 726                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 727                             optopt);
 728                         usage(B_FALSE);
 729                 }
 730         }
 731 
 732         argc -= optind;
 733         argv += optind;
 734 
 735         /* get pool name and check number of arguments */
 736         if (argc < 1) {
 737                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
 738                 usage(B_FALSE);
 739         }
 740         if (argc < 2) {
 741                 (void) fprintf(stderr, gettext("missing vdev specification\n"));
 742                 usage(B_FALSE);
 743         }
 744 
 745         poolname = argv[0];
 746 
 747         argc--;
 748         argv++;
 749 
 750         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
 751                 return (1);
 752 
 753         if ((config = zpool_get_config(zhp, NULL)) == NULL) {
 754                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
 755                     poolname);
 756                 zpool_close(zhp);
 757                 return (1);
 758         }
 759 
 760         if (zpool_is_bootable(zhp))
 761                 boot_type = ZPOOL_COPY_BOOT_LABEL;
 762         else
 763                 boot_type = ZPOOL_NO_BOOT_LABEL;
 764 
 765         /* unless manually specified use "ashift" pool property (if set) */
 766         if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
 767                 int intval;
 768                 zprop_source_t src;
 769                 char strval[ZPOOL_MAXPROPLEN];
 770 
 771                 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
 772                 if (src != ZPROP_SRC_DEFAULT) {
 773                         (void) sprintf(strval, "%" PRId32, intval);
 774                         verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
 775                             &props, B_TRUE) == 0);
 776                 }
 777         }
 778 
 779         /* pass off to get_vdev_spec for processing */
 780         boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
 781         nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
 782             boot_type, boot_size, argc, argv);
 783         if (nvroot == NULL) {
 784                 zpool_close(zhp);
 785                 return (1);
 786         }
 787 
 788         if (dryrun) {
 789                 nvlist_t *poolnvroot;
 790 
 791                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
 792                     &poolnvroot) == 0);
 793 
 794                 (void) printf(gettext("would update '%s' to the following "
 795                     "configuration:\n"), zpool_get_name(zhp));
 796 
 797                 /* print original main pool and new tree */
 798                 print_vdev_tree(zhp, poolname, poolnvroot, 0, "",
 799                     name_flags | VDEV_NAME_TYPE_ID);
 800                 print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags);
 801 
 802                 /* print other classes: 'dedup', 'special', and 'log' */
 803                 print_vdev_tree(zhp, "dedup", poolnvroot, 0,
 804                     VDEV_ALLOC_BIAS_DEDUP, name_flags);
 805                 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_DEDUP,
 806                     name_flags);
 807 
 808                 print_vdev_tree(zhp, "special", poolnvroot, 0,
 809                     VDEV_ALLOC_BIAS_SPECIAL, name_flags);
 810                 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_SPECIAL,
 811                     name_flags);
 812 
 813                 print_vdev_tree(zhp, "logs", poolnvroot, 0, VDEV_ALLOC_BIAS_LOG,
 814                     name_flags);
 815                 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_LOG,
 816                     name_flags);
 817 
 818                 ret = 0;
 819         } else {
 820                 ret = (zpool_add(zhp, nvroot) != 0);
 821         }
 822 
 823         nvlist_free(props);
 824         nvlist_free(nvroot);
 825         zpool_close(zhp);
 826 
 827         return (ret);
 828 }
 829 
 830 /*
 831  * zpool remove  <pool> <vdev> ...
 832  *
 833  * Removes the given vdev from the pool.
 834  */
 835 int
 836 zpool_do_remove(int argc, char **argv)
 837 {
 838         char *poolname;
 839         int i, ret = 0;
 840         zpool_handle_t *zhp;
 841         boolean_t stop = B_FALSE;
 842         boolean_t noop = B_FALSE;
 843         boolean_t parsable = B_FALSE;
 844         char c;
 845 
 846         /* check options */
 847         while ((c = getopt(argc, argv, "nps")) != -1) {
 848                 switch (c) {
 849                 case 'n':
 850                         noop = B_TRUE;
 851                         break;
 852                 case 'p':
 853                         parsable = B_TRUE;
 854                         break;
 855                 case 's':
 856                         stop = B_TRUE;
 857                         break;
 858                 case '?':
 859                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 860                             optopt);
 861                         usage(B_FALSE);
 862                 }
 863         }
 864 
 865         argc -= optind;
 866         argv += optind;
 867 
 868         /* get pool name and check number of arguments */
 869         if (argc < 1) {
 870                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
 871                 usage(B_FALSE);
 872         }
 873 
 874         poolname = argv[0];
 875 
 876         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
 877                 return (1);
 878 
 879         if (stop && noop) {
 880                 (void) fprintf(stderr, gettext("stop request ignored\n"));
 881                 return (0);
 882         }
 883 
 884         if (stop) {
 885                 if (argc > 1) {
 886                         (void) fprintf(stderr, gettext("too many arguments\n"));
 887                         usage(B_FALSE);
 888                 }
 889                 if (zpool_vdev_remove_cancel(zhp) != 0)
 890                         ret = 1;
 891         } else {
 892                 if (argc < 2) {
 893                         (void) fprintf(stderr, gettext("missing device\n"));
 894                         usage(B_FALSE);
 895                 }
 896 
 897                 for (i = 1; i < argc; i++) {
 898                         if (noop) {
 899                                 uint64_t size;
 900 
 901                                 if (zpool_vdev_indirect_size(zhp, argv[i],
 902                                     &size) != 0) {
 903                                         ret = 1;
 904                                         break;
 905                                 }
 906                                 if (parsable) {
 907                                         (void) printf("%s %llu\n",
 908                                             argv[i], size);
 909                                 } else {
 910                                         char valstr[32];
 911                                         zfs_nicenum(size, valstr,
 912                                             sizeof (valstr));
 913                                         (void) printf("Memory that will be "
 914                                             "used after removing %s: %s\n",
 915                                             argv[i], valstr);
 916                                 }
 917                         } else {
 918                                 if (zpool_vdev_remove(zhp, argv[i]) != 0)
 919                                         ret = 1;
 920                         }
 921                 }
 922         }
 923 
 924         return (ret);
 925 }
 926 
 927 /*
 928  * zpool labelclear [-f] <vdev>
 929  *
 930  *      -f      Force clearing the label for the vdevs which are members of
 931  *              the exported or foreign pools.
 932  *
 933  * Verifies that the vdev is not active and zeros out the label information
 934  * on the device.
 935  */
 936 int
 937 zpool_do_labelclear(int argc, char **argv)
 938 {
 939         char vdev[MAXPATHLEN];
 940         char *name = NULL;
 941         struct stat st;
 942         int c, fd, ret = 0;
 943         nvlist_t *config;
 944         pool_state_t state;
 945         boolean_t inuse = B_FALSE;
 946         boolean_t force = B_FALSE;
 947 
 948         /* check options */
 949         while ((c = getopt(argc, argv, "f")) != -1) {
 950                 switch (c) {
 951                 case 'f':
 952                         force = B_TRUE;
 953                         break;
 954                 default:
 955                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 956                             optopt);
 957                         usage(B_FALSE);
 958                 }
 959         }
 960 
 961         argc -= optind;
 962         argv += optind;
 963 
 964         /* get vdev name */
 965         if (argc < 1) {
 966                 (void) fprintf(stderr, gettext("missing vdev name\n"));
 967                 usage(B_FALSE);
 968         }
 969         if (argc > 1) {
 970                 (void) fprintf(stderr, gettext("too many arguments\n"));
 971                 usage(B_FALSE);
 972         }
 973 
 974         /*
 975          * Check if we were given absolute path and use it as is.
 976          * Otherwise if the provided vdev name doesn't point to a file,
 977          * try prepending dsk path and appending s0.
 978          */
 979         (void) strlcpy(vdev, argv[0], sizeof (vdev));
 980         if (vdev[0] != '/' && stat(vdev, &st) != 0) {
 981                 char *s;
 982 
 983                 (void) snprintf(vdev, sizeof (vdev), "%s/%s",
 984                     ZFS_DISK_ROOT, argv[0]);
 985                 if ((s = strrchr(argv[0], 's')) == NULL ||
 986                     !isdigit(*(s + 1)))
 987                         (void) strlcat(vdev, "s0", sizeof (vdev));
 988                 if (stat(vdev, &st) != 0) {
 989                         (void) fprintf(stderr, gettext(
 990                             "failed to find device %s, try specifying absolute "
 991                             "path instead\n"), argv[0]);
 992                         return (1);
 993                 }
 994         }
 995 
 996         if ((fd = open(vdev, O_RDWR)) < 0) {
 997                 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
 998                     vdev, strerror(errno));
 999                 return (1);
1000         }
1001 
1002         if (zpool_read_label(fd, &config, NULL) != 0) {
1003                 (void) fprintf(stderr,
1004                     gettext("failed to read label from %s\n"), vdev);
1005                 return (1);
1006         }
1007         nvlist_free(config);
1008 
1009         ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
1010         if (ret != 0) {
1011                 (void) fprintf(stderr,
1012                     gettext("failed to check state for %s\n"), vdev);
1013                 return (1);
1014         }
1015 
1016         if (!inuse)
1017                 goto wipe_label;
1018 
1019         switch (state) {
1020         default:
1021         case POOL_STATE_ACTIVE:
1022         case POOL_STATE_SPARE:
1023         case POOL_STATE_L2CACHE:
1024                 (void) fprintf(stderr, gettext(
1025                     "%s is a member (%s) of pool \"%s\"\n"),
1026                     vdev, zpool_pool_state_to_name(state), name);
1027                 ret = 1;
1028                 goto errout;
1029 
1030         case POOL_STATE_EXPORTED:
1031                 if (force)
1032                         break;
1033                 (void) fprintf(stderr, gettext(
1034                     "use '-f' to override the following error:\n"
1035                     "%s is a member of exported pool \"%s\"\n"),
1036                     vdev, name);
1037                 ret = 1;
1038                 goto errout;
1039 
1040         case POOL_STATE_POTENTIALLY_ACTIVE:
1041                 if (force)
1042                         break;
1043                 (void) fprintf(stderr, gettext(
1044                     "use '-f' to override the following error:\n"
1045                     "%s is a member of potentially active pool \"%s\"\n"),
1046                     vdev, name);
1047                 ret = 1;
1048                 goto errout;
1049 
1050         case POOL_STATE_DESTROYED:
1051                 /* inuse should never be set for a destroyed pool */
1052                 assert(0);
1053                 break;
1054         }
1055 
1056 wipe_label:
1057         ret = zpool_clear_label(fd);
1058         if (ret != 0) {
1059                 (void) fprintf(stderr,
1060                     gettext("failed to clear label for %s\n"), vdev);
1061         }
1062 
1063 errout:
1064         free(name);
1065         (void) close(fd);
1066 
1067         return (ret);
1068 }
1069 
1070 /*
1071  * zpool create [-fnd] [-B] [-o property=value] ...
1072  *              [-O file-system-property=value] ...
1073  *              [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ...
1074  *
1075  *      -B      Create boot partition.
1076  *      -f      Force creation, even if devices appear in use
1077  *      -n      Do not create the pool, but display the resulting layout if it
1078  *              were to be created.
1079  *      -R      Create a pool under an alternate root
1080  *      -m      Set default mountpoint for the root dataset.  By default it's
1081  *              '/<pool>'
1082  *      -t      Use the temporary name until the pool is exported.
1083  *      -o      Set property=value.
1084  *      -o      Set feature@feature=enabled|disabled.
1085  *      -d      Don't automatically enable all supported pool features
1086  *              (individual features can be enabled with -o).
1087  *      -O      Set fsproperty=value in the pool's root file system
1088  *
1089  * Creates the named pool according to the given vdev specification.  The
1090  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
1091  * we get the nvlist back from get_vdev_spec(), we either print out the contents
1092  * (if '-n' was specified), or pass it to libzfs to do the creation.
1093  */
1094 
1095 #define SYSTEM256       (256 * 1024 * 1024)
1096 int
1097 zpool_do_create(int argc, char **argv)
1098 {
1099         boolean_t force = B_FALSE;
1100         boolean_t dryrun = B_FALSE;
1101         boolean_t enable_all_pool_feat = B_TRUE;
1102         zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
1103         uint64_t boot_size = 0;
1104         int c;
1105         nvlist_t *nvroot = NULL;
1106         char *poolname;
1107         char *tname = NULL;
1108         int ret = 1;
1109         char *altroot = NULL;
1110         char *mountpoint = NULL;
1111         nvlist_t *fsprops = NULL;
1112         nvlist_t *props = NULL;
1113         char *propval;
1114 
1115         /* check options */
1116         while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) {
1117                 switch (c) {
1118                 case 'f':
1119                         force = B_TRUE;
1120                         break;
1121                 case 'n':
1122                         dryrun = B_TRUE;
1123                         break;
1124                 case 'd':
1125                         enable_all_pool_feat = B_FALSE;
1126                         break;
1127                 case 'B':
1128                         /*
1129                          * We should create the system partition.
1130                          * Also make sure the size is set.
1131                          */
1132                         boot_type = ZPOOL_CREATE_BOOT_LABEL;
1133                         if (boot_size == 0)
1134                                 boot_size = SYSTEM256;
1135                         break;
1136                 case 'R':
1137                         altroot = optarg;
1138                         if (add_prop_list(zpool_prop_to_name(
1139                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1140                                 goto errout;
1141                         if (add_prop_list_default(zpool_prop_to_name(
1142                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1143                                 goto errout;
1144                         break;
1145                 case 'm':
1146                         /* Equivalent to -O mountpoint=optarg */
1147                         mountpoint = optarg;
1148                         break;
1149                 case 'o':
1150                         if ((propval = strchr(optarg, '=')) == NULL) {
1151                                 (void) fprintf(stderr, gettext("missing "
1152                                     "'=' for -o option\n"));
1153                                 goto errout;
1154                         }
1155                         *propval = '\0';
1156                         propval++;
1157 
1158                         if (add_prop_list(optarg, propval, &props, B_TRUE))
1159                                 goto errout;
1160 
1161                         /*
1162                          * Get bootsize value for make_root_vdev().
1163                          */
1164                         if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
1165                                 if (zfs_nicestrtonum(g_zfs, propval,
1166                                     &boot_size) < 0 || boot_size == 0) {
1167                                         (void) fprintf(stderr,
1168                                             gettext("bad boot partition size "
1169                                             "'%s': %s\n"),  propval,
1170                                             libzfs_error_description(g_zfs));
1171                                         goto errout;
1172                                 }
1173                         }
1174 
1175                         /*
1176                          * If the user is creating a pool that doesn't support
1177                          * feature flags, don't enable any features.
1178                          */
1179                         if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
1180                                 char *end;
1181                                 u_longlong_t ver;
1182 
1183                                 ver = strtoull(propval, &end, 10);
1184                                 if (*end == '\0' &&
1185                                     ver < SPA_VERSION_FEATURES) {
1186                                         enable_all_pool_feat = B_FALSE;
1187                                 }
1188                         }
1189                         if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
1190                                 altroot = propval;
1191                         break;
1192                 case 'O':
1193                         if ((propval = strchr(optarg, '=')) == NULL) {
1194                                 (void) fprintf(stderr, gettext("missing "
1195                                     "'=' for -O option\n"));
1196                                 goto errout;
1197                         }
1198                         *propval = '\0';
1199                         propval++;
1200 
1201                         /*
1202                          * Mountpoints are checked and then added later.
1203                          * Uniquely among properties, they can be specified
1204                          * more than once, to avoid conflict with -m.
1205                          */
1206                         if (0 == strcmp(optarg,
1207                             zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1208                                 mountpoint = propval;
1209                         } else if (add_prop_list(optarg, propval, &fsprops,
1210                             B_FALSE)) {
1211                                 goto errout;
1212                         }
1213                         break;
1214                 case 't':
1215                         /*
1216                          * Sanity check temporary pool name.
1217                          */
1218                         if (strchr(optarg, '/') != NULL) {
1219                                 (void) fprintf(stderr, gettext("cannot create "
1220                                     "'%s': invalid character '/' in temporary "
1221                                     "name\n"), optarg);
1222                                 (void) fprintf(stderr, gettext("use 'zfs "
1223                                     "create' to create a dataset\n"));
1224                                 goto errout;
1225                         }
1226 
1227                         if (add_prop_list(zpool_prop_to_name(
1228                             ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
1229                                 goto errout;
1230                         if (add_prop_list_default(zpool_prop_to_name(
1231                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1232                                 goto errout;
1233                         tname = optarg;
1234                         break;
1235                 case ':':
1236                         (void) fprintf(stderr, gettext("missing argument for "
1237                             "'%c' option\n"), optopt);
1238                         goto badusage;
1239                 case '?':
1240                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1241                             optopt);
1242                         goto badusage;
1243                 }
1244         }
1245 
1246         argc -= optind;
1247         argv += optind;
1248 
1249         /* get pool name and check number of arguments */
1250         if (argc < 1) {
1251                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1252                 goto badusage;
1253         }
1254         if (argc < 2) {
1255                 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1256                 goto badusage;
1257         }
1258 
1259         poolname = argv[0];
1260 
1261         /*
1262          * As a special case, check for use of '/' in the name, and direct the
1263          * user to use 'zfs create' instead.
1264          */
1265         if (strchr(poolname, '/') != NULL) {
1266                 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1267                     "character '/' in pool name\n"), poolname);
1268                 (void) fprintf(stderr, gettext("use 'zfs create' to "
1269                     "create a dataset\n"));
1270                 goto errout;
1271         }
1272 
1273         /*
1274          * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1275          * and not set otherwise.
1276          */
1277         if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1278                 const char *propname;
1279                 char *strptr, *buf = NULL;
1280                 int rv;
1281 
1282                 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1283                 if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1284                         (void) asprintf(&buf, "%" PRIu64, boot_size);
1285                         if (buf == NULL) {
1286                                 (void) fprintf(stderr,
1287                                     gettext("internal error: out of memory\n"));
1288                                 goto errout;
1289                         }
1290                         rv = add_prop_list(propname, buf, &props, B_TRUE);
1291                         free(buf);
1292                         if (rv != 0)
1293                                 goto errout;
1294                 }
1295         } else {
1296                 const char *propname;
1297                 char *strptr;
1298 
1299                 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1300                 if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1301                         (void) fprintf(stderr, gettext("error: setting boot "
1302                             "partition size requires option '-B'\n"));
1303                         goto errout;
1304                 }
1305         }
1306 
1307         /* pass off to get_vdev_spec for bulk processing */
1308         nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
1309             boot_type, boot_size, argc - 1, argv + 1);
1310         if (nvroot == NULL)
1311                 goto errout;
1312 
1313         /* make_root_vdev() allows 0 toplevel children if there are spares */
1314         if (!zfs_allocatable_devs(nvroot)) {
1315                 (void) fprintf(stderr, gettext("invalid vdev "
1316                     "specification: at least one toplevel vdev must be "
1317                     "specified\n"));
1318                 goto errout;
1319         }
1320 
1321         if (altroot != NULL && altroot[0] != '/') {
1322                 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1323                     "must be an absolute path\n"), altroot);
1324                 goto errout;
1325         }
1326 
1327         /*
1328          * Check the validity of the mountpoint and direct the user to use the
1329          * '-m' mountpoint option if it looks like its in use.
1330          */
1331         if (mountpoint == NULL ||
1332             (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1333             strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1334                 char buf[MAXPATHLEN];
1335                 DIR *dirp;
1336 
1337                 if (mountpoint && mountpoint[0] != '/') {
1338                         (void) fprintf(stderr, gettext("invalid mountpoint "
1339                             "'%s': must be an absolute path, 'legacy', or "
1340                             "'none'\n"), mountpoint);
1341                         goto errout;
1342                 }
1343 
1344                 if (mountpoint == NULL) {
1345                         if (altroot != NULL)
1346                                 (void) snprintf(buf, sizeof (buf), "%s/%s",
1347                                     altroot, poolname);
1348                         else
1349                                 (void) snprintf(buf, sizeof (buf), "/%s",
1350                                     poolname);
1351                 } else {
1352                         if (altroot != NULL)
1353                                 (void) snprintf(buf, sizeof (buf), "%s%s",
1354                                     altroot, mountpoint);
1355                         else
1356                                 (void) snprintf(buf, sizeof (buf), "%s",
1357                                     mountpoint);
1358                 }
1359 
1360                 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1361                         (void) fprintf(stderr, gettext("mountpoint '%s' : "
1362                             "%s\n"), buf, strerror(errno));
1363                         (void) fprintf(stderr, gettext("use '-m' "
1364                             "option to provide a different default\n"));
1365                         goto errout;
1366                 } else if (dirp) {
1367                         int count = 0;
1368 
1369                         while (count < 3 && readdir(dirp) != NULL)
1370                                 count++;
1371                         (void) closedir(dirp);
1372 
1373                         if (count > 2) {
1374                                 (void) fprintf(stderr, gettext("mountpoint "
1375                                     "'%s' exists and is not empty\n"), buf);
1376                                 (void) fprintf(stderr, gettext("use '-m' "
1377                                     "option to provide a "
1378                                     "different default\n"));
1379                                 goto errout;
1380                         }
1381                 }
1382         }
1383 
1384         /*
1385          * Now that the mountpoint's validity has been checked, ensure that
1386          * the property is set appropriately prior to creating the pool.
1387          */
1388         if (mountpoint != NULL) {
1389                 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1390                     mountpoint, &fsprops, B_FALSE);
1391                 if (ret != 0)
1392                         goto errout;
1393         }
1394 
1395         ret = 1;
1396         if (dryrun) {
1397                 /*
1398                  * For a dry run invocation, print out a basic message and run
1399                  * through all the vdevs in the list and print out in an
1400                  * appropriate hierarchy.
1401                  */
1402                 (void) printf(gettext("would create '%s' with the "
1403                     "following layout:\n\n"), poolname);
1404 
1405                 print_vdev_tree(NULL, poolname, nvroot, 0, "", 0);
1406                 print_vdev_tree(NULL, "dedup", nvroot, 0,
1407                     VDEV_ALLOC_BIAS_DEDUP, 0);
1408                 print_vdev_tree(NULL, "special", nvroot, 0,
1409                     VDEV_ALLOC_BIAS_SPECIAL, 0);
1410                 print_vdev_tree(NULL, "logs", nvroot, 0,
1411                     VDEV_ALLOC_BIAS_LOG, 0);
1412 
1413                 ret = 0;
1414         } else {
1415                 /*
1416                  * Hand off to libzfs.
1417                  */
1418 
1419                 spa_feature_t i;
1420                 for (i = 0; i < SPA_FEATURES; i++) {
1421                         char propname[MAXPATHLEN];
1422                         char *propval;
1423                         zfeature_info_t *feat = &spa_feature_table[i];
1424                         (void) snprintf(propname, sizeof (propname),
1425                             "feature@%s", feat->fi_uname);
1426 
1427                         /*
1428                          * Only features contained in props will be enabled:
1429                          * remove from the nvlist every ZFS_FEATURE_DISABLED
1430                          * value and add every missing ZFS_FEATURE_ENABLED if
1431                          * enable_all_pool_feat is set.
1432                          */
1433                         if (!nvlist_lookup_string(props, propname, &propval)) {
1434                                 if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0)
1435                                         (void) nvlist_remove_all(props,
1436                                             propname);
1437                         } else if (enable_all_pool_feat) {
1438                                 ret = add_prop_list(propname,
1439                                     ZFS_FEATURE_ENABLED, &props, B_TRUE);
1440                                 if (ret != 0)
1441                                         goto errout;
1442                         }
1443                 }
1444 
1445                 ret = 1;
1446                 if (zpool_create(g_zfs, poolname,
1447                     nvroot, props, fsprops) == 0) {
1448                         zfs_handle_t *pool = zfs_open(g_zfs,
1449                             tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
1450                         if (pool != NULL) {
1451                                 if (zfs_mount(pool, NULL, 0) == 0)
1452                                         ret = zfs_shareall(pool);
1453                                 zfs_close(pool);
1454                         }
1455                 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1456                         (void) fprintf(stderr, gettext("pool name may have "
1457                             "been omitted\n"));
1458                 }
1459         }
1460 
1461 errout:
1462         nvlist_free(nvroot);
1463         nvlist_free(fsprops);
1464         nvlist_free(props);
1465         return (ret);
1466 badusage:
1467         nvlist_free(fsprops);
1468         nvlist_free(props);
1469         usage(B_FALSE);
1470         return (2);
1471 }
1472 
1473 /*
1474  * zpool destroy <pool>
1475  *
1476  *      -f      Forcefully unmount any datasets
1477  *
1478  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
1479  */
1480 int
1481 zpool_do_destroy(int argc, char **argv)
1482 {
1483         boolean_t force = B_FALSE;
1484         int c;
1485         char *pool;
1486         zpool_handle_t *zhp;
1487         int ret;
1488 
1489         /* check options */
1490         while ((c = getopt(argc, argv, "f")) != -1) {
1491                 switch (c) {
1492                 case 'f':
1493                         force = B_TRUE;
1494                         break;
1495                 case '?':
1496                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1497                             optopt);
1498                         usage(B_FALSE);
1499                 }
1500         }
1501 
1502         argc -= optind;
1503         argv += optind;
1504 
1505         /* check arguments */
1506         if (argc < 1) {
1507                 (void) fprintf(stderr, gettext("missing pool argument\n"));
1508                 usage(B_FALSE);
1509         }
1510         if (argc > 1) {
1511                 (void) fprintf(stderr, gettext("too many arguments\n"));
1512                 usage(B_FALSE);
1513         }
1514 
1515         pool = argv[0];
1516 
1517         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1518                 /*
1519                  * As a special case, check for use of '/' in the name, and
1520                  * direct the user to use 'zfs destroy' instead.
1521                  */
1522                 if (strchr(pool, '/') != NULL)
1523                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1524                             "destroy a dataset\n"));
1525                 return (1);
1526         }
1527 
1528         if (zpool_disable_datasets(zhp, force) != 0) {
1529                 (void) fprintf(stderr, gettext("could not destroy '%s': "
1530                     "could not unmount datasets\n"), zpool_get_name(zhp));
1531                 return (1);
1532         }
1533 
1534         /* The history must be logged as part of the export */
1535         log_history = B_FALSE;
1536 
1537         ret = (zpool_destroy(zhp, history_str) != 0);
1538 
1539         zpool_close(zhp);
1540 
1541         return (ret);
1542 }
1543 
1544 /*
1545  * zpool export [-f] <pool> ...
1546  *
1547  *      -f      Forcefully unmount datasets
1548  *
1549  * Export the given pools.  By default, the command will attempt to cleanly
1550  * unmount any active datasets within the pool.  If the '-f' flag is specified,
1551  * then the datasets will be forcefully unmounted.
1552  */
1553 int
1554 zpool_do_export(int argc, char **argv)
1555 {
1556         boolean_t force = B_FALSE;
1557         boolean_t hardforce = B_FALSE;
1558         int c;
1559         zpool_handle_t *zhp;
1560         int ret;
1561         int i;
1562 
1563         /* check options */
1564         while ((c = getopt(argc, argv, "fF")) != -1) {
1565                 switch (c) {
1566                 case 'f':
1567                         force = B_TRUE;
1568                         break;
1569                 case 'F':
1570                         hardforce = B_TRUE;
1571                         break;
1572                 case '?':
1573                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1574                             optopt);
1575                         usage(B_FALSE);
1576                 }
1577         }
1578 
1579         argc -= optind;
1580         argv += optind;
1581 
1582         /* check arguments */
1583         if (argc < 1) {
1584                 (void) fprintf(stderr, gettext("missing pool argument\n"));
1585                 usage(B_FALSE);
1586         }
1587 
1588         ret = 0;
1589         for (i = 0; i < argc; i++) {
1590                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1591                         ret = 1;
1592                         continue;
1593                 }
1594 
1595                 if (zpool_disable_datasets(zhp, force) != 0) {
1596                         ret = 1;
1597                         zpool_close(zhp);
1598                         continue;
1599                 }
1600 
1601                 /* The history must be logged as part of the export */
1602                 log_history = B_FALSE;
1603 
1604                 if (hardforce) {
1605                         if (zpool_export_force(zhp, history_str) != 0)
1606                                 ret = 1;
1607                 } else if (zpool_export(zhp, force, history_str) != 0) {
1608                         ret = 1;
1609                 }
1610 
1611                 zpool_close(zhp);
1612         }
1613 
1614         return (ret);
1615 }
1616 
1617 /*
1618  * Given a vdev configuration, determine the maximum width needed for the device
1619  * name column.
1620  */
1621 static int
1622 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
1623     int name_flags)
1624 {
1625         char *name;
1626         nvlist_t **child;
1627         uint_t c, children;
1628         int ret;
1629 
1630         name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID);
1631         if (strlen(name) + depth > max)
1632                 max = strlen(name) + depth;
1633 
1634         free(name);
1635 
1636         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1637             &child, &children) == 0) {
1638                 for (c = 0; c < children; c++)
1639                         if ((ret = max_width(zhp, child[c], depth + 2,
1640                             max, name_flags)) > max)
1641                                 max = ret;
1642         }
1643 
1644         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1645             &child, &children) == 0) {
1646                 for (c = 0; c < children; c++)
1647                         if ((ret = max_width(zhp, child[c], depth + 2,
1648                             max, name_flags)) > max)
1649                                 max = ret;
1650         }
1651 
1652         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1653             &child, &children) == 0) {
1654                 for (c = 0; c < children; c++)
1655                         if ((ret = max_width(zhp, child[c], depth + 2,
1656                             max, name_flags)) > max)
1657                                 max = ret;
1658         }
1659 
1660         return (max);
1661 }
1662 
1663 typedef struct spare_cbdata {
1664         uint64_t        cb_guid;
1665         zpool_handle_t  *cb_zhp;
1666 } spare_cbdata_t;
1667 
1668 static boolean_t
1669 find_vdev(nvlist_t *nv, uint64_t search)
1670 {
1671         uint64_t guid;
1672         nvlist_t **child;
1673         uint_t c, children;
1674 
1675         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1676             search == guid)
1677                 return (B_TRUE);
1678 
1679         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1680             &child, &children) == 0) {
1681                 for (c = 0; c < children; c++)
1682                         if (find_vdev(child[c], search))
1683                                 return (B_TRUE);
1684         }
1685 
1686         return (B_FALSE);
1687 }
1688 
1689 static int
1690 find_spare(zpool_handle_t *zhp, void *data)
1691 {
1692         spare_cbdata_t *cbp = data;
1693         nvlist_t *config, *nvroot;
1694 
1695         config = zpool_get_config(zhp, NULL);
1696         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1697             &nvroot) == 0);
1698 
1699         if (find_vdev(nvroot, cbp->cb_guid)) {
1700                 cbp->cb_zhp = zhp;
1701                 return (1);
1702         }
1703 
1704         zpool_close(zhp);
1705         return (0);
1706 }
1707 
1708 typedef struct status_cbdata {
1709         int             cb_count;
1710         int             cb_name_flags;
1711         int             cb_namewidth;
1712         boolean_t       cb_allpools;
1713         boolean_t       cb_verbose;
1714         boolean_t       cb_literal;
1715         boolean_t       cb_explain;
1716         boolean_t       cb_first;
1717         boolean_t       cb_dedup_stats;
1718         boolean_t       cb_print_status;
1719         boolean_t       cb_print_slow_ios;
1720         boolean_t       cb_print_vdev_init;
1721         boolean_t       cb_print_vdev_trim;
1722 } status_cbdata_t;
1723 
1724 /*
1725  * Print vdev initialization status for leaves
1726  */
1727 static void
1728 print_status_initialize(vdev_stat_t *vs, boolean_t verbose)
1729 {
1730         if (verbose) {
1731                 if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE ||
1732                     vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
1733                     vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) &&
1734                     !vs->vs_scan_removing) {
1735                         char zbuf[1024];
1736                         char tbuf[256];
1737                         struct tm zaction_ts;
1738 
1739                         time_t t = vs->vs_initialize_action_time;
1740                         int initialize_pct = 100;
1741                         if (vs->vs_initialize_state !=
1742                             VDEV_INITIALIZE_COMPLETE) {
1743                                 initialize_pct = (vs->vs_initialize_bytes_done *
1744                                     100 / (vs->vs_initialize_bytes_est + 1));
1745                         }
1746 
1747                         (void) localtime_r(&t, &zaction_ts);
1748                         (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1749 
1750                         switch (vs->vs_initialize_state) {
1751                         case VDEV_INITIALIZE_SUSPENDED:
1752                                 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1753                                     gettext("suspended, started at"), tbuf);
1754                                 break;
1755                         case VDEV_INITIALIZE_ACTIVE:
1756                                 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1757                                     gettext("started at"), tbuf);
1758                                 break;
1759                         case VDEV_INITIALIZE_COMPLETE:
1760                                 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1761                                     gettext("completed at"), tbuf);
1762                                 break;
1763                         }
1764 
1765                         (void) printf(gettext("  (%d%% initialized%s)"),
1766                             initialize_pct, zbuf);
1767                 } else {
1768                         (void) printf(gettext("  (uninitialized)"));
1769                 }
1770         } else if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) {
1771                 (void) printf(gettext("  (initializing)"));
1772         }
1773 }
1774 
1775 /*
1776  * Print vdev TRIM status for leaves
1777  */
1778 static void
1779 print_status_trim(vdev_stat_t *vs, boolean_t verbose)
1780 {
1781         if (verbose) {
1782                 if ((vs->vs_trim_state == VDEV_TRIM_ACTIVE ||
1783                     vs->vs_trim_state == VDEV_TRIM_SUSPENDED ||
1784                     vs->vs_trim_state == VDEV_TRIM_COMPLETE) &&
1785                     !vs->vs_scan_removing) {
1786                         char zbuf[1024];
1787                         char tbuf[256];
1788                         struct tm zaction_ts;
1789 
1790                         time_t t = vs->vs_trim_action_time;
1791                         int trim_pct = 100;
1792                         if (vs->vs_trim_state != VDEV_TRIM_COMPLETE) {
1793                                 trim_pct = (vs->vs_trim_bytes_done *
1794                                     100 / (vs->vs_trim_bytes_est + 1));
1795                         }
1796 
1797                         (void) localtime_r(&t, &zaction_ts);
1798                         (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1799 
1800                         switch (vs->vs_trim_state) {
1801                         case VDEV_TRIM_SUSPENDED:
1802                                 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1803                                     gettext("suspended, started at"), tbuf);
1804                                 break;
1805                         case VDEV_TRIM_ACTIVE:
1806                                 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1807                                     gettext("started at"), tbuf);
1808                                 break;
1809                         case VDEV_TRIM_COMPLETE:
1810                                 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1811                                     gettext("completed at"), tbuf);
1812                                 break;
1813                         }
1814 
1815                         (void) printf(gettext("  (%d%% trimmed%s)"),
1816                             trim_pct, zbuf);
1817                 } else if (vs->vs_trim_notsup) {
1818                         (void) printf(gettext("  (trim unsupported)"));
1819                 } else {
1820                         (void) printf(gettext("  (untrimmed)"));
1821                 }
1822         } else if (vs->vs_trim_state == VDEV_TRIM_ACTIVE) {
1823                 (void) printf(gettext("  (trimming)"));
1824         }
1825 }
1826 
1827 /*
1828  * Print out configuration state as requested by status_callback.
1829  */
1830 static void
1831 print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
1832     nvlist_t *nv, int depth, boolean_t isspare)
1833 {
1834         nvlist_t **child, *root;
1835         uint_t c, children;
1836         pool_scan_stat_t *ps = NULL;
1837         vdev_stat_t *vs;
1838         char rbuf[6], wbuf[6], cbuf[6];
1839         char *vname;
1840         uint64_t notpresent;
1841         spare_cbdata_t spare_cb;
1842         const char *state;
1843         char *type;
1844 
1845         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1846             &child, &children) != 0)
1847                 children = 0;
1848 
1849         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1850             (uint64_t **)&vs, &c) == 0);
1851 
1852         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1853 
1854         if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1855                 return;
1856 
1857         state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1858         if (isspare) {
1859                 /*
1860                  * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1861                  * online drives.
1862                  */
1863                 if (vs->vs_aux == VDEV_AUX_SPARED)
1864                         state = "INUSE";
1865                 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1866                         state = "AVAIL";
1867         }
1868 
1869         (void) printf("\t%*s%-*s  %-8s", depth, "", cb->cb_namewidth - depth,
1870             name, state);
1871 
1872         if (!isspare) {
1873                 if (cb->cb_literal) {
1874                         printf(" %5llu %5llu %5llu",
1875                             (u_longlong_t)vs->vs_read_errors,
1876                             (u_longlong_t)vs->vs_write_errors,
1877                             (u_longlong_t)vs->vs_checksum_errors);
1878                 } else {
1879                         zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1880                         zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1881                         zfs_nicenum(vs->vs_checksum_errors, cbuf,
1882                             sizeof (cbuf));
1883                         printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1884                 }
1885 
1886                 if (cb->cb_print_slow_ios) {
1887                         if (children == 0)  {
1888                                 /* Only leafs vdevs have slow IOs */
1889                                 zfs_nicenum(vs->vs_slow_ios, rbuf,
1890                                     sizeof (rbuf));
1891                         } else {
1892                                 (void) snprintf(rbuf, sizeof (rbuf), "-");
1893                         }
1894 
1895                         if (cb->cb_literal)
1896                                 printf(" %5llu", (u_longlong_t)vs->vs_slow_ios);
1897                         else
1898                                 printf(" %5s", rbuf);
1899                 }
1900 
1901         }
1902 
1903         if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1904             &notpresent) == 0) {
1905                 char *path;
1906                 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1907                 (void) printf("  was %s", path);
1908         } else if (vs->vs_aux != 0) {
1909                 (void) printf("  ");
1910 
1911                 switch (vs->vs_aux) {
1912                 case VDEV_AUX_OPEN_FAILED:
1913                         (void) printf(gettext("cannot open"));
1914                         break;
1915 
1916                 case VDEV_AUX_BAD_GUID_SUM:
1917                         (void) printf(gettext("missing device"));
1918                         break;
1919 
1920                 case VDEV_AUX_NO_REPLICAS:
1921                         (void) printf(gettext("insufficient replicas"));
1922                         break;
1923 
1924                 case VDEV_AUX_VERSION_NEWER:
1925                         (void) printf(gettext("newer version"));
1926                         break;
1927 
1928                 case VDEV_AUX_UNSUP_FEAT:
1929                         (void) printf(gettext("unsupported feature(s)"));
1930                         break;
1931 
1932                 case VDEV_AUX_SPARED:
1933                         verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1934                             &spare_cb.cb_guid) == 0);
1935                         if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) {
1936                                 if (strcmp(zpool_get_name(spare_cb.cb_zhp),
1937                                     zpool_get_name(zhp)) == 0)
1938                                         (void) printf(gettext("currently in "
1939                                             "use"));
1940                                 else
1941                                         (void) printf(gettext("in use by "
1942                                             "pool '%s'"),
1943                                             zpool_get_name(spare_cb.cb_zhp));
1944                                 zpool_close(spare_cb.cb_zhp);
1945                         } else {
1946                                 (void) printf(gettext("currently in use"));
1947                         }
1948                         break;
1949 
1950                 case VDEV_AUX_ERR_EXCEEDED:
1951                         (void) printf(gettext("too many errors"));
1952                         break;
1953 
1954                 case VDEV_AUX_IO_FAILURE:
1955                         (void) printf(gettext("experienced I/O failures"));
1956                         break;
1957 
1958                 case VDEV_AUX_BAD_LOG:
1959                         (void) printf(gettext("bad intent log"));
1960                         break;
1961 
1962                 case VDEV_AUX_EXTERNAL:
1963                         (void) printf(gettext("external device fault"));
1964                         break;
1965 
1966                 case VDEV_AUX_SPLIT_POOL:
1967                         (void) printf(gettext("split into new pool"));
1968                         break;
1969 
1970                 case VDEV_AUX_ACTIVE:
1971                         (void) printf(gettext("currently in use"));
1972                         break;
1973 
1974                 case VDEV_AUX_CHILDREN_OFFLINE:
1975                         (void) printf(gettext("all children offline"));
1976                         break;
1977 
1978                 default:
1979                         (void) printf(gettext("corrupted data"));
1980                         break;
1981                 }
1982         }
1983 
1984         /* The root vdev has the scrub/resilver stats */
1985         root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
1986             ZPOOL_CONFIG_VDEV_TREE);
1987         (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS,
1988             (uint64_t **)&ps, &c);
1989 
1990         if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) {
1991                 if (vs->vs_scan_processed != 0) {
1992                         (void) printf(gettext("  (%s)"),
1993                             (ps->pss_func == POOL_SCAN_RESILVER) ?
1994                             "resilvering" : "repairing");
1995                 } else if (vs->vs_resilver_deferred) {
1996                         (void) printf(gettext("  (awaiting resilver)"));
1997                 }
1998         }
1999 
2000         /* Display vdev initialization and trim status for leaves */
2001         if (children == 0) {
2002                 print_status_initialize(vs, cb->cb_print_vdev_init);
2003                 print_status_trim(vs, cb->cb_print_vdev_trim);
2004         }
2005 
2006         (void) printf("\n");
2007 
2008         for (c = 0; c < children; c++) {
2009                 uint64_t islog = B_FALSE, ishole = B_FALSE;
2010 
2011                 /* Don't print logs or holes here */
2012                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2013                     &islog);
2014                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
2015                     &ishole);
2016                 if (islog || ishole)
2017                         continue;
2018                 /* Only print normal classes here */
2019                 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2020                         continue;
2021 
2022                 vname = zpool_vdev_name(g_zfs, zhp, child[c],
2023                     cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2024 
2025                 print_status_config(zhp, cb, vname, child[c], depth + 2,
2026                     isspare);
2027                 free(vname);
2028         }
2029 }
2030 
2031 /*
2032  * Print the configuration of an exported pool.  Iterate over all vdevs in the
2033  * pool, printing out the name and status for each one.
2034  */
2035 static void
2036 print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
2037     int depth)
2038 {
2039         nvlist_t **child;
2040         uint_t c, children;
2041         vdev_stat_t *vs;
2042         char *type, *vname;
2043 
2044         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
2045         if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
2046             strcmp(type, VDEV_TYPE_HOLE) == 0)
2047                 return;
2048 
2049         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2050             (uint64_t **)&vs, &c) == 0);
2051 
2052         (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name);
2053         (void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
2054 
2055         if (vs->vs_aux != 0) {
2056                 (void) printf("  ");
2057 
2058                 switch (vs->vs_aux) {
2059                 case VDEV_AUX_OPEN_FAILED:
2060                         (void) printf(gettext("cannot open"));
2061                         break;
2062 
2063                 case VDEV_AUX_BAD_GUID_SUM:
2064                         (void) printf(gettext("missing device"));
2065                         break;
2066 
2067                 case VDEV_AUX_NO_REPLICAS:
2068                         (void) printf(gettext("insufficient replicas"));
2069                         break;
2070 
2071                 case VDEV_AUX_VERSION_NEWER:
2072                         (void) printf(gettext("newer version"));
2073                         break;
2074 
2075                 case VDEV_AUX_UNSUP_FEAT:
2076                         (void) printf(gettext("unsupported feature(s)"));
2077                         break;
2078 
2079                 case VDEV_AUX_ERR_EXCEEDED:
2080                         (void) printf(gettext("too many errors"));
2081                         break;
2082 
2083                 case VDEV_AUX_ACTIVE:
2084                         (void) printf(gettext("currently in use"));
2085                         break;
2086 
2087                 case VDEV_AUX_CHILDREN_OFFLINE:
2088                         (void) printf(gettext("all children offline"));
2089                         break;
2090 
2091                 default:
2092                         (void) printf(gettext("corrupted data"));
2093                         break;
2094                 }
2095         }
2096         (void) printf("\n");
2097 
2098         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2099             &child, &children) != 0)
2100                 return;
2101 
2102         for (c = 0; c < children; c++) {
2103                 uint64_t is_log = B_FALSE;
2104 
2105                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2106                     &is_log);
2107                 if (is_log)
2108                         continue;
2109                 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2110                         continue;
2111 
2112                 vname = zpool_vdev_name(g_zfs, NULL, child[c],
2113                     cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2114                 print_import_config(cb, vname, child[c], depth + 2);
2115                 free(vname);
2116         }
2117 
2118         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2119             &child, &children) == 0) {
2120                 (void) printf(gettext("\tcache\n"));
2121                 for (c = 0; c < children; c++) {
2122                         vname = zpool_vdev_name(g_zfs, NULL, child[c],
2123                             cb->cb_name_flags);
2124                         (void) printf("\t  %s\n", vname);
2125                         free(vname);
2126                 }
2127         }
2128 
2129         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
2130             &child, &children) == 0) {
2131                 (void) printf(gettext("\tspares\n"));
2132                 for (c = 0; c < children; c++) {
2133                         vname = zpool_vdev_name(g_zfs, NULL, child[c],
2134                             cb->cb_name_flags);
2135                         (void) printf("\t  %s\n", vname);
2136                         free(vname);
2137                 }
2138         }
2139 }
2140 
2141 /*
2142  * Print specialized class vdevs.
2143  *
2144  * These are recorded as top level vdevs in the main pool child array
2145  * but with "is_log" set to 1 or an "alloc_bias" string. We use either
2146  * print_status_config() or print_import_config() to print the top level
2147  * class vdevs then any of their children (eg mirrored slogs) are printed
2148  * recursively - which works because only the top level vdev is marked.
2149  */
2150 static void
2151 print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
2152     const char *class)
2153 {
2154         uint_t c, children;
2155         nvlist_t **child;
2156         boolean_t printed = B_FALSE;
2157 
2158         assert(zhp != NULL || !cb->cb_verbose);
2159 
2160         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
2161             &children) != 0)
2162                 return;
2163 
2164         for (c = 0; c < children; c++) {
2165                 uint64_t is_log = B_FALSE;
2166                 char *bias = NULL;
2167                 char *type = NULL;
2168 
2169                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2170                     &is_log);
2171 
2172                 if (is_log) {
2173                         bias = VDEV_ALLOC_CLASS_LOGS;
2174                 } else {
2175                         (void) nvlist_lookup_string(child[c],
2176                             ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
2177                         (void) nvlist_lookup_string(child[c],
2178                             ZPOOL_CONFIG_TYPE, &type);
2179                 }
2180 
2181                 if (bias == NULL || strcmp(bias, class) != 0)
2182                         continue;
2183                 if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
2184                         continue;
2185 
2186                 if (!printed) {
2187                         (void) printf("\t%s\t\n", gettext(class));
2188                         printed = B_TRUE;
2189                 }
2190 
2191                 char *name = zpool_vdev_name(g_zfs, zhp, child[c],
2192                     cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2193                 if (cb->cb_print_status)
2194                         print_status_config(zhp, cb, name, child[c], 2,
2195                             B_FALSE);
2196                 else
2197                         print_import_config(cb, name, child[c], 2);
2198                 free(name);
2199         }
2200 }
2201 
2202 /*
2203  * Display the status for the given pool.
2204  */
2205 static void
2206 show_import(nvlist_t *config)
2207 {
2208         uint64_t pool_state;
2209         vdev_stat_t *vs;
2210         char *name;
2211         uint64_t guid;
2212         uint64_t hostid = 0;
2213         char *msgid;
2214         char *hostname = "unknown";
2215         nvlist_t *nvroot, *nvinfo;
2216         int reason;
2217         zpool_errata_t errata;
2218         const char *health;
2219         uint_t vsc;
2220         char *comment;
2221         status_cbdata_t cb = { 0 };
2222 
2223         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2224             &name) == 0);
2225         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2226             &guid) == 0);
2227         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2228             &pool_state) == 0);
2229         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2230             &nvroot) == 0);
2231 
2232         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
2233             (uint64_t **)&vs, &vsc) == 0);
2234         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2235 
2236         reason = zpool_import_status(config, &msgid, &errata);
2237 
2238         (void) printf(gettext("   pool: %s\n"), name);
2239         (void) printf(gettext("     id: %llu\n"), (u_longlong_t)guid);
2240         (void) printf(gettext("  state: %s"), health);
2241         if (pool_state == POOL_STATE_DESTROYED)
2242                 (void) printf(gettext(" (DESTROYED)"));
2243         (void) printf("\n");
2244 
2245         switch (reason) {
2246         case ZPOOL_STATUS_MISSING_DEV_R:
2247         case ZPOOL_STATUS_MISSING_DEV_NR:
2248         case ZPOOL_STATUS_BAD_GUID_SUM:
2249                 (void) printf(gettext(" status: One or more devices are "
2250                     "missing from the system.\n"));
2251                 break;
2252 
2253         case ZPOOL_STATUS_CORRUPT_LABEL_R:
2254         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2255                 (void) printf(gettext(" status: One or more devices contains "
2256                     "corrupted data.\n"));
2257                 break;
2258 
2259         case ZPOOL_STATUS_CORRUPT_DATA:
2260                 (void) printf(
2261                     gettext(" status: The pool data is corrupted.\n"));
2262                 break;
2263 
2264         case ZPOOL_STATUS_OFFLINE_DEV:
2265                 (void) printf(gettext(" status: One or more devices "
2266                     "are offlined.\n"));
2267                 break;
2268 
2269         case ZPOOL_STATUS_CORRUPT_POOL:
2270                 (void) printf(gettext(" status: The pool metadata is "
2271                     "corrupted.\n"));
2272                 break;
2273 
2274         case ZPOOL_STATUS_VERSION_OLDER:
2275                 (void) printf(gettext(" status: The pool is formatted using a "
2276                     "legacy on-disk version.\n"));
2277                 break;
2278 
2279         case ZPOOL_STATUS_VERSION_NEWER:
2280                 (void) printf(gettext(" status: The pool is formatted using an "
2281                     "incompatible version.\n"));
2282                 break;
2283 
2284         case ZPOOL_STATUS_FEAT_DISABLED:
2285                 (void) printf(gettext(" status: Some supported features are "
2286                     "not enabled on the pool.\n"));
2287                 break;
2288 
2289         case ZPOOL_STATUS_UNSUP_FEAT_READ:
2290                 (void) printf(gettext("status: The pool uses the following "
2291                     "feature(s) not supported on this system:\n"));
2292                 zpool_print_unsup_feat(config);
2293                 break;
2294 
2295         case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2296                 (void) printf(gettext("status: The pool can only be accessed "
2297                     "in read-only mode on this system. It\n\tcannot be "
2298                     "accessed in read-write mode because it uses the "
2299                     "following\n\tfeature(s) not supported on this system:\n"));
2300                 zpool_print_unsup_feat(config);
2301                 break;
2302 
2303         case ZPOOL_STATUS_HOSTID_ACTIVE:
2304                 (void) printf(gettext(" status: The pool is currently "
2305                     "imported by another system.\n"));
2306                 break;
2307 
2308         case ZPOOL_STATUS_HOSTID_REQUIRED:
2309                 (void) printf(gettext(" status: The pool has the "
2310                     "multihost property on.  It cannot\n\tbe safely imported "
2311                     "when the system hostid is not set.\n"));
2312                 break;
2313 
2314         case ZPOOL_STATUS_HOSTID_MISMATCH:
2315                 (void) printf(gettext(" status: The pool was last accessed by "
2316                     "another system.\n"));
2317                 break;
2318 
2319         case ZPOOL_STATUS_FAULTED_DEV_R:
2320         case ZPOOL_STATUS_FAULTED_DEV_NR:
2321                 (void) printf(gettext(" status: One or more devices are "
2322                     "faulted.\n"));
2323                 break;
2324 
2325         case ZPOOL_STATUS_BAD_LOG:
2326                 (void) printf(gettext(" status: An intent log record cannot be "
2327                     "read.\n"));
2328                 break;
2329 
2330         case ZPOOL_STATUS_RESILVERING:
2331                 (void) printf(gettext(" status: One or more devices were being "
2332                     "resilvered.\n"));
2333                 break;
2334 
2335         case ZPOOL_STATUS_ERRATA:
2336                 (void) printf(gettext(" status: Errata #%d detected.\n"),
2337                     errata);
2338                 break;
2339 
2340         default:
2341                 /*
2342                  * No other status can be seen when importing pools.
2343                  */
2344                 assert(reason == ZPOOL_STATUS_OK);
2345         }
2346 
2347         /*
2348          * Print out an action according to the overall state of the pool.
2349          */
2350         if (vs->vs_state == VDEV_STATE_HEALTHY) {
2351                 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
2352                     reason == ZPOOL_STATUS_FEAT_DISABLED) {
2353                         (void) printf(gettext(" action: The pool can be "
2354                             "imported using its name or numeric identifier, "
2355                             "though\n\tsome features will not be available "
2356                             "without an explicit 'zpool upgrade'.\n"));
2357                 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
2358                         (void) printf(gettext(" action: The pool can be "
2359                             "imported using its name or numeric "
2360                             "identifier and\n\tthe '-f' flag.\n"));
2361                 } else if (reason == ZPOOL_STATUS_ERRATA) {
2362                         switch (errata) {
2363                         case ZPOOL_ERRATA_NONE:
2364                                 break;
2365 
2366                         case ZPOOL_ERRATA_ZOL_2094_SCRUB:
2367                                 (void) printf(gettext(" action: The pool can "
2368                                     "be imported using its name or numeric "
2369                                     "identifier,\n\thowever there is a compat"
2370                                     "ibility issue which should be corrected"
2371                                     "\n\tby running 'zpool scrub'\n"));
2372                                 break;
2373 
2374                         case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
2375                                 (void) printf(gettext(" action: The pool can"
2376                                     "not be imported with this version of ZFS "
2377                                     "due to\n\tan active asynchronous destroy. "
2378                                     "Revert to an earlier version\n\tand "
2379                                     "allow the destroy to complete before "
2380                                     "updating.\n"));
2381                                 break;
2382 
2383                         case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
2384                                 (void) printf(gettext(" action: Existing "
2385                                     "encrypted datasets contain an on-disk "
2386                                     "incompatibility, which\n\tneeds to be "
2387                                     "corrected. Backup these datasets to new "
2388                                     "encrypted datasets\n\tand destroy the "
2389                                     "old ones.\n"));
2390                                 break;
2391                         case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
2392                                 (void) printf(gettext(" action: Any existing "
2393                                     "encrypted datasets contain an on-disk "
2394                                     "incompatibility which\n\tmay cause "
2395                                     "on-disk corruption with 'zfs recv' and "
2396                                     "which needs to be\n\tcorrected. Enable "
2397                                     "the bookmark_v2 feature and backup "
2398                                     "these datasets to new encrypted "
2399                                     "datasets and\n\tdestroy the old ones. "
2400                                     "If this pool does not contain any "
2401                                     "encrypted datasets, simply enable\n\t"
2402                                     "the bookmark_v2 feature.\n"));
2403                                 break;
2404                         default:
2405                                 /*
2406                                  * All errata must contain an action message.
2407                                  */
2408                                 assert(0);
2409                         }
2410                 } else {
2411                         (void) printf(gettext(" action: The pool can be "
2412                             "imported using its name or numeric "
2413                             "identifier.\n"));
2414                 }
2415         } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
2416                 (void) printf(gettext(" action: The pool can be imported "
2417                     "despite missing or damaged devices.  The\n\tfault "
2418                     "tolerance of the pool may be compromised if imported.\n"));
2419         } else {
2420                 switch (reason) {
2421                 case ZPOOL_STATUS_VERSION_NEWER:
2422                         (void) printf(gettext(" action: The pool cannot be "
2423                             "imported.  Access the pool on a system running "
2424                             "newer\n\tsoftware, or recreate the pool from "
2425                             "backup.\n"));
2426                         break;
2427                 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2428                         (void) printf(gettext("action: The pool cannot be "
2429                             "imported. Access the pool on a system that "
2430                             "supports\n\tthe required feature(s), or recreate "
2431                             "the pool from backup.\n"));
2432                         break;
2433                 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2434                         (void) printf(gettext("action: The pool cannot be "
2435                             "imported in read-write mode. Import the pool "
2436                             "with\n"
2437                             "\t\"-o readonly=on\", access the pool on a system "
2438                             "that supports the\n\trequired feature(s), or "
2439                             "recreate the pool from backup.\n"));
2440                         break;
2441                 case ZPOOL_STATUS_MISSING_DEV_R:
2442                 case ZPOOL_STATUS_MISSING_DEV_NR:
2443                 case ZPOOL_STATUS_BAD_GUID_SUM:
2444                         (void) printf(gettext(" action: The pool cannot be "
2445                             "imported. Attach the missing\n\tdevices and try "
2446                             "again.\n"));
2447                         break;
2448                 case ZPOOL_STATUS_HOSTID_ACTIVE:
2449                         VERIFY0(nvlist_lookup_nvlist(config,
2450                             ZPOOL_CONFIG_LOAD_INFO, &nvinfo));
2451 
2452                         if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2453                                 hostname = fnvlist_lookup_string(nvinfo,
2454                                     ZPOOL_CONFIG_MMP_HOSTNAME);
2455 
2456                         if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2457                                 hostid = fnvlist_lookup_uint64(nvinfo,
2458                                     ZPOOL_CONFIG_MMP_HOSTID);
2459 
2460                         (void) printf(gettext(" action: The pool must be "
2461                             "exported from %s (hostid=%lx)\n\tbefore it "
2462                             "can be safely imported.\n"), hostname,
2463                             (unsigned long) hostid);
2464                         break;
2465                 case ZPOOL_STATUS_HOSTID_REQUIRED:
2466                         (void) printf(gettext(" action: Check the SMF "
2467                             "svc:/system/hostid service.\n"));
2468                         break;
2469                 default:
2470                         (void) printf(gettext(" action: The pool cannot be "
2471                             "imported due to damaged devices or data.\n"));
2472                 }
2473         }
2474 
2475         /* Print the comment attached to the pool. */
2476         if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
2477                 (void) printf(gettext("comment: %s\n"), comment);
2478 
2479         /*
2480          * If the state is "closed" or "can't open", and the aux state
2481          * is "corrupt data":
2482          */
2483         if (((vs->vs_state == VDEV_STATE_CLOSED) ||
2484             (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
2485             (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
2486                 if (pool_state == POOL_STATE_DESTROYED)
2487                         (void) printf(gettext("\tThe pool was destroyed, "
2488                             "but can be imported using the '-Df' flags.\n"));
2489                 else if (pool_state != POOL_STATE_EXPORTED)
2490                         (void) printf(gettext("\tThe pool may be active on "
2491                             "another system, but can be imported using\n\t"
2492                             "the '-f' flag.\n"));
2493         }
2494 
2495         if (msgid != NULL)
2496                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
2497                     msgid);
2498 
2499         (void) printf(gettext(" config:\n\n"));
2500 
2501         cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name),
2502             VDEV_NAME_TYPE_ID);
2503         if (cb.cb_namewidth < 10)
2504                 cb.cb_namewidth = 10;
2505 
2506         print_import_config(&cb, name, nvroot, 0);
2507 
2508         print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP);
2509         print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
2510         print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS);
2511 
2512         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2513                 (void) printf(gettext("\n\tAdditional devices are known to "
2514                     "be part of this pool, though their\n\texact "
2515                     "configuration cannot be determined.\n"));
2516         }
2517 }
2518 
2519 static boolean_t
2520 zfs_force_import_required(nvlist_t *config)
2521 {
2522         uint64_t state;
2523         uint64_t hostid = 0;
2524         nvlist_t *nvinfo;
2525 
2526         state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE);
2527         (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
2528 
2529         if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
2530                 return (B_TRUE);
2531 
2532         nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2533         if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) {
2534                 mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo,
2535                     ZPOOL_CONFIG_MMP_STATE);
2536 
2537                 if (mmp_state != MMP_STATE_INACTIVE)
2538                         return (B_TRUE);
2539         }
2540 
2541         return (B_FALSE);
2542 }
2543 
2544 /*
2545  * Perform the import for the given configuration.  This passes the heavy
2546  * lifting off to zpool_import_props(), and then mounts the datasets contained
2547  * within the pool.
2548  */
2549 static int
2550 do_import(nvlist_t *config, const char *newname, const char *mntopts,
2551     nvlist_t *props, int flags)
2552 {
2553         int ret = 0;
2554         zpool_handle_t *zhp;
2555         char *name;
2556         uint64_t version;
2557 
2558         name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
2559         version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
2560 
2561         if (!SPA_VERSION_IS_SUPPORTED(version)) {
2562                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
2563                     "is formatted using an unsupported ZFS version\n"), name);
2564                 return (1);
2565         } else if (zfs_force_import_required(config) &&
2566             !(flags & ZFS_IMPORT_ANY_HOST)) {
2567                 mmp_state_t mmp_state = MMP_STATE_INACTIVE;
2568                 nvlist_t *nvinfo;
2569 
2570                 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2571                 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE))
2572                         mmp_state = fnvlist_lookup_uint64(nvinfo,
2573                             ZPOOL_CONFIG_MMP_STATE);
2574 
2575                 if (mmp_state == MMP_STATE_ACTIVE) {
2576                         char *hostname = "<unknown>";
2577                         uint64_t hostid = 0;
2578 
2579                         if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2580                                 hostname = fnvlist_lookup_string(nvinfo,
2581                                     ZPOOL_CONFIG_MMP_HOSTNAME);
2582 
2583                         if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2584                                 hostid = fnvlist_lookup_uint64(nvinfo,
2585                                     ZPOOL_CONFIG_MMP_HOSTID);
2586 
2587                         (void) fprintf(stderr, gettext("cannot import '%s': "
2588                             "pool is imported on %s (hostid: "
2589                             "0x%lx)\nExport the pool on the other system, "
2590                             "then run 'zpool import'.\n"),
2591                             name, hostname, (unsigned long) hostid);
2592                 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
2593                         (void) fprintf(stderr, gettext("Cannot import '%s': "
2594                             "pool has the multihost property on and the\n"
2595                             "system's hostid is not set.\n"), name);
2596                 } else {
2597                         char *hostname = "<unknown>";
2598                         uint64_t timestamp = 0;
2599                         uint64_t hostid = 0;
2600 
2601                         if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
2602                                 hostname = fnvlist_lookup_string(config,
2603                                     ZPOOL_CONFIG_HOSTNAME);
2604 
2605                         if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP))
2606                                 timestamp = fnvlist_lookup_uint64(config,
2607                                     ZPOOL_CONFIG_TIMESTAMP);
2608 
2609                         if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
2610                                 hostid = fnvlist_lookup_uint64(config,
2611                                     ZPOOL_CONFIG_HOSTID);
2612 
2613                         (void) fprintf(stderr, gettext("cannot import '%s': "
2614                             "pool was previously in use from another system.\n"
2615                             "Last accessed by %s (hostid=%lx) at %s"
2616                             "The pool can be imported, use 'zpool import -f' "
2617                             "to import the pool.\n"), name, hostname,
2618                             (unsigned long)hostid, ctime((time_t *)&timestamp));
2619 
2620                 }
2621 
2622                 return (1);
2623         }
2624 
2625         if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2626                 return (1);
2627 
2628         if (newname != NULL)
2629                 name = (char *)newname;
2630 
2631         if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2632                 return (1);
2633 
2634         /*
2635          * Loading keys is best effort. We don't want to return immediately
2636          * if it fails but we do want to give the error to the caller.
2637          */
2638         if (flags & ZFS_IMPORT_LOAD_KEYS) {
2639                 ret = zfs_crypto_attempt_load_keys(g_zfs, name);
2640                 if (ret != 0)
2641                         ret = 1;
2642         }
2643 
2644         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2645             !(flags & ZFS_IMPORT_ONLY) &&
2646             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2647                 zpool_close(zhp);
2648                 return (1);
2649         }
2650 
2651         zpool_close(zhp);
2652         return (ret);
2653 }
2654 
2655 typedef struct target_exists_args {
2656         const char      *poolname;
2657         uint64_t        poolguid;
2658 } target_exists_args_t;
2659 
2660 static int
2661 name_or_guid_exists(zpool_handle_t *zhp, void *data)
2662 {
2663         target_exists_args_t *args = data;
2664         nvlist_t *config = zpool_get_config(zhp, NULL);
2665         int found = 0;
2666 
2667         if (config == NULL)
2668                 return (0);
2669 
2670         if (args->poolname != NULL) {
2671                 char *pool_name;
2672 
2673                 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2674                     &pool_name) == 0);
2675                 if (strcmp(pool_name, args->poolname) == 0)
2676                         found = 1;
2677         } else {
2678                 uint64_t pool_guid;
2679 
2680                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2681                     &pool_guid) == 0);
2682                 if (pool_guid == args->poolguid)
2683                         found = 1;
2684         }
2685         zpool_close(zhp);
2686 
2687         return (found);
2688 }
2689 /*
2690  * zpool checkpoint <pool>
2691  *       checkpoint --discard <pool>
2692  *
2693  *      -d      Discard the checkpoint from a checkpointed
2694  *      --discard  pool.
2695  *
2696  * Checkpoints the specified pool, by taking a "snapshot" of its
2697  * current state. A pool can only have one checkpoint at a time.
2698  */
2699 int
2700 zpool_do_checkpoint(int argc, char **argv)
2701 {
2702         boolean_t discard;
2703         char *pool;
2704         zpool_handle_t *zhp;
2705         int c, err;
2706 
2707         struct option long_options[] = {
2708                 {"discard", no_argument, NULL, 'd'},
2709                 {0, 0, 0, 0}
2710         };
2711 
2712         discard = B_FALSE;
2713         while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) {
2714                 switch (c) {
2715                 case 'd':
2716                         discard = B_TRUE;
2717                         break;
2718                 case '?':
2719                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2720                             optopt);
2721                         usage(B_FALSE);
2722                 }
2723         }
2724 
2725         argc -= optind;
2726         argv += optind;
2727 
2728         if (argc < 1) {
2729                 (void) fprintf(stderr, gettext("missing pool argument\n"));
2730                 usage(B_FALSE);
2731         }
2732 
2733         if (argc > 1) {
2734                 (void) fprintf(stderr, gettext("too many arguments\n"));
2735                 usage(B_FALSE);
2736         }
2737 
2738         pool = argv[0];
2739 
2740         if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
2741                 /* As a special case, check for use of '/' in the name */
2742                 if (strchr(pool, '/') != NULL)
2743                         (void) fprintf(stderr, gettext("'zpool checkpoint' "
2744                             "doesn't work on datasets. To save the state "
2745                             "of a dataset from a specific point in time "
2746                             "please use 'zfs snapshot'\n"));
2747                 return (1);
2748         }
2749 
2750         if (discard)
2751                 err = (zpool_discard_checkpoint(zhp) != 0);
2752         else
2753                 err = (zpool_checkpoint(zhp) != 0);
2754 
2755         zpool_close(zhp);
2756 
2757         return (err);
2758 }
2759 
2760 #define CHECKPOINT_OPT  1024
2761 
2762 /*
2763  * zpool import [-d dir] [-D]
2764  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
2765  *              [-d dir | -c cachefile] [-f] -a
2766  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
2767  *              [-d dir | -c cachefile] [-f] [-n] [-F] [-t]
2768  *              <pool | id> [newpool]
2769  *
2770  *      -c      Read pool information from a cachefile instead of searching
2771  *              devices.
2772  *
2773  *      -d      Scan in a specific directory, other than /dev/dsk.  More than
2774  *              one directory can be specified using multiple '-d' options.
2775  *
2776  *      -D      Scan for previously destroyed pools or import all or only
2777  *              specified destroyed pools.
2778  *
2779  *      -R      Temporarily import the pool, with all mountpoints relative to
2780  *              the given root.  The pool will remain exported when the machine
2781  *              is rebooted.
2782  *
2783  *      -V      Import even in the presence of faulted vdevs.  This is an
2784  *              intentionally undocumented option for testing purposes, and
2785  *              treats the pool configuration as complete, leaving any bad
2786  *              vdevs in the FAULTED state. In other words, it does verbatim
2787  *              import.
2788  *
2789  *      -f      Force import, even if it appears that the pool is active.
2790  *
2791  *      -F      Attempt rewind if necessary.
2792  *
2793  *      -n      See if rewind would work, but don't actually rewind.
2794  *
2795  *      -N      Import the pool but don't mount datasets.
2796  *
2797  *      -t      Use newpool as a temporary pool name instead of renaming
2798  *              the pool.
2799  *
2800  *      -T      Specify a starting txg to use for import. This option is
2801  *              intentionally undocumented option for testing purposes.
2802  *
2803  *      -a      Import all pools found.
2804  *
2805  *      -o      Set property=value and/or temporary mount options (without '=').
2806  *  -l  Load encryption keys while importing.
2807  *
2808  *      --rewind-to-checkpoint
2809  *              Import the pool and revert back to the checkpoint.
2810  *
2811  * The import command scans for pools to import, and import pools based on pool
2812  * name and GUID.  The pool can also be renamed as part of the import process.
2813  */
2814 int
2815 zpool_do_import(int argc, char **argv)
2816 {
2817         char **searchdirs = NULL;
2818         int nsearch = 0;
2819         int c;
2820         int err = 0;
2821         nvlist_t *pools = NULL;
2822         boolean_t do_all = B_FALSE;
2823         boolean_t do_destroyed = B_FALSE;
2824         char *mntopts = NULL;
2825         nvpair_t *elem;
2826         nvlist_t *config;
2827         uint64_t searchguid = 0;
2828         char *searchname = NULL;
2829         char *propval;
2830         nvlist_t *found_config;
2831         nvlist_t *policy = NULL;
2832         nvlist_t *props = NULL;
2833         boolean_t first;
2834         int flags = ZFS_IMPORT_NORMAL;
2835         uint32_t rewind_policy = ZPOOL_NO_REWIND;
2836         boolean_t dryrun = B_FALSE;
2837         boolean_t do_rewind = B_FALSE;
2838         boolean_t xtreme_rewind = B_FALSE;
2839         boolean_t pool_exists = B_FALSE;
2840         uint64_t pool_state, txg = -1ULL;
2841         char *cachefile = NULL;
2842         importargs_t idata = { 0 };
2843         char *endptr;
2844 
2845 
2846         struct option long_options[] = {
2847                 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
2848                 {0, 0, 0, 0}
2849         };
2850 
2851         /* check options */
2852         while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:rR:tT:VX",
2853             long_options, NULL)) != -1) {
2854                 switch (c) {
2855                 case 'a':
2856                         do_all = B_TRUE;
2857                         break;
2858                 case 'c':
2859                         cachefile = optarg;
2860                         break;
2861                 case 'd':
2862                         if (searchdirs == NULL) {
2863                                 searchdirs = safe_malloc(sizeof (char *));
2864                         } else {
2865                                 char **tmp = safe_malloc((nsearch + 1) *
2866                                     sizeof (char *));
2867                                 bcopy(searchdirs, tmp, nsearch *
2868                                     sizeof (char *));
2869                                 free(searchdirs);
2870                                 searchdirs = tmp;
2871                         }
2872                         searchdirs[nsearch++] = optarg;
2873                         break;
2874                 case 'D':
2875                         do_destroyed = B_TRUE;
2876                         break;
2877                 case 'f':
2878                         flags |= ZFS_IMPORT_ANY_HOST;
2879                         break;
2880                 case 'F':
2881                         do_rewind = B_TRUE;
2882                         break;
2883                 case 'l':
2884                         flags |= ZFS_IMPORT_LOAD_KEYS;
2885                         break;
2886                 case 'm':
2887                         flags |= ZFS_IMPORT_MISSING_LOG;
2888                         break;
2889                 case 'n':
2890                         dryrun = B_TRUE;
2891                         break;
2892                 case 'N':
2893                         flags |= ZFS_IMPORT_ONLY;
2894                         break;
2895                 case 'o':
2896                         if ((propval = strchr(optarg, '=')) != NULL) {
2897                                 *propval = '\0';
2898                                 propval++;
2899                                 if (add_prop_list(optarg, propval,
2900                                     &props, B_TRUE))
2901                                         goto error;
2902                         } else {
2903                                 mntopts = optarg;
2904                         }
2905                         break;
2906                 case 'R':
2907                         if (add_prop_list(zpool_prop_to_name(
2908                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2909                                 goto error;
2910                         if (add_prop_list_default(zpool_prop_to_name(
2911                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2912                                 goto error;
2913                         break;
2914                 case 't':
2915                         flags |= ZFS_IMPORT_TEMP_NAME;
2916                         if (add_prop_list_default(zpool_prop_to_name(
2917                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2918                                 goto error;
2919                         break;
2920                 case 'T':
2921                         errno = 0;
2922                         txg = strtoull(optarg, &endptr, 0);
2923                         if (errno != 0 || *endptr != '\0') {
2924                                 (void) fprintf(stderr,
2925                                     gettext("invalid txg value\n"));
2926                                 usage(B_FALSE);
2927                         }
2928                         rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2929                         break;
2930                 case 'V':
2931                         flags |= ZFS_IMPORT_VERBATIM;
2932                         break;
2933                 case 'X':
2934                         xtreme_rewind = B_TRUE;
2935                         break;
2936                 case CHECKPOINT_OPT:
2937                         flags |= ZFS_IMPORT_CHECKPOINT;
2938                         break;
2939                 case ':':
2940                         (void) fprintf(stderr, gettext("missing argument for "
2941                             "'%c' option\n"), optopt);
2942                         usage(B_FALSE);
2943                         break;
2944                 case '?':
2945                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2946                             optopt);
2947                         usage(B_FALSE);
2948                 }
2949         }
2950 
2951         argc -= optind;
2952         argv += optind;
2953 
2954         if (cachefile && nsearch != 0) {
2955                 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2956                 usage(B_FALSE);
2957         }
2958 
2959         if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) {
2960                 (void) fprintf(stderr, gettext("-l is incompatible with -N\n"));
2961                 usage(B_FALSE);
2962         }
2963 
2964         if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) {
2965                 (void) fprintf(stderr, gettext("-l is only meaningful during "
2966                     "an import\n"));
2967                 usage(B_FALSE);
2968         }
2969 
2970         if ((dryrun || xtreme_rewind) && !do_rewind) {
2971                 (void) fprintf(stderr,
2972                     gettext("-n or -X only meaningful with -F\n"));
2973                 usage(B_FALSE);
2974         }
2975         if (dryrun)
2976                 rewind_policy = ZPOOL_TRY_REWIND;
2977         else if (do_rewind)
2978                 rewind_policy = ZPOOL_DO_REWIND;
2979         if (xtreme_rewind)
2980                 rewind_policy |= ZPOOL_EXTREME_REWIND;
2981 
2982         /* In the future, we can capture further policy and include it here */
2983         if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2984             nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
2985             nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
2986             rewind_policy) != 0)
2987                 goto error;
2988 
2989         if (searchdirs == NULL) {
2990                 searchdirs = safe_malloc(sizeof (char *));
2991                 searchdirs[0] = ZFS_DISK_ROOT;
2992                 nsearch = 1;
2993         }
2994 
2995         /* check argument count */
2996         if (do_all) {
2997                 if (argc != 0) {
2998                         (void) fprintf(stderr, gettext("too many arguments\n"));
2999                         usage(B_FALSE);
3000                 }
3001         } else {
3002                 if (argc > 2) {
3003                         (void) fprintf(stderr, gettext("too many arguments\n"));
3004                         usage(B_FALSE);
3005                 }
3006 
3007                 /*
3008                  * Check for the SYS_CONFIG privilege.  We do this explicitly
3009                  * here because otherwise any attempt to discover pools will
3010                  * silently fail.
3011                  */
3012                 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
3013                         (void) fprintf(stderr, gettext("cannot "
3014                             "discover pools: permission denied\n"));
3015                         free(searchdirs);
3016                         nvlist_free(policy);
3017                         return (1);
3018                 }
3019         }
3020 
3021         /*
3022          * Depending on the arguments given, we do one of the following:
3023          *
3024          *      <none>    Iterate through all pools and display information about
3025          *              each one.
3026          *
3027          *      -a      Iterate through all pools and try to import each one.
3028          *
3029          *      <id>      Find the pool that corresponds to the given GUID/pool
3030          *              name and import that one.
3031          *
3032          *      -D      Above options applies only to destroyed pools.
3033          */
3034         if (argc != 0) {
3035                 char *endptr;
3036 
3037                 errno = 0;
3038                 searchguid = strtoull(argv[0], &endptr, 10);
3039                 if (errno != 0 || *endptr != '\0') {
3040                         searchname = argv[0];
3041                         searchguid = 0;
3042                 }
3043                 found_config = NULL;
3044 
3045                 /*
3046                  * User specified a name or guid.  Ensure it's unique.
3047                  */
3048                 target_exists_args_t search = {searchname, searchguid};
3049                 pool_exists = zpool_iter(g_zfs, name_or_guid_exists, &search);
3050         }
3051 
3052         idata.path = searchdirs;
3053         idata.paths = nsearch;
3054         idata.poolname = searchname;
3055         idata.guid = searchguid;
3056         idata.cachefile = cachefile;
3057         idata.policy = policy;
3058 
3059         pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
3060 
3061         if (pools != NULL && pool_exists &&
3062             (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
3063                 (void) fprintf(stderr, gettext("cannot import '%s': "
3064                     "a pool with that name already exists\n"),
3065                     argv[0]);
3066                 (void) fprintf(stderr, gettext("use the form 'zpool import "
3067                     "[-t] <pool | id> <newpool>' to give it a new temporary "
3068                     "or permanent name\n"));
3069                 err = 1;
3070         } else if (pools == NULL && pool_exists) {
3071                 (void) fprintf(stderr, gettext("cannot import '%s': "
3072                     "a pool with that name is already created/imported,\n"),
3073                     argv[0]);
3074                 (void) fprintf(stderr, gettext("and no additional pools "
3075                     "with that name were found\n"));
3076                 err = 1;
3077         } else if (pools == NULL) {
3078                 if (argc != 0) {
3079                         (void) fprintf(stderr, gettext("cannot import '%s': "
3080                             "no such pool available\n"), argv[0]);
3081                 }
3082                 err = 1;
3083         }
3084 
3085         if (err == 1) {
3086                 free(searchdirs);
3087                 nvlist_free(policy);
3088                 return (1);
3089         }
3090 
3091         /*
3092          * At this point we have a list of import candidate configs. Even if
3093          * we were searching by pool name or guid, we still need to
3094          * post-process the list to deal with pool state and possible
3095          * duplicate names.
3096          */
3097         err = 0;
3098         elem = NULL;
3099         first = B_TRUE;
3100         while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
3101 
3102                 verify(nvpair_value_nvlist(elem, &config) == 0);
3103 
3104                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
3105                     &pool_state) == 0);
3106                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
3107                         continue;
3108                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
3109                         continue;
3110 
3111                 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
3112                     policy) == 0);
3113 
3114                 if (argc == 0) {
3115                         if (first)
3116                                 first = B_FALSE;
3117                         else if (!do_all)
3118                                 (void) printf("\n");
3119 
3120                         if (do_all) {
3121                                 err |= do_import(config, NULL, mntopts,
3122                                     props, flags);
3123                         } else {
3124                                 show_import(config);
3125                         }
3126                 } else if (searchname != NULL) {
3127                         char *name;
3128 
3129                         /*
3130                          * We are searching for a pool based on name.
3131                          */
3132                         verify(nvlist_lookup_string(config,
3133                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
3134 
3135                         if (strcmp(name, searchname) == 0) {
3136                                 if (found_config != NULL) {
3137                                         (void) fprintf(stderr, gettext(
3138                                             "cannot import '%s': more than "
3139                                             "one matching pool\n"), searchname);
3140                                         (void) fprintf(stderr, gettext(
3141                                             "import by numeric ID instead\n"));
3142                                         err = B_TRUE;
3143                                 }
3144                                 found_config = config;
3145                         }
3146                 } else {
3147                         uint64_t guid;
3148 
3149                         /*
3150                          * Search for a pool by guid.
3151                          */
3152                         verify(nvlist_lookup_uint64(config,
3153                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
3154 
3155                         if (guid == searchguid)
3156                                 found_config = config;
3157                 }
3158         }
3159 
3160         /*
3161          * If we were searching for a specific pool, verify that we found a
3162          * pool, and then do the import.
3163          */
3164         if (argc != 0 && err == 0) {
3165                 if (found_config == NULL) {
3166                         (void) fprintf(stderr, gettext("cannot import '%s': "
3167                             "no such pool available\n"), argv[0]);
3168                         err = B_TRUE;
3169                 } else {
3170                         err |= do_import(found_config, argc == 1 ? NULL :
3171                             argv[1], mntopts, props, flags);
3172                 }
3173         }
3174 
3175         /*
3176          * If we were just looking for pools, report an error if none were
3177          * found.
3178          */
3179         if (argc == 0 && first)
3180                 (void) fprintf(stderr,
3181                     gettext("no pools available to import\n"));
3182 
3183 error:
3184         nvlist_free(props);
3185         nvlist_free(pools);
3186         nvlist_free(policy);
3187         free(searchdirs);
3188 
3189         return (err ? 1 : 0);
3190 }
3191 
3192 /*
3193  * zpool sync [-f] [pool] ...
3194  *
3195  * -f (undocumented) force uberblock (and config including zpool cache file)
3196  *    update.
3197  *
3198  * Sync the specified pool(s).
3199  * Without arguments "zpool sync" will sync all pools.
3200  * This command initiates TXG sync(s) and will return after the TXG(s) commit.
3201  *
3202  */
3203 static int
3204 zpool_do_sync(int argc, char **argv)
3205 {
3206         int ret;
3207         boolean_t force = B_FALSE;
3208 
3209         /* check options */
3210         while ((ret  = getopt(argc, argv, "f")) != -1) {
3211                 switch (ret) {
3212                 case 'f':
3213                         force = B_TRUE;
3214                         break;
3215                 case '?':
3216                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3217                             optopt);
3218                         usage(B_FALSE);
3219                 }
3220         }
3221 
3222         argc -= optind;
3223         argv += optind;
3224 
3225         /* if argc == 0 we will execute zpool_sync_one on all pools */
3226         ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force);
3227 
3228         return (ret);
3229 }
3230 
3231 typedef struct iostat_cbdata {
3232         uint64_t cb_flags;
3233         int cb_name_flags;
3234         int cb_namewidth;
3235         int cb_iteration;
3236         char **cb_vdev_names; /* Only show these vdevs */
3237         unsigned int cb_vdev_names_count;
3238         boolean_t cb_verbose;
3239         boolean_t cb_literal;
3240         boolean_t cb_scripted;
3241         zpool_list_t *cb_list;
3242 } iostat_cbdata_t;
3243 
3244 /*  iostat labels */
3245 typedef struct name_and_columns {
3246         const char *name;       /* Column name */
3247         unsigned int columns;   /* Center name to this number of columns */
3248 } name_and_columns_t;
3249 
3250 #define IOSTAT_MAX_LABELS       13      /* Max number of labels on one line */
3251 
3252 static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] =
3253 {
3254         [IOS_DEFAULT] = {{"capacity", 2}, {"operations", 2}, {"bandwidth", 2},
3255             {NULL}},
3256         [IOS_LATENCY] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3257             {"asyncq_wait", 2}, {"scrub"}, {"trim", 1}, {NULL}},
3258         [IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2},
3259             {"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2},
3260             {"trimq_write", 2}, {NULL}},
3261         [IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3262             {"asyncq_wait", 2}, {NULL}},
3263         [IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2},
3264             {"async_read", 2}, {"async_write", 2}, {"scrub", 2},
3265             {"trim", 2}, {NULL}},
3266 
3267 };
3268 
3269 /* Shorthand - if "columns" field not set, default to 1 column */
3270 static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] =
3271 {
3272         [IOS_DEFAULT] = {{"alloc"}, {"free"}, {"read"}, {"write"}, {"read"},
3273             {"write"}, {NULL}},
3274         [IOS_LATENCY] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
3275             {"write"}, {"read"}, {"write"}, {"wait"}, {"wait"}, {NULL}},
3276         [IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"},
3277             {"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"},
3278             {"pend"}, {"activ"}, {NULL}},
3279         [IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
3280             {"write"}, {"read"}, {"write"}, {"scrub"}, {"trim"}, {NULL}},
3281         [IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
3282             {"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"}, {NULL}},
3283 };
3284 
3285 static const char *histo_to_title[] = {
3286         [IOS_L_HISTO] = "latency",
3287         [IOS_RQ_HISTO] = "req_size",
3288 };
3289 
3290 /*
3291  * Return the number of labels in a null-terminated name_and_columns_t
3292  * array.
3293  *
3294  */
3295 static unsigned int
3296 label_array_len(const name_and_columns_t *labels)
3297 {
3298         int i = 0;
3299 
3300         while (labels[i].name)
3301                 i++;
3302 
3303         return (i);
3304 }
3305 
3306 /*
3307  * Return the number of strings in a null-terminated string array.
3308  * For example:
3309  *
3310  *     const char foo[] = {"bar", "baz", NULL}
3311  *
3312  * returns 2
3313  */
3314 static uint64_t
3315 str_array_len(const char *array[])
3316 {
3317         uint64_t i = 0;
3318         while (array[i])
3319                 i++;
3320 
3321         return (i);
3322 }
3323 
3324 
3325 /*
3326  * Return a default column width for default/latency/queue columns. This does
3327  * not include histograms, which have their columns autosized.
3328  */
3329 static unsigned int
3330 default_column_width(iostat_cbdata_t *cb, enum iostat_type type)
3331 {
3332         unsigned long column_width = 5; /* Normal niceprint */
3333         static unsigned long widths[] = {
3334                 /*
3335                  * Choose some sane default column sizes for printing the
3336                  * raw numbers.
3337                  */
3338                 [IOS_DEFAULT] = 15, /* 1PB capacity */
3339                 [IOS_LATENCY] = 10, /* 1B ns = 10sec */
3340                 [IOS_QUEUES] = 6,   /* 1M queue entries */
3341                 [IOS_L_HISTO] = 10, /* 1B ns = 10sec */
3342                 [IOS_RQ_HISTO] = 6, /* 1M queue entries */
3343         };
3344 
3345         if (cb->cb_literal)
3346                 column_width = widths[type];
3347 
3348         return (column_width);
3349 }
3350 
3351 /*
3352  * Print the column labels, i.e:
3353  *
3354  *   capacity     operations     bandwidth
3355  * alloc   free   read  write   read  write  ...
3356  *
3357  * If force_column_width is set, use it for the column width.  If not set, use
3358  * the default column width.
3359  */
3360 void
3361 print_iostat_labels(iostat_cbdata_t *cb, unsigned int force_column_width,
3362     const name_and_columns_t labels[][IOSTAT_MAX_LABELS])
3363 {
3364         int i, idx, s;
3365         int text_start, rw_column_width, spaces_to_end;
3366         uint64_t flags = cb->cb_flags;
3367         uint64_t f;
3368         unsigned int column_width = force_column_width;
3369 
3370         /* For each bit set in flags */
3371         for (f = flags; f; f &= ~(1ULL << idx)) {
3372                 idx = lowbit64(f) - 1;
3373                 if (!force_column_width)
3374                         column_width = default_column_width(cb, idx);
3375                 /* Print our top labels centered over "read  write" label. */
3376                 for (i = 0; i < label_array_len(labels[idx]); i++) {
3377                         const char *name = labels[idx][i].name;
3378                         /*
3379                          * We treat labels[][].columns == 0 as shorthand
3380                          * for one column.  It makes writing out the label
3381                          * tables more concise.
3382                          */
3383                         unsigned int columns = MAX(1, labels[idx][i].columns);
3384                         unsigned int slen = strlen(name);
3385 
3386                         rw_column_width = (column_width * columns) +
3387                             (2 * (columns - 1));
3388 
3389                         text_start = (int)((rw_column_width) / columns -
3390                             slen / columns);
3391                         if (text_start < 0)
3392                                 text_start = 0;
3393 
3394                         printf("  ");   /* Two spaces between columns */
3395 
3396                         /* Space from beginning of column to label */
3397                         for (s = 0; s < text_start; s++)
3398                                 printf(" ");
3399 
3400                         printf("%s", name);
3401 
3402                         /* Print space after label to end of column */
3403                         spaces_to_end = rw_column_width - text_start - slen;
3404                         if (spaces_to_end < 0)
3405                                 spaces_to_end = 0;
3406 
3407                         for (s = 0; s < spaces_to_end; s++)
3408                                 printf(" ");
3409                 }
3410         }
3411 }
3412 
3413 /*
3414  * Utility function to print out a line of dashes like:
3415  *
3416  *      --------------------------------  -----  -----  -----  -----  -----
3417  *
3418  * ...or a dashed named-row line like:
3419  *
3420  *      logs                                  -      -      -      -      -
3421  *
3422  * @cb:                         iostat data
3423  *
3424  * @force_column_width          If non-zero, use the value as the column width.
3425  *                              Otherwise use the default column widths.
3426  *
3427  * @name:                       Print a dashed named-row line starting
3428  *                              with @name.  Otherwise, print a regular
3429  *                              dashed line.
3430  */
3431 static void
3432 print_iostat_dashes(iostat_cbdata_t *cb, unsigned int force_column_width,
3433     const char *name)
3434 {
3435         int i;
3436         unsigned int namewidth;
3437         uint64_t flags = cb->cb_flags;
3438         uint64_t f;
3439         int idx;
3440         const name_and_columns_t *labels;
3441         const char *title;
3442 
3443 
3444         if (cb->cb_flags & IOS_ANYHISTO_M) {
3445                 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
3446         } else if (cb->cb_vdev_names_count) {
3447                 title = "vdev";
3448         } else  {
3449                 title = "pool";
3450         }
3451 
3452         namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
3453             name ? strlen(name) : 0);
3454 
3455 
3456         if (name) {
3457                 printf("%-*s", namewidth, name);
3458         } else {
3459                 for (i = 0; i < namewidth; i++)
3460                         (void) printf("-");
3461         }
3462 
3463         /* For each bit in flags */
3464         for (f = flags; f; f &= ~(1ULL << idx)) {
3465                 unsigned int column_width;
3466                 idx = lowbit64(f) - 1;
3467                 if (force_column_width)
3468                         column_width = force_column_width;
3469                 else
3470                         column_width = default_column_width(cb, idx);
3471 
3472                 labels = iostat_bottom_labels[idx];
3473                 for (i = 0; i < label_array_len(labels); i++) {
3474                         if (name)
3475                                 printf("  %*s-", column_width - 1, " ");
3476                         else
3477                                 printf("  %.*s", column_width,
3478                                     "--------------------");
3479                 }
3480         }
3481 }
3482 
3483 
3484 static void
3485 print_iostat_separator_impl(iostat_cbdata_t *cb,
3486     unsigned int force_column_width)
3487 {
3488         print_iostat_dashes(cb, force_column_width, NULL);
3489 }
3490 
3491 static void
3492 print_iostat_separator(iostat_cbdata_t *cb)
3493 {
3494         print_iostat_separator_impl(cb, 0);
3495 }
3496 
3497 static void
3498 print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
3499     const char *histo_vdev_name)
3500 {
3501         unsigned int namewidth;
3502         const char *title;
3503 
3504         if (cb->cb_flags & IOS_ANYHISTO_M) {
3505                 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
3506         } else if (cb->cb_vdev_names_count) {
3507                 title = "vdev";
3508         } else  {
3509                 title = "pool";
3510         }
3511 
3512         namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
3513             histo_vdev_name ? strlen(histo_vdev_name) : 0);
3514 
3515         if (histo_vdev_name)
3516                 printf("%-*s", namewidth, histo_vdev_name);
3517         else
3518                 printf("%*s", namewidth, "");
3519 
3520 
3521         print_iostat_labels(cb, force_column_width, iostat_top_labels);
3522         printf("\n");
3523 
3524         printf("%-*s", namewidth, title);
3525 
3526         print_iostat_labels(cb, force_column_width, iostat_bottom_labels);
3527 
3528         printf("\n");
3529 
3530         print_iostat_separator_impl(cb, force_column_width);
3531 
3532         printf("\n");
3533 }
3534 
3535 static void
3536 print_iostat_header(iostat_cbdata_t *cb)
3537 {
3538         print_iostat_header_impl(cb, 0, NULL);
3539 }
3540 
3541 /*
3542  * Display a single statistic.
3543  */
3544 static void
3545 print_one_stat(uint64_t value, enum zfs_nicenum_format format,
3546     unsigned int column_size, boolean_t scripted)
3547 {
3548         char buf[64];
3549 
3550         zfs_nicenum_format(value, buf, sizeof (buf), format);
3551 
3552         if (scripted)
3553                 printf("\t%s", buf);
3554         else
3555                 printf("  %*s", column_size, buf);
3556 }
3557 
3558 /*
3559  * Calculate the default vdev stats
3560  *
3561  * Subtract oldvs from newvs, apply a scaling factor, and save the resulting
3562  * stats into calcvs.
3563  */
3564 static void
3565 calc_default_iostats(vdev_stat_t *oldvs, vdev_stat_t *newvs,
3566     vdev_stat_t *calcvs)
3567 {
3568         int i;
3569 
3570         memcpy(calcvs, newvs, sizeof (*calcvs));
3571         for (i = 0; i < ARRAY_SIZE(calcvs->vs_ops); i++)
3572                 calcvs->vs_ops[i] = (newvs->vs_ops[i] - oldvs->vs_ops[i]);
3573 
3574         for (i = 0; i < ARRAY_SIZE(calcvs->vs_bytes); i++)
3575                 calcvs->vs_bytes[i] = (newvs->vs_bytes[i] - oldvs->vs_bytes[i]);
3576 }
3577 
3578 /*
3579  * Internal representation of the extended iostats data.
3580  *
3581  * The extended iostat stats are exported in nvlists as either uint64_t arrays
3582  * or single uint64_t's.  We make both look like arrays to make them easier
3583  * to process.  In order to make single uint64_t's look like arrays, we set
3584  * __data to the stat data, and then set *data = &__data with count = 1.  Then,
3585  * we can just use *data and count.
3586  */
3587 struct stat_array {
3588         uint64_t *data;
3589         uint_t count;   /* Number of entries in data[] */
3590         uint64_t __data; /* Only used when data is a single uint64_t */
3591 };
3592 
3593 static uint64_t
3594 stat_histo_max(struct stat_array *nva, unsigned int len)
3595 {
3596         uint64_t max = 0;
3597         int i;
3598         for (i = 0; i < len; i++)
3599                 max = MAX(max, array64_max(nva[i].data, nva[i].count));
3600 
3601         return (max);
3602 }
3603 
3604 /*
3605  * Helper function to lookup a uint64_t array or uint64_t value and store its
3606  * data as a stat_array.  If the nvpair is a single uint64_t value, then we make
3607  * it look like a one element array to make it easier to process.
3608  */
3609 static int
3610 nvpair64_to_stat_array(nvlist_t *nvl, const char *name,
3611     struct stat_array *nva)
3612 {
3613         nvpair_t *tmp;
3614         int ret;
3615 
3616         verify(nvlist_lookup_nvpair(nvl, name, &tmp) == 0);
3617         switch (nvpair_type(tmp)) {
3618         case DATA_TYPE_UINT64_ARRAY:
3619                 ret = nvpair_value_uint64_array(tmp, &nva->data, &nva->count);
3620                 break;
3621         case DATA_TYPE_UINT64:
3622                 ret = nvpair_value_uint64(tmp, &nva->__data);
3623                 nva->data = &nva->__data;
3624                 nva->count = 1;
3625                 break;
3626         default:
3627                 /* Not a uint64_t */
3628                 ret = EINVAL;
3629                 break;
3630         }
3631 
3632         return (ret);
3633 }
3634 
3635 /*
3636  * Given a list of nvlist names, look up the extended stats in newnv and oldnv,
3637  * subtract them, and return the results in a newly allocated stat_array.
3638  * You must free the returned array after you are done with it with
3639  * free_calc_stats().
3640  *
3641  * Additionally, you can set "oldnv" to NULL if you simply want the newnv
3642  * values.
3643  */
3644 static struct stat_array *
3645 calc_and_alloc_stats_ex(const char **names, unsigned int len, nvlist_t *oldnv,
3646     nvlist_t *newnv)
3647 {
3648         nvlist_t *oldnvx = NULL, *newnvx;
3649         struct stat_array *oldnva, *newnva, *calcnva;
3650         int i, j;
3651         unsigned int alloc_size = (sizeof (struct stat_array)) * len;
3652 
3653         /* Extract our extended stats nvlist from the main list */
3654         verify(nvlist_lookup_nvlist(newnv, ZPOOL_CONFIG_VDEV_STATS_EX,
3655             &newnvx) == 0);
3656         if (oldnv) {
3657                 verify(nvlist_lookup_nvlist(oldnv, ZPOOL_CONFIG_VDEV_STATS_EX,
3658                     &oldnvx) == 0);
3659         }
3660 
3661         newnva = safe_malloc(alloc_size);
3662         oldnva = safe_malloc(alloc_size);
3663         calcnva = safe_malloc(alloc_size);
3664 
3665         for (j = 0; j < len; j++) {
3666                 verify(nvpair64_to_stat_array(newnvx, names[j],
3667                     &newnva[j]) == 0);
3668                 calcnva[j].count = newnva[j].count;
3669                 alloc_size = calcnva[j].count * sizeof (calcnva[j].data[0]);
3670                 calcnva[j].data = safe_malloc(alloc_size);
3671                 memcpy(calcnva[j].data, newnva[j].data, alloc_size);
3672 
3673                 if (oldnvx) {
3674                         verify(nvpair64_to_stat_array(oldnvx, names[j],
3675                             &oldnva[j]) == 0);
3676                         for (i = 0; i < oldnva[j].count; i++)
3677                                 calcnva[j].data[i] -= oldnva[j].data[i];
3678                 }
3679         }
3680         free(newnva);
3681         free(oldnva);
3682         return (calcnva);
3683 }
3684 
3685 static void
3686 free_calc_stats(struct stat_array *nva, unsigned int len)
3687 {
3688         int i;
3689         for (i = 0; i < len; i++)
3690                 free(nva[i].data);
3691 
3692         free(nva);
3693 }
3694 
3695 static void
3696 print_iostat_histo(struct stat_array *nva, unsigned int len,
3697     iostat_cbdata_t *cb, unsigned int column_width, unsigned int namewidth,
3698     double scale)
3699 {
3700         int i, j;
3701         char buf[6];
3702         uint64_t val;
3703         enum zfs_nicenum_format format;
3704         unsigned int buckets;
3705         unsigned int start_bucket;
3706 
3707         if (cb->cb_literal)
3708                 format = ZFS_NICENUM_RAW;
3709         else
3710                 format = ZFS_NICENUM_1024;
3711 
3712         /* All these histos are the same size, so just use nva[0].count */
3713         buckets = nva[0].count;
3714 
3715         if (cb->cb_flags & IOS_RQ_HISTO_M) {
3716                 /* Start at 512 - req size should never be lower than this */
3717                 start_bucket = 9;
3718         } else {
3719                 start_bucket = 0;
3720         }
3721 
3722         for (j = start_bucket; j < buckets; j++) {
3723                 /* Print histogram bucket label */
3724                 if (cb->cb_flags & IOS_L_HISTO_M) {
3725                         /* Ending range of this bucket */
3726                         val = (1ULL << (j + 1)) - 1;
3727                         zfs_nicetime(val, buf, sizeof (buf));
3728                 } else {
3729                         /* Request size (starting range of bucket) */
3730                         val = (1UL << j);
3731                         zfs_nicenum(val, buf, sizeof (buf));
3732                 }
3733 
3734                 if (cb->cb_scripted)
3735                         printf("%llu", (u_longlong_t)val);
3736                 else
3737                         printf("%-*s", namewidth, buf);
3738 
3739                 /* Print the values on the line */
3740                 for (i = 0; i < len; i++) {
3741                         print_one_stat(nva[i].data[j] * scale, format,
3742                             column_width, cb->cb_scripted);
3743                 }
3744                 printf("\n");
3745         }
3746 }
3747 
3748 static void
3749 print_solid_separator(unsigned int length)
3750 {
3751         while (length--)
3752                 printf("-");
3753         printf("\n");
3754 }
3755 
3756 static void
3757 print_iostat_histos(iostat_cbdata_t *cb, nvlist_t *oldnv,
3758     nvlist_t *newnv, double scale, const char *name)
3759 {
3760         unsigned int column_width;
3761         unsigned int namewidth;
3762         unsigned int entire_width;
3763         enum iostat_type type;
3764         struct stat_array *nva;
3765         const char **names;
3766         unsigned int names_len;
3767 
3768         /* What type of histo are we? */
3769         type = IOS_HISTO_IDX(cb->cb_flags);
3770 
3771         /* Get NULL-terminated array of nvlist names for our histo */
3772         names = vsx_type_to_nvlist[type];
3773         names_len = str_array_len(names); /* num of names */
3774 
3775         nva = calc_and_alloc_stats_ex(names, names_len, oldnv, newnv);
3776 
3777         if (cb->cb_literal) {
3778                 column_width = MAX(5,
3779                     (unsigned int) log10(stat_histo_max(nva, names_len)) + 1);
3780         } else {
3781                 column_width = 5;
3782         }
3783 
3784         namewidth = MAX(cb->cb_namewidth,
3785             strlen(histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]));
3786 
3787         /*
3788          * Calculate the entire line width of what we're printing.  The
3789          * +2 is for the two spaces between columns:
3790          */
3791         /*       read  write                            */
3792         /*      -----  -----                            */
3793         /*      |___|  <---------- column_width              */
3794         /*                                              */
3795         /*      |__________|  <--- entire_width              */
3796         /*                                              */
3797         entire_width = namewidth + (column_width + 2) *
3798             label_array_len(iostat_bottom_labels[type]);
3799 
3800         if (cb->cb_scripted)
3801                 printf("%s\n", name);
3802         else
3803                 print_iostat_header_impl(cb, column_width, name);
3804 
3805         print_iostat_histo(nva, names_len, cb, column_width,
3806             namewidth, scale);
3807 
3808         free_calc_stats(nva, names_len);
3809         if (!cb->cb_scripted)
3810                 print_solid_separator(entire_width);
3811 }
3812 
3813 /*
3814  * Calculate the average latency of a power-of-two latency histogram
3815  */
3816 static uint64_t
3817 single_histo_average(uint64_t *histo, unsigned int buckets)
3818 {
3819         int i;
3820         uint64_t count = 0, total = 0;
3821 
3822         for (i = 0; i < buckets; i++) {
3823                 /*
3824                  * Our buckets are power-of-two latency ranges.  Use the
3825                  * midpoint latency of each bucket to calculate the average.
3826                  * For example:
3827                  *
3828                  * Bucket       Midpoint
3829                  * 8ns-15ns:    12ns
3830                  * 16ns-31ns:   24ns
3831                  * ...
3832                  */
3833                 if (histo[i] != 0) {
3834                         total += histo[i] * (((1UL << i) + ((1UL << i)/2)));
3835                         count += histo[i];
3836                 }
3837         }
3838 
3839         /* Prevent divide by zero */
3840         return (count == 0 ? 0 : total / count);
3841 }
3842 
3843 static void
3844 print_iostat_queues(iostat_cbdata_t *cb, nvlist_t *oldnv,
3845     nvlist_t *newnv)
3846 {
3847         int i;
3848         uint64_t val;
3849         const char *names[] = {
3850                 ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE,
3851                 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
3852                 ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE,
3853                 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
3854                 ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE,
3855                 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
3856                 ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE,
3857                 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
3858                 ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE,
3859                 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
3860                 ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE,
3861                 ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
3862         };
3863 
3864         struct stat_array *nva;
3865 
3866         unsigned int column_width = default_column_width(cb, IOS_QUEUES);
3867         enum zfs_nicenum_format format;
3868 
3869         nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), NULL, newnv);
3870 
3871         if (cb->cb_literal)
3872                 format = ZFS_NICENUM_RAW;
3873         else
3874                 format = ZFS_NICENUM_1024;
3875 
3876         for (i = 0; i < ARRAY_SIZE(names); i++) {
3877                 val = nva[i].data[0];
3878                 print_one_stat(val, format, column_width, cb->cb_scripted);
3879         }
3880 
3881         free_calc_stats(nva, ARRAY_SIZE(names));
3882 }
3883 
3884 static void
3885 print_iostat_latency(iostat_cbdata_t *cb, nvlist_t *oldnv,
3886     nvlist_t *newnv)
3887 {
3888         int i;
3889         uint64_t val;
3890         const char *names[] = {
3891                 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
3892                 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
3893                 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
3894                 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
3895                 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
3896                 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
3897                 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
3898                 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
3899                 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
3900                 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
3901         };
3902         struct stat_array *nva;
3903 
3904         unsigned int column_width = default_column_width(cb, IOS_LATENCY);
3905         enum zfs_nicenum_format format;
3906 
3907         nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), oldnv, newnv);
3908 
3909         if (cb->cb_literal)
3910                 format = ZFS_NICENUM_RAWTIME;
3911         else
3912                 format = ZFS_NICENUM_TIME;
3913 
3914         /* Print our avg latencies on the line */
3915         for (i = 0; i < ARRAY_SIZE(names); i++) {
3916                 /* Compute average latency for a latency histo */
3917                 val = single_histo_average(nva[i].data, nva[i].count);
3918                 print_one_stat(val, format, column_width, cb->cb_scripted);
3919         }
3920         free_calc_stats(nva, ARRAY_SIZE(names));
3921 }
3922 
3923 /*
3924  * Print default statistics (capacity/operations/bandwidth)
3925  */
3926 static void
3927 print_iostat_default(vdev_stat_t *vs, iostat_cbdata_t *cb, double scale)
3928 {
3929         unsigned int column_width = default_column_width(cb, IOS_DEFAULT);
3930         enum zfs_nicenum_format format;
3931         char na;        /* char to print for "not applicable" values */
3932 
3933         if (cb->cb_literal) {
3934                 format = ZFS_NICENUM_RAW;
3935                 na = '0';
3936         } else {
3937                 format = ZFS_NICENUM_1024;
3938                 na = '-';
3939         }
3940 
3941         /* only toplevel vdevs have capacity stats */
3942         if (vs->vs_space == 0) {
3943                 if (cb->cb_scripted)
3944                         printf("\t%c\t%c", na, na);
3945                 else
3946                         printf("  %*c  %*c", column_width, na, column_width,
3947                             na);
3948         } else {
3949                 print_one_stat(vs->vs_alloc, format, column_width,
3950                     cb->cb_scripted);
3951                 print_one_stat(vs->vs_space - vs->vs_alloc, format,
3952                     column_width, cb->cb_scripted);
3953         }
3954 
3955         print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_READ] * scale),
3956             format, column_width, cb->cb_scripted);
3957         print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_WRITE] * scale),
3958             format, column_width, cb->cb_scripted);
3959         print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_READ] * scale),
3960             format, column_width, cb->cb_scripted);
3961         print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_WRITE] * scale),
3962             format, column_width, cb->cb_scripted);
3963 }
3964 
3965 static const char *class_name[] = {
3966         VDEV_ALLOC_BIAS_DEDUP,
3967         VDEV_ALLOC_BIAS_SPECIAL,
3968         VDEV_ALLOC_CLASS_LOGS
3969 };
3970 
3971 /*
3972  * Print out all the statistics for the given vdev.  This can either be the
3973  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
3974  * is a verbose output, and we don't want to display the toplevel pool stats.
3975  *
3976  * Returns the number of stat lines printed.
3977  */
3978 unsigned int
3979 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
3980     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
3981 {
3982         nvlist_t **oldchild, **newchild;
3983         uint_t c, children, oldchildren;
3984         vdev_stat_t *oldvs, *newvs, *calcvs;
3985         vdev_stat_t zerovs = { 0 };
3986         char *vname;
3987         int i;
3988         int ret = 0;
3989         uint64_t tdelta;
3990         double scale;
3991 
3992         if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3993                 return (0);
3994 
3995         calcvs = safe_malloc(sizeof (*calcvs));
3996 
3997         if (oldnv != NULL) {
3998                 verify(nvlist_lookup_uint64_array(oldnv,
3999                     ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
4000         } else {
4001                 oldvs = &zerovs;
4002         }
4003 
4004         /* Do we only want to see a specific vdev? */
4005         for (i = 0; i < cb->cb_vdev_names_count; i++) {
4006                 /* Yes we do.  Is this the vdev? */
4007                 if (strcmp(name, cb->cb_vdev_names[i]) == 0) {
4008                         /*
4009                          * This is our vdev.  Since it is the only vdev we
4010                          * will be displaying, make depth = 0 so that it
4011                          * doesn't get indented.
4012                          */
4013                         depth = 0;
4014                         break;
4015                 }
4016         }
4017 
4018         if (cb->cb_vdev_names_count && (i == cb->cb_vdev_names_count)) {
4019                 /* Couldn't match the name */
4020                 goto children;
4021         }
4022 
4023 
4024         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
4025             (uint64_t **)&newvs, &c) == 0);
4026 
4027         /*
4028          * Print the vdev name unless it's is a histogram.  Histograms
4029          * display the vdev name in the header itself.
4030          */
4031         if (!(cb->cb_flags & IOS_ANYHISTO_M)) {
4032                 if (cb->cb_scripted) {
4033                         printf("%s", name);
4034                 } else {
4035                         if (strlen(name) + depth > cb->cb_namewidth)
4036                                 (void) printf("%*s%s", depth, "", name);
4037                         else
4038                                 (void) printf("%*s%s%*s", depth, "", name,
4039                                     (int)(cb->cb_namewidth - strlen(name) -
4040                                     depth), "");
4041                 }
4042         }
4043 
4044         /* Calculate our scaling factor */
4045         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
4046         if ((oldvs->vs_timestamp == 0) && (cb->cb_flags & IOS_ANYHISTO_M)) {
4047                 /*
4048                  * If we specify printing histograms with no time interval, then
4049                  * print the histogram numbers over the entire lifetime of the
4050                  * vdev.
4051                  */
4052                 scale = 1;
4053         } else {
4054                 if (tdelta == 0)
4055                         scale = 1.0;
4056                 else
4057                         scale = (double)NANOSEC / tdelta;
4058         }
4059 
4060         if (cb->cb_flags & IOS_DEFAULT_M) {
4061                 calc_default_iostats(oldvs, newvs, calcvs);
4062                 print_iostat_default(calcvs, cb, scale);
4063         }
4064         if (cb->cb_flags & IOS_LATENCY_M)
4065                 print_iostat_latency(cb, oldnv, newnv);
4066         if (cb->cb_flags & IOS_QUEUES_M)
4067                 print_iostat_queues(cb, oldnv, newnv);
4068         if (cb->cb_flags & IOS_ANYHISTO_M) {
4069                 printf("\n");
4070                 print_iostat_histos(cb, oldnv, newnv, scale, name);
4071         }
4072 
4073         if (!(cb->cb_flags & IOS_ANYHISTO_M))
4074                 printf("\n");
4075 
4076         ret++;
4077 
4078 children:
4079 
4080         free(calcvs);
4081 
4082         if (!cb->cb_verbose)
4083                 return (ret);
4084 
4085         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
4086             &newchild, &children) != 0)
4087                 return (ret);
4088 
4089         if (oldnv) {
4090                 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
4091                     &oldchild, &oldchildren) != 0)
4092                         return (ret);
4093 
4094                 children = MIN(oldchildren, children);
4095         }
4096 
4097         /*
4098          * print normal top-level devices
4099          */
4100         for (c = 0; c < children; c++) {
4101                 uint64_t ishole = B_FALSE, islog = B_FALSE;
4102 
4103                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
4104                     &ishole);
4105 
4106                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
4107                     &islog);
4108 
4109                 if (ishole || islog)
4110                         continue;
4111 
4112                 if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
4113                         continue;
4114 
4115                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4116                     cb->cb_name_flags);
4117                 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
4118                     newchild[c], cb, depth + 2);
4119                 free(vname);
4120         }
4121 
4122         /*
4123          * print all other top-level devices
4124          */
4125         for (uint_t n = 0; n < 3; n++) {
4126                 boolean_t printed = B_FALSE;
4127 
4128                 for (c = 0; c < children; c++) {
4129                         uint64_t islog = B_FALSE;
4130                         char *bias = NULL;
4131                         char *type = NULL;
4132 
4133                         (void) nvlist_lookup_uint64(newchild[c],
4134                             ZPOOL_CONFIG_IS_LOG, &islog);
4135                         if (islog) {
4136                                 bias = VDEV_ALLOC_CLASS_LOGS;
4137                         } else {
4138                                 (void) nvlist_lookup_string(newchild[c],
4139                                     ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
4140                                 (void) nvlist_lookup_string(newchild[c],
4141                                     ZPOOL_CONFIG_TYPE, &type);
4142                         }
4143                         if (bias == NULL || strcmp(bias, class_name[n]) != 0)
4144                                 continue;
4145                         if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
4146                                 continue;
4147 
4148                         if (!printed) {
4149                                 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) &&
4150                                     !cb->cb_scripted && !cb->cb_vdev_names) {
4151                                         print_iostat_dashes(cb, 0,
4152                                             class_name[n]);
4153                                 }
4154                                 printf("\n");
4155                                 printed = B_TRUE;
4156                         }
4157 
4158                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4159                             cb->cb_name_flags);
4160                         ret += print_vdev_stats(zhp, vname, oldnv ?
4161                             oldchild[c] : NULL, newchild[c], cb, depth + 2);
4162                         free(vname);
4163                 }
4164 
4165         }
4166 
4167         /*
4168          * Include level 2 ARC devices in iostat output
4169          */
4170         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
4171             &newchild, &children) != 0)
4172                 return (ret);
4173 
4174         if (oldnv) {
4175                 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
4176                     &oldchild, &oldchildren) != 0)
4177                         return (ret);
4178 
4179                 children = MIN(oldchildren, children);
4180         }
4181 
4182         if (children > 0) {
4183                 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && !cb->cb_scripted &&
4184                     !cb->cb_vdev_names) {
4185                         print_iostat_dashes(cb, 0, "cache");
4186                 }
4187                 printf("\n");
4188 
4189                 for (c = 0; c < children; c++) {
4190                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4191                             cb->cb_name_flags);
4192                         ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c]
4193                             : NULL, newchild[c], cb, depth + 2);
4194                         free(vname);
4195                 }
4196         }
4197 
4198         return (ret);
4199 }
4200 
4201 static int
4202 refresh_iostat(zpool_handle_t *zhp, void *data)
4203 {
4204         iostat_cbdata_t *cb = data;
4205         boolean_t missing;
4206 
4207         /*
4208          * If the pool has disappeared, remove it from the list and continue.
4209          */
4210         if (zpool_refresh_stats(zhp, &missing) != 0)
4211                 return (-1);
4212 
4213         if (missing)
4214                 pool_list_remove(cb->cb_list, zhp);
4215 
4216         return (0);
4217 }
4218 
4219 /*
4220  * Callback to print out the iostats for the given pool.
4221  */
4222 int
4223 print_iostat(zpool_handle_t *zhp, void *data)
4224 {
4225         iostat_cbdata_t *cb = data;
4226         nvlist_t *oldconfig, *newconfig;
4227         nvlist_t *oldnvroot, *newnvroot;
4228         int ret;
4229 
4230         newconfig = zpool_get_config(zhp, &oldconfig);
4231 
4232         if (cb->cb_iteration == 1)
4233                 oldconfig = NULL;
4234 
4235         verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
4236             &newnvroot) == 0);
4237 
4238         if (oldconfig == NULL)
4239                 oldnvroot = NULL;
4240         else
4241                 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
4242                     &oldnvroot) == 0);
4243 
4244         ret = print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot,
4245             cb, 0);
4246         if ((ret != 0) && !(cb->cb_flags & IOS_ANYHISTO_M) &&
4247             !cb->cb_scripted && cb->cb_verbose && !cb->cb_vdev_names_count) {
4248                 print_iostat_separator(cb);
4249                 printf("\n");
4250         }
4251 
4252         return (ret);
4253 }
4254 
4255 static int
4256 get_columns(void)
4257 {
4258         struct winsize ws;
4259         int columns = 80;
4260         int error;
4261 
4262         if (isatty(STDOUT_FILENO)) {
4263                 error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
4264                 if (error == 0)
4265                         columns = ws.ws_col;
4266         } else {
4267                 columns = 999;
4268         }
4269 
4270         return (columns);
4271 }
4272 
4273 /*
4274  * Return the required length of the pool/vdev name column.  The minimum
4275  * allowed width and output formatting flags must be provided.
4276  */
4277 static int
4278 get_namewidth(zpool_handle_t *zhp, int min_width, int flags, boolean_t verbose)
4279 {
4280         nvlist_t *config, *nvroot;
4281         int width = min_width;
4282 
4283         if ((config = zpool_get_config(zhp, NULL)) != NULL) {
4284                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4285                     &nvroot) == 0);
4286                 unsigned int poolname_len = strlen(zpool_get_name(zhp));
4287                 if (verbose == B_FALSE) {
4288                         width = MAX(poolname_len, min_width);
4289                 } else {
4290                         width = MAX(poolname_len,
4291                             max_width(zhp, nvroot, 0, min_width, flags));
4292                 }
4293         }
4294 
4295         return (width);
4296 }
4297 
4298 /*
4299  * Parse the input string, get the 'interval' and 'count' value if there is one.
4300  */
4301 static void
4302 get_interval_count(int *argcp, char **argv, float *iv,
4303     unsigned long *cnt)
4304 {
4305         float interval = 0;
4306         unsigned long count = 0;
4307         int argc = *argcp, errno;
4308 
4309         /*
4310          * Determine if the last argument is an integer or a pool name
4311          */
4312         if (argc > 0 && isnumber(argv[argc - 1])) {
4313                 char *end;
4314 
4315                 errno = 0;
4316                 interval = strtof(argv[argc - 1], &end);
4317 
4318                 if (*end == '\0' && errno == 0) {
4319                         if (interval == 0) {
4320                                 (void) fprintf(stderr, gettext("interval "
4321                                     "cannot be zero\n"));
4322                                 usage(B_FALSE);
4323                         }
4324                         /*
4325                          * Ignore the last parameter
4326                          */
4327                         argc--;
4328                 } else {
4329                         /*
4330                          * If this is not a valid number, just plow on.  The
4331                          * user will get a more informative error message later
4332                          * on.
4333                          */
4334                         interval = 0;
4335                 }
4336         }
4337 
4338         /*
4339          * If the last argument is also an integer, then we have both a count
4340          * and an interval.
4341          */
4342         if (argc > 0 && isnumber(argv[argc - 1])) {
4343                 char *end;
4344 
4345                 errno = 0;
4346                 count = interval;
4347                 interval = strtof(argv[argc - 1], &end);
4348 
4349                 if (*end == '\0' && errno == 0) {
4350                         if (interval == 0) {
4351                                 (void) fprintf(stderr, gettext("interval "
4352                                     "cannot be zero\n"));
4353                                 usage(B_FALSE);
4354                         }
4355 
4356                         /*
4357                          * Ignore the last parameter
4358                          */
4359                         argc--;
4360                 } else {
4361                         interval = 0;
4362                 }
4363         }
4364 
4365         *iv = interval;
4366         *cnt = count;
4367         *argcp = argc;
4368 }
4369 
4370 static void
4371 get_timestamp_arg(char c)
4372 {
4373         if (c == 'u')
4374                 timestamp_fmt = UDATE;
4375         else if (c == 'd')
4376                 timestamp_fmt = DDATE;
4377         else
4378                 usage(B_FALSE);
4379 }
4380 
4381 /*
4382  * Return stat flags that are supported by all pools by both the module and
4383  * zpool iostat.  "*data" should be initialized to all 0xFFs before running.
4384  * It will get ANDed down until only the flags that are supported on all pools
4385  * remain.
4386  */
4387 static int
4388 get_stat_flags_cb(zpool_handle_t *zhp, void *data)
4389 {
4390         uint64_t *mask = data;
4391         nvlist_t *config, *nvroot, *nvx;
4392         uint64_t flags = 0;
4393         int i, j;
4394 
4395         config = zpool_get_config(zhp, NULL);
4396         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4397             &nvroot) == 0);
4398 
4399         /* Default stats are always supported, but for completeness.. */
4400         if (nvlist_exists(nvroot, ZPOOL_CONFIG_VDEV_STATS))
4401                 flags |= IOS_DEFAULT_M;
4402 
4403         /* Get our extended stats nvlist from the main list */
4404         if (nvlist_lookup_nvlist(nvroot, ZPOOL_CONFIG_VDEV_STATS_EX,
4405             &nvx) != 0) {
4406                 /*
4407                  * No extended stats; they're probably running an older
4408                  * module.  No big deal, we support that too.
4409                  */
4410                 goto end;
4411         }
4412 
4413         /* For each extended stat, make sure all its nvpairs are supported */
4414         for (j = 0; j < ARRAY_SIZE(vsx_type_to_nvlist); j++) {
4415                 if (!vsx_type_to_nvlist[j][0])
4416                         continue;
4417 
4418                 /* Start off by assuming the flag is supported, then check */
4419                 flags |= (1ULL << j);
4420                 for (i = 0; vsx_type_to_nvlist[j][i]; i++) {
4421                         if (!nvlist_exists(nvx, vsx_type_to_nvlist[j][i])) {
4422                                 /* flag isn't supported */
4423                                 flags = flags & ~(1ULL  << j);
4424                                 break;
4425                         }
4426                 }
4427         }
4428 end:
4429         *mask = *mask & flags;
4430         return (0);
4431 }
4432 
4433 /*
4434  * Return a bitmask of stats that are supported on all pools by both the module
4435  * and zpool iostat.
4436  */
4437 static uint64_t
4438 get_stat_flags(zpool_list_t *list)
4439 {
4440         uint64_t mask = -1;
4441 
4442         /*
4443          * get_stat_flags_cb() will lop off bits from "mask" until only the
4444          * flags that are supported on all pools remain.
4445          */
4446         (void) pool_list_iter(list, B_FALSE, get_stat_flags_cb, &mask);
4447         return (mask);
4448 }
4449 
4450 /*
4451  * Return 1 if cb_data->cb_vdev_names[0] is this vdev's name, 0 otherwise.
4452  */
4453 static int
4454 is_vdev_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_data)
4455 {
4456         iostat_cbdata_t *cb = cb_data;
4457         char *name;
4458 
4459         name = zpool_vdev_name(g_zfs, zhp, nv, cb->cb_name_flags);
4460 
4461         if (strcmp(name, cb->cb_vdev_names[0]) == 0)
4462                 return (1); /* match */
4463 
4464         return (0);
4465 }
4466 
4467 /*
4468  * Returns 1 if cb_data->cb_vdev_names[0] is a vdev name, 0 otherwise.
4469  */
4470 static int
4471 is_vdev(zpool_handle_t *zhp, void *cb_data)
4472 {
4473         return (for_each_vdev(zhp, is_vdev_cb, cb_data));
4474 }
4475 
4476 /*
4477  * Check if vdevs are in a pool
4478  *
4479  * Return 1 if all argv[] strings are vdev names in pool "pool_name". Otherwise
4480  * return 0.  If pool_name is NULL, then search all pools.
4481  */
4482 static int
4483 are_vdevs_in_pool(int argc, char **argv, char *pool_name,
4484     iostat_cbdata_t *cb)
4485 {
4486         char **tmp_name;
4487         int ret = 0;
4488         int i;
4489         int pool_count = 0;
4490 
4491         if ((argc == 0) || !*argv)
4492                 return (0);
4493 
4494         if (pool_name)
4495                 pool_count = 1;
4496 
4497         /* Temporarily hijack cb_vdev_names for a second... */
4498         tmp_name = cb->cb_vdev_names;
4499 
4500         /* Go though our list of prospective vdev names */
4501         for (i = 0; i < argc; i++) {
4502                 cb->cb_vdev_names = argv + i;
4503 
4504                 /* Is this name a vdev in our pools? */
4505                 ret = for_each_pool(pool_count, &pool_name, B_TRUE, NULL,
4506                     is_vdev, cb);
4507                 if (!ret) {
4508                         /* No match */
4509                         break;
4510                 }
4511         }
4512 
4513         cb->cb_vdev_names = tmp_name;
4514 
4515         return (ret);
4516 }
4517 
4518 static int
4519 is_pool_cb(zpool_handle_t *zhp, void *data)
4520 {
4521         char *name = data;
4522         if (strcmp(name, zpool_get_name(zhp)) == 0)
4523                 return (1);
4524 
4525         return (0);
4526 }
4527 
4528 /*
4529  * Do we have a pool named *name?  If so, return 1, otherwise 0.
4530  */
4531 static int
4532 is_pool(char *name)
4533 {
4534         return (for_each_pool(0, NULL, B_TRUE, NULL,  is_pool_cb, name));
4535 }
4536 
4537 /* Are all our argv[] strings pool names?  If so return 1, 0 otherwise. */
4538 static int
4539 are_all_pools(int argc, char **argv)
4540 {
4541         if ((argc == 0) || !*argv)
4542                 return (0);
4543 
4544         while (--argc >= 0)
4545                 if (!is_pool(argv[argc]))
4546                         return (0);
4547 
4548         return (1);
4549 }
4550 
4551 /*
4552  * Helper function to print out vdev/pool names we can't resolve.  Used for an
4553  * error message.
4554  */
4555 static void
4556 error_list_unresolved_vdevs(int argc, char **argv, char *pool_name,
4557     iostat_cbdata_t *cb)
4558 {
4559         int i;
4560         char *name;
4561         char *str;
4562         for (i = 0; i < argc; i++) {
4563                 name = argv[i];
4564 
4565                 if (is_pool(name))
4566                         str = gettext("pool");
4567                 else if (are_vdevs_in_pool(1, &name, pool_name, cb))
4568                         str = gettext("vdev in this pool");
4569                 else if (are_vdevs_in_pool(1, &name, NULL, cb))
4570                         str = gettext("vdev in another pool");
4571                 else
4572                         str = gettext("unknown");
4573 
4574                 fprintf(stderr, "\t%s (%s)\n", name, str);
4575         }
4576 }
4577 
4578 /*
4579  * Same as get_interval_count(), but with additional checks to not misinterpret
4580  * guids as interval/count values.  Assumes VDEV_NAME_GUID is set in
4581  * cb.cb_name_flags.
4582  */
4583 static void
4584 get_interval_count_filter_guids(int *argc, char **argv, float *interval,
4585     unsigned long *count, iostat_cbdata_t *cb)
4586 {
4587         char **tmpargv = argv;
4588         int argc_for_interval = 0;
4589 
4590         /* Is the last arg an interval value?  Or a guid? */
4591         if (*argc >= 1 && !are_vdevs_in_pool(1, &argv[*argc - 1], NULL, cb)) {
4592                 /*
4593                  * The last arg is not a guid, so it's probably an
4594                  * interval value.
4595                  */
4596                 argc_for_interval++;
4597 
4598                 if (*argc >= 2 &&
4599                     !are_vdevs_in_pool(1, &argv[*argc - 2], NULL, cb)) {
4600                         /*
4601                          * The 2nd to last arg is not a guid, so it's probably
4602                          * an interval value.
4603                          */
4604                         argc_for_interval++;
4605                 }
4606         }
4607 
4608         /* Point to our list of possible intervals */
4609         tmpargv = &argv[*argc - argc_for_interval];
4610 
4611         *argc = *argc - argc_for_interval;
4612         get_interval_count(&argc_for_interval, tmpargv,
4613             interval, count);
4614 }
4615 
4616 /*
4617  * Floating point sleep().  Allows you to pass in a floating point value for
4618  * seconds.
4619  */
4620 static void
4621 fsleep(float sec)
4622 {
4623         struct timespec req;
4624         req.tv_sec = floor(sec);
4625         req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC;
4626         (void) nanosleep(&req, NULL);
4627 }
4628 
4629 /*
4630  * Set the minimum pool/vdev name column width.  The width must be at least 10,
4631  * but may be as large as the column width - 42 so it still fits on one line.
4632  */
4633 static int
4634 get_namewidth_iostat(zpool_handle_t *zhp, void *data)
4635 {
4636         iostat_cbdata_t *cb = data;
4637         int width, columns;
4638 
4639         width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags,
4640             cb->cb_verbose);
4641         columns = get_columns();
4642 
4643         if (width < 10)
4644                 width = 10;
4645         if (width > columns - 42)
4646                 width = columns - 42;
4647 
4648         cb->cb_namewidth = width;
4649 
4650         return (0);
4651 }
4652 
4653 /*
4654  * zpool iostat [-ghHLpPvy] [[-lq]|[-r|-w]] [-n name] [-T d|u]
4655  *              [[ pool ...]|[pool vdev ...]|[vdev ...]]
4656  *              [interval [count]]
4657  *
4658  *      -g      Display guid for individual vdev name.
4659  *      -L      Follow links when resolving vdev path name.
4660  *      -P      Display full path for vdev name.
4661  *      -v      Display statistics for individual vdevs
4662  *      -h      Display help
4663  *      -p      Display values in parsable (exact) format.
4664  *      -H      Scripted mode.  Don't display headers, and separate properties
4665  *              by a single tab.
4666  *      -l      Display average latency
4667  *      -q      Display queue depths
4668  *      -w      Display latency histograms
4669  *      -r      Display request size histogram
4670  *      -T      Display a timestamp in date(1) or Unix format
4671  *      -n      Only print headers once
4672  *
4673  * This command can be tricky because we want to be able to deal with pool
4674  * creation/destruction as well as vdev configuration changes.  The bulk of this
4675  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
4676  * on pool_list_update() to detect the addition of new pools.  Configuration
4677  * changes are all handled within libzfs.
4678  */
4679 int
4680 zpool_do_iostat(int argc, char **argv)
4681 {
4682         int c;
4683         int ret;
4684         int npools;
4685         float interval = 0;
4686         unsigned long count = 0;
4687         int winheight = 24;
4688         struct winsize win;
4689         zpool_list_t *list;
4690         boolean_t verbose = B_FALSE;
4691         boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE;
4692         boolean_t queues = B_FALSE, parseable = B_FALSE, scripted = B_FALSE;
4693         boolean_t omit_since_boot = B_FALSE;
4694         boolean_t guid = B_FALSE;
4695         boolean_t follow_links = B_FALSE;
4696         boolean_t full_name = B_FALSE;
4697         boolean_t headers_once = B_FALSE;
4698         iostat_cbdata_t cb = { 0 };
4699 
4700         /* Used for printing error message */
4701         const char flag_to_arg[] = {[IOS_LATENCY] = 'l', [IOS_QUEUES] = 'q',
4702             [IOS_L_HISTO] = 'w', [IOS_RQ_HISTO] = 'r'};
4703 
4704         uint64_t unsupported_flags;
4705 
4706         /* check options */
4707         while ((c = getopt(argc, argv, "gLPT:vyhplqrwnH")) != -1) {
4708                 switch (c) {
4709                 case 'g':
4710                         guid = B_TRUE;
4711                         break;
4712                 case 'L':
4713                         follow_links = B_TRUE;
4714                         break;
4715                 case 'P':
4716                         full_name = B_TRUE;
4717                         break;
4718                 case 'T':
4719                         get_timestamp_arg(*optarg);
4720                         break;
4721                 case 'v':
4722                         verbose = B_TRUE;
4723                         break;
4724                 case 'p':
4725                         parseable = B_TRUE;
4726                         break;
4727                 case 'l':
4728                         latency = B_TRUE;
4729                         break;
4730                 case 'q':
4731                         queues = B_TRUE;
4732                         break;
4733                 case 'H':
4734                         scripted = B_TRUE;
4735                         break;
4736                 case 'w':
4737                         l_histo = B_TRUE;
4738                         break;
4739                 case 'r':
4740                         rq_histo = B_TRUE;
4741                         break;
4742                 case 'y':
4743                         omit_since_boot = B_TRUE;
4744                         break;
4745                 case 'n':
4746                         headers_once = B_TRUE;
4747                         break;
4748                 case 'h':
4749                         usage(B_FALSE);
4750                         break;
4751                 case '?':
4752                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4753                             optopt);
4754                         usage(B_FALSE);
4755                 }
4756         }
4757 
4758         argc -= optind;
4759         argv += optind;
4760 
4761         cb.cb_literal = parseable;
4762         cb.cb_scripted = scripted;
4763 
4764         if (guid)
4765                 cb.cb_name_flags |= VDEV_NAME_GUID;
4766         if (follow_links)
4767                 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
4768         if (full_name)
4769                 cb.cb_name_flags |= VDEV_NAME_PATH;
4770         cb.cb_iteration = 0;
4771         cb.cb_namewidth = 0;
4772         cb.cb_verbose = verbose;
4773 
4774         /* Get our interval and count values (if any) */
4775         if (guid) {
4776                 get_interval_count_filter_guids(&argc, argv, &interval,
4777                     &count, &cb);
4778         } else {
4779                 get_interval_count(&argc, argv, &interval, &count);
4780         }
4781 
4782         if (argc == 0) {
4783                 /* No args, so just print the defaults. */
4784         } else if (are_all_pools(argc, argv)) {
4785                 /* All the args are pool names */
4786         } else if (are_vdevs_in_pool(argc, argv, NULL, &cb)) {
4787                 /* All the args are vdevs */
4788                 cb.cb_vdev_names = argv;
4789                 cb.cb_vdev_names_count = argc;
4790                 argc = 0; /* No pools to process */
4791         } else if (are_all_pools(1, argv)) {
4792                 /* The first arg is a pool name */
4793                 if (are_vdevs_in_pool(argc - 1, argv + 1, argv[0], &cb)) {
4794                         /* ...and the rest are vdev names */
4795                         cb.cb_vdev_names = argv + 1;
4796                         cb.cb_vdev_names_count = argc - 1;
4797                         argc = 1; /* One pool to process */
4798                 } else {
4799                         fprintf(stderr, gettext("Expected either a list of "));
4800                         fprintf(stderr, gettext("pools, or list of vdevs in"));
4801                         fprintf(stderr, " \"%s\", ", argv[0]);
4802                         fprintf(stderr, gettext("but got:\n"));
4803                         error_list_unresolved_vdevs(argc - 1, argv + 1,
4804                             argv[0], &cb);
4805                         fprintf(stderr, "\n");
4806                         usage(B_FALSE);
4807                         return (1);
4808                 }
4809         } else {
4810                 /*
4811                  * The args don't make sense. The first arg isn't a pool name,
4812                  * nor are all the args vdevs.
4813                  */
4814                 fprintf(stderr, gettext("Unable to parse pools/vdevs list.\n"));
4815                 fprintf(stderr, "\n");
4816                 return (1);
4817         }
4818 
4819         if (cb.cb_vdev_names_count != 0) {
4820                 /*
4821                  * If user specified vdevs, it implies verbose.
4822                  */
4823                 cb.cb_verbose = B_TRUE;
4824         }
4825 
4826         /*
4827          * Construct the list of all interesting pools.
4828          */
4829         ret = 0;
4830         if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
4831                 return (1);
4832 
4833         if (pool_list_count(list) == 0 && argc != 0) {
4834                 pool_list_free(list);
4835                 return (1);
4836         }
4837 
4838         if (pool_list_count(list) == 0 && interval == 0) {
4839                 pool_list_free(list);
4840                 (void) fprintf(stderr, gettext("no pools available\n"));
4841                 return (1);
4842         }
4843 
4844         if ((l_histo || rq_histo) && (queues || latency)) {
4845                 pool_list_free(list);
4846                 (void) fprintf(stderr,
4847                     gettext("[-r|-w] isn't allowed with [-q|-l]\n"));
4848                 usage(B_FALSE);
4849                 return (1);
4850         }
4851 
4852         if (l_histo && rq_histo) {
4853                 pool_list_free(list);
4854                 (void) fprintf(stderr,
4855                     gettext("Only one of [-r|-w] can be passed at a time\n"));
4856                 usage(B_FALSE);
4857                 return (1);
4858         }
4859 
4860         /*
4861          * Enter the main iostat loop.
4862          */
4863         cb.cb_list = list;
4864 
4865         if (l_histo) {
4866                 /*
4867                  * Histograms tables look out of place when you try to display
4868                  * them with the other stats, so make a rule that you can only
4869                  * print histograms by themselves.
4870                  */
4871                 cb.cb_flags = IOS_L_HISTO_M;
4872         } else if (rq_histo) {
4873                 cb.cb_flags = IOS_RQ_HISTO_M;
4874         } else {
4875                 cb.cb_flags = IOS_DEFAULT_M;
4876                 if (latency)
4877                         cb.cb_flags |= IOS_LATENCY_M;
4878                 if (queues)
4879                         cb.cb_flags |= IOS_QUEUES_M;
4880         }
4881 
4882         /*
4883          * See if the module supports all the stats we want to display.
4884          */
4885         unsupported_flags = cb.cb_flags & ~get_stat_flags(list);
4886         if (unsupported_flags) {
4887                 uint64_t f;
4888                 int idx;
4889                 fprintf(stderr,
4890                     gettext("The loaded zfs module doesn't support:"));
4891 
4892                 /* for each bit set in unsupported_flags */
4893                 for (f = unsupported_flags; f; f &= ~(1ULL << idx)) {
4894                         idx = lowbit64(f) - 1;
4895                         fprintf(stderr, " -%c", flag_to_arg[idx]);
4896                 }
4897 
4898                 fprintf(stderr, ".  Try running a newer module.\n"),
4899                     pool_list_free(list);
4900 
4901                 return (1);
4902         }
4903 
4904         for (;;) {
4905                 if ((npools = pool_list_count(list)) == 0)
4906                         (void) fprintf(stderr, gettext("no pools available\n"));
4907                 else {
4908                         /*
4909                          * If this is the first iteration and -y was supplied
4910                          * we skip any printing.
4911                          */
4912                         boolean_t skip = (omit_since_boot &&
4913                             cb.cb_iteration == 0);
4914 
4915                         /*
4916                          * Refresh all statistics.  This is done as an
4917                          * explicit step before calculating the maximum name
4918                          * width, so that any configuration changes are
4919                          * properly accounted for.
4920                          */
4921                         (void) pool_list_iter(list, B_FALSE, refresh_iostat,
4922                             &cb);
4923 
4924                         /*
4925                          * Iterate over all pools to determine the maximum width
4926                          * for the pool / device name column across all pools.
4927                          */
4928                         cb.cb_namewidth = 0;
4929                         (void) pool_list_iter(list, B_FALSE,
4930                             get_namewidth_iostat, &cb);
4931 
4932                         if (timestamp_fmt != NODATE)
4933                                 print_timestamp(timestamp_fmt);
4934 
4935                         /*
4936                          * Check terminal size so we can print headers
4937                          * even when terminal window has its height
4938                          * changed.
4939                          */
4940                         if (headers_once == B_FALSE) {
4941                                 if (ioctl(1, TIOCGWINSZ, &win) != -1) {
4942                                         if (win.ws_row <= 0) {
4943                                                 headers_once = B_TRUE;
4944                                         } else {
4945                                                 winheight = win.ws_row;
4946                                         }
4947                                 }
4948                         }
4949                         /*
4950                          * Are we connected to TTY? If not, headers_once
4951                          * should be true, to avoid breaking scripts.
4952                          */
4953                         if (isatty(fileno(stdout)) == 0)
4954                                 headers_once = B_TRUE;
4955 
4956                         /*
4957                          * If it's the first time and we're not skipping it,
4958                          * or either skip or verbose mode, print the header.
4959                          *
4960                          * The histogram code explicitly prints its header on
4961                          * every vdev, so skip this for histograms.
4962                          */
4963                         if (((++cb.cb_iteration == 1 && !skip) ||
4964                             (skip != verbose) ||
4965                             (!headers_once &&
4966                             (cb.cb_iteration % winheight) == 0)) &&
4967                             (!(cb.cb_flags & IOS_ANYHISTO_M)) &&
4968                             !cb.cb_scripted)
4969                                 print_iostat_header(&cb);
4970 
4971                         if (skip) {
4972                                 (void) fsleep(interval);
4973                                 continue;
4974                         }
4975 
4976                         (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
4977 
4978                         /*
4979                          * If there's more than one pool, and we're not in
4980                          * verbose mode (which prints a separator for us),
4981                          * then print a separator.
4982                          *
4983                          * In addition, if we're printing specific vdevs then
4984                          * we also want an ending separator.
4985                          */
4986                         if (((npools > 1 && !verbose &&
4987                             !(cb.cb_flags & IOS_ANYHISTO_M)) ||
4988                             (!(cb.cb_flags & IOS_ANYHISTO_M) &&
4989                             cb.cb_vdev_names_count)) &&
4990                             !cb.cb_scripted) {
4991                                 print_iostat_separator(&cb);
4992                                 printf("\n");
4993                         }
4994                 }
4995 
4996                 /*
4997                  * Flush the output so that redirection to a file isn't buffered
4998                  * indefinitely.
4999                  */
5000                 (void) fflush(stdout);
5001 
5002                 if (interval == 0)
5003                         break;
5004 
5005                 if (count != 0 && --count == 0)
5006                         break;
5007 
5008                 (void) fsleep(interval);
5009         }
5010 
5011         pool_list_free(list);
5012 
5013         return (ret);
5014 }
5015 
5016 typedef struct list_cbdata {
5017         boolean_t       cb_verbose;
5018         int             cb_name_flags;
5019         int             cb_namewidth;
5020         boolean_t       cb_scripted;
5021         zprop_list_t    *cb_proplist;
5022         boolean_t       cb_literal;
5023 } list_cbdata_t;
5024 
5025 
5026 /*
5027  * Given a list of columns to display, output appropriate headers for each one.
5028  */
5029 static void
5030 print_header(list_cbdata_t *cb)
5031 {
5032         zprop_list_t *pl = cb->cb_proplist;
5033         char headerbuf[ZPOOL_MAXPROPLEN];
5034         const char *header;
5035         boolean_t first = B_TRUE;
5036         boolean_t right_justify;
5037         size_t width = 0;
5038 
5039         for (; pl != NULL; pl = pl->pl_next) {
5040                 width = pl->pl_width;
5041                 if (first && cb->cb_verbose) {
5042                         /*
5043                          * Reset the width to accommodate the verbose listing
5044                          * of devices.
5045                          */
5046                         width = cb->cb_namewidth;
5047                 }
5048 
5049                 if (!first)
5050                         (void) printf("  ");
5051                 else
5052                         first = B_FALSE;
5053 
5054                 right_justify = B_FALSE;
5055                 if (pl->pl_prop != ZPROP_INVAL) {
5056                         header = zpool_prop_column_name(pl->pl_prop);
5057                         right_justify = zpool_prop_align_right(pl->pl_prop);
5058                 } else {
5059                         int i;
5060 
5061                         for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
5062                                 headerbuf[i] = toupper(pl->pl_user_prop[i]);
5063                         headerbuf[i] = '\0';
5064                         header = headerbuf;
5065                 }
5066 
5067                 if (pl->pl_next == NULL && !right_justify)
5068                         (void) printf("%s", header);
5069                 else if (right_justify)
5070                         (void) printf("%*s", width, header);
5071                 else
5072                         (void) printf("%-*s", width, header);
5073 
5074         }
5075 
5076         (void) printf("\n");
5077 }
5078 
5079 /*
5080  * Given a pool and a list of properties, print out all the properties according
5081  * to the described layout. Used by zpool_do_list().
5082  */
5083 static void
5084 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
5085 {
5086         zprop_list_t *pl = cb->cb_proplist;
5087         boolean_t first = B_TRUE;
5088         char property[ZPOOL_MAXPROPLEN];
5089         char *propstr;
5090         boolean_t right_justify;
5091         size_t width;
5092 
5093         for (; pl != NULL; pl = pl->pl_next) {
5094 
5095                 width = pl->pl_width;
5096                 if (first && cb->cb_verbose) {
5097                         /*
5098                          * Reset the width to accommodate the verbose listing
5099                          * of devices.
5100                          */
5101                         width = cb->cb_namewidth;
5102                 }
5103 
5104                 if (!first) {
5105                         if (cb->cb_scripted)
5106                                 (void) printf("\t");
5107                         else
5108                                 (void) printf("  ");
5109                 } else {
5110                         first = B_FALSE;
5111                 }
5112 
5113                 right_justify = B_FALSE;
5114                 if (pl->pl_prop != ZPROP_INVAL) {
5115                         if (zpool_get_prop(zhp, pl->pl_prop, property,
5116                             sizeof (property), NULL, cb->cb_literal) != 0)
5117                                 propstr = "-";
5118                         else
5119                                 propstr = property;
5120 
5121                         right_justify = zpool_prop_align_right(pl->pl_prop);
5122                 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
5123                     zpool_prop_unsupported(pl->pl_user_prop)) &&
5124                     zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
5125                     sizeof (property)) == 0) {
5126                         propstr = property;
5127                 } else {
5128                         propstr = "-";
5129                 }
5130 
5131 
5132                 /*
5133                  * If this is being called in scripted mode, or if this is the
5134                  * last column and it is left-justified, don't include a width
5135                  * format specifier.
5136                  */
5137                 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
5138                         (void) printf("%s", propstr);
5139                 else if (right_justify)
5140                         (void) printf("%*s", width, propstr);
5141                 else
5142                         (void) printf("%-*s", width, propstr);
5143         }
5144 
5145         (void) printf("\n");
5146 }
5147 
5148 static void
5149 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
5150     boolean_t valid)
5151 {
5152         char propval[64];
5153         boolean_t fixed;
5154         size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
5155 
5156         switch (prop) {
5157         case ZPOOL_PROP_EXPANDSZ:
5158         case ZPOOL_PROP_CHECKPOINT:
5159                 if (value == 0)
5160                         (void) strlcpy(propval, "-", sizeof (propval));
5161                 else
5162                         zfs_nicenum(value, propval, sizeof (propval));
5163                 break;
5164         case ZPOOL_PROP_FRAGMENTATION:
5165                 if (value == ZFS_FRAG_INVALID) {
5166                         (void) strlcpy(propval, "-", sizeof (propval));
5167                 } else {
5168                         (void) snprintf(propval, sizeof (propval), "%llu%%",
5169                             value);
5170                 }
5171                 break;
5172         case ZPOOL_PROP_CAPACITY:
5173                 (void) snprintf(propval, sizeof (propval),
5174                     value < 1000 ? "%1.2f%%" : value < 10000 ?
5175                     "%2.1f%%" : "%3.0f%%", value / 100.0);
5176                 break;
5177         default:
5178                 zfs_nicenum(value, propval, sizeof (propval));
5179         }
5180 
5181         if (!valid)
5182                 (void) strlcpy(propval, "-", sizeof (propval));
5183 
5184         if (scripted)
5185                 (void) printf("\t%s", propval);
5186         else
5187                 (void) printf("  %*s", width, propval);
5188 }
5189 
5190 /*
5191  * print static default line per vdev
5192  */
5193 void
5194 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
5195     list_cbdata_t *cb, int depth)
5196 {
5197         nvlist_t **child;
5198         vdev_stat_t *vs;
5199         uint_t c, children;
5200         char *vname;
5201         boolean_t scripted = cb->cb_scripted;
5202         uint64_t islog = B_FALSE;
5203         char *dashes = "%-*s      -      -      -         -      -      -\n";
5204 
5205         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
5206             (uint64_t **)&vs, &c) == 0);
5207 
5208         if (name != NULL) {
5209                 boolean_t toplevel = (vs->vs_space != 0);
5210                 uint64_t cap;
5211 
5212                 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
5213                         return;
5214 
5215                 if (scripted)
5216                         (void) printf("\t%s", name);
5217                 else if (strlen(name) + depth > cb->cb_namewidth)
5218                         (void) printf("%*s%s", depth, "", name);
5219                 else
5220                         (void) printf("%*s%s%*s", depth, "", name,
5221                             (int)(cb->cb_namewidth - strlen(name) - depth), "");
5222 
5223                 /*
5224                  * Print the properties for the individual vdevs. Some
5225                  * properties are only applicable to toplevel vdevs. The
5226                  * 'toplevel' boolean value is passed to the print_one_column()
5227                  * to indicate that the value is valid.
5228                  */
5229                 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
5230                     toplevel);
5231                 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
5232                     toplevel);
5233                 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
5234                     scripted, toplevel);
5235                 print_one_column(ZPOOL_PROP_CHECKPOINT,
5236                     vs->vs_checkpoint_space, scripted, toplevel);
5237                 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
5238                     B_TRUE);
5239                 print_one_column(ZPOOL_PROP_FRAGMENTATION,
5240                     vs->vs_fragmentation, scripted,
5241                     (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
5242                 cap = (vs->vs_space == 0) ? 0 :
5243                     (vs->vs_alloc * 10000 / vs->vs_space);
5244                 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
5245                 (void) printf("\n");
5246         }
5247 
5248         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
5249             &child, &children) != 0)
5250                 return;
5251 
5252         /* list the normal vdevs first */
5253         for (c = 0; c < children; c++) {
5254                 uint64_t ishole = B_FALSE;
5255 
5256                 if (nvlist_lookup_uint64(child[c],
5257                     ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
5258                         continue;
5259 
5260                 if (nvlist_lookup_uint64(child[c],
5261                     ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog)
5262                         continue;
5263 
5264                 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
5265                         continue;
5266 
5267                 vname = zpool_vdev_name(g_zfs, zhp, child[c],
5268                     cb->cb_name_flags);
5269                 print_list_stats(zhp, vname, child[c], cb, depth + 2);
5270                 free(vname);
5271         }
5272 
5273         /* list the classes: 'logs', 'dedup', and 'special' */
5274         for (uint_t n = 0; n < 3; n++) {
5275                 boolean_t printed = B_FALSE;
5276 
5277                 for (c = 0; c < children; c++) {
5278                         char *bias = NULL;
5279                         char *type = NULL;
5280 
5281                         if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
5282                             &islog) == 0 && islog) {
5283                                 bias = VDEV_ALLOC_CLASS_LOGS;
5284                         } else {
5285                                 (void) nvlist_lookup_string(child[c],
5286                                     ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
5287                                 (void) nvlist_lookup_string(child[c],
5288                                     ZPOOL_CONFIG_TYPE, &type);
5289                         }
5290                         if (bias == NULL || strcmp(bias, class_name[n]) != 0)
5291                                 continue;
5292                         if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
5293                                 continue;
5294 
5295                         if (!printed) {
5296                                 /* LINTED E_SEC_PRINTF_VAR_FMT */
5297                                 (void) printf(dashes, cb->cb_namewidth,
5298                                     class_name[n]);
5299                                 printed = B_TRUE;
5300                         }
5301                         vname = zpool_vdev_name(g_zfs, zhp, child[c],
5302                             cb->cb_name_flags);
5303                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
5304                         free(vname);
5305                 }
5306         }
5307 
5308         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
5309             &child, &children) == 0 && children > 0) {
5310                 /* LINTED E_SEC_PRINTF_VAR_FMT */
5311                 (void) printf(dashes, cb->cb_namewidth, "cache");
5312                 for (c = 0; c < children; c++) {
5313                         vname = zpool_vdev_name(g_zfs, zhp, child[c],
5314                             cb->cb_name_flags);
5315                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
5316                         free(vname);
5317                 }
5318         }
5319 
5320         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
5321             &children) == 0 && children > 0) {
5322                 /* LINTED E_SEC_PRINTF_VAR_FMT */
5323                 (void) printf(dashes, cb->cb_namewidth, "spare");
5324                 for (c = 0; c < children; c++) {
5325                         vname = zpool_vdev_name(g_zfs, zhp, child[c],
5326                             cb->cb_name_flags);
5327                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
5328                         free(vname);
5329                 }
5330         }
5331 }
5332 
5333 /*
5334  * Generic callback function to list a pool.
5335  */
5336 int
5337 list_callback(zpool_handle_t *zhp, void *data)
5338 {
5339         list_cbdata_t *cbp = data;
5340         nvlist_t *config;
5341         nvlist_t *nvroot;
5342 
5343         config = zpool_get_config(zhp, NULL);
5344 
5345         if (cbp->cb_verbose) {
5346                 config = zpool_get_config(zhp, NULL);
5347 
5348                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
5349                     &nvroot) == 0);
5350         }
5351 
5352         if (cbp->cb_verbose)
5353                 cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
5354                     cbp->cb_name_flags);
5355 
5356         print_pool(zhp, cbp);
5357 
5358         if (cbp->cb_verbose)
5359                 print_list_stats(zhp, NULL, nvroot, cbp, 0);
5360 
5361         return (0);
5362 }
5363 
5364 /*
5365  * Set the minimum pool/vdev name column width.  The width must be at least 9,
5366  * but may be as large as needed.
5367  */
5368 static int
5369 get_namewidth_list(zpool_handle_t *zhp, void *data)
5370 {
5371         list_cbdata_t *cb = data;
5372         int width;
5373 
5374         width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags,
5375             cb->cb_verbose);
5376 
5377         if (width < 9)
5378                 width = 9;
5379 
5380         cb->cb_namewidth = width;
5381 
5382         return (0);
5383 }
5384 
5385 /*
5386  * zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
5387  *
5388  *      -g      Display guid for individual vdev name.
5389  *      -H      Scripted mode.  Don't display headers, and separate properties
5390  *              by a single tab.
5391  *      -L      Follow links when resolving vdev path name.
5392  *      -o      List of properties to display.  Defaults to
5393  *              "name,size,allocated,free,expandsize,fragmentation,capacity,"
5394  *              "dedupratio,health,altroot"
5395  *      -p      Diplay values in parsable (exact) format.
5396  *      -P      Display full path for vdev name.
5397  *      -T      Display a timestamp in date(1) or Unix format
5398  *
5399  * List all pools in the system, whether or not they're healthy.  Output space
5400  * statistics for each one, as well as health status summary.
5401  */
5402 int
5403 zpool_do_list(int argc, char **argv)
5404 {
5405         int c;
5406         int ret;
5407         list_cbdata_t cb = { 0 };
5408         static char default_props[] =
5409             "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
5410             "capacity,dedupratio,health,altroot";
5411         char *props = default_props;
5412         float interval = 0;
5413         unsigned long count = 0;
5414         zpool_list_t *list;
5415         boolean_t first = B_TRUE;
5416 
5417         /* check options */
5418         while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
5419                 switch (c) {
5420                 case 'g':
5421                         cb.cb_name_flags |= VDEV_NAME_GUID;
5422                         break;
5423                 case 'H':
5424                         cb.cb_scripted = B_TRUE;
5425                         break;
5426                 case 'L':
5427                         cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
5428                         break;
5429                 case 'o':
5430                         props = optarg;
5431                         break;
5432                 case 'P':
5433                         cb.cb_name_flags |= VDEV_NAME_PATH;
5434                         break;
5435                 case 'p':
5436                         cb.cb_literal = B_TRUE;
5437                         break;
5438                 case 'T':
5439                         get_timestamp_arg(*optarg);
5440                         break;
5441                 case 'v':
5442                         cb.cb_verbose = B_TRUE;
5443                         cb.cb_namewidth = 8;    /* 8 until precalc is avail */
5444                         break;
5445                 case ':':
5446                         (void) fprintf(stderr, gettext("missing argument for "
5447                             "'%c' option\n"), optopt);
5448                         usage(B_FALSE);
5449                         break;
5450                 case '?':
5451                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5452                             optopt);
5453                         usage(B_FALSE);
5454                 }
5455         }
5456 
5457         argc -= optind;
5458         argv += optind;
5459 
5460         get_interval_count(&argc, argv, &interval, &count);
5461 
5462         if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
5463                 usage(B_FALSE);
5464 
5465         for (;;) {
5466                 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
5467                     &ret)) == NULL)
5468                         return (1);
5469 
5470                 if (pool_list_count(list) == 0)
5471                         break;
5472 
5473                 cb.cb_namewidth = 0;
5474                 (void) pool_list_iter(list, B_FALSE, get_namewidth_list, &cb);
5475 
5476                 if (timestamp_fmt != NODATE)
5477                         print_timestamp(timestamp_fmt);
5478 
5479                 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
5480                         print_header(&cb);
5481                         first = B_FALSE;
5482                 }
5483                 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
5484 
5485                 if (interval == 0)
5486                         break;
5487 
5488                 if (count != 0 && --count == 0)
5489                         break;
5490 
5491                 pool_list_free(list);
5492                 (void) fsleep(interval);
5493         }
5494 
5495         if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
5496                 (void) printf(gettext("no pools available\n"));
5497                 ret = 0;
5498         }
5499 
5500         pool_list_free(list);
5501         zprop_free_list(cb.cb_proplist);
5502         return (ret);
5503 }
5504 
5505 static int
5506 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
5507 {
5508         boolean_t force = B_FALSE;
5509         int c;
5510         nvlist_t *nvroot;
5511         char *poolname, *old_disk, *new_disk;
5512         zpool_handle_t *zhp;
5513         zpool_boot_label_t boot_type;
5514         uint64_t boot_size;
5515         nvlist_t *props = NULL;
5516         char *propval;
5517         int ret;
5518 
5519         /* check options */
5520         while ((c = getopt(argc, argv, "fo:")) != -1) {
5521                 switch (c) {
5522                 case 'f':
5523                         force = B_TRUE;
5524                         break;
5525                 case 'o':
5526                         if ((propval = strchr(optarg, '=')) == NULL) {
5527                                 (void) fprintf(stderr, gettext("missing "
5528                                     "'=' for -o option\n"));
5529                                 usage(B_FALSE);
5530                         }
5531                         *propval = '\0';
5532                         propval++;
5533 
5534                         if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
5535                             (add_prop_list(optarg, propval, &props, B_TRUE)))
5536                                 usage(B_FALSE);
5537                         break;
5538                 case '?':
5539                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5540                             optopt);
5541                         usage(B_FALSE);
5542                 }
5543         }
5544 
5545         argc -= optind;
5546         argv += optind;
5547 
5548         /* get pool name and check number of arguments */
5549         if (argc < 1) {
5550                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
5551                 usage(B_FALSE);
5552         }
5553 
5554         poolname = argv[0];
5555 
5556         if (argc < 2) {
5557                 (void) fprintf(stderr,
5558                     gettext("missing <device> specification\n"));
5559                 usage(B_FALSE);
5560         }
5561 
5562         old_disk = argv[1];
5563 
5564         if (argc < 3) {
5565                 if (!replacing) {
5566                         (void) fprintf(stderr,
5567                             gettext("missing <new_device> specification\n"));
5568                         usage(B_FALSE);
5569                 }
5570                 new_disk = old_disk;
5571                 argc -= 1;
5572                 argv += 1;
5573         } else {
5574                 new_disk = argv[2];
5575                 argc -= 2;
5576                 argv += 2;
5577         }
5578 
5579         if (argc > 1) {
5580                 (void) fprintf(stderr, gettext("too many arguments\n"));
5581                 usage(B_FALSE);
5582         }
5583 
5584         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5585                 return (1);
5586 
5587         if (zpool_get_config(zhp, NULL) == NULL) {
5588                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
5589                     poolname);
5590                 zpool_close(zhp);
5591                 return (1);
5592         }
5593 
5594         if (zpool_is_bootable(zhp))
5595                 boot_type = ZPOOL_COPY_BOOT_LABEL;
5596         else
5597                 boot_type = ZPOOL_NO_BOOT_LABEL;
5598 
5599         boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
5600 
5601         /* unless manually specified use "ashift" pool property (if set) */
5602         if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
5603                 int intval;
5604                 zprop_source_t src;
5605                 char strval[ZPOOL_MAXPROPLEN];
5606 
5607                 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
5608                 if (src != ZPROP_SRC_DEFAULT) {
5609                         (void) sprintf(strval, "%" PRId32, intval);
5610                         verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
5611                             &props, B_TRUE) == 0);
5612                 }
5613         }
5614 
5615         nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE,
5616             boot_type, boot_size, argc, argv);
5617         if (nvroot == NULL) {
5618                 zpool_close(zhp);
5619                 return (1);
5620         }
5621 
5622         ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
5623 
5624         nvlist_free(nvroot);
5625         zpool_close(zhp);
5626 
5627         return (ret);
5628 }
5629 
5630 /*
5631  * zpool replace [-f] <pool> <device> <new_device>
5632  *
5633  *      -f      Force attach, even if <new_device> appears to be in use.
5634  *
5635  * Replace <device> with <new_device>.
5636  */
5637 /* ARGSUSED */
5638 int
5639 zpool_do_replace(int argc, char **argv)
5640 {
5641         return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
5642 }
5643 
5644 /*
5645  * zpool attach [-f] [-o property=value] <pool> <device> <new_device>
5646  *
5647  *      -f      Force attach, even if <new_device> appears to be in use.
5648  *      -o      Set property=value.
5649  *
5650  * Attach <new_device> to the mirror containing <device>.  If <device> is not
5651  * part of a mirror, then <device> will be transformed into a mirror of
5652  * <device> and <new_device>.  In either case, <new_device> will begin life
5653  * with a DTL of [0, now], and will immediately begin to resilver itself.
5654  */
5655 int
5656 zpool_do_attach(int argc, char **argv)
5657 {
5658         return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
5659 }
5660 
5661 /*
5662  * zpool detach [-f] <pool> <device>
5663  *
5664  *      -f      Force detach of <device>, even if DTLs argue against it
5665  *              (not supported yet)
5666  *
5667  * Detach a device from a mirror.  The operation will be refused if <device>
5668  * is the last device in the mirror, or if the DTLs indicate that this device
5669  * has the only valid copy of some data.
5670  */
5671 /* ARGSUSED */
5672 int
5673 zpool_do_detach(int argc, char **argv)
5674 {
5675         int c;
5676         char *poolname, *path;
5677         zpool_handle_t *zhp;
5678         int ret;
5679 
5680         /* check options */
5681         while ((c = getopt(argc, argv, "f")) != -1) {
5682                 switch (c) {
5683                 case 'f':
5684                 case '?':
5685                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5686                             optopt);
5687                         usage(B_FALSE);
5688                 }
5689         }
5690 
5691         argc -= optind;
5692         argv += optind;
5693 
5694         /* get pool name and check number of arguments */
5695         if (argc < 1) {
5696                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
5697                 usage(B_FALSE);
5698         }
5699 
5700         if (argc < 2) {
5701                 (void) fprintf(stderr,
5702                     gettext("missing <device> specification\n"));
5703                 usage(B_FALSE);
5704         }
5705 
5706         poolname = argv[0];
5707         path = argv[1];
5708 
5709         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5710                 return (1);
5711 
5712         ret = zpool_vdev_detach(zhp, path);
5713 
5714         zpool_close(zhp);
5715 
5716         return (ret);
5717 }
5718 
5719 /*
5720  * zpool split [-gLnP] [-o prop=val] ...
5721  *              [-o mntopt] ...
5722  *              [-R altroot] <pool> <newpool> [<device> ...]
5723  *
5724  *      -g      Display guid for individual vdev name.
5725  *      -L      Follow links when resolving vdev path name.
5726  *      -n      Do not split the pool, but display the resulting layout if
5727  *              it were to be split.
5728  *      -o      Set property=value, or set mount options.
5729  *      -P      Display full path for vdev name.
5730  *      -R      Mount the split-off pool under an alternate root.
5731  *      -l      Load encryption keys while importing.
5732  *
5733  * Splits the named pool and gives it the new pool name.  Devices to be split
5734  * off may be listed, provided that no more than one device is specified
5735  * per top-level vdev mirror.  The newly split pool is left in an exported
5736  * state unless -R is specified.
5737  *
5738  * Restrictions: the top-level of the pool pool must only be made up of
5739  * mirrors; all devices in the pool must be healthy; no device may be
5740  * undergoing a resilvering operation.
5741  */
5742 int
5743 zpool_do_split(int argc, char **argv)
5744 {
5745         char *srcpool, *newpool, *propval;
5746         char *mntopts = NULL;
5747         splitflags_t flags;
5748         int c, ret = 0;
5749         boolean_t loadkeys = B_FALSE;
5750         zpool_handle_t *zhp;
5751         nvlist_t *config, *props = NULL;
5752 
5753         flags.dryrun = B_FALSE;
5754         flags.import = B_FALSE;
5755         flags.name_flags = 0;
5756 
5757         /* check options */
5758         while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) {
5759                 switch (c) {
5760                 case 'g':
5761                         flags.name_flags |= VDEV_NAME_GUID;
5762                         break;
5763                 case 'L':
5764                         flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
5765                         break;
5766                 case 'R':
5767                         flags.import = B_TRUE;
5768                         if (add_prop_list(
5769                             zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
5770                             &props, B_TRUE) != 0) {
5771                                 nvlist_free(props);
5772                                 usage(B_FALSE);
5773                         }
5774                         break;
5775                 case 'l':
5776                         loadkeys = B_TRUE;
5777                         break;
5778                 case 'n':
5779                         flags.dryrun = B_TRUE;
5780                         break;
5781                 case 'o':
5782                         if ((propval = strchr(optarg, '=')) != NULL) {
5783                                 *propval = '\0';
5784                                 propval++;
5785                                 if (add_prop_list(optarg, propval,
5786                                     &props, B_TRUE) != 0) {
5787                                         nvlist_free(props);
5788                                         usage(B_FALSE);
5789                                 }
5790                         } else {
5791                                 mntopts = optarg;
5792                         }
5793                         break;
5794                 case 'P':
5795                         flags.name_flags |= VDEV_NAME_PATH;
5796                         break;
5797                 case ':':
5798                         (void) fprintf(stderr, gettext("missing argument for "
5799                             "'%c' option\n"), optopt);
5800                         usage(B_FALSE);
5801                         break;
5802                 case '?':
5803                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5804                             optopt);
5805                         usage(B_FALSE);
5806                         break;
5807                 }
5808         }
5809 
5810         if (!flags.import && mntopts != NULL) {
5811                 (void) fprintf(stderr, gettext("setting mntopts is only "
5812                     "valid when importing the pool\n"));
5813                 usage(B_FALSE);
5814         }
5815 
5816         if (!flags.import && loadkeys) {
5817                 (void) fprintf(stderr, gettext("loading keys is only "
5818                     "valid when importing the pool\n"));
5819                 usage(B_FALSE);
5820         }
5821 
5822         argc -= optind;
5823         argv += optind;
5824 
5825         if (argc < 1) {
5826                 (void) fprintf(stderr, gettext("Missing pool name\n"));
5827                 usage(B_FALSE);
5828         }
5829         if (argc < 2) {
5830                 (void) fprintf(stderr, gettext("Missing new pool name\n"));
5831                 usage(B_FALSE);
5832         }
5833 
5834         srcpool = argv[0];
5835         newpool = argv[1];
5836 
5837         argc -= 2;
5838         argv += 2;
5839 
5840         if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
5841                 return (1);
5842 
5843         config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
5844         if (config == NULL) {
5845                 ret = 1;
5846         } else {
5847                 if (flags.dryrun) {
5848                         (void) printf(gettext("would create '%s' with the "
5849                             "following layout:\n\n"), newpool);
5850                         print_vdev_tree(NULL, newpool, config, 0, "",
5851                             flags.name_flags);
5852                 }
5853                 nvlist_free(config);
5854         }
5855 
5856         zpool_close(zhp);
5857 
5858         if (ret != 0 || flags.dryrun || !flags.import)
5859                 return (ret);
5860 
5861         /*
5862          * The split was successful. Now we need to open the new
5863          * pool and import it.
5864          */
5865         if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
5866                 return (1);
5867 
5868         if (loadkeys) {
5869                 ret = zfs_crypto_attempt_load_keys(g_zfs, newpool);
5870                 if (ret != 0)
5871                         ret = 1;
5872         }
5873 
5874         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
5875             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
5876                 ret = 1;
5877                 (void) fprintf(stderr, gettext("Split was successful, but "
5878                     "the datasets could not all be mounted\n"));
5879                 (void) fprintf(stderr, gettext("Try doing '%s' with a "
5880                     "different altroot\n"), "zpool import");
5881         }
5882         zpool_close(zhp);
5883 
5884         return (ret);
5885 }
5886 
5887 
5888 
5889 /*
5890  * zpool online <pool> <device> ...
5891  */
5892 int
5893 zpool_do_online(int argc, char **argv)
5894 {
5895         int c, i;
5896         char *poolname;
5897         zpool_handle_t *zhp;
5898         int ret = 0;
5899         vdev_state_t newstate;
5900         int flags = 0;
5901 
5902         /* check options */
5903         while ((c = getopt(argc, argv, "et")) != -1) {
5904                 switch (c) {
5905                 case 'e':
5906                         flags |= ZFS_ONLINE_EXPAND;
5907                         break;
5908                 case 't':
5909                 case '?':
5910                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5911                             optopt);
5912                         usage(B_FALSE);
5913                 }
5914         }
5915 
5916         argc -= optind;
5917         argv += optind;
5918 
5919         /* get pool name and check number of arguments */
5920         if (argc < 1) {
5921                 (void) fprintf(stderr, gettext("missing pool name\n"));
5922                 usage(B_FALSE);
5923         }
5924         if (argc < 2) {
5925                 (void) fprintf(stderr, gettext("missing device name\n"));
5926                 usage(B_FALSE);
5927         }
5928 
5929         poolname = argv[0];
5930 
5931         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5932                 return (1);
5933 
5934         for (i = 1; i < argc; i++) {
5935                 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
5936                         if (newstate != VDEV_STATE_HEALTHY) {
5937                                 (void) printf(gettext("warning: device '%s' "
5938                                     "onlined, but remains in faulted state\n"),
5939                                     argv[i]);
5940                                 if (newstate == VDEV_STATE_FAULTED)
5941                                         (void) printf(gettext("use 'zpool "
5942                                             "clear' to restore a faulted "
5943                                             "device\n"));
5944                                 else
5945                                         (void) printf(gettext("use 'zpool "
5946                                             "replace' to replace devices "
5947                                             "that are no longer present\n"));
5948                         }
5949                 } else {
5950                         ret = 1;
5951                 }
5952         }
5953 
5954         zpool_close(zhp);
5955 
5956         return (ret);
5957 }
5958 
5959 /*
5960  * zpool offline [-ft] <pool> <device> ...
5961  *
5962  *      -f      Force the device into the offline state, even if doing
5963  *              so would appear to compromise pool availability.
5964  *              (not supported yet)
5965  *
5966  *      -t      Only take the device off-line temporarily.  The offline
5967  *              state will not be persistent across reboots.
5968  */
5969 /* ARGSUSED */
5970 int
5971 zpool_do_offline(int argc, char **argv)
5972 {
5973         int c, i;
5974         char *poolname;
5975         zpool_handle_t *zhp;
5976         int ret = 0;
5977         boolean_t istmp = B_FALSE;
5978 
5979         /* check options */
5980         while ((c = getopt(argc, argv, "ft")) != -1) {
5981                 switch (c) {
5982                 case 't':
5983                         istmp = B_TRUE;
5984                         break;
5985                 case 'f':
5986                 case '?':
5987                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5988                             optopt);
5989                         usage(B_FALSE);
5990                 }
5991         }
5992 
5993         argc -= optind;
5994         argv += optind;
5995 
5996         /* get pool name and check number of arguments */
5997         if (argc < 1) {
5998                 (void) fprintf(stderr, gettext("missing pool name\n"));
5999                 usage(B_FALSE);
6000         }
6001         if (argc < 2) {
6002                 (void) fprintf(stderr, gettext("missing device name\n"));
6003                 usage(B_FALSE);
6004         }
6005 
6006         poolname = argv[0];
6007 
6008         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6009                 return (1);
6010 
6011         for (i = 1; i < argc; i++) {
6012                 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
6013                         ret = 1;
6014         }
6015 
6016         zpool_close(zhp);
6017 
6018         return (ret);
6019 }
6020 
6021 /*
6022  * zpool clear <pool> [device]
6023  *
6024  * Clear all errors associated with a pool or a particular device.
6025  */
6026 int
6027 zpool_do_clear(int argc, char **argv)
6028 {
6029         int c;
6030         int ret = 0;
6031         boolean_t dryrun = B_FALSE;
6032         boolean_t do_rewind = B_FALSE;
6033         boolean_t xtreme_rewind = B_FALSE;
6034         uint32_t rewind_policy = ZPOOL_NO_REWIND;
6035         nvlist_t *policy = NULL;
6036         zpool_handle_t *zhp;
6037         char *pool, *device;
6038 
6039         /* check options */
6040         while ((c = getopt(argc, argv, "FnX")) != -1) {
6041                 switch (c) {
6042                 case 'F':
6043                         do_rewind = B_TRUE;
6044                         break;
6045                 case 'n':
6046                         dryrun = B_TRUE;
6047                         break;
6048                 case 'X':
6049                         xtreme_rewind = B_TRUE;
6050                         break;
6051                 case '?':
6052                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6053                             optopt);
6054                         usage(B_FALSE);
6055                 }
6056         }
6057 
6058         argc -= optind;
6059         argv += optind;
6060 
6061         if (argc < 1) {
6062                 (void) fprintf(stderr, gettext("missing pool name\n"));
6063                 usage(B_FALSE);
6064         }
6065 
6066         if (argc > 2) {
6067                 (void) fprintf(stderr, gettext("too many arguments\n"));
6068                 usage(B_FALSE);
6069         }
6070 
6071         if ((dryrun || xtreme_rewind) && !do_rewind) {
6072                 (void) fprintf(stderr,
6073                     gettext("-n or -X only meaningful with -F\n"));
6074                 usage(B_FALSE);
6075         }
6076         if (dryrun)
6077                 rewind_policy = ZPOOL_TRY_REWIND;
6078         else if (do_rewind)
6079                 rewind_policy = ZPOOL_DO_REWIND;
6080         if (xtreme_rewind)
6081                 rewind_policy |= ZPOOL_EXTREME_REWIND;
6082 
6083         /* In future, further rewind policy choices can be passed along here */
6084         if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
6085             nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
6086             rewind_policy) != 0) {
6087                 return (1);
6088         }
6089 
6090         pool = argv[0];
6091         device = argc == 2 ? argv[1] : NULL;
6092 
6093         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
6094                 nvlist_free(policy);
6095                 return (1);
6096         }
6097 
6098         if (zpool_clear(zhp, device, policy) != 0)
6099                 ret = 1;
6100 
6101         zpool_close(zhp);
6102 
6103         nvlist_free(policy);
6104 
6105         return (ret);
6106 }
6107 
6108 /*
6109  * zpool reguid <pool>
6110  */
6111 int
6112 zpool_do_reguid(int argc, char **argv)
6113 {
6114         int c;
6115         char *poolname;
6116         zpool_handle_t *zhp;
6117         int ret = 0;
6118 
6119         /* check options */
6120         while ((c = getopt(argc, argv, "")) != -1) {
6121                 switch (c) {
6122                 case '?':
6123                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6124                             optopt);
6125                         usage(B_FALSE);
6126                 }
6127         }
6128 
6129         argc -= optind;
6130         argv += optind;
6131 
6132         /* get pool name and check number of arguments */
6133         if (argc < 1) {
6134                 (void) fprintf(stderr, gettext("missing pool name\n"));
6135                 usage(B_FALSE);
6136         }
6137 
6138         if (argc > 1) {
6139                 (void) fprintf(stderr, gettext("too many arguments\n"));
6140                 usage(B_FALSE);
6141         }
6142 
6143         poolname = argv[0];
6144         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6145                 return (1);
6146 
6147         ret = zpool_reguid(zhp);
6148 
6149         zpool_close(zhp);
6150         return (ret);
6151 }
6152 
6153 
6154 /*
6155  * zpool reopen <pool>
6156  *
6157  * Reopen the pool so that the kernel can update the sizes of all vdevs.
6158  */
6159 int
6160 zpool_do_reopen(int argc, char **argv)
6161 {
6162         int c;
6163         int ret = 0;
6164         zpool_handle_t *zhp;
6165         char *pool;
6166 
6167         /* check options */
6168         while ((c = getopt(argc, argv, "")) != -1) {
6169                 switch (c) {
6170                 case '?':
6171                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6172                             optopt);
6173                         usage(B_FALSE);
6174                 }
6175         }
6176 
6177         argc--;
6178         argv++;
6179 
6180         if (argc < 1) {
6181                 (void) fprintf(stderr, gettext("missing pool name\n"));
6182                 usage(B_FALSE);
6183         }
6184 
6185         if (argc > 1) {
6186                 (void) fprintf(stderr, gettext("too many arguments\n"));
6187                 usage(B_FALSE);
6188         }
6189 
6190         pool = argv[0];
6191         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
6192                 return (1);
6193 
6194         ret = zpool_reopen(zhp);
6195         zpool_close(zhp);
6196         return (ret);
6197 }
6198 
6199 typedef struct scrub_cbdata {
6200         int     cb_type;
6201         int     cb_argc;
6202         char    **cb_argv;
6203         pool_scrub_cmd_t cb_scrub_cmd;
6204 } scrub_cbdata_t;
6205 
6206 static boolean_t
6207 zpool_has_checkpoint(zpool_handle_t *zhp)
6208 {
6209         nvlist_t *config, *nvroot;
6210 
6211         config = zpool_get_config(zhp, NULL);
6212 
6213         if (config != NULL) {
6214                 pool_checkpoint_stat_t *pcs = NULL;
6215                 uint_t c;
6216 
6217                 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
6218                 (void) nvlist_lookup_uint64_array(nvroot,
6219                     ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
6220 
6221                 if (pcs == NULL || pcs->pcs_state == CS_NONE)
6222                         return (B_FALSE);
6223 
6224                 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
6225                     pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
6226                 return (B_TRUE);
6227         }
6228 
6229         return (B_FALSE);
6230 }
6231 
6232 int
6233 scrub_callback(zpool_handle_t *zhp, void *data)
6234 {
6235         scrub_cbdata_t *cb = data;
6236         int err;
6237 
6238         /*
6239          * Ignore faulted pools.
6240          */
6241         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
6242                 (void) fprintf(stderr, gettext("cannot scan '%s': pool is "
6243                     "currently unavailable\n"), zpool_get_name(zhp));
6244                 return (1);
6245         }
6246 
6247         err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
6248 
6249         if (err == 0 && zpool_has_checkpoint(zhp) &&
6250             cb->cb_type == POOL_SCAN_SCRUB) {
6251                 (void) printf(gettext("warning: will not scrub state that "
6252                     "belongs to the checkpoint of pool '%s'\n"),
6253                     zpool_get_name(zhp));
6254         }
6255 
6256         return (err != 0);
6257 }
6258 
6259 /*
6260  * zpool scrub [-s | -p] <pool> ...
6261  *
6262  *      -s      Stop.  Stops any in-progress scrub.
6263  *      -p      Pause. Pause in-progress scrub.
6264  */
6265 int
6266 zpool_do_scrub(int argc, char **argv)
6267 {
6268         int c;
6269         scrub_cbdata_t cb;
6270 
6271         cb.cb_type = POOL_SCAN_SCRUB;
6272         cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
6273 
6274         /* check options */
6275         while ((c = getopt(argc, argv, "sp")) != -1) {
6276                 switch (c) {
6277                 case 's':
6278                         cb.cb_type = POOL_SCAN_NONE;
6279                         break;
6280                 case 'p':
6281                         cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
6282                         break;
6283                 case '?':
6284                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6285                             optopt);
6286                         usage(B_FALSE);
6287                 }
6288         }
6289 
6290         if (cb.cb_type == POOL_SCAN_NONE &&
6291             cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
6292                 (void) fprintf(stderr, gettext("invalid option combination: "
6293                     "-s and -p are mutually exclusive\n"));
6294                 usage(B_FALSE);
6295         }
6296 
6297         cb.cb_argc = argc;
6298         cb.cb_argv = argv;
6299         argc -= optind;
6300         argv += optind;
6301 
6302         if (argc < 1) {
6303                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
6304                 usage(B_FALSE);
6305         }
6306 
6307         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
6308 }
6309 
6310 /*
6311  * zpool resilver <pool> ...
6312  *
6313  *      Restarts any in-progress resilver
6314  */
6315 int
6316 zpool_do_resilver(int argc, char **argv)
6317 {
6318         int c;
6319         scrub_cbdata_t cb;
6320 
6321         cb.cb_type = POOL_SCAN_RESILVER;
6322         cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
6323         cb.cb_argc = argc;
6324         cb.cb_argv = argv;
6325 
6326         /* check options */
6327         while ((c = getopt(argc, argv, "")) != -1) {
6328                 switch (c) {
6329                 case '?':
6330                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6331                             optopt);
6332                         usage(B_FALSE);
6333                 }
6334         }
6335 
6336         argc -= optind;
6337         argv += optind;
6338 
6339         if (argc < 1) {
6340                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
6341                 usage(B_FALSE);
6342         }
6343 
6344         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
6345 }
6346 
6347 /*
6348  * zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...]
6349  *
6350  *      -c              Cancel. Ends any in-progress trim.
6351  *      -d              Secure trim.  Requires kernel and device support.
6352  *      -r <rate> Sets the TRIM rate in bytes (per second). Supports
6353  *                      adding a multiplier suffix such as 'k' or 'm'.
6354  *      -s              Suspend. TRIM can then be restarted with no flags.
6355  */
6356 int
6357 zpool_do_trim(int argc, char **argv)
6358 {
6359         struct option long_options[] = {
6360                 {"cancel",      no_argument,            NULL,   'c'},
6361                 {"secure",      no_argument,            NULL,   'd'},
6362                 {"rate",        required_argument,      NULL,   'r'},
6363                 {"suspend",     no_argument,            NULL,   's'},
6364                 {0, 0, 0, 0}
6365         };
6366 
6367         pool_trim_func_t cmd_type = POOL_TRIM_START;
6368         uint64_t rate = 0;
6369         boolean_t secure = B_FALSE;
6370 
6371         int c;
6372         while ((c = getopt_long(argc, argv, "cdr:s", long_options, NULL))
6373             != -1) {
6374                 switch (c) {
6375                 case 'c':
6376                         if (cmd_type != POOL_TRIM_START &&
6377                             cmd_type != POOL_TRIM_CANCEL) {
6378                                 (void) fprintf(stderr, gettext("-c cannot be "
6379                                     "combined with other options\n"));
6380                                 usage(B_FALSE);
6381                         }
6382                         cmd_type = POOL_TRIM_CANCEL;
6383                         break;
6384                 case 'd':
6385                         if (cmd_type != POOL_TRIM_START) {
6386                                 (void) fprintf(stderr, gettext("-d cannot be "
6387                                     "combined with the -c or -s options\n"));
6388                                 usage(B_FALSE);
6389                         }
6390                         secure = B_TRUE;
6391                         break;
6392                 case 'r':
6393                         if (cmd_type != POOL_TRIM_START) {
6394                                 (void) fprintf(stderr, gettext("-r cannot be "
6395                                     "combined with the -c or -s options\n"));
6396                                 usage(B_FALSE);
6397                         }
6398                         if (zfs_nicestrtonum(NULL, optarg, &rate) == -1) {
6399                                 (void) fprintf(stderr,
6400                                     gettext("invalid value for rate\n"));
6401                                 usage(B_FALSE);
6402                         }
6403                         break;
6404                 case 's':
6405                         if (cmd_type != POOL_TRIM_START &&
6406                             cmd_type != POOL_TRIM_SUSPEND) {
6407                                 (void) fprintf(stderr, gettext("-s cannot be "
6408                                     "combined with other options\n"));
6409                                 usage(B_FALSE);
6410                         }
6411                         cmd_type = POOL_TRIM_SUSPEND;
6412                         break;
6413                 case '?':
6414                         if (optopt != 0) {
6415                                 (void) fprintf(stderr,
6416                                     gettext("invalid option '%c'\n"), optopt);
6417                         } else {
6418                                 (void) fprintf(stderr,
6419                                     gettext("invalid option '%s'\n"),
6420                                     argv[optind - 1]);
6421                         }
6422                         usage(B_FALSE);
6423                 }
6424         }
6425 
6426         argc -= optind;
6427         argv += optind;
6428 
6429         if (argc < 1) {
6430                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
6431                 usage(B_FALSE);
6432                 return (-1);
6433         }
6434 
6435         char *poolname = argv[0];
6436         zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
6437         if (zhp == NULL)
6438                 return (-1);
6439 
6440         trimflags_t trim_flags = {
6441                 .secure = secure,
6442                 .rate = rate,
6443         };
6444 
6445         nvlist_t *vdevs = fnvlist_alloc();
6446         if (argc == 1) {
6447                 /* no individual leaf vdevs specified, so add them all */
6448                 nvlist_t *config = zpool_get_config(zhp, NULL);
6449                 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
6450                     ZPOOL_CONFIG_VDEV_TREE);
6451                 zpool_collect_leaves(zhp, nvroot, vdevs);
6452                 trim_flags.fullpool = B_TRUE;
6453         } else {
6454                 trim_flags.fullpool = B_FALSE;
6455                 for (int i = 1; i < argc; i++) {
6456                         fnvlist_add_boolean(vdevs, argv[i]);
6457                 }
6458         }
6459 
6460         int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
6461 
6462         fnvlist_free(vdevs);
6463         zpool_close(zhp);
6464 
6465         return (error);
6466 }
6467 
6468 /*
6469  * zpool initialize [-c | -s] <pool> [<vdev> ...]
6470  * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
6471  * if none specified.
6472  *
6473  *      -c      Cancel. Ends active initializing.
6474  *      -s      Suspend. Initializing can then be restarted with no flags.
6475  */
6476 int
6477 zpool_do_initialize(int argc, char **argv)
6478 {
6479         int c;
6480         char *poolname;
6481         zpool_handle_t *zhp;
6482         nvlist_t *vdevs;
6483         int err = 0;
6484 
6485         struct option long_options[] = {
6486                 {"cancel",      no_argument,            NULL, 'c'},
6487                 {"suspend",     no_argument,            NULL, 's'},
6488                 {0, 0, 0, 0}
6489         };
6490 
6491         pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
6492         while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) {
6493                 switch (c) {
6494                 case 'c':
6495                         if (cmd_type != POOL_INITIALIZE_START &&
6496                             cmd_type != POOL_INITIALIZE_CANCEL) {
6497                                 (void) fprintf(stderr, gettext("-c cannot be "
6498                                     "combined with other options\n"));
6499                                 usage(B_FALSE);
6500                         }
6501                         cmd_type = POOL_INITIALIZE_CANCEL;
6502                         break;
6503                 case 's':
6504                         if (cmd_type != POOL_INITIALIZE_START &&
6505                             cmd_type != POOL_INITIALIZE_SUSPEND) {
6506                                 (void) fprintf(stderr, gettext("-s cannot be "
6507                                     "combined with other options\n"));
6508                                 usage(B_FALSE);
6509                         }
6510                         cmd_type = POOL_INITIALIZE_SUSPEND;
6511                         break;
6512                 case '?':
6513                         if (optopt != 0) {
6514                                 (void) fprintf(stderr,
6515                                     gettext("invalid option '%c'\n"), optopt);
6516                         } else {
6517                                 (void) fprintf(stderr,
6518                                     gettext("invalid option '%s'\n"),
6519                                     argv[optind - 1]);
6520                         }
6521                         usage(B_FALSE);
6522                 }
6523         }
6524 
6525         argc -= optind;
6526         argv += optind;
6527 
6528         if (argc < 1) {
6529                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
6530                 usage(B_FALSE);
6531                 return (-1);
6532         }
6533 
6534         poolname = argv[0];
6535         zhp = zpool_open(g_zfs, poolname);
6536         if (zhp == NULL)
6537                 return (-1);
6538 
6539         vdevs = fnvlist_alloc();
6540         if (argc == 1) {
6541                 /* no individual leaf vdevs specified, so add them all */
6542                 nvlist_t *config = zpool_get_config(zhp, NULL);
6543                 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
6544                     ZPOOL_CONFIG_VDEV_TREE);
6545                 zpool_collect_leaves(zhp, nvroot, vdevs);
6546         } else {
6547                 for (int i = 1; i < argc; i++) {
6548                         fnvlist_add_boolean(vdevs, argv[i]);
6549                 }
6550         }
6551 
6552         err = zpool_initialize(zhp, cmd_type, vdevs);
6553 
6554         fnvlist_free(vdevs);
6555         zpool_close(zhp);
6556 
6557         return (err);
6558 }
6559 
6560 /*
6561  * Print out detailed scrub status.
6562  */
6563 static void
6564 print_scan_status(pool_scan_stat_t *ps)
6565 {
6566         time_t start, end, pause;
6567         uint64_t total_secs_left;
6568         uint64_t elapsed, secs_left, mins_left, hours_left, days_left;
6569         uint64_t pass_scanned, scanned, pass_issued, issued, total;
6570         uint_t scan_rate, issue_rate;
6571         double fraction_done;
6572         char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
6573         char srate_buf[7], irate_buf[7];
6574 
6575         (void) printf(gettext("  scan: "));
6576 
6577         /* If there's never been a scan, there's not much to say. */
6578         if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
6579             ps->pss_func >= POOL_SCAN_FUNCS) {
6580                 (void) printf(gettext("none requested\n"));
6581                 return;
6582         }
6583 
6584         start = ps->pss_start_time;
6585         end = ps->pss_end_time;
6586         pause = ps->pss_pass_scrub_pause;
6587 
6588         zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
6589 
6590         assert(ps->pss_func == POOL_SCAN_SCRUB ||
6591             ps->pss_func == POOL_SCAN_RESILVER);
6592 
6593         /*
6594          * Scan is finished or canceled.
6595          */
6596         if (ps->pss_state == DSS_FINISHED) {
6597                 total_secs_left = end - start;
6598                 days_left = total_secs_left / 60 / 60 / 24;
6599                 hours_left = (total_secs_left / 60 / 60) % 24;
6600                 mins_left = (total_secs_left / 60) % 60;
6601                 secs_left = (total_secs_left % 60);
6602 
6603                 if (ps->pss_func == POOL_SCAN_SCRUB) {
6604                         (void) printf(gettext("scrub repaired %s "
6605                             "in %llu days %02llu:%02llu:%02llu "
6606                             "with %llu errors on %s"), processed_buf,
6607                             (u_longlong_t)days_left, (u_longlong_t)hours_left,
6608                             (u_longlong_t)mins_left, (u_longlong_t)secs_left,
6609                             (u_longlong_t)ps->pss_errors, ctime(&end));
6610                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
6611                         (void) printf(gettext("resilvered %s "
6612                             "in %llu days %02llu:%02llu:%02llu "
6613                             "with %llu errors on %s"), processed_buf,
6614                             (u_longlong_t)days_left, (u_longlong_t)hours_left,
6615                             (u_longlong_t)mins_left, (u_longlong_t)secs_left,
6616                             (u_longlong_t)ps->pss_errors, ctime(&end));
6617                 }
6618                 return;
6619         } else if (ps->pss_state == DSS_CANCELED) {
6620                 if (ps->pss_func == POOL_SCAN_SCRUB) {
6621                         (void) printf(gettext("scrub canceled on %s"),
6622                             ctime(&end));
6623                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
6624                         (void) printf(gettext("resilver canceled on %s"),
6625                             ctime(&end));
6626                 }
6627                 return;
6628         }
6629 
6630         assert(ps->pss_state == DSS_SCANNING);
6631 
6632         /* Scan is in progress. Resilvers can't be paused. */
6633         if (ps->pss_func == POOL_SCAN_SCRUB) {
6634                 if (pause == 0) {
6635                         (void) printf(gettext("scrub in progress since %s"),
6636                             ctime(&start));
6637                 } else {
6638                         (void) printf(gettext("scrub paused since %s"),
6639                             ctime(&pause));
6640                         (void) printf(gettext("\tscrub started on %s"),
6641                             ctime(&start));
6642                 }
6643         } else if (ps->pss_func == POOL_SCAN_RESILVER) {
6644                 (void) printf(gettext("resilver in progress since %s"),
6645                     ctime(&start));
6646         }
6647 
6648         scanned = ps->pss_examined;
6649         pass_scanned = ps->pss_pass_exam;
6650         issued = ps->pss_issued;
6651         pass_issued = ps->pss_pass_issued;
6652         total = ps->pss_to_examine;
6653 
6654         /* we are only done with a block once we have issued the IO for it  */
6655         fraction_done = (double)issued / total;
6656 
6657         /* elapsed time for this pass, rounding up to 1 if it's 0 */
6658         elapsed = time(NULL) - ps->pss_pass_start;
6659         elapsed -= ps->pss_pass_scrub_spent_paused;
6660         elapsed = (elapsed != 0) ? elapsed : 1;
6661 
6662         scan_rate = pass_scanned / elapsed;
6663         issue_rate = pass_issued / elapsed;
6664         total_secs_left = (issue_rate != 0 && total >= issued) ?
6665             ((total - issued) / issue_rate) : UINT64_MAX;
6666 
6667         days_left = total_secs_left / 60 / 60 / 24;
6668         hours_left = (total_secs_left / 60 / 60) % 24;
6669         mins_left = (total_secs_left / 60) % 60;
6670         secs_left = (total_secs_left % 60);
6671 
6672         /* format all of the numbers we will be reporting */
6673         zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf));
6674         zfs_nicenum(issued, issued_buf, sizeof (issued_buf));
6675         zfs_nicenum(total, total_buf, sizeof (total_buf));
6676         zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf));
6677         zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf));
6678 
6679         /* do not print estimated time if we have a paused scrub */
6680         if (pause == 0) {
6681                 (void) printf(gettext("\t%s scanned at %s/s, "
6682                     "%s issued at %s/s, %s total\n"),
6683                     scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
6684         } else {
6685                 (void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
6686                     scanned_buf, issued_buf, total_buf);
6687         }
6688 
6689         if (ps->pss_func == POOL_SCAN_RESILVER) {
6690                 (void) printf(gettext("\t%s resilvered, %.2f%% done"),
6691                     processed_buf, 100 * fraction_done);
6692         } else if (ps->pss_func == POOL_SCAN_SCRUB) {
6693                 (void) printf(gettext("\t%s repaired, %.2f%% done"),
6694                     processed_buf, 100 * fraction_done);
6695         }
6696 
6697         if (pause == 0) {
6698                 if (total_secs_left != UINT64_MAX &&
6699                     issue_rate >= 10 * 1024 * 1024) {
6700                         (void) printf(gettext(", %llu days "
6701                             "%02llu:%02llu:%02llu to go\n"),
6702                             (u_longlong_t)days_left, (u_longlong_t)hours_left,
6703                             (u_longlong_t)mins_left, (u_longlong_t)secs_left);
6704                 } else {
6705                         (void) printf(gettext(", no estimated "
6706                             "completion time\n"));
6707                 }
6708         } else {
6709                 (void) printf(gettext("\n"));
6710         }
6711 }
6712 
6713 /*
6714  * As we don't scrub checkpointed blocks, we want to warn the
6715  * user that we skipped scanning some blocks if a checkpoint exists
6716  * or existed at any time during the scan.
6717  */
6718 static void
6719 print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
6720 {
6721         if (ps == NULL || pcs == NULL)
6722                 return;
6723 
6724         if (pcs->pcs_state == CS_NONE ||
6725             pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
6726                 return;
6727 
6728         assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
6729 
6730         if (ps->pss_state == DSS_NONE)
6731                 return;
6732 
6733         if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
6734             ps->pss_end_time < pcs->pcs_start_time)
6735                 return;
6736 
6737         if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
6738                 (void) printf(gettext("    scan warning: skipped blocks "
6739                     "that are only referenced by the checkpoint.\n"));
6740         } else {
6741                 assert(ps->pss_state == DSS_SCANNING);
6742                 (void) printf(gettext("    scan warning: skipping blocks "
6743                     "that are only referenced by the checkpoint.\n"));
6744         }
6745 }
6746 
6747 /*
6748  * Print out detailed removal status.
6749  */
6750 static void
6751 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
6752 {
6753         char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
6754         time_t start, end;
6755         nvlist_t *config, *nvroot;
6756         nvlist_t **child;
6757         uint_t children;
6758         char *vdev_name;
6759 
6760         if (prs == NULL || prs->prs_state == DSS_NONE)
6761                 return;
6762 
6763         /*
6764          * Determine name of vdev.
6765          */
6766         config = zpool_get_config(zhp, NULL);
6767         nvroot = fnvlist_lookup_nvlist(config,
6768             ZPOOL_CONFIG_VDEV_TREE);
6769         verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
6770             &child, &children) == 0);
6771         assert(prs->prs_removing_vdev < children);
6772         vdev_name = zpool_vdev_name(g_zfs, zhp,
6773             child[prs->prs_removing_vdev], B_TRUE);
6774 
6775         (void) printf(gettext("remove: "));
6776 
6777         start = prs->prs_start_time;
6778         end = prs->prs_end_time;
6779         zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
6780 
6781         /*
6782          * Removal is finished or canceled.
6783          */
6784         if (prs->prs_state == DSS_FINISHED) {
6785                 uint64_t minutes_taken = (end - start) / 60;
6786 
6787                 (void) printf(gettext("Removal of vdev %llu copied %s "
6788                     "in %lluh%um, completed on %s"),
6789                     (longlong_t)prs->prs_removing_vdev,
6790                     copied_buf,
6791                     (u_longlong_t)(minutes_taken / 60),
6792                     (uint_t)(minutes_taken % 60),
6793                     ctime((time_t *)&end));
6794         } else if (prs->prs_state == DSS_CANCELED) {
6795                 (void) printf(gettext("Removal of %s canceled on %s"),
6796                     vdev_name, ctime(&end));
6797         } else {
6798                 uint64_t copied, total, elapsed, mins_left, hours_left;
6799                 double fraction_done;
6800                 uint_t rate;
6801 
6802                 assert(prs->prs_state == DSS_SCANNING);
6803 
6804                 /*
6805                  * Removal is in progress.
6806                  */
6807                 (void) printf(gettext(
6808                     "Evacuation of %s in progress since %s"),
6809                     vdev_name, ctime(&start));
6810 
6811                 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
6812                 total = prs->prs_to_copy;
6813                 fraction_done = (double)copied / total;
6814 
6815                 /* elapsed time for this pass */
6816                 elapsed = time(NULL) - prs->prs_start_time;
6817                 elapsed = elapsed > 0 ? elapsed : 1;
6818                 rate = copied / elapsed;
6819                 rate = rate > 0 ? rate : 1;
6820                 mins_left = ((total - copied) / rate) / 60;
6821                 hours_left = mins_left / 60;
6822 
6823                 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
6824                 zfs_nicenum(total, total_buf, sizeof (total_buf));
6825                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
6826 
6827                 /*
6828                  * do not print estimated time if hours_left is more than
6829                  * 30 days
6830                  */
6831                 (void) printf(gettext("    %s copied out of %s at %s/s, "
6832                     "%.2f%% done"),
6833                     examined_buf, total_buf, rate_buf, 100 * fraction_done);
6834                 if (hours_left < (30 * 24)) {
6835                         (void) printf(gettext(", %lluh%um to go\n"),
6836                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
6837                 } else {
6838                         (void) printf(gettext(
6839                             ", (copy is slow, no estimated time)\n"));
6840                 }
6841         }
6842 
6843         if (prs->prs_mapping_memory > 0) {
6844                 char mem_buf[7];
6845                 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
6846                 (void) printf(gettext("    %s memory used for "
6847                     "removed device mappings\n"),
6848                     mem_buf);
6849         }
6850 }
6851 
6852 static void
6853 print_checkpoint_status(pool_checkpoint_stat_t *pcs)
6854 {
6855         time_t start;
6856         char space_buf[7];
6857 
6858         if (pcs == NULL || pcs->pcs_state == CS_NONE)
6859                 return;
6860 
6861         (void) printf(gettext("checkpoint: "));
6862 
6863         start = pcs->pcs_start_time;
6864         zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
6865 
6866         if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
6867                 char *date = ctime(&start);
6868 
6869                 /*
6870                  * ctime() adds a newline at the end of the generated
6871                  * string, thus the weird format specifier and the
6872                  * strlen() call used to chop it off from the output.
6873                  */
6874                 (void) printf(gettext("created %.*s, consumes %s\n"),
6875                     strlen(date) - 1, date, space_buf);
6876                 return;
6877         }
6878 
6879         assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
6880 
6881         (void) printf(gettext("discarding, %s remaining.\n"),
6882             space_buf);
6883 }
6884 
6885 static void
6886 print_error_log(zpool_handle_t *zhp)
6887 {
6888         nvlist_t *nverrlist = NULL;
6889         nvpair_t *elem;
6890         char *pathname;
6891         size_t len = MAXPATHLEN * 2;
6892 
6893         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
6894                 (void) printf("errors: List of errors unavailable "
6895                     "(insufficient privileges)\n");
6896                 return;
6897         }
6898 
6899         (void) printf("errors: Permanent errors have been "
6900             "detected in the following files:\n\n");
6901 
6902         pathname = safe_malloc(len);
6903         elem = NULL;
6904         while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
6905                 nvlist_t *nv;
6906                 uint64_t dsobj, obj;
6907 
6908                 verify(nvpair_value_nvlist(elem, &nv) == 0);
6909                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
6910                     &dsobj) == 0);
6911                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
6912                     &obj) == 0);
6913                 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
6914                 (void) printf("%7s %s\n", "", pathname);
6915         }
6916         free(pathname);
6917         nvlist_free(nverrlist);
6918 }
6919 
6920 static void
6921 print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares,
6922     uint_t nspares)
6923 {
6924         uint_t i;
6925         char *name;
6926 
6927         if (nspares == 0)
6928                 return;
6929 
6930         (void) printf(gettext("\tspares\n"));
6931 
6932         for (i = 0; i < nspares; i++) {
6933                 name = zpool_vdev_name(g_zfs, zhp, spares[i],
6934                     cb->cb_name_flags);
6935                 print_status_config(zhp, cb, name, spares[i], 2, B_TRUE);
6936                 free(name);
6937         }
6938 }
6939 
6940 static void
6941 print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache,
6942     uint_t nl2cache)
6943 {
6944         uint_t i;
6945         char *name;
6946 
6947         if (nl2cache == 0)
6948                 return;
6949 
6950         (void) printf(gettext("\tcache\n"));
6951 
6952         for (i = 0; i < nl2cache; i++) {
6953                 name = zpool_vdev_name(g_zfs, zhp, l2cache[i],
6954                     cb->cb_name_flags);
6955                 print_status_config(zhp, cb, name, l2cache[i], 2, B_FALSE);
6956                 free(name);
6957         }
6958 }
6959 
6960 static void
6961 print_dedup_stats(nvlist_t *config)
6962 {
6963         ddt_histogram_t *ddh;
6964         ddt_stat_t *dds;
6965         ddt_object_t *ddo;
6966         uint_t c;
6967 
6968         /*
6969          * If the pool was faulted then we may not have been able to
6970          * obtain the config. Otherwise, if we have anything in the dedup
6971          * table continue processing the stats.
6972          */
6973         if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
6974             (uint64_t **)&ddo, &c) != 0)
6975                 return;
6976 
6977         (void) printf("\n");
6978         (void) printf(gettext(" dedup: "));
6979         if (ddo->ddo_count == 0) {
6980                 (void) printf(gettext("no DDT entries\n"));
6981                 return;
6982         }
6983 
6984         (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
6985             (u_longlong_t)ddo->ddo_count,
6986             (u_longlong_t)ddo->ddo_dspace,
6987             (u_longlong_t)ddo->ddo_mspace);
6988 
6989         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
6990             (uint64_t **)&dds, &c) == 0);
6991         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
6992             (uint64_t **)&ddh, &c) == 0);
6993         zpool_dump_ddt(dds, ddh);
6994 }
6995 
6996 /*
6997  * Display a summary of pool status.  Displays a summary such as:
6998  *
6999  *        pool: tank
7000  *      status: DEGRADED
7001  *      reason: One or more devices ...
7002  *         see: http://illumos.org/msg/ZFS-xxxx-01
7003  *      config:
7004  *              mirror          DEGRADED
7005  *                c1t0d0        OK
7006  *                c2t0d0        UNAVAIL
7007  *
7008  * When given the '-v' option, we print out the complete config.  If the '-e'
7009  * option is specified, then we print out error rate information as well.
7010  */
7011 int
7012 status_callback(zpool_handle_t *zhp, void *data)
7013 {
7014         status_cbdata_t *cbp = data;
7015         nvlist_t *config, *nvroot;
7016         char *msgid;
7017         int reason;
7018         zpool_errata_t errata;
7019         const char *health;
7020         uint_t c;
7021         vdev_stat_t *vs;
7022 
7023         config = zpool_get_config(zhp, NULL);
7024         reason = zpool_get_status(zhp, &msgid, &errata);
7025 
7026         cbp->cb_count++;
7027 
7028         /*
7029          * If we were given 'zpool status -x', only report those pools with
7030          * problems.
7031          */
7032         if (cbp->cb_explain &&
7033             (reason == ZPOOL_STATUS_OK ||
7034             reason == ZPOOL_STATUS_VERSION_OLDER ||
7035             reason == ZPOOL_STATUS_FEAT_DISABLED)) {
7036                 if (!cbp->cb_allpools) {
7037                         (void) printf(gettext("pool '%s' is healthy\n"),
7038                             zpool_get_name(zhp));
7039                         if (cbp->cb_first)
7040                                 cbp->cb_first = B_FALSE;
7041                 }
7042                 return (0);
7043         }
7044 
7045         if (cbp->cb_first)
7046                 cbp->cb_first = B_FALSE;
7047         else
7048                 (void) printf("\n");
7049 
7050         nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
7051         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
7052             (uint64_t **)&vs, &c) == 0);
7053         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
7054 
7055         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
7056         (void) printf(gettext(" state: %s\n"), health);
7057 
7058         switch (reason) {
7059         case ZPOOL_STATUS_MISSING_DEV_R:
7060                 (void) printf(gettext("status: One or more devices could not "
7061                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
7062                     "continue functioning in a degraded state.\n"));
7063                 (void) printf(gettext("action: Attach the missing device and "
7064                     "online it using 'zpool online'.\n"));
7065                 break;
7066 
7067         case ZPOOL_STATUS_MISSING_DEV_NR:
7068                 (void) printf(gettext("status: One or more devices could not "
7069                     "be opened.  There are insufficient\n\treplicas for the "
7070                     "pool to continue functioning.\n"));
7071                 (void) printf(gettext("action: Attach the missing device and "
7072                     "online it using 'zpool online'.\n"));
7073                 break;
7074 
7075         case ZPOOL_STATUS_CORRUPT_LABEL_R:
7076                 (void) printf(gettext("status: One or more devices could not "
7077                     "be used because the label is missing or\n\tinvalid.  "
7078                     "Sufficient replicas exist for the pool to continue\n\t"
7079                     "functioning in a degraded state.\n"));
7080                 (void) printf(gettext("action: Replace the device using "
7081                     "'zpool replace'.\n"));
7082                 break;
7083 
7084         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
7085                 (void) printf(gettext("status: One or more devices could not "
7086                     "be used because the label is missing \n\tor invalid.  "
7087                     "There are insufficient replicas for the pool to "
7088                     "continue\n\tfunctioning.\n"));
7089                 zpool_explain_recover(zpool_get_handle(zhp),
7090                     zpool_get_name(zhp), reason, config);
7091                 break;
7092 
7093         case ZPOOL_STATUS_FAILING_DEV:
7094                 (void) printf(gettext("status: One or more devices has "
7095                     "experienced an unrecoverable error.  An\n\tattempt was "
7096                     "made to correct the error.  Applications are "
7097                     "unaffected.\n"));
7098                 (void) printf(gettext("action: Determine if the device needs "
7099                     "to be replaced, and clear the errors\n\tusing "
7100                     "'zpool clear' or replace the device with 'zpool "
7101                     "replace'.\n"));
7102                 break;
7103 
7104         case ZPOOL_STATUS_OFFLINE_DEV:
7105                 (void) printf(gettext("status: One or more devices has "
7106                     "been taken offline by the administrator.\n\tSufficient "
7107                     "replicas exist for the pool to continue functioning in "
7108                     "a\n\tdegraded state.\n"));
7109                 (void) printf(gettext("action: Online the device using "
7110                     "'zpool online' or replace the device with\n\t'zpool "
7111                     "replace'.\n"));
7112                 break;
7113 
7114         case ZPOOL_STATUS_REMOVED_DEV:
7115                 (void) printf(gettext("status: One or more devices has "
7116                     "been removed by the administrator.\n\tSufficient "
7117                     "replicas exist for the pool to continue functioning in "
7118                     "a\n\tdegraded state.\n"));
7119                 (void) printf(gettext("action: Online the device using "
7120                     "'zpool online' or replace the device with\n\t'zpool "
7121                     "replace'.\n"));
7122                 break;
7123 
7124         case ZPOOL_STATUS_RESILVERING:
7125                 (void) printf(gettext("status: One or more devices is "
7126                     "currently being resilvered.  The pool will\n\tcontinue "
7127                     "to function, possibly in a degraded state.\n"));
7128                 (void) printf(gettext("action: Wait for the resilver to "
7129                     "complete.\n"));
7130                 break;
7131 
7132         case ZPOOL_STATUS_CORRUPT_DATA:
7133                 (void) printf(gettext("status: One or more devices has "
7134                     "experienced an error resulting in data\n\tcorruption.  "
7135                     "Applications may be affected.\n"));
7136                 (void) printf(gettext("action: Restore the file in question "
7137                     "if possible.  Otherwise restore the\n\tentire pool from "
7138                     "backup.\n"));
7139                 break;
7140 
7141         case ZPOOL_STATUS_CORRUPT_POOL:
7142                 (void) printf(gettext("status: The pool metadata is corrupted "
7143                     "and the pool cannot be opened.\n"));
7144                 zpool_explain_recover(zpool_get_handle(zhp),
7145                     zpool_get_name(zhp), reason, config);
7146                 break;
7147 
7148         case ZPOOL_STATUS_VERSION_OLDER:
7149                 (void) printf(gettext("status: The pool is formatted using a "
7150                     "legacy on-disk format.  The pool can\n\tstill be used, "
7151                     "but some features are unavailable.\n"));
7152                 (void) printf(gettext("action: Upgrade the pool using 'zpool "
7153                     "upgrade'.  Once this is done, the\n\tpool will no longer "
7154                     "be accessible on software that does not support feature\n"
7155                     "\tflags.\n"));
7156                 break;
7157 
7158         case ZPOOL_STATUS_VERSION_NEWER:
7159                 (void) printf(gettext("status: The pool has been upgraded to a "
7160                     "newer, incompatible on-disk version.\n\tThe pool cannot "
7161                     "be accessed on this system.\n"));
7162                 (void) printf(gettext("action: Access the pool from a system "
7163                     "running more recent software, or\n\trestore the pool from "
7164                     "backup.\n"));
7165                 break;
7166 
7167         case ZPOOL_STATUS_FEAT_DISABLED:
7168                 (void) printf(gettext("status: Some supported features are not "
7169                     "enabled on the pool. The pool can\n\tstill be used, but "
7170                     "some features are unavailable.\n"));
7171                 (void) printf(gettext("action: Enable all features using "
7172                     "'zpool upgrade'. Once this is done,\n\tthe pool may no "
7173                     "longer be accessible by software that does not support\n\t"
7174                     "the features. See zpool-features(5) for details.\n"));
7175                 break;
7176 
7177         case ZPOOL_STATUS_UNSUP_FEAT_READ:
7178                 (void) printf(gettext("status: The pool cannot be accessed on "
7179                     "this system because it uses the\n\tfollowing feature(s) "
7180                     "not supported on this system:\n"));
7181                 zpool_print_unsup_feat(config);
7182                 (void) printf("\n");
7183                 (void) printf(gettext("action: Access the pool from a system "
7184                     "that supports the required feature(s),\n\tor restore the "
7185                     "pool from backup.\n"));
7186                 break;
7187 
7188         case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
7189                 (void) printf(gettext("status: The pool can only be accessed "
7190                     "in read-only mode on this system. It\n\tcannot be "
7191                     "accessed in read-write mode because it uses the "
7192                     "following\n\tfeature(s) not supported on this system:\n"));
7193                 zpool_print_unsup_feat(config);
7194                 (void) printf("\n");
7195                 (void) printf(gettext("action: The pool cannot be accessed in "
7196                     "read-write mode. Import the pool with\n"
7197                     "\t\"-o readonly=on\", access the pool from a system that "
7198                     "supports the\n\trequired feature(s), or restore the "
7199                     "pool from backup.\n"));
7200                 break;
7201 
7202         case ZPOOL_STATUS_FAULTED_DEV_R:
7203                 (void) printf(gettext("status: One or more devices are "
7204                     "faulted in response to persistent errors.\n\tSufficient "
7205                     "replicas exist for the pool to continue functioning "
7206                     "in a\n\tdegraded state.\n"));
7207                 (void) printf(gettext("action: Replace the faulted device, "
7208                     "or use 'zpool clear' to mark the device\n\trepaired.\n"));
7209                 break;
7210 
7211         case ZPOOL_STATUS_FAULTED_DEV_NR:
7212                 (void) printf(gettext("status: One or more devices are "
7213                     "faulted in response to persistent errors.  There are "
7214                     "insufficient replicas for the pool to\n\tcontinue "
7215                     "functioning.\n"));
7216                 (void) printf(gettext("action: Destroy and re-create the pool "
7217                     "from a backup source.  Manually marking the device\n"
7218                     "\trepaired using 'zpool clear' may allow some data "
7219                     "to be recovered.\n"));
7220                 break;
7221 
7222         case ZPOOL_STATUS_IO_FAILURE_MMP:
7223                 (void) printf(gettext("status: The pool is suspended because "
7224                     "multihost writes failed or were delayed;\n\tanother "
7225                     "system could import the pool undetected.\n"));
7226                 (void) printf(gettext("action: Make sure the pool's devices "
7227                     "are connected, then reboot your system and\n\timport the "
7228                     "pool.\n"));
7229                 break;
7230 
7231         case ZPOOL_STATUS_IO_FAILURE_WAIT:
7232         case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
7233                 (void) printf(gettext("status: One or more devices are "
7234                     "faulted in response to IO failures.\n"));
7235                 (void) printf(gettext("action: Make sure the affected devices "
7236                     "are connected, then run 'zpool clear'.\n"));
7237                 break;
7238 
7239         case ZPOOL_STATUS_BAD_LOG:
7240                 (void) printf(gettext("status: An intent log record "
7241                     "could not be read.\n"
7242                     "\tWaiting for adminstrator intervention to fix the "
7243                     "faulted pool.\n"));
7244                 (void) printf(gettext("action: Either restore the affected "
7245                     "device(s) and run 'zpool online',\n"
7246                     "\tor ignore the intent log records by running "
7247                     "'zpool clear'.\n"));
7248                 break;
7249 
7250         case ZPOOL_STATUS_ERRATA:
7251                 (void) printf(gettext("status: Errata #%d detected.\n"),
7252                     errata);
7253 
7254                 switch (errata) {
7255                 case ZPOOL_ERRATA_NONE:
7256                         break;
7257 
7258                 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
7259                         (void) printf(gettext("action: To correct the issue "
7260                             "run 'zpool scrub'.\n"));
7261                         break;
7262 
7263                 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
7264                         (void) printf(gettext("\tExisting encrypted datasets "
7265                             "contain an on-disk incompatibility\n\twhich "
7266                             "needs to be corrected.\n"));
7267                         (void) printf(gettext("action: To correct the issue "
7268                             "backup existing encrypted datasets to new\n\t"
7269                             "encrypted datasets and destroy the old ones. "
7270                             "'zfs mount -o ro' can\n\tbe used to temporarily "
7271                             "mount existing encrypted datasets readonly.\n"));
7272                         break;
7273 
7274                 case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
7275                         (void) printf(gettext("\tExisting encrypted datasets "
7276                             "contain an on-disk incompatibility\n\twhich "
7277                             "needs to be corrected.\n"));
7278                         (void) printf(gettext("action: To correct the issue "
7279                             "enable the bookmark_v2 feature and "
7280                             "backup\n\tany existing encrypted datasets to "
7281                             "new encrypted datasets and\n\tdestroy the old "
7282                             "ones. If this pool does not contain any\n\t"
7283                             "encrypted datasets, simply enable the "
7284                             "bookmark_v2 feature\n"));
7285                         break;
7286 
7287                 default:
7288                         /*
7289                          * All errata which allow the pool to be imported
7290                          * must contain an action message.
7291                          */
7292                         assert(0);
7293                 }
7294                 break;
7295 
7296         default:
7297                 /*
7298                  * The remaining errors can't actually be generated, yet.
7299                  */
7300                 assert(reason == ZPOOL_STATUS_OK);
7301         }
7302 
7303         if (msgid != NULL)
7304                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
7305                     msgid);
7306 
7307         if (config != NULL) {
7308                 uint64_t nerr;
7309                 nvlist_t **spares, **l2cache;
7310                 uint_t nspares, nl2cache;
7311                 pool_checkpoint_stat_t *pcs = NULL;
7312                 pool_scan_stat_t *ps = NULL;
7313                 pool_removal_stat_t *prs = NULL;
7314 
7315                 (void) nvlist_lookup_uint64_array(nvroot,
7316                     ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
7317                 (void) nvlist_lookup_uint64_array(nvroot,
7318                     ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
7319                 (void) nvlist_lookup_uint64_array(nvroot,
7320                     ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
7321 
7322                 print_scan_status(ps);
7323                 print_checkpoint_scan_warning(ps, pcs);
7324                 print_removal_status(zhp, prs);
7325                 print_checkpoint_status(pcs);
7326 
7327                 cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
7328                     cbp->cb_name_flags);
7329                 if (cbp->cb_namewidth < 10)
7330                         cbp->cb_namewidth = 10;
7331 
7332                 (void) printf(gettext("config:\n\n"));
7333                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"),
7334                     cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
7335                     "CKSUM");
7336 
7337                 if (cbp->cb_print_slow_ios)
7338                         (void) printf(" %5s", gettext("SLOW"));
7339 
7340                 print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
7341                     B_FALSE);
7342 
7343                 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP);
7344                 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
7345                 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS);
7346 
7347                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
7348                     &l2cache, &nl2cache) == 0)
7349                         print_l2cache(zhp, cbp, l2cache, nl2cache);
7350 
7351                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
7352                     &spares, &nspares) == 0)
7353                         print_spares(zhp, cbp, spares, nspares);
7354 
7355                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
7356                     &nerr) == 0) {
7357                         nvlist_t *nverrlist = NULL;
7358 
7359                         /*
7360                          * If the approximate error count is small, get a
7361                          * precise count by fetching the entire log and
7362                          * uniquifying the results.
7363                          */
7364                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
7365                             zpool_get_errlog(zhp, &nverrlist) == 0) {
7366                                 nvpair_t *elem;
7367 
7368                                 elem = NULL;
7369                                 nerr = 0;
7370                                 while ((elem = nvlist_next_nvpair(nverrlist,
7371                                     elem)) != NULL) {
7372                                         nerr++;
7373                                 }
7374                         }
7375                         nvlist_free(nverrlist);
7376 
7377                         (void) printf("\n");
7378 
7379                         if (nerr == 0)
7380                                 (void) printf(gettext("errors: No known data "
7381                                     "errors\n"));
7382                         else if (!cbp->cb_verbose)
7383                                 (void) printf(gettext("errors: %llu data "
7384                                     "errors, use '-v' for a list\n"),
7385                                     (u_longlong_t)nerr);
7386                         else
7387                                 print_error_log(zhp);
7388                 }
7389 
7390                 if (cbp->cb_dedup_stats)
7391                         print_dedup_stats(config);
7392         } else {
7393                 (void) printf(gettext("config: The configuration cannot be "
7394                     "determined.\n"));
7395         }
7396 
7397         return (0);
7398 }
7399 
7400 /*
7401  * zpool status [-igLpPstvx] [-T d|u] [pool] ... [interval [count]]
7402  *
7403  *      -i      Display vdev initialization status.
7404  *      -g      Display guid for individual vdev name.
7405  *      -L      Follow links when resolving vdev path name.
7406  *      -p      Display values in parsable (exact) format.
7407  *      -P      Display full path for vdev name.
7408  *      -s      Display slow IOs column.
7409  *      -v      Display complete error logs
7410  *      -x      Display only pools with potential problems
7411  *      -D      Display dedup status (undocumented)
7412  *      -t      Display vdev TRIM status.
7413  *      -T      Display a timestamp in date(1) or Unix format
7414  *
7415  * Describes the health status of all pools or some subset.
7416  */
7417 int
7418 zpool_do_status(int argc, char **argv)
7419 {
7420         int c;
7421         int ret;
7422         float interval = 0;
7423         unsigned long count = 0;
7424         status_cbdata_t cb = { 0 };
7425 
7426         /* check options */
7427         while ((c = getopt(argc, argv, "igLpPsvxDtT:")) != -1) {
7428                 switch (c) {
7429                 case 'i':
7430                         cb.cb_print_vdev_init = B_TRUE;
7431                         break;
7432                 case 'g':
7433                         cb.cb_name_flags |= VDEV_NAME_GUID;
7434                         break;
7435                 case 'L':
7436                         cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
7437                         break;
7438                 case 'p':
7439                         cb.cb_literal = B_TRUE;
7440                         break;
7441                 case 'P':
7442                         cb.cb_name_flags |= VDEV_NAME_PATH;
7443                         break;
7444                 case 's':
7445                         cb.cb_print_slow_ios = B_TRUE;
7446                         break;
7447                 case 'v':
7448                         cb.cb_verbose = B_TRUE;
7449                         break;
7450                 case 'x':
7451                         cb.cb_explain = B_TRUE;
7452                         break;
7453                 case 'D':
7454                         cb.cb_dedup_stats = B_TRUE;
7455                         break;
7456                 case 't':
7457                         cb.cb_print_vdev_trim = B_TRUE;
7458                         break;
7459                 case 'T':
7460                         get_timestamp_arg(*optarg);
7461                         break;
7462                 case '?':
7463                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7464                             optopt);
7465                         usage(B_FALSE);
7466                 }
7467         }
7468 
7469         argc -= optind;
7470         argv += optind;
7471 
7472         get_interval_count(&argc, argv, &interval, &count);
7473 
7474         if (argc == 0)
7475                 cb.cb_allpools = B_TRUE;
7476 
7477         cb.cb_first = B_TRUE;
7478         cb.cb_print_status = B_TRUE;
7479 
7480         for (;;) {
7481                 if (timestamp_fmt != NODATE)
7482                         print_timestamp(timestamp_fmt);
7483 
7484                 ret = for_each_pool(argc, argv, B_TRUE, NULL,
7485                     status_callback, &cb);
7486 
7487                 if (argc == 0 && cb.cb_count == 0)
7488                         (void) printf(gettext("no pools available\n"));
7489                 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
7490                         (void) printf(gettext("all pools are healthy\n"));
7491 
7492                 if (ret != 0)
7493                         return (ret);
7494 
7495                 if (interval == 0)
7496                         break;
7497 
7498                 if (count != 0 && --count == 0)
7499                         break;
7500 
7501                 (void) fsleep(interval);
7502         }
7503 
7504         return (0);
7505 }
7506 
7507 typedef struct upgrade_cbdata {
7508         int     cb_first;
7509         int     cb_argc;
7510         uint64_t cb_version;
7511         char    **cb_argv;
7512 } upgrade_cbdata_t;
7513 
7514 static int
7515 upgrade_version(zpool_handle_t *zhp, uint64_t version)
7516 {
7517         int ret;
7518         nvlist_t *config;
7519         uint64_t oldversion;
7520 
7521         config = zpool_get_config(zhp, NULL);
7522         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
7523             &oldversion) == 0);
7524 
7525         assert(SPA_VERSION_IS_SUPPORTED(oldversion));
7526         assert(oldversion < version);
7527 
7528         ret = zpool_upgrade(zhp, version);
7529         if (ret != 0)
7530                 return (ret);
7531 
7532         if (version >= SPA_VERSION_FEATURES) {
7533                 (void) printf(gettext("Successfully upgraded "
7534                     "'%s' from version %llu to feature flags.\n"),
7535                     zpool_get_name(zhp), oldversion);
7536         } else {
7537                 (void) printf(gettext("Successfully upgraded "
7538                     "'%s' from version %llu to version %llu.\n"),
7539                     zpool_get_name(zhp), oldversion, version);
7540         }
7541 
7542         return (0);
7543 }
7544 
7545 static int
7546 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
7547 {
7548         int i, ret, count;
7549         boolean_t firstff = B_TRUE;
7550         nvlist_t *enabled = zpool_get_features(zhp);
7551 
7552         count = 0;
7553         for (i = 0; i < SPA_FEATURES; i++) {
7554                 const char *fname = spa_feature_table[i].fi_uname;
7555                 const char *fguid = spa_feature_table[i].fi_guid;
7556                 if (!nvlist_exists(enabled, fguid)) {
7557                         char *propname;
7558                         verify(-1 != asprintf(&propname, "feature@%s", fname));
7559                         ret = zpool_set_prop(zhp, propname,
7560                             ZFS_FEATURE_ENABLED);
7561                         if (ret != 0) {
7562                                 free(propname);
7563                                 return (ret);
7564                         }
7565                         count++;
7566 
7567                         if (firstff) {
7568                                 (void) printf(gettext("Enabled the "
7569                                     "following features on '%s':\n"),
7570                                     zpool_get_name(zhp));
7571                                 firstff = B_FALSE;
7572                         }
7573                         (void) printf(gettext("  %s\n"), fname);
7574                         free(propname);
7575                 }
7576         }
7577 
7578         if (countp != NULL)
7579                 *countp = count;
7580         return (0);
7581 }
7582 
7583 static int
7584 upgrade_cb(zpool_handle_t *zhp, void *arg)
7585 {
7586         upgrade_cbdata_t *cbp = arg;
7587         nvlist_t *config;
7588         uint64_t version;
7589         boolean_t printnl = B_FALSE;
7590         int ret;
7591 
7592         config = zpool_get_config(zhp, NULL);
7593         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
7594             &version) == 0);
7595 
7596         assert(SPA_VERSION_IS_SUPPORTED(version));
7597 
7598         if (version < cbp->cb_version) {
7599                 cbp->cb_first = B_FALSE;
7600                 ret = upgrade_version(zhp, cbp->cb_version);
7601                 if (ret != 0)
7602                         return (ret);
7603                 printnl = B_TRUE;
7604 
7605                 /*
7606                  * If they did "zpool upgrade -a", then we could
7607                  * be doing ioctls to different pools.  We need
7608                  * to log this history once to each pool, and bypass
7609                  * the normal history logging that happens in main().
7610                  */
7611                 (void) zpool_log_history(g_zfs, history_str);
7612                 log_history = B_FALSE;
7613         }
7614 
7615         if (cbp->cb_version >= SPA_VERSION_FEATURES) {
7616                 int count;
7617                 ret = upgrade_enable_all(zhp, &count);
7618                 if (ret != 0)
7619                         return (ret);
7620 
7621                 if (count > 0) {
7622                         cbp->cb_first = B_FALSE;
7623                         printnl = B_TRUE;
7624                 }
7625         }
7626 
7627         if (printnl) {
7628                 (void) printf(gettext("\n"));
7629         }
7630 
7631         return (0);
7632 }
7633 
7634 static int
7635 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
7636 {
7637         upgrade_cbdata_t *cbp = arg;
7638         nvlist_t *config;
7639         uint64_t version;
7640 
7641         config = zpool_get_config(zhp, NULL);
7642         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
7643             &version) == 0);
7644 
7645         assert(SPA_VERSION_IS_SUPPORTED(version));
7646 
7647         if (version < SPA_VERSION_FEATURES) {
7648                 if (cbp->cb_first) {
7649                         (void) printf(gettext("The following pools are "
7650                             "formatted with legacy version numbers and can\n"
7651                             "be upgraded to use feature flags.  After "
7652                             "being upgraded, these pools\nwill no "
7653                             "longer be accessible by software that does not "
7654                             "support feature\nflags.\n\n"));
7655                         (void) printf(gettext("VER  POOL\n"));
7656                         (void) printf(gettext("---  ------------\n"));
7657                         cbp->cb_first = B_FALSE;
7658                 }
7659 
7660                 (void) printf("%2llu   %s\n", (u_longlong_t)version,
7661                     zpool_get_name(zhp));
7662         }
7663 
7664         return (0);
7665 }
7666 
7667 static int
7668 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
7669 {
7670         upgrade_cbdata_t *cbp = arg;
7671         nvlist_t *config;
7672         uint64_t version;
7673 
7674         config = zpool_get_config(zhp, NULL);
7675         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
7676             &version) == 0);
7677 
7678         if (version >= SPA_VERSION_FEATURES) {
7679                 int i;
7680                 boolean_t poolfirst = B_TRUE;
7681                 nvlist_t *enabled = zpool_get_features(zhp);
7682 
7683                 for (i = 0; i < SPA_FEATURES; i++) {
7684                         const char *fguid = spa_feature_table[i].fi_guid;
7685                         const char *fname = spa_feature_table[i].fi_uname;
7686                         if (!nvlist_exists(enabled, fguid)) {
7687                                 if (cbp->cb_first) {
7688                                         (void) printf(gettext("\nSome "
7689                                             "supported features are not "
7690                                             "enabled on the following pools. "
7691                                             "Once a\nfeature is enabled the "
7692                                             "pool may become incompatible with "
7693                                             "software\nthat does not support "
7694                                             "the feature. See "
7695                                             "zpool-features(5) for "
7696                                             "details.\n\n"));
7697                                         (void) printf(gettext("POOL  "
7698                                             "FEATURE\n"));
7699                                         (void) printf(gettext("------"
7700                                             "---------\n"));
7701                                         cbp->cb_first = B_FALSE;
7702                                 }
7703 
7704                                 if (poolfirst) {
7705                                         (void) printf(gettext("%s\n"),
7706                                             zpool_get_name(zhp));
7707                                         poolfirst = B_FALSE;
7708                                 }
7709 
7710                                 (void) printf(gettext("      %s\n"), fname);
7711                         }
7712                 }
7713         }
7714 
7715         return (0);
7716 }
7717 
7718 /* ARGSUSED */
7719 static int
7720 upgrade_one(zpool_handle_t *zhp, void *data)
7721 {
7722         boolean_t printnl = B_FALSE;
7723         upgrade_cbdata_t *cbp = data;
7724         uint64_t cur_version;
7725         int ret;
7726 
7727         if (strcmp("log", zpool_get_name(zhp)) == 0) {
7728                 (void) printf(gettext("'log' is now a reserved word\n"
7729                     "Pool 'log' must be renamed using export and import"
7730                     " to upgrade.\n"));
7731                 return (1);
7732         }
7733 
7734         cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
7735         if (cur_version > cbp->cb_version) {
7736                 (void) printf(gettext("Pool '%s' is already formatted "
7737                     "using more current version '%llu'.\n\n"),
7738                     zpool_get_name(zhp), cur_version);
7739                 return (0);
7740         }
7741 
7742         if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
7743                 (void) printf(gettext("Pool '%s' is already formatted "
7744                     "using version %llu.\n\n"), zpool_get_name(zhp),
7745                     cbp->cb_version);
7746                 return (0);
7747         }
7748 
7749         if (cur_version != cbp->cb_version) {
7750                 printnl = B_TRUE;
7751                 ret = upgrade_version(zhp, cbp->cb_version);
7752                 if (ret != 0)
7753                         return (ret);
7754         }
7755 
7756         if (cbp->cb_version >= SPA_VERSION_FEATURES) {
7757                 int count = 0;
7758                 ret = upgrade_enable_all(zhp, &count);
7759                 if (ret != 0)
7760                         return (ret);
7761 
7762                 if (count != 0) {
7763                         printnl = B_TRUE;
7764                 } else if (cur_version == SPA_VERSION) {
7765                         (void) printf(gettext("Pool '%s' already has all "
7766                             "supported features enabled.\n"),
7767                             zpool_get_name(zhp));
7768                 }
7769         }
7770 
7771         if (printnl) {
7772                 (void) printf(gettext("\n"));
7773         }
7774 
7775         return (0);
7776 }
7777 
7778 /*
7779  * zpool upgrade
7780  * zpool upgrade -v
7781  * zpool upgrade [-V version] <-a | pool ...>
7782  *
7783  * With no arguments, display downrev'd ZFS pool available for upgrade.
7784  * Individual pools can be upgraded by specifying the pool, and '-a' will
7785  * upgrade all pools.
7786  */
7787 int
7788 zpool_do_upgrade(int argc, char **argv)
7789 {
7790         int c;
7791         upgrade_cbdata_t cb = { 0 };
7792         int ret = 0;
7793         boolean_t showversions = B_FALSE;
7794         boolean_t upgradeall = B_FALSE;
7795         char *end;
7796 
7797 
7798         /* check options */
7799         while ((c = getopt(argc, argv, ":avV:")) != -1) {
7800                 switch (c) {
7801                 case 'a':
7802                         upgradeall = B_TRUE;
7803                         break;
7804                 case 'v':
7805                         showversions = B_TRUE;
7806                         break;
7807                 case 'V':
7808                         cb.cb_version = strtoll(optarg, &end, 10);
7809                         if (*end != '\0' ||
7810                             !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
7811                                 (void) fprintf(stderr,
7812                                     gettext("invalid version '%s'\n"), optarg);
7813                                 usage(B_FALSE);
7814                         }
7815                         break;
7816                 case ':':
7817                         (void) fprintf(stderr, gettext("missing argument for "
7818                             "'%c' option\n"), optopt);
7819                         usage(B_FALSE);
7820                         break;
7821                 case '?':
7822                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7823                             optopt);
7824                         usage(B_FALSE);
7825                 }
7826         }
7827 
7828         cb.cb_argc = argc;
7829         cb.cb_argv = argv;
7830         argc -= optind;
7831         argv += optind;
7832 
7833         if (cb.cb_version == 0) {
7834                 cb.cb_version = SPA_VERSION;
7835         } else if (!upgradeall && argc == 0) {
7836                 (void) fprintf(stderr, gettext("-V option is "
7837                     "incompatible with other arguments\n"));
7838                 usage(B_FALSE);
7839         }
7840 
7841         if (showversions) {
7842                 if (upgradeall || argc != 0) {
7843                         (void) fprintf(stderr, gettext("-v option is "
7844                             "incompatible with other arguments\n"));
7845                         usage(B_FALSE);
7846                 }
7847         } else if (upgradeall) {
7848                 if (argc != 0) {
7849                         (void) fprintf(stderr, gettext("-a option should not "
7850                             "be used along with a pool name\n"));
7851                         usage(B_FALSE);
7852                 }
7853         }
7854 
7855         (void) printf(gettext("This system supports ZFS pool feature "
7856             "flags.\n\n"));
7857         if (showversions) {
7858                 int i;
7859 
7860                 (void) printf(gettext("The following features are "
7861                     "supported:\n\n"));
7862                 (void) printf(gettext("FEAT DESCRIPTION\n"));
7863                 (void) printf("----------------------------------------------"
7864                     "---------------\n");
7865                 for (i = 0; i < SPA_FEATURES; i++) {
7866                         zfeature_info_t *fi = &spa_feature_table[i];
7867                         const char *ro =
7868                             (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
7869                             " (read-only compatible)" : "";
7870 
7871                         (void) printf("%-37s%s\n", fi->fi_uname, ro);
7872                         (void) printf("     %s\n", fi->fi_desc);
7873                 }
7874                 (void) printf("\n");
7875 
7876                 (void) printf(gettext("The following legacy versions are also "
7877                     "supported:\n\n"));
7878                 (void) printf(gettext("VER  DESCRIPTION\n"));
7879                 (void) printf("---  -----------------------------------------"
7880                     "---------------\n");
7881                 (void) printf(gettext(" 1   Initial ZFS version\n"));
7882                 (void) printf(gettext(" 2   Ditto blocks "
7883                     "(replicated metadata)\n"));
7884                 (void) printf(gettext(" 3   Hot spares and double parity "
7885                     "RAID-Z\n"));
7886                 (void) printf(gettext(" 4   zpool history\n"));
7887                 (void) printf(gettext(" 5   Compression using the gzip "
7888                     "algorithm\n"));
7889                 (void) printf(gettext(" 6   bootfs pool property\n"));
7890                 (void) printf(gettext(" 7   Separate intent log devices\n"));
7891                 (void) printf(gettext(" 8   Delegated administration\n"));
7892                 (void) printf(gettext(" 9   refquota and refreservation "
7893                     "properties\n"));
7894                 (void) printf(gettext(" 10  Cache devices\n"));
7895                 (void) printf(gettext(" 11  Improved scrub performance\n"));
7896                 (void) printf(gettext(" 12  Snapshot properties\n"));
7897                 (void) printf(gettext(" 13  snapused property\n"));
7898                 (void) printf(gettext(" 14  passthrough-x aclinherit\n"));
7899                 (void) printf(gettext(" 15  user/group space accounting\n"));
7900                 (void) printf(gettext(" 16  stmf property support\n"));
7901                 (void) printf(gettext(" 17  Triple-parity RAID-Z\n"));
7902                 (void) printf(gettext(" 18  Snapshot user holds\n"));
7903                 (void) printf(gettext(" 19  Log device removal\n"));
7904                 (void) printf(gettext(" 20  Compression using zle "
7905                     "(zero-length encoding)\n"));
7906                 (void) printf(gettext(" 21  Deduplication\n"));
7907                 (void) printf(gettext(" 22  Received properties\n"));
7908                 (void) printf(gettext(" 23  Slim ZIL\n"));
7909                 (void) printf(gettext(" 24  System attributes\n"));
7910                 (void) printf(gettext(" 25  Improved scrub stats\n"));
7911                 (void) printf(gettext(" 26  Improved snapshot deletion "
7912                     "performance\n"));
7913                 (void) printf(gettext(" 27  Improved snapshot creation "
7914                     "performance\n"));
7915                 (void) printf(gettext(" 28  Multiple vdev replacements\n"));
7916                 (void) printf(gettext("\nFor more information on a particular "
7917                     "version, including supported releases,\n"));
7918                 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
7919         } else if (argc == 0 && upgradeall) {
7920                 cb.cb_first = B_TRUE;
7921                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
7922                 if (ret == 0 && cb.cb_first) {
7923                         if (cb.cb_version == SPA_VERSION) {
7924                                 (void) printf(gettext("All pools are already "
7925                                     "formatted using feature flags.\n\n"));
7926                                 (void) printf(gettext("Every feature flags "
7927                                     "pool already has all supported features "
7928                                     "enabled.\n"));
7929                         } else {
7930                                 (void) printf(gettext("All pools are already "
7931                                     "formatted with version %llu or higher.\n"),
7932                                     cb.cb_version);
7933                         }
7934                 }
7935         } else if (argc == 0) {
7936                 cb.cb_first = B_TRUE;
7937                 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
7938                 assert(ret == 0);
7939 
7940                 if (cb.cb_first) {
7941                         (void) printf(gettext("All pools are formatted "
7942                             "using feature flags.\n\n"));
7943                 } else {
7944                         (void) printf(gettext("\nUse 'zpool upgrade -v' "
7945                             "for a list of available legacy versions.\n"));
7946                 }
7947 
7948                 cb.cb_first = B_TRUE;
7949                 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
7950                 assert(ret == 0);
7951 
7952                 if (cb.cb_first) {
7953                         (void) printf(gettext("Every feature flags pool has "
7954                             "all supported features enabled.\n"));
7955                 } else {
7956                         (void) printf(gettext("\n"));
7957                 }
7958         } else {
7959                 ret = for_each_pool(argc, argv, B_FALSE, NULL,
7960                     upgrade_one, &cb);
7961         }
7962 
7963         return (ret);
7964 }
7965 
7966 typedef struct hist_cbdata {
7967         boolean_t first;
7968         boolean_t longfmt;
7969         boolean_t internal;
7970 } hist_cbdata_t;
7971 
7972 static void
7973 print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb)
7974 {
7975         nvlist_t **records;
7976         uint_t numrecords;
7977         int i;
7978 
7979         verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
7980             &records, &numrecords) == 0);
7981         for (i = 0; i < numrecords; i++) {
7982                 nvlist_t *rec = records[i];
7983                 char tbuf[30] = "";
7984 
7985                 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
7986                         time_t tsec;
7987                         struct tm t;
7988 
7989                         tsec = fnvlist_lookup_uint64(records[i],
7990                             ZPOOL_HIST_TIME);
7991                         (void) localtime_r(&tsec, &t);
7992                         (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
7993                 }
7994 
7995                 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
7996                         (void) printf("%s %s", tbuf,
7997                             fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
7998                 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
7999                         int ievent =
8000                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
8001                         if (!cb->internal)
8002                                 continue;
8003                         if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
8004                                 (void) printf("%s unrecognized record:\n",
8005                                     tbuf);
8006                                 dump_nvlist(rec, 4);
8007                                 continue;
8008                         }
8009                         (void) printf("%s [internal %s txg:%lld] %s", tbuf,
8010                             zfs_history_event_names[ievent],
8011                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
8012                             fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
8013                 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
8014                         if (!cb->internal)
8015                                 continue;
8016                         (void) printf("%s [txg:%lld] %s", tbuf,
8017                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
8018                             fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
8019                         if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
8020                                 (void) printf(" %s (%llu)",
8021                                     fnvlist_lookup_string(rec,
8022                                     ZPOOL_HIST_DSNAME),
8023                                     fnvlist_lookup_uint64(rec,
8024                                     ZPOOL_HIST_DSID));
8025                         }
8026                         (void) printf(" %s", fnvlist_lookup_string(rec,
8027                             ZPOOL_HIST_INT_STR));
8028                 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
8029                         if (!cb->internal)
8030                                 continue;
8031                         (void) printf("%s ioctl %s\n", tbuf,
8032                             fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
8033                         if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
8034                                 (void) printf("    input:\n");
8035                                 dump_nvlist(fnvlist_lookup_nvlist(rec,
8036                                     ZPOOL_HIST_INPUT_NVL), 8);
8037                         }
8038                         if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
8039                                 (void) printf("    output:\n");
8040                                 dump_nvlist(fnvlist_lookup_nvlist(rec,
8041                                     ZPOOL_HIST_OUTPUT_NVL), 8);
8042                         }
8043                         if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
8044                                 (void) printf("    errno: %lld\n",
8045                                     fnvlist_lookup_int64(rec,
8046                                     ZPOOL_HIST_ERRNO));
8047                         }
8048                 } else {
8049                         if (!cb->internal)
8050                                 continue;
8051                         (void) printf("%s unrecognized record:\n", tbuf);
8052                         dump_nvlist(rec, 4);
8053                 }
8054 
8055                 if (!cb->longfmt) {
8056                         (void) printf("\n");
8057                         continue;
8058                 }
8059                 (void) printf(" [");
8060                 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
8061                         uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
8062                         struct passwd *pwd = getpwuid(who);
8063                         (void) printf("user %d ", (int)who);
8064                         if (pwd != NULL)
8065                                 (void) printf("(%s) ", pwd->pw_name);
8066                 }
8067                 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
8068                         (void) printf("on %s",
8069                             fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
8070                 }
8071                 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
8072                         (void) printf(":%s",
8073                             fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
8074                 }
8075                 (void) printf("]");
8076                 (void) printf("\n");
8077         }
8078 }
8079 
8080 /*
8081  * Print out the command history for a specific pool.
8082  */
8083 static int
8084 get_history_one(zpool_handle_t *zhp, void *data)
8085 {
8086         nvlist_t *nvhis;
8087         int ret;
8088         hist_cbdata_t *cb = (hist_cbdata_t *)data;
8089         uint64_t off = 0;
8090         boolean_t eof = B_FALSE;
8091 
8092         cb->first = B_FALSE;
8093 
8094         (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
8095 
8096         while (!eof) {
8097                 if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0)
8098                         return (ret);
8099 
8100                 print_history_records(nvhis, cb);
8101                 nvlist_free(nvhis);
8102         }
8103         (void) printf("\n");
8104 
8105         return (ret);
8106 }
8107 
8108 /*
8109  * zpool history <pool>
8110  *
8111  * Displays the history of commands that modified pools.
8112  */
8113 int
8114 zpool_do_history(int argc, char **argv)
8115 {
8116         hist_cbdata_t cbdata = { 0 };
8117         int ret;
8118         int c;
8119 
8120         cbdata.first = B_TRUE;
8121         /* check options */
8122         while ((c = getopt(argc, argv, "li")) != -1) {
8123                 switch (c) {
8124                 case 'l':
8125                         cbdata.longfmt = B_TRUE;
8126                         break;
8127                 case 'i':
8128                         cbdata.internal = B_TRUE;
8129                         break;
8130                 case '?':
8131                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
8132                             optopt);
8133                         usage(B_FALSE);
8134                 }
8135         }
8136         argc -= optind;
8137         argv += optind;
8138 
8139         ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
8140             &cbdata);
8141 
8142         if (argc == 0 && cbdata.first == B_TRUE) {
8143                 (void) printf(gettext("no pools available\n"));
8144                 return (0);
8145         }
8146 
8147         return (ret);
8148 }
8149 
8150 static int
8151 get_callback(zpool_handle_t *zhp, void *data)
8152 {
8153         zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
8154         char value[MAXNAMELEN];
8155         zprop_source_t srctype;
8156         zprop_list_t *pl;
8157 
8158         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
8159 
8160                 /*
8161                  * Skip the special fake placeholder. This will also skip
8162                  * over the name property when 'all' is specified.
8163                  */
8164                 if (pl->pl_prop == ZPOOL_PROP_NAME &&
8165                     pl == cbp->cb_proplist)
8166                         continue;
8167 
8168                 if (pl->pl_prop == ZPROP_INVAL &&
8169                     (zpool_prop_feature(pl->pl_user_prop) ||
8170                     zpool_prop_unsupported(pl->pl_user_prop))) {
8171                         srctype = ZPROP_SRC_LOCAL;
8172 
8173                         if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
8174                             value, sizeof (value)) == 0) {
8175                                 zprop_print_one_property(zpool_get_name(zhp),
8176                                     cbp, pl->pl_user_prop, value, srctype,
8177                                     NULL, NULL);
8178                         }
8179                 } else {
8180                         if (zpool_get_prop(zhp, pl->pl_prop, value,
8181                             sizeof (value), &srctype, cbp->cb_literal) != 0)
8182                                 continue;
8183 
8184                         zprop_print_one_property(zpool_get_name(zhp), cbp,
8185                             zpool_prop_to_name(pl->pl_prop), value, srctype,
8186                             NULL, NULL);
8187                 }
8188         }
8189         return (0);
8190 }
8191 
8192 /*
8193  * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
8194  *
8195  *      -H      Scripted mode.  Don't display headers, and separate properties
8196  *              by a single tab.
8197  *      -o      List of columns to display.  Defaults to
8198  *              "name,property,value,source".
8199  *      -p      Diplay values in parsable (exact) format.
8200  *
8201  * Get properties of pools in the system. Output space statistics
8202  * for each one as well as other attributes.
8203  */
8204 int
8205 zpool_do_get(int argc, char **argv)
8206 {
8207         zprop_get_cbdata_t cb = { 0 };
8208         zprop_list_t fake_name = { 0 };
8209         int ret;
8210         int c, i;
8211         char *value;
8212 
8213         cb.cb_first = B_TRUE;
8214 
8215         /*
8216          * Set up default columns and sources.
8217          */
8218         cb.cb_sources = ZPROP_SRC_ALL;
8219         cb.cb_columns[0] = GET_COL_NAME;
8220         cb.cb_columns[1] = GET_COL_PROPERTY;
8221         cb.cb_columns[2] = GET_COL_VALUE;
8222         cb.cb_columns[3] = GET_COL_SOURCE;
8223         cb.cb_type = ZFS_TYPE_POOL;
8224 
8225         /* check options */
8226         while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
8227                 switch (c) {
8228                 case 'p':
8229                         cb.cb_literal = B_TRUE;
8230                         break;
8231                 case 'H':
8232                         cb.cb_scripted = B_TRUE;
8233                         break;
8234                 case 'o':
8235                         bzero(&cb.cb_columns, sizeof (cb.cb_columns));
8236                         i = 0;
8237                         while (*optarg != '\0') {
8238                                 static char *col_subopts[] =
8239                                 { "name", "property", "value", "source",
8240                                 "all", NULL };
8241 
8242                                 if (i == ZFS_GET_NCOLS) {
8243                                         (void) fprintf(stderr, gettext("too "
8244                                         "many fields given to -o "
8245                                         "option\n"));
8246                                         usage(B_FALSE);
8247                                 }
8248 
8249                                 switch (getsubopt(&optarg, col_subopts,
8250                                     &value)) {
8251                                 case 0:
8252                                         cb.cb_columns[i++] = GET_COL_NAME;
8253                                         break;
8254                                 case 1:
8255                                         cb.cb_columns[i++] = GET_COL_PROPERTY;
8256                                         break;
8257                                 case 2:
8258                                         cb.cb_columns[i++] = GET_COL_VALUE;
8259                                         break;
8260                                 case 3:
8261                                         cb.cb_columns[i++] = GET_COL_SOURCE;
8262                                         break;
8263                                 case 4:
8264                                         if (i > 0) {
8265                                                 (void) fprintf(stderr,
8266                                                     gettext("\"all\" conflicts "
8267                                                     "with specific fields "
8268                                                     "given to -o option\n"));
8269                                                 usage(B_FALSE);
8270                                         }
8271                                         cb.cb_columns[0] = GET_COL_NAME;
8272                                         cb.cb_columns[1] = GET_COL_PROPERTY;
8273                                         cb.cb_columns[2] = GET_COL_VALUE;
8274                                         cb.cb_columns[3] = GET_COL_SOURCE;
8275                                         i = ZFS_GET_NCOLS;
8276                                         break;
8277                                 default:
8278                                         (void) fprintf(stderr,
8279                                             gettext("invalid column name "
8280                                             "'%s'\n"), value);
8281                                         usage(B_FALSE);
8282                                 }
8283                         }
8284                         break;
8285                 case '?':
8286                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
8287                             optopt);
8288                         usage(B_FALSE);
8289                 }
8290         }
8291 
8292         argc -= optind;
8293         argv += optind;
8294 
8295         if (argc < 1) {
8296                 (void) fprintf(stderr, gettext("missing property "
8297                     "argument\n"));
8298                 usage(B_FALSE);
8299         }
8300 
8301         if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
8302             ZFS_TYPE_POOL) != 0)
8303                 usage(B_FALSE);
8304 
8305         argc--;
8306         argv++;
8307 
8308         if (cb.cb_proplist != NULL) {
8309                 fake_name.pl_prop = ZPOOL_PROP_NAME;
8310                 fake_name.pl_width = strlen(gettext("NAME"));
8311                 fake_name.pl_next = cb.cb_proplist;
8312                 cb.cb_proplist = &fake_name;
8313         }
8314 
8315         ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
8316             get_callback, &cb);
8317 
8318         if (cb.cb_proplist == &fake_name)
8319                 zprop_free_list(fake_name.pl_next);
8320         else
8321                 zprop_free_list(cb.cb_proplist);
8322 
8323         return (ret);
8324 }
8325 
8326 typedef struct set_cbdata {
8327         char *cb_propname;
8328         char *cb_value;
8329         boolean_t cb_any_successful;
8330 } set_cbdata_t;
8331 
8332 int
8333 set_callback(zpool_handle_t *zhp, void *data)
8334 {
8335         int error;
8336         set_cbdata_t *cb = (set_cbdata_t *)data;
8337 
8338         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
8339 
8340         if (!error)
8341                 cb->cb_any_successful = B_TRUE;
8342 
8343         return (error);
8344 }
8345 
8346 int
8347 zpool_do_set(int argc, char **argv)
8348 {
8349         set_cbdata_t cb = { 0 };
8350         int error;
8351 
8352         if (argc > 1 && argv[1][0] == '-') {
8353                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
8354                     argv[1][1]);
8355                 usage(B_FALSE);
8356         }
8357 
8358         if (argc < 2) {
8359                 (void) fprintf(stderr, gettext("missing property=value "
8360                     "argument\n"));
8361                 usage(B_FALSE);
8362         }
8363 
8364         if (argc < 3) {
8365                 (void) fprintf(stderr, gettext("missing pool name\n"));
8366                 usage(B_FALSE);
8367         }
8368 
8369         if (argc > 3) {
8370                 (void) fprintf(stderr, gettext("too many pool names\n"));
8371                 usage(B_FALSE);
8372         }
8373 
8374         cb.cb_propname = argv[1];
8375         cb.cb_value = strchr(cb.cb_propname, '=');
8376         if (cb.cb_value == NULL) {
8377                 (void) fprintf(stderr, gettext("missing value in "
8378                     "property=value argument\n"));
8379                 usage(B_FALSE);
8380         }
8381 
8382         *(cb.cb_value) = '\0';
8383         cb.cb_value++;
8384 
8385         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
8386             set_callback, &cb);
8387 
8388         return (error);
8389 }
8390 
8391 static int
8392 find_command_idx(char *command, int *idx)
8393 {
8394         int i;
8395 
8396         for (i = 0; i < NCOMMAND; i++) {
8397                 if (command_table[i].name == NULL)
8398                         continue;
8399 
8400                 if (strcmp(command, command_table[i].name) == 0) {
8401                         *idx = i;
8402                         return (0);
8403                 }
8404         }
8405         return (1);
8406 }
8407 
8408 int
8409 main(int argc, char **argv)
8410 {
8411         int ret = 0;
8412         int i;
8413         char *cmdname;
8414 
8415         (void) setlocale(LC_ALL, "");
8416         (void) textdomain(TEXT_DOMAIN);
8417 
8418         if ((g_zfs = libzfs_init()) == NULL) {
8419                 (void) fprintf(stderr, gettext("internal error: failed to "
8420                     "initialize ZFS library\n"));
8421                 return (1);
8422         }
8423 
8424         libzfs_print_on_error(g_zfs, B_TRUE);
8425 
8426         opterr = 0;
8427 
8428         /*
8429          * Make sure the user has specified some command.
8430          */
8431         if (argc < 2) {
8432                 (void) fprintf(stderr, gettext("missing command\n"));
8433                 usage(B_FALSE);
8434         }
8435 
8436         cmdname = argv[1];
8437 
8438         /*
8439          * Special case '-?'
8440          */
8441         if (strcmp(cmdname, "-?") == 0)
8442                 usage(B_TRUE);
8443 
8444         zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
8445 
8446         /*
8447          * Run the appropriate command.
8448          */
8449         if (find_command_idx(cmdname, &i) == 0) {
8450                 current_command = &command_table[i];
8451                 ret = command_table[i].func(argc - 1, argv + 1);
8452         } else if (strchr(cmdname, '=')) {
8453                 verify(find_command_idx("set", &i) == 0);
8454                 current_command = &command_table[i];
8455                 ret = command_table[i].func(argc, argv);
8456         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
8457                 /*
8458                  * 'freeze' is a vile debugging abomination, so we treat
8459                  * it as such.
8460                  */
8461                 char buf[16384];
8462                 int fd = open(ZFS_DEV, O_RDWR);
8463                 (void) strcpy((void *)buf, argv[2]);
8464                 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
8465         } else {
8466                 (void) fprintf(stderr, gettext("unrecognized "
8467                     "command '%s'\n"), cmdname);
8468                 usage(B_FALSE);
8469         }
8470 
8471         if (ret == 0 && log_history)
8472                 (void) zpool_log_history(g_zfs, history_str);
8473 
8474         libzfs_fini(g_zfs);
8475 
8476         /*
8477          * The 'ZFS_ABORT' environment variable causes us to dump core on exit
8478          * for the purposes of running ::findleaks.
8479          */
8480         if (getenv("ZFS_ABORT") != NULL) {
8481                 (void) printf("dumping core by request\n");
8482                 abort();
8483         }
8484 
8485         return (ret);
8486 }