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