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