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                         searchguid = 0;
1994                 }
1995                 found_config = NULL;
1996 
1997                 /*
1998                  * User specified a name or guid.  Ensure it's unique.
1999                  */
2000                 idata.unique = B_TRUE;
2001         }
2002 
2003 
2004         idata.path = searchdirs;
2005         idata.paths = nsearch;
2006         idata.poolname = searchname;
2007         idata.guid = searchguid;
2008         idata.cachefile = cachefile;
2009 
2010         pools = zpool_search_import(g_zfs, &idata);
2011 
2012         if (pools != NULL && idata.exists &&
2013             (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2014                 (void) fprintf(stderr, gettext("cannot import '%s': "
2015                     "a pool with that name already exists\n"),
2016                     argv[0]);
2017                 (void) fprintf(stderr, gettext("use the form '%s "
2018                     "<pool | id> <newpool>' to give it a new name\n"),
2019                     "zpool import");
2020                 err = 1;
2021         } else if (pools == NULL && idata.exists) {
2022                 (void) fprintf(stderr, gettext("cannot import '%s': "
2023                     "a pool with that name is already created/imported,\n"),
2024                     argv[0]);
2025                 (void) fprintf(stderr, gettext("and no additional pools "
2026                     "with that name were found\n"));
2027                 err = 1;
2028         } else if (pools == NULL) {
2029                 if (argc != 0) {
2030                         (void) fprintf(stderr, gettext("cannot import '%s': "
2031                             "no such pool available\n"), argv[0]);
2032                 }
2033                 err = 1;
2034         }
2035 
2036         if (err == 1) {
2037                 free(searchdirs);
2038                 nvlist_free(policy);
2039                 return (1);
2040         }
2041 
2042         /*
2043          * At this point we have a list of import candidate configs. Even if
2044          * we were searching by pool name or guid, we still need to
2045          * post-process the list to deal with pool state and possible
2046          * duplicate names.
2047          */
2048         err = 0;
2049         elem = NULL;
2050         first = B_TRUE;
2051         while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2052 
2053                 verify(nvpair_value_nvlist(elem, &config) == 0);
2054 
2055                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2056                     &pool_state) == 0);
2057                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2058                         continue;
2059                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2060                         continue;
2061 
2062                 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2063                     policy) == 0);
2064 
2065                 if (argc == 0) {
2066                         if (first)
2067                                 first = B_FALSE;
2068                         else if (!do_all)
2069                                 (void) printf("\n");
2070 
2071                         if (do_all) {
2072                                 err |= do_import(config, NULL, mntopts,
2073                                     props, flags);
2074                         } else {
2075                                 show_import(config);
2076                         }
2077                 } else if (searchname != NULL) {
2078                         char *name;
2079 
2080                         /*
2081                          * We are searching for a pool based on name.
2082                          */
2083                         verify(nvlist_lookup_string(config,
2084                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2085 
2086                         if (strcmp(name, searchname) == 0) {
2087                                 if (found_config != NULL) {
2088                                         (void) fprintf(stderr, gettext(
2089                                             "cannot import '%s': more than "
2090                                             "one matching pool\n"), searchname);
2091                                         (void) fprintf(stderr, gettext(
2092                                             "import by numeric ID instead\n"));
2093                                         err = B_TRUE;
2094                                 }
2095                                 found_config = config;
2096                         }
2097                 } else {
2098                         uint64_t guid;
2099 
2100                         /*
2101                          * Search for a pool by guid.
2102                          */
2103                         verify(nvlist_lookup_uint64(config,
2104                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2105 
2106                         if (guid == searchguid)
2107                                 found_config = config;
2108                 }
2109         }
2110 
2111         /*
2112          * If we were searching for a specific pool, verify that we found a
2113          * pool, and then do the import.
2114          */
2115         if (argc != 0 && err == 0) {
2116                 if (found_config == NULL) {
2117                         (void) fprintf(stderr, gettext("cannot import '%s': "
2118                             "no such pool available\n"), argv[0]);
2119                         err = B_TRUE;
2120                 } else {
2121                         err |= do_import(found_config, argc == 1 ? NULL :
2122                             argv[1], mntopts, props, flags);
2123                 }
2124         }
2125 
2126         /*
2127          * If we were just looking for pools, report an error if none were
2128          * found.
2129          */
2130         if (argc == 0 && first)
2131                 (void) fprintf(stderr,
2132                     gettext("no pools available to import\n"));
2133 
2134 error:
2135         nvlist_free(props);
2136         nvlist_free(pools);
2137         nvlist_free(policy);
2138         free(searchdirs);
2139 
2140         return (err ? 1 : 0);
2141 }
2142 
2143 typedef struct iostat_cbdata {
2144         boolean_t cb_verbose;
2145         int cb_namewidth;
2146         int cb_iteration;
2147         zpool_list_t *cb_list;
2148 } iostat_cbdata_t;
2149 
2150 static void
2151 print_iostat_separator(iostat_cbdata_t *cb)
2152 {
2153         int i = 0;
2154 
2155         for (i = 0; i < cb->cb_namewidth; i++)
2156                 (void) printf("-");
2157         (void) printf("  -----  -----  -----  -----  -----  -----\n");
2158 }
2159 
2160 static void
2161 print_iostat_header(iostat_cbdata_t *cb)
2162 {
2163         (void) printf("%*s     capacity     operations    bandwidth\n",
2164             cb->cb_namewidth, "");
2165         (void) printf("%-*s  alloc   free   read  write   read  write\n",
2166             cb->cb_namewidth, "pool");
2167         print_iostat_separator(cb);
2168 }
2169 
2170 /*
2171  * Display a single statistic.
2172  */
2173 static void
2174 print_one_stat(uint64_t value)
2175 {
2176         char buf[64];
2177 
2178         zfs_nicenum(value, buf, sizeof (buf));
2179         (void) printf("  %5s", buf);
2180 }
2181 
2182 /*
2183  * Print out all the statistics for the given vdev.  This can either be the
2184  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2185  * is a verbose output, and we don't want to display the toplevel pool stats.
2186  */
2187 void
2188 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2189     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2190 {
2191         nvlist_t **oldchild, **newchild;
2192         uint_t c, children;
2193         vdev_stat_t *oldvs, *newvs;
2194         vdev_stat_t zerovs = { 0 };
2195         uint64_t tdelta;
2196         double scale;
2197         char *vname;
2198 
2199         if (oldnv != NULL) {
2200                 verify(nvlist_lookup_uint64_array(oldnv,
2201                     ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2202         } else {
2203                 oldvs = &zerovs;
2204         }
2205 
2206         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2207             (uint64_t **)&newvs, &c) == 0);
2208 
2209         if (strlen(name) + depth > cb->cb_namewidth)
2210                 (void) printf("%*s%s", depth, "", name);
2211         else
2212                 (void) printf("%*s%s%*s", depth, "", name,
2213                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
2214 
2215         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2216 
2217         if (tdelta == 0)
2218                 scale = 1.0;
2219         else
2220                 scale = (double)NANOSEC / tdelta;
2221 
2222         /* only toplevel vdevs have capacity stats */
2223         if (newvs->vs_space == 0) {
2224                 (void) printf("      -      -");
2225         } else {
2226                 print_one_stat(newvs->vs_alloc);
2227                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2228         }
2229 
2230         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2231             oldvs->vs_ops[ZIO_TYPE_READ])));
2232 
2233         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2234             oldvs->vs_ops[ZIO_TYPE_WRITE])));
2235 
2236         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2237             oldvs->vs_bytes[ZIO_TYPE_READ])));
2238 
2239         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2240             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2241 
2242         (void) printf("\n");
2243 
2244         if (!cb->cb_verbose)
2245                 return;
2246 
2247         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2248             &newchild, &children) != 0)
2249                 return;
2250 
2251         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2252             &oldchild, &c) != 0)
2253                 return;
2254 
2255         for (c = 0; c < children; c++) {
2256                 uint64_t ishole = B_FALSE, islog = B_FALSE;
2257 
2258                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2259                     &ishole);
2260 
2261                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2262                     &islog);
2263 
2264                 if (ishole || islog)
2265                         continue;
2266 
2267                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2268                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2269                     newchild[c], cb, depth + 2);
2270                 free(vname);
2271         }
2272 
2273         /*
2274          * Log device section
2275          */
2276 
2277         if (num_logs(newnv) > 0) {
2278                 (void) printf("%-*s      -      -      -      -      -      "
2279                     "-\n", cb->cb_namewidth, "logs");
2280 
2281                 for (c = 0; c < children; c++) {
2282                         uint64_t islog = B_FALSE;
2283                         (void) nvlist_lookup_uint64(newchild[c],
2284                             ZPOOL_CONFIG_IS_LOG, &islog);
2285 
2286                         if (islog) {
2287                                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2288                                     B_FALSE);
2289                                 print_vdev_stats(zhp, vname, oldnv ?
2290                                     oldchild[c] : NULL, newchild[c],
2291                                     cb, depth + 2);
2292                                 free(vname);
2293                         }
2294                 }
2295 
2296         }
2297 
2298         /*
2299          * Include level 2 ARC devices in iostat output
2300          */
2301         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2302             &newchild, &children) != 0)
2303                 return;
2304 
2305         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2306             &oldchild, &c) != 0)
2307                 return;
2308 
2309         if (children > 0) {
2310                 (void) printf("%-*s      -      -      -      -      -      "
2311                     "-\n", cb->cb_namewidth, "cache");
2312                 for (c = 0; c < children; c++) {
2313                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2314                             B_FALSE);
2315                         print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2316                             newchild[c], cb, depth + 2);
2317                         free(vname);
2318                 }
2319         }
2320 }
2321 
2322 static int
2323 refresh_iostat(zpool_handle_t *zhp, void *data)
2324 {
2325         iostat_cbdata_t *cb = data;
2326         boolean_t missing;
2327 
2328         /*
2329          * If the pool has disappeared, remove it from the list and continue.
2330          */
2331         if (zpool_refresh_stats(zhp, &missing) != 0)
2332                 return (-1);
2333 
2334         if (missing)
2335                 pool_list_remove(cb->cb_list, zhp);
2336 
2337         return (0);
2338 }
2339 
2340 /*
2341  * Callback to print out the iostats for the given pool.
2342  */
2343 int
2344 print_iostat(zpool_handle_t *zhp, void *data)
2345 {
2346         iostat_cbdata_t *cb = data;
2347         nvlist_t *oldconfig, *newconfig;
2348         nvlist_t *oldnvroot, *newnvroot;
2349 
2350         newconfig = zpool_get_config(zhp, &oldconfig);
2351 
2352         if (cb->cb_iteration == 1)
2353                 oldconfig = NULL;
2354 
2355         verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2356             &newnvroot) == 0);
2357 
2358         if (oldconfig == NULL)
2359                 oldnvroot = NULL;
2360         else
2361                 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2362                     &oldnvroot) == 0);
2363 
2364         /*
2365          * Print out the statistics for the pool.
2366          */
2367         print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2368 
2369         if (cb->cb_verbose)
2370                 print_iostat_separator(cb);
2371 
2372         return (0);
2373 }
2374 
2375 int
2376 get_namewidth(zpool_handle_t *zhp, void *data)
2377 {
2378         iostat_cbdata_t *cb = data;
2379         nvlist_t *config, *nvroot;
2380 
2381         if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2382                 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2383                     &nvroot) == 0);
2384                 if (!cb->cb_verbose)
2385                         cb->cb_namewidth = strlen(zpool_get_name(zhp));
2386                 else
2387                         cb->cb_namewidth = max_width(zhp, nvroot, 0,
2388                             cb->cb_namewidth);
2389         }
2390 
2391         /*
2392          * The width must fall into the range [10,38].  The upper limit is the
2393          * maximum we can have and still fit in 80 columns.
2394          */
2395         if (cb->cb_namewidth < 10)
2396                 cb->cb_namewidth = 10;
2397         if (cb->cb_namewidth > 38)
2398                 cb->cb_namewidth = 38;
2399 
2400         return (0);
2401 }
2402 
2403 /*
2404  * Parse the input string, get the 'interval' and 'count' value if there is one.
2405  */
2406 static void
2407 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2408     unsigned long *cnt)
2409 {
2410         unsigned long interval = 0, count = 0;
2411         int argc = *argcp, errno;
2412 
2413         /*
2414          * Determine if the last argument is an integer or a pool name
2415          */
2416         if (argc > 0 && isdigit(argv[argc - 1][0])) {
2417                 char *end;
2418 
2419                 errno = 0;
2420                 interval = strtoul(argv[argc - 1], &end, 10);
2421 
2422                 if (*end == '\0' && errno == 0) {
2423                         if (interval == 0) {
2424                                 (void) fprintf(stderr, gettext("interval "
2425                                     "cannot be zero\n"));
2426                                 usage(B_FALSE);
2427                         }
2428                         /*
2429                          * Ignore the last parameter
2430                          */
2431                         argc--;
2432                 } else {
2433                         /*
2434                          * If this is not a valid number, just plow on.  The
2435                          * user will get a more informative error message later
2436                          * on.
2437                          */
2438                         interval = 0;
2439                 }
2440         }
2441 
2442         /*
2443          * If the last argument is also an integer, then we have both a count
2444          * and an interval.
2445          */
2446         if (argc > 0 && isdigit(argv[argc - 1][0])) {
2447                 char *end;
2448 
2449                 errno = 0;
2450                 count = interval;
2451                 interval = strtoul(argv[argc - 1], &end, 10);
2452 
2453                 if (*end == '\0' && errno == 0) {
2454                         if (interval == 0) {
2455                                 (void) fprintf(stderr, gettext("interval "
2456                                     "cannot be zero\n"));
2457                                 usage(B_FALSE);
2458                         }
2459 
2460                         /*
2461                          * Ignore the last parameter
2462                          */
2463                         argc--;
2464                 } else {
2465                         interval = 0;
2466                 }
2467         }
2468 
2469         *iv = interval;
2470         *cnt = count;
2471         *argcp = argc;
2472 }
2473 
2474 static void
2475 get_timestamp_arg(char c)
2476 {
2477         if (c == 'u')
2478                 timestamp_fmt = UDATE;
2479         else if (c == 'd')
2480                 timestamp_fmt = DDATE;
2481         else
2482                 usage(B_FALSE);
2483 }
2484 
2485 /*
2486  * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2487  *
2488  *      -v      Display statistics for individual vdevs
2489  *      -T      Display a timestamp in date(1) or Unix format
2490  *
2491  * This command can be tricky because we want to be able to deal with pool
2492  * creation/destruction as well as vdev configuration changes.  The bulk of this
2493  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
2494  * on pool_list_update() to detect the addition of new pools.  Configuration
2495  * changes are all handled within libzfs.
2496  */
2497 int
2498 zpool_do_iostat(int argc, char **argv)
2499 {
2500         int c;
2501         int ret;
2502         int npools;
2503         unsigned long interval = 0, count = 0;
2504         zpool_list_t *list;
2505         boolean_t verbose = B_FALSE;
2506         iostat_cbdata_t cb;
2507 
2508         /* check options */
2509         while ((c = getopt(argc, argv, "T:v")) != -1) {
2510                 switch (c) {
2511                 case 'T':
2512                         get_timestamp_arg(*optarg);
2513                         break;
2514                 case 'v':
2515                         verbose = B_TRUE;
2516                         break;
2517                 case '?':
2518                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2519                             optopt);
2520                         usage(B_FALSE);
2521                 }
2522         }
2523 
2524         argc -= optind;
2525         argv += optind;
2526 
2527         get_interval_count(&argc, argv, &interval, &count);
2528 
2529         /*
2530          * Construct the list of all interesting pools.
2531          */
2532         ret = 0;
2533         if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2534                 return (1);
2535 
2536         if (pool_list_count(list) == 0 && argc != 0) {
2537                 pool_list_free(list);
2538                 return (1);
2539         }
2540 
2541         if (pool_list_count(list) == 0 && interval == 0) {
2542                 pool_list_free(list);
2543                 (void) fprintf(stderr, gettext("no pools available\n"));
2544                 return (1);
2545         }
2546 
2547         /*
2548          * Enter the main iostat loop.
2549          */
2550         cb.cb_list = list;
2551         cb.cb_verbose = verbose;
2552         cb.cb_iteration = 0;
2553         cb.cb_namewidth = 0;
2554 
2555         for (;;) {
2556                 pool_list_update(list);
2557 
2558                 if ((npools = pool_list_count(list)) == 0)
2559                         break;
2560 
2561                 /*
2562                  * Refresh all statistics.  This is done as an explicit step
2563                  * before calculating the maximum name width, so that any
2564                  * configuration changes are properly accounted for.
2565                  */
2566                 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2567 
2568                 /*
2569                  * Iterate over all pools to determine the maximum width
2570                  * for the pool / device name column across all pools.
2571                  */
2572                 cb.cb_namewidth = 0;
2573                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2574 
2575                 if (timestamp_fmt != NODATE)
2576                         print_timestamp(timestamp_fmt);
2577 
2578                 /*
2579                  * If it's the first time, or verbose mode, print the header.
2580                  */
2581                 if (++cb.cb_iteration == 1 || verbose)
2582                         print_iostat_header(&cb);
2583 
2584                 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2585 
2586                 /*
2587                  * If there's more than one pool, and we're not in verbose mode
2588                  * (which prints a separator for us), then print a separator.
2589                  */
2590                 if (npools > 1 && !verbose)
2591                         print_iostat_separator(&cb);
2592 
2593                 if (verbose)
2594                         (void) printf("\n");
2595 
2596                 /*
2597                  * Flush the output so that redirection to a file isn't buffered
2598                  * indefinitely.
2599                  */
2600                 (void) fflush(stdout);
2601 
2602                 if (interval == 0)
2603                         break;
2604 
2605                 if (count != 0 && --count == 0)
2606                         break;
2607 
2608                 (void) sleep(interval);
2609         }
2610 
2611         pool_list_free(list);
2612 
2613         return (ret);
2614 }
2615 
2616 typedef struct list_cbdata {
2617         boolean_t       cb_verbose;
2618         int             cb_namewidth;
2619         boolean_t       cb_scripted;
2620         zprop_list_t    *cb_proplist;
2621 } list_cbdata_t;
2622 
2623 /*
2624  * Given a list of columns to display, output appropriate headers for each one.
2625  */
2626 static void
2627 print_header(list_cbdata_t *cb)
2628 {
2629         zprop_list_t *pl = cb->cb_proplist;
2630         char headerbuf[ZPOOL_MAXPROPLEN];
2631         const char *header;
2632         boolean_t first = B_TRUE;
2633         boolean_t right_justify;
2634         size_t width = 0;
2635 
2636         for (; pl != NULL; pl = pl->pl_next) {
2637                 width = pl->pl_width;
2638                 if (first && cb->cb_verbose) {
2639                         /*
2640                          * Reset the width to accommodate the verbose listing
2641                          * of devices.
2642                          */
2643                         width = cb->cb_namewidth;
2644                 }
2645 
2646                 if (!first)
2647                         (void) printf("  ");
2648                 else
2649                         first = B_FALSE;
2650 
2651                 right_justify = B_FALSE;
2652                 if (pl->pl_prop != ZPROP_INVAL) {
2653                         header = zpool_prop_column_name(pl->pl_prop);
2654                         right_justify = zpool_prop_align_right(pl->pl_prop);
2655                 } else {
2656                         int i;
2657 
2658                         for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
2659                                 headerbuf[i] = toupper(pl->pl_user_prop[i]);
2660                         headerbuf[i] = '\0';
2661                         header = headerbuf;
2662                 }
2663 
2664                 if (pl->pl_next == NULL && !right_justify)
2665                         (void) printf("%s", header);
2666                 else if (right_justify)
2667                         (void) printf("%*s", width, header);
2668                 else
2669                         (void) printf("%-*s", width, header);
2670 
2671         }
2672 
2673         (void) printf("\n");
2674 }
2675 
2676 /*
2677  * Given a pool and a list of properties, print out all the properties according
2678  * to the described layout.
2679  */
2680 static void
2681 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
2682 {
2683         zprop_list_t *pl = cb->cb_proplist;
2684         boolean_t first = B_TRUE;
2685         char property[ZPOOL_MAXPROPLEN];
2686         char *propstr;
2687         boolean_t right_justify;
2688         size_t width;
2689 
2690         for (; pl != NULL; pl = pl->pl_next) {
2691 
2692                 width = pl->pl_width;
2693                 if (first && cb->cb_verbose) {
2694                         /*
2695                          * Reset the width to accommodate the verbose listing
2696                          * of devices.
2697                          */
2698                         width = cb->cb_namewidth;
2699                 }
2700 
2701                 if (!first) {
2702                         if (cb->cb_scripted)
2703                                 (void) printf("\t");
2704                         else
2705                                 (void) printf("  ");
2706                 } else {
2707                         first = B_FALSE;
2708                 }
2709 
2710                 right_justify = B_FALSE;
2711                 if (pl->pl_prop != ZPROP_INVAL) {
2712                         if (pl->pl_prop == ZPOOL_PROP_EXPANDSZ &&
2713                             zpool_get_prop_int(zhp, pl->pl_prop, NULL) == 0)
2714                                 propstr = "-";
2715                         else if (zpool_get_prop(zhp, pl->pl_prop, property,
2716                             sizeof (property), NULL) != 0)
2717                                 propstr = "-";
2718                         else
2719                                 propstr = property;
2720 
2721                         right_justify = zpool_prop_align_right(pl->pl_prop);
2722                 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
2723                     zpool_prop_unsupported(pl->pl_user_prop)) &&
2724                     zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
2725                     sizeof (property)) == 0) {
2726                         propstr = property;
2727                 } else {
2728                         propstr = "-";
2729                 }
2730 
2731 
2732                 /*
2733                  * If this is being called in scripted mode, or if this is the
2734                  * last column and it is left-justified, don't include a width
2735                  * format specifier.
2736                  */
2737                 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
2738                         (void) printf("%s", propstr);
2739                 else if (right_justify)
2740                         (void) printf("%*s", width, propstr);
2741                 else
2742                         (void) printf("%-*s", width, propstr);
2743         }
2744 
2745         (void) printf("\n");
2746 }
2747 
2748 static void
2749 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted)
2750 {
2751         char propval[64];
2752         boolean_t fixed;
2753         size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
2754 
2755         zfs_nicenum(value, propval, sizeof (propval));
2756 
2757         if (prop == ZPOOL_PROP_EXPANDSZ && value == 0)
2758                 (void) strlcpy(propval, "-", sizeof (propval));
2759 
2760         if (scripted)
2761                 (void) printf("\t%s", propval);
2762         else
2763                 (void) printf("  %*s", width, propval);
2764 }
2765 
2766 void
2767 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2768     list_cbdata_t *cb, int depth)
2769 {
2770         nvlist_t **child;
2771         vdev_stat_t *vs;
2772         uint_t c, children;
2773         char *vname;
2774         boolean_t scripted = cb->cb_scripted;
2775 
2776         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2777             (uint64_t **)&vs, &c) == 0);
2778 
2779         if (name != NULL) {
2780                 if (scripted)
2781                         (void) printf("\t%s", name);
2782                 else if (strlen(name) + depth > cb->cb_namewidth)
2783                         (void) printf("%*s%s", depth, "", name);
2784                 else
2785                         (void) printf("%*s%s%*s", depth, "", name,
2786                             (int)(cb->cb_namewidth - strlen(name) - depth), "");
2787 
2788                 /* only toplevel vdevs have capacity stats */
2789                 if (vs->vs_space == 0) {
2790                         if (scripted)
2791                                 (void) printf("\t-\t-\t-");
2792                         else
2793                                 (void) printf("      -      -      -");
2794                 } else {
2795                         print_one_column(ZPOOL_PROP_SIZE, vs->vs_space,
2796                             scripted);
2797                         print_one_column(ZPOOL_PROP_CAPACITY, vs->vs_alloc,
2798                             scripted);
2799                         print_one_column(ZPOOL_PROP_FREE,
2800                             vs->vs_space - vs->vs_alloc, scripted);
2801                 }
2802                 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize,
2803                     scripted);
2804                 (void) printf("\n");
2805         }
2806 
2807         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2808             &child, &children) != 0)
2809                 return;
2810 
2811         for (c = 0; c < children; c++) {
2812                 uint64_t ishole = B_FALSE;
2813 
2814                 if (nvlist_lookup_uint64(child[c],
2815                     ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
2816                         continue;
2817 
2818                 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
2819                 print_list_stats(zhp, vname, child[c], cb, depth + 2);
2820                 free(vname);
2821         }
2822 
2823         /*
2824          * Include level 2 ARC devices in iostat output
2825          */
2826         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2827             &child, &children) != 0)
2828                 return;
2829 
2830         if (children > 0) {
2831                 (void) printf("%-*s      -      -      -      -      -      "
2832                     "-\n", cb->cb_namewidth, "cache");
2833                 for (c = 0; c < children; c++) {
2834                         vname = zpool_vdev_name(g_zfs, zhp, child[c],
2835                             B_FALSE);
2836                         print_list_stats(zhp, vname, child[c], cb, depth + 2);
2837                         free(vname);
2838                 }
2839         }
2840 }
2841 
2842 
2843 /*
2844  * Generic callback function to list a pool.
2845  */
2846 int
2847 list_callback(zpool_handle_t *zhp, void *data)
2848 {
2849         list_cbdata_t *cbp = data;
2850         nvlist_t *config;
2851         nvlist_t *nvroot;
2852 
2853         config = zpool_get_config(zhp, NULL);
2854 
2855         print_pool(zhp, cbp);
2856         if (!cbp->cb_verbose)
2857                 return (0);
2858 
2859         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2860             &nvroot) == 0);
2861         print_list_stats(zhp, NULL, nvroot, cbp, 0);
2862 
2863         return (0);
2864 }
2865 
2866 /*
2867  * zpool list [-H] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
2868  *
2869  *      -H      Scripted mode.  Don't display headers, and separate properties
2870  *              by a single tab.
2871  *      -o      List of properties to display.  Defaults to
2872  *              "name,size,allocated,free,capacity,health,altroot"
2873  *      -T      Display a timestamp in date(1) or Unix format
2874  *
2875  * List all pools in the system, whether or not they're healthy.  Output space
2876  * statistics for each one, as well as health status summary.
2877  */
2878 int
2879 zpool_do_list(int argc, char **argv)
2880 {
2881         int c;
2882         int ret;
2883         list_cbdata_t cb = { 0 };
2884         static char default_props[] =
2885             "name,size,allocated,free,expandsize,capacity,dedupratio,"
2886             "health,altroot";
2887         char *props = default_props;
2888         unsigned long interval = 0, count = 0;
2889         zpool_list_t *list;
2890         boolean_t first = B_TRUE;
2891 
2892         /* check options */
2893         while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) {
2894                 switch (c) {
2895                 case 'H':
2896                         cb.cb_scripted = B_TRUE;
2897                         break;
2898                 case 'o':
2899                         props = optarg;
2900                         break;
2901                 case 'T':
2902                         get_timestamp_arg(*optarg);
2903                         break;
2904                 case 'v':
2905                         cb.cb_verbose = B_TRUE;
2906                         break;
2907                 case ':':
2908                         (void) fprintf(stderr, gettext("missing argument for "
2909                             "'%c' option\n"), optopt);
2910                         usage(B_FALSE);
2911                         break;
2912                 case '?':
2913                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2914                             optopt);
2915                         usage(B_FALSE);
2916                 }
2917         }
2918 
2919         argc -= optind;
2920         argv += optind;
2921 
2922         get_interval_count(&argc, argv, &interval, &count);
2923 
2924         if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2925                 usage(B_FALSE);
2926 
2927         if ((list = pool_list_get(argc, argv, &cb.cb_proplist, &ret)) == NULL)
2928                 return (1);
2929 
2930         if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
2931                 (void) printf(gettext("no pools available\n"));
2932                 zprop_free_list(cb.cb_proplist);
2933                 return (0);
2934         }
2935 
2936         for (;;) {
2937                 pool_list_update(list);
2938 
2939                 if (pool_list_count(list) == 0)
2940                         break;
2941 
2942                 cb.cb_namewidth = 0;
2943                 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2944 
2945                 if (timestamp_fmt != NODATE)
2946                         print_timestamp(timestamp_fmt);
2947 
2948                 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
2949                         print_header(&cb);
2950                         first = B_FALSE;
2951                 }
2952                 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
2953 
2954                 if (interval == 0)
2955                         break;
2956 
2957                 if (count != 0 && --count == 0)
2958                         break;
2959 
2960                 (void) sleep(interval);
2961         }
2962 
2963         zprop_free_list(cb.cb_proplist);
2964         return (ret);
2965 }
2966 
2967 static nvlist_t *
2968 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2969 {
2970         nvlist_t **child;
2971         uint_t c, children;
2972         nvlist_t *match;
2973         char *path;
2974 
2975         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2976             &child, &children) != 0) {
2977                 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2978                 if (strncmp(name, "/dev/dsk/", 9) == 0)
2979                         name += 9;
2980                 if (strncmp(path, "/dev/dsk/", 9) == 0)
2981                         path += 9;
2982                 if (strcmp(name, path) == 0)
2983                         return (nv);
2984                 return (NULL);
2985         }
2986 
2987         for (c = 0; c < children; c++)
2988                 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2989                         return (match);
2990 
2991         return (NULL);
2992 }
2993 
2994 static int
2995 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2996 {
2997         boolean_t force = B_FALSE;
2998         int c;
2999         nvlist_t *nvroot;
3000         char *poolname, *old_disk, *new_disk;
3001         zpool_handle_t *zhp;
3002         int ret;
3003 
3004         /* check options */
3005         while ((c = getopt(argc, argv, "f")) != -1) {
3006                 switch (c) {
3007                 case 'f':
3008                         force = B_TRUE;
3009                         break;
3010                 case '?':
3011                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3012                             optopt);
3013                         usage(B_FALSE);
3014                 }
3015         }
3016 
3017         argc -= optind;
3018         argv += optind;
3019 
3020         /* get pool name and check number of arguments */
3021         if (argc < 1) {
3022                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3023                 usage(B_FALSE);
3024         }
3025 
3026         poolname = argv[0];
3027 
3028         if (argc < 2) {
3029                 (void) fprintf(stderr,
3030                     gettext("missing <device> specification\n"));
3031                 usage(B_FALSE);
3032         }
3033 
3034         old_disk = argv[1];
3035 
3036         if (argc < 3) {
3037                 if (!replacing) {
3038                         (void) fprintf(stderr,
3039                             gettext("missing <new_device> specification\n"));
3040                         usage(B_FALSE);
3041                 }
3042                 new_disk = old_disk;
3043                 argc -= 1;
3044                 argv += 1;
3045         } else {
3046                 new_disk = argv[2];
3047                 argc -= 2;
3048                 argv += 2;
3049         }
3050 
3051         if (argc > 1) {
3052                 (void) fprintf(stderr, gettext("too many arguments\n"));
3053                 usage(B_FALSE);
3054         }
3055 
3056         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3057                 return (1);
3058 
3059         if (zpool_get_config(zhp, NULL) == NULL) {
3060                 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3061                     poolname);
3062                 zpool_close(zhp);
3063                 return (1);
3064         }
3065 
3066         nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3067             argc, argv);
3068         if (nvroot == NULL) {
3069                 zpool_close(zhp);
3070                 return (1);
3071         }
3072 
3073         ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3074 
3075         nvlist_free(nvroot);
3076         zpool_close(zhp);
3077 
3078         return (ret);
3079 }
3080 
3081 /*
3082  * zpool replace [-f] <pool> <device> <new_device>
3083  *
3084  *      -f      Force attach, even if <new_device> appears to be in use.
3085  *
3086  * Replace <device> with <new_device>.
3087  */
3088 /* ARGSUSED */
3089 int
3090 zpool_do_replace(int argc, char **argv)
3091 {
3092         return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3093 }
3094 
3095 /*
3096  * zpool attach [-f] <pool> <device> <new_device>
3097  *
3098  *      -f      Force attach, even if <new_device> appears to be in use.
3099  *
3100  * Attach <new_device> to the mirror containing <device>.  If <device> is not
3101  * part of a mirror, then <device> will be transformed into a mirror of
3102  * <device> and <new_device>.  In either case, <new_device> will begin life
3103  * with a DTL of [0, now], and will immediately begin to resilver itself.
3104  */
3105 int
3106 zpool_do_attach(int argc, char **argv)
3107 {
3108         return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3109 }
3110 
3111 /*
3112  * zpool detach [-f] <pool> <device>
3113  *
3114  *      -f      Force detach of <device>, even if DTLs argue against it
3115  *              (not supported yet)
3116  *
3117  * Detach a device from a mirror.  The operation will be refused if <device>
3118  * is the last device in the mirror, or if the DTLs indicate that this device
3119  * has the only valid copy of some data.
3120  */
3121 /* ARGSUSED */
3122 int
3123 zpool_do_detach(int argc, char **argv)
3124 {
3125         int c;
3126         char *poolname, *path;
3127         zpool_handle_t *zhp;
3128         int ret;
3129 
3130         /* check options */
3131         while ((c = getopt(argc, argv, "f")) != -1) {
3132                 switch (c) {
3133                 case 'f':
3134                 case '?':
3135                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3136                             optopt);
3137                         usage(B_FALSE);
3138                 }
3139         }
3140 
3141         argc -= optind;
3142         argv += optind;
3143 
3144         /* get pool name and check number of arguments */
3145         if (argc < 1) {
3146                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3147                 usage(B_FALSE);
3148         }
3149 
3150         if (argc < 2) {
3151                 (void) fprintf(stderr,
3152                     gettext("missing <device> specification\n"));
3153                 usage(B_FALSE);
3154         }
3155 
3156         poolname = argv[0];
3157         path = argv[1];
3158 
3159         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3160                 return (1);
3161 
3162         ret = zpool_vdev_detach(zhp, path);
3163 
3164         zpool_close(zhp);
3165 
3166         return (ret);
3167 }
3168 
3169 /*
3170  * zpool split [-n] [-o prop=val] ...
3171  *              [-o mntopt] ...
3172  *              [-R altroot] <pool> <newpool> [<device> ...]
3173  *
3174  *      -n      Do not split the pool, but display the resulting layout if
3175  *              it were to be split.
3176  *      -o      Set property=value, or set mount options.
3177  *      -R      Mount the split-off pool under an alternate root.
3178  *
3179  * Splits the named pool and gives it the new pool name.  Devices to be split
3180  * off may be listed, provided that no more than one device is specified
3181  * per top-level vdev mirror.  The newly split pool is left in an exported
3182  * state unless -R is specified.
3183  *
3184  * Restrictions: the top-level of the pool pool must only be made up of
3185  * mirrors; all devices in the pool must be healthy; no device may be
3186  * undergoing a resilvering operation.
3187  */
3188 int
3189 zpool_do_split(int argc, char **argv)
3190 {
3191         char *srcpool, *newpool, *propval;
3192         char *mntopts = NULL;
3193         splitflags_t flags;
3194         int c, ret = 0;
3195         zpool_handle_t *zhp;
3196         nvlist_t *config, *props = NULL;
3197 
3198         flags.dryrun = B_FALSE;
3199         flags.import = B_FALSE;
3200 
3201         /* check options */
3202         while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3203                 switch (c) {
3204                 case 'R':
3205                         flags.import = B_TRUE;
3206                         if (add_prop_list(
3207                             zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3208                             &props, B_TRUE) != 0) {
3209                                 if (props)
3210                                         nvlist_free(props);
3211                                 usage(B_FALSE);
3212                         }
3213                         break;
3214                 case 'n':
3215                         flags.dryrun = B_TRUE;
3216                         break;
3217                 case 'o':
3218                         if ((propval = strchr(optarg, '=')) != NULL) {
3219                                 *propval = '\0';
3220                                 propval++;
3221                                 if (add_prop_list(optarg, propval,
3222                                     &props, B_TRUE) != 0) {
3223                                         if (props)
3224                                                 nvlist_free(props);
3225                                         usage(B_FALSE);
3226                                 }
3227                         } else {
3228                                 mntopts = optarg;
3229                         }
3230                         break;
3231                 case ':':
3232                         (void) fprintf(stderr, gettext("missing argument for "
3233                             "'%c' option\n"), optopt);
3234                         usage(B_FALSE);
3235                         break;
3236                 case '?':
3237                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3238                             optopt);
3239                         usage(B_FALSE);
3240                         break;
3241                 }
3242         }
3243 
3244         if (!flags.import && mntopts != NULL) {
3245                 (void) fprintf(stderr, gettext("setting mntopts is only "
3246                     "valid when importing the pool\n"));
3247                 usage(B_FALSE);
3248         }
3249 
3250         argc -= optind;
3251         argv += optind;
3252 
3253         if (argc < 1) {
3254                 (void) fprintf(stderr, gettext("Missing pool name\n"));
3255                 usage(B_FALSE);
3256         }
3257         if (argc < 2) {
3258                 (void) fprintf(stderr, gettext("Missing new pool name\n"));
3259                 usage(B_FALSE);
3260         }
3261 
3262         srcpool = argv[0];
3263         newpool = argv[1];
3264 
3265         argc -= 2;
3266         argv += 2;
3267 
3268         if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3269                 return (1);
3270 
3271         config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3272         if (config == NULL) {
3273                 ret = 1;
3274         } else {
3275                 if (flags.dryrun) {
3276                         (void) printf(gettext("would create '%s' with the "
3277                             "following layout:\n\n"), newpool);
3278                         print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3279                 }
3280                 nvlist_free(config);
3281         }
3282 
3283         zpool_close(zhp);
3284 
3285         if (ret != 0 || flags.dryrun || !flags.import)
3286                 return (ret);
3287 
3288         /*
3289          * The split was successful. Now we need to open the new
3290          * pool and import it.
3291          */
3292         if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3293                 return (1);
3294         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3295             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3296                 ret = 1;
3297                 (void) fprintf(stderr, gettext("Split was successful, but "
3298                     "the datasets could not all be mounted\n"));
3299                 (void) fprintf(stderr, gettext("Try doing '%s' with a "
3300                     "different altroot\n"), "zpool import");
3301         }
3302         zpool_close(zhp);
3303 
3304         return (ret);
3305 }
3306 
3307 
3308 
3309 /*
3310  * zpool online <pool> <device> ...
3311  */
3312 int
3313 zpool_do_online(int argc, char **argv)
3314 {
3315         int c, i;
3316         char *poolname;
3317         zpool_handle_t *zhp;
3318         int ret = 0;
3319         vdev_state_t newstate;
3320         int flags = 0;
3321 
3322         /* check options */
3323         while ((c = getopt(argc, argv, "et")) != -1) {
3324                 switch (c) {
3325                 case 'e':
3326                         flags |= ZFS_ONLINE_EXPAND;
3327                         break;
3328                 case 't':
3329                 case '?':
3330                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3331                             optopt);
3332                         usage(B_FALSE);
3333                 }
3334         }
3335 
3336         argc -= optind;
3337         argv += optind;
3338 
3339         /* get pool name and check number of arguments */
3340         if (argc < 1) {
3341                 (void) fprintf(stderr, gettext("missing pool name\n"));
3342                 usage(B_FALSE);
3343         }
3344         if (argc < 2) {
3345                 (void) fprintf(stderr, gettext("missing device name\n"));
3346                 usage(B_FALSE);
3347         }
3348 
3349         poolname = argv[0];
3350 
3351         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3352                 return (1);
3353 
3354         for (i = 1; i < argc; i++) {
3355                 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3356                         if (newstate != VDEV_STATE_HEALTHY) {
3357                                 (void) printf(gettext("warning: device '%s' "
3358                                     "onlined, but remains in faulted state\n"),
3359                                     argv[i]);
3360                                 if (newstate == VDEV_STATE_FAULTED)
3361                                         (void) printf(gettext("use 'zpool "
3362                                             "clear' to restore a faulted "
3363                                             "device\n"));
3364                                 else
3365                                         (void) printf(gettext("use 'zpool "
3366                                             "replace' to replace devices "
3367                                             "that are no longer present\n"));
3368                         }
3369                 } else {
3370                         ret = 1;
3371                 }
3372         }
3373 
3374         zpool_close(zhp);
3375 
3376         return (ret);
3377 }
3378 
3379 /*
3380  * zpool offline [-ft] <pool> <device> ...
3381  *
3382  *      -f      Force the device into the offline state, even if doing
3383  *              so would appear to compromise pool availability.
3384  *              (not supported yet)
3385  *
3386  *      -t      Only take the device off-line temporarily.  The offline
3387  *              state will not be persistent across reboots.
3388  */
3389 /* ARGSUSED */
3390 int
3391 zpool_do_offline(int argc, char **argv)
3392 {
3393         int c, i;
3394         char *poolname;
3395         zpool_handle_t *zhp;
3396         int ret = 0;
3397         boolean_t istmp = B_FALSE;
3398 
3399         /* check options */
3400         while ((c = getopt(argc, argv, "ft")) != -1) {
3401                 switch (c) {
3402                 case 't':
3403                         istmp = B_TRUE;
3404                         break;
3405                 case 'f':
3406                 case '?':
3407                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3408                             optopt);
3409                         usage(B_FALSE);
3410                 }
3411         }
3412 
3413         argc -= optind;
3414         argv += optind;
3415 
3416         /* get pool name and check number of arguments */
3417         if (argc < 1) {
3418                 (void) fprintf(stderr, gettext("missing pool name\n"));
3419                 usage(B_FALSE);
3420         }
3421         if (argc < 2) {
3422                 (void) fprintf(stderr, gettext("missing device name\n"));
3423                 usage(B_FALSE);
3424         }
3425 
3426         poolname = argv[0];
3427 
3428         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3429                 return (1);
3430 
3431         for (i = 1; i < argc; i++) {
3432                 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3433                         ret = 1;
3434         }
3435 
3436         zpool_close(zhp);
3437 
3438         return (ret);
3439 }
3440 
3441 /*
3442  * zpool clear <pool> [device]
3443  *
3444  * Clear all errors associated with a pool or a particular device.
3445  */
3446 int
3447 zpool_do_clear(int argc, char **argv)
3448 {
3449         int c;
3450         int ret = 0;
3451         boolean_t dryrun = B_FALSE;
3452         boolean_t do_rewind = B_FALSE;
3453         boolean_t xtreme_rewind = B_FALSE;
3454         uint32_t rewind_policy = ZPOOL_NO_REWIND;
3455         nvlist_t *policy = NULL;
3456         zpool_handle_t *zhp;
3457         char *pool, *device;
3458 
3459         /* check options */
3460         while ((c = getopt(argc, argv, "FnX")) != -1) {
3461                 switch (c) {
3462                 case 'F':
3463                         do_rewind = B_TRUE;
3464                         break;
3465                 case 'n':
3466                         dryrun = B_TRUE;
3467                         break;
3468                 case 'X':
3469                         xtreme_rewind = B_TRUE;
3470                         break;
3471                 case '?':
3472                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3473                             optopt);
3474                         usage(B_FALSE);
3475                 }
3476         }
3477 
3478         argc -= optind;
3479         argv += optind;
3480 
3481         if (argc < 1) {
3482                 (void) fprintf(stderr, gettext("missing pool name\n"));
3483                 usage(B_FALSE);
3484         }
3485 
3486         if (argc > 2) {
3487                 (void) fprintf(stderr, gettext("too many arguments\n"));
3488                 usage(B_FALSE);
3489         }
3490 
3491         if ((dryrun || xtreme_rewind) && !do_rewind) {
3492                 (void) fprintf(stderr,
3493                     gettext("-n or -X only meaningful with -F\n"));
3494                 usage(B_FALSE);
3495         }
3496         if (dryrun)
3497                 rewind_policy = ZPOOL_TRY_REWIND;
3498         else if (do_rewind)
3499                 rewind_policy = ZPOOL_DO_REWIND;
3500         if (xtreme_rewind)
3501                 rewind_policy |= ZPOOL_EXTREME_REWIND;
3502 
3503         /* In future, further rewind policy choices can be passed along here */
3504         if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3505             nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
3506                 return (1);
3507 
3508         pool = argv[0];
3509         device = argc == 2 ? argv[1] : NULL;
3510 
3511         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3512                 nvlist_free(policy);
3513                 return (1);
3514         }
3515 
3516         if (zpool_clear(zhp, device, policy) != 0)
3517                 ret = 1;
3518 
3519         zpool_close(zhp);
3520 
3521         nvlist_free(policy);
3522 
3523         return (ret);
3524 }
3525 
3526 /*
3527  * zpool reguid <pool>
3528  */
3529 int
3530 zpool_do_reguid(int argc, char **argv)
3531 {
3532         int c;
3533         char *poolname;
3534         zpool_handle_t *zhp;
3535         int ret = 0;
3536 
3537         /* check options */
3538         while ((c = getopt(argc, argv, "")) != -1) {
3539                 switch (c) {
3540                 case '?':
3541                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3542                             optopt);
3543                         usage(B_FALSE);
3544                 }
3545         }
3546 
3547         argc -= optind;
3548         argv += optind;
3549 
3550         /* get pool name and check number of arguments */
3551         if (argc < 1) {
3552                 (void) fprintf(stderr, gettext("missing pool name\n"));
3553                 usage(B_FALSE);
3554         }
3555 
3556         if (argc > 1) {
3557                 (void) fprintf(stderr, gettext("too many arguments\n"));
3558                 usage(B_FALSE);
3559         }
3560 
3561         poolname = argv[0];
3562         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3563                 return (1);
3564 
3565         ret = zpool_reguid(zhp);
3566 
3567         zpool_close(zhp);
3568         return (ret);
3569 }
3570 
3571 
3572 /*
3573  * zpool reopen <pool>
3574  *
3575  * Reopen the pool so that the kernel can update the sizes of all vdevs.
3576  */
3577 int
3578 zpool_do_reopen(int argc, char **argv)
3579 {
3580         int c;
3581         int ret = 0;
3582         zpool_handle_t *zhp;
3583         char *pool;
3584 
3585         /* check options */
3586         while ((c = getopt(argc, argv, "")) != -1) {
3587                 switch (c) {
3588                 case '?':
3589                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3590                             optopt);
3591                         usage(B_FALSE);
3592                 }
3593         }
3594 
3595         argc--;
3596         argv++;
3597 
3598         if (argc < 1) {
3599                 (void) fprintf(stderr, gettext("missing pool name\n"));
3600                 usage(B_FALSE);
3601         }
3602 
3603         if (argc > 1) {
3604                 (void) fprintf(stderr, gettext("too many arguments\n"));
3605                 usage(B_FALSE);
3606         }
3607 
3608         pool = argv[0];
3609         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
3610                 return (1);
3611 
3612         ret = zpool_reopen(zhp);
3613         zpool_close(zhp);
3614         return (ret);
3615 }
3616 
3617 typedef struct scrub_cbdata {
3618         int     cb_type;
3619         int     cb_argc;
3620         char    **cb_argv;
3621 } scrub_cbdata_t;
3622 
3623 int
3624 scrub_callback(zpool_handle_t *zhp, void *data)
3625 {
3626         scrub_cbdata_t *cb = data;
3627         int err;
3628 
3629         /*
3630          * Ignore faulted pools.
3631          */
3632         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
3633                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
3634                     "currently unavailable\n"), zpool_get_name(zhp));
3635                 return (1);
3636         }
3637 
3638         err = zpool_scan(zhp, cb->cb_type);
3639 
3640         return (err != 0);
3641 }
3642 
3643 /*
3644  * zpool scrub [-s] <pool> ...
3645  *
3646  *      -s      Stop.  Stops any in-progress scrub.
3647  */
3648 int
3649 zpool_do_scrub(int argc, char **argv)
3650 {
3651         int c;
3652         scrub_cbdata_t cb;
3653 
3654         cb.cb_type = POOL_SCAN_SCRUB;
3655 
3656         /* check options */
3657         while ((c = getopt(argc, argv, "s")) != -1) {
3658                 switch (c) {
3659                 case 's':
3660                         cb.cb_type = POOL_SCAN_NONE;
3661                         break;
3662                 case '?':
3663                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3664                             optopt);
3665                         usage(B_FALSE);
3666                 }
3667         }
3668 
3669         cb.cb_argc = argc;
3670         cb.cb_argv = argv;
3671         argc -= optind;
3672         argv += optind;
3673 
3674         if (argc < 1) {
3675                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3676                 usage(B_FALSE);
3677         }
3678 
3679         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
3680 }
3681 
3682 typedef struct status_cbdata {
3683         int             cb_count;
3684         boolean_t       cb_allpools;
3685         boolean_t       cb_verbose;
3686         boolean_t       cb_explain;
3687         boolean_t       cb_first;
3688         boolean_t       cb_dedup_stats;
3689 } status_cbdata_t;
3690 
3691 /*
3692  * Print out detailed scrub status.
3693  */
3694 void
3695 print_scan_status(pool_scan_stat_t *ps)
3696 {
3697         time_t start, end;
3698         uint64_t elapsed, mins_left, hours_left;
3699         uint64_t pass_exam, examined, total;
3700         uint_t rate;
3701         double fraction_done;
3702         char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
3703 
3704         (void) printf(gettext("  scan: "));
3705 
3706         /* If there's never been a scan, there's not much to say. */
3707         if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
3708             ps->pss_func >= POOL_SCAN_FUNCS) {
3709                 (void) printf(gettext("none requested\n"));
3710                 return;
3711         }
3712 
3713         start = ps->pss_start_time;
3714         end = ps->pss_end_time;
3715         zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
3716 
3717         assert(ps->pss_func == POOL_SCAN_SCRUB ||
3718             ps->pss_func == POOL_SCAN_RESILVER);
3719         /*
3720          * Scan is finished or canceled.
3721          */
3722         if (ps->pss_state == DSS_FINISHED) {
3723                 uint64_t minutes_taken = (end - start) / 60;
3724                 char *fmt;
3725 
3726                 if (ps->pss_func == POOL_SCAN_SCRUB) {
3727                         fmt = gettext("scrub repaired %s in %lluh%um with "
3728                             "%llu errors on %s");
3729                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3730                         fmt = gettext("resilvered %s in %lluh%um with "
3731                             "%llu errors on %s");
3732                 }
3733                 /* LINTED */
3734                 (void) printf(fmt, processed_buf,
3735                     (u_longlong_t)(minutes_taken / 60),
3736                     (uint_t)(minutes_taken % 60),
3737                     (u_longlong_t)ps->pss_errors,
3738                     ctime((time_t *)&end));
3739                 return;
3740         } else if (ps->pss_state == DSS_CANCELED) {
3741                 if (ps->pss_func == POOL_SCAN_SCRUB) {
3742                         (void) printf(gettext("scrub canceled on %s"),
3743                             ctime(&end));
3744                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3745                         (void) printf(gettext("resilver canceled on %s"),
3746                             ctime(&end));
3747                 }
3748                 return;
3749         }
3750 
3751         assert(ps->pss_state == DSS_SCANNING);
3752 
3753         /*
3754          * Scan is in progress.
3755          */
3756         if (ps->pss_func == POOL_SCAN_SCRUB) {
3757                 (void) printf(gettext("scrub in progress since %s"),
3758                     ctime(&start));
3759         } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3760                 (void) printf(gettext("resilver in progress since %s"),
3761                     ctime(&start));
3762         }
3763 
3764         examined = ps->pss_examined ? ps->pss_examined : 1;
3765         total = ps->pss_to_examine;
3766         fraction_done = (double)examined / total;
3767 
3768         /* elapsed time for this pass */
3769         elapsed = time(NULL) - ps->pss_pass_start;
3770         elapsed = elapsed ? elapsed : 1;
3771         pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
3772         rate = pass_exam / elapsed;
3773         rate = rate ? rate : 1;
3774         mins_left = ((total - examined) / rate) / 60;
3775         hours_left = mins_left / 60;
3776 
3777         zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
3778         zfs_nicenum(total, total_buf, sizeof (total_buf));
3779         zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
3780 
3781         /*
3782          * do not print estimated time if hours_left is more than 30 days
3783          */
3784         (void) printf(gettext("    %s scanned out of %s at %s/s"),
3785             examined_buf, total_buf, rate_buf);
3786         if (hours_left < (30 * 24)) {
3787                 (void) printf(gettext(", %lluh%um to go\n"),
3788                     (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
3789         } else {
3790                 (void) printf(gettext(
3791                     ", (scan is slow, no estimated time)\n"));
3792         }
3793 
3794         if (ps->pss_func == POOL_SCAN_RESILVER) {
3795                 (void) printf(gettext("    %s resilvered, %.2f%% done\n"),
3796                     processed_buf, 100 * fraction_done);
3797         } else if (ps->pss_func == POOL_SCAN_SCRUB) {
3798                 (void) printf(gettext("    %s repaired, %.2f%% done\n"),
3799                     processed_buf, 100 * fraction_done);
3800         }
3801 }
3802 
3803 static void
3804 print_error_log(zpool_handle_t *zhp)
3805 {
3806         nvlist_t *nverrlist = NULL;
3807         nvpair_t *elem;
3808         char *pathname;
3809         size_t len = MAXPATHLEN * 2;
3810 
3811         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
3812                 (void) printf("errors: List of errors unavailable "
3813                     "(insufficient privileges)\n");
3814                 return;
3815         }
3816 
3817         (void) printf("errors: Permanent errors have been "
3818             "detected in the following files:\n\n");
3819 
3820         pathname = safe_malloc(len);
3821         elem = NULL;
3822         while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
3823                 nvlist_t *nv;
3824                 uint64_t dsobj, obj;
3825 
3826                 verify(nvpair_value_nvlist(elem, &nv) == 0);
3827                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
3828                     &dsobj) == 0);
3829                 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
3830                     &obj) == 0);
3831                 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
3832                 (void) printf("%7s %s\n", "", pathname);
3833         }
3834         free(pathname);
3835         nvlist_free(nverrlist);
3836 }
3837 
3838 static void
3839 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
3840     int namewidth)
3841 {
3842         uint_t i;
3843         char *name;
3844 
3845         if (nspares == 0)
3846                 return;
3847 
3848         (void) printf(gettext("\tspares\n"));
3849 
3850         for (i = 0; i < nspares; i++) {
3851                 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
3852                 print_status_config(zhp, name, spares[i],
3853                     namewidth, 2, B_TRUE);
3854                 free(name);
3855         }
3856 }
3857 
3858 static void
3859 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
3860     int namewidth)
3861 {
3862         uint_t i;
3863         char *name;
3864 
3865         if (nl2cache == 0)
3866                 return;
3867 
3868         (void) printf(gettext("\tcache\n"));
3869 
3870         for (i = 0; i < nl2cache; i++) {
3871                 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
3872                 print_status_config(zhp, name, l2cache[i],
3873                     namewidth, 2, B_FALSE);
3874                 free(name);
3875         }
3876 }
3877 
3878 static void
3879 print_dedup_stats(nvlist_t *config)
3880 {
3881         ddt_histogram_t *ddh;
3882         ddt_stat_t *dds;
3883         ddt_object_t *ddo;
3884         uint_t c;
3885 
3886         /*
3887          * If the pool was faulted then we may not have been able to
3888          * obtain the config. Otherwise, if we have anything in the dedup
3889          * table continue processing the stats.
3890          */
3891         if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
3892             (uint64_t **)&ddo, &c) != 0)
3893                 return;
3894 
3895         (void) printf("\n");
3896         (void) printf(gettext(" dedup: "));
3897         if (ddo->ddo_count == 0) {
3898                 (void) printf(gettext("no DDT entries\n"));
3899                 return;
3900         }
3901 
3902         (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
3903             (u_longlong_t)ddo->ddo_count,
3904             (u_longlong_t)ddo->ddo_dspace,
3905             (u_longlong_t)ddo->ddo_mspace);
3906 
3907         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
3908             (uint64_t **)&dds, &c) == 0);
3909         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
3910             (uint64_t **)&ddh, &c) == 0);
3911         zpool_dump_ddt(dds, ddh);
3912 }
3913 
3914 /*
3915  * Display a summary of pool status.  Displays a summary such as:
3916  *
3917  *        pool: tank
3918  *      status: DEGRADED
3919  *      reason: One or more devices ...
3920  *         see: http://illumos.org/msg/ZFS-xxxx-01
3921  *      config:
3922  *              mirror          DEGRADED
3923  *                c1t0d0        OK
3924  *                c2t0d0        UNAVAIL
3925  *
3926  * When given the '-v' option, we print out the complete config.  If the '-e'
3927  * option is specified, then we print out error rate information as well.
3928  */
3929 int
3930 status_callback(zpool_handle_t *zhp, void *data)
3931 {
3932         status_cbdata_t *cbp = data;
3933         nvlist_t *config, *nvroot;
3934         char *msgid;
3935         int reason;
3936         const char *health;
3937         uint_t c;
3938         vdev_stat_t *vs;
3939 
3940         config = zpool_get_config(zhp, NULL);
3941         reason = zpool_get_status(zhp, &msgid);
3942 
3943         cbp->cb_count++;
3944 
3945         /*
3946          * If we were given 'zpool status -x', only report those pools with
3947          * problems.
3948          */
3949         if (cbp->cb_explain &&
3950             (reason == ZPOOL_STATUS_OK ||
3951             reason == ZPOOL_STATUS_VERSION_OLDER ||
3952             reason == ZPOOL_STATUS_FEAT_DISABLED)) {
3953                 if (!cbp->cb_allpools) {
3954                         (void) printf(gettext("pool '%s' is healthy\n"),
3955                             zpool_get_name(zhp));
3956                         if (cbp->cb_first)
3957                                 cbp->cb_first = B_FALSE;
3958                 }
3959                 return (0);
3960         }
3961 
3962         if (cbp->cb_first)
3963                 cbp->cb_first = B_FALSE;
3964         else
3965                 (void) printf("\n");
3966 
3967         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3968             &nvroot) == 0);
3969         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
3970             (uint64_t **)&vs, &c) == 0);
3971         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3972 
3973         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
3974         (void) printf(gettext(" state: %s\n"), health);
3975 
3976         switch (reason) {
3977         case ZPOOL_STATUS_MISSING_DEV_R:
3978                 (void) printf(gettext("status: One or more devices could not "
3979                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
3980                     "continue functioning in a degraded state.\n"));
3981                 (void) printf(gettext("action: Attach the missing device and "
3982                     "online it using 'zpool online'.\n"));
3983                 break;
3984 
3985         case ZPOOL_STATUS_MISSING_DEV_NR:
3986                 (void) printf(gettext("status: One or more devices could not "
3987                     "be opened.  There are insufficient\n\treplicas for the "
3988                     "pool to continue functioning.\n"));
3989                 (void) printf(gettext("action: Attach the missing device and "
3990                     "online it using 'zpool online'.\n"));
3991                 break;
3992 
3993         case ZPOOL_STATUS_CORRUPT_LABEL_R:
3994                 (void) printf(gettext("status: One or more devices could not "
3995                     "be used because the label is missing or\n\tinvalid.  "
3996                     "Sufficient replicas exist for the pool to continue\n\t"
3997                     "functioning in a degraded state.\n"));
3998                 (void) printf(gettext("action: Replace the device using "
3999                     "'zpool replace'.\n"));
4000                 break;
4001 
4002         case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4003                 (void) printf(gettext("status: One or more devices could not "
4004                     "be used because the label is missing \n\tor invalid.  "
4005                     "There are insufficient replicas for the pool to "
4006                     "continue\n\tfunctioning.\n"));
4007                 zpool_explain_recover(zpool_get_handle(zhp),
4008                     zpool_get_name(zhp), reason, config);
4009                 break;
4010 
4011         case ZPOOL_STATUS_FAILING_DEV:
4012                 (void) printf(gettext("status: One or more devices has "
4013                     "experienced an unrecoverable error.  An\n\tattempt was "
4014                     "made to correct the error.  Applications are "
4015                     "unaffected.\n"));
4016                 (void) printf(gettext("action: Determine if the device needs "
4017                     "to be replaced, and clear the errors\n\tusing "
4018                     "'zpool clear' or replace the device with 'zpool "
4019                     "replace'.\n"));
4020                 break;
4021 
4022         case ZPOOL_STATUS_OFFLINE_DEV:
4023                 (void) printf(gettext("status: One or more devices has "
4024                     "been taken offline by the administrator.\n\tSufficient "
4025                     "replicas exist for the pool to continue functioning in "
4026                     "a\n\tdegraded state.\n"));
4027                 (void) printf(gettext("action: Online the device using "
4028                     "'zpool online' or replace the device with\n\t'zpool "
4029                     "replace'.\n"));
4030                 break;
4031 
4032         case ZPOOL_STATUS_REMOVED_DEV:
4033                 (void) printf(gettext("status: One or more devices has "
4034                     "been removed by the administrator.\n\tSufficient "
4035                     "replicas exist for the pool to continue functioning in "
4036                     "a\n\tdegraded state.\n"));
4037                 (void) printf(gettext("action: Online the device using "
4038                     "'zpool online' or replace the device with\n\t'zpool "
4039                     "replace'.\n"));
4040                 break;
4041 
4042         case ZPOOL_STATUS_RESILVERING:
4043                 (void) printf(gettext("status: One or more devices is "
4044                     "currently being resilvered.  The pool will\n\tcontinue "
4045                     "to function, possibly in a degraded state.\n"));
4046                 (void) printf(gettext("action: Wait for the resilver to "
4047                     "complete.\n"));
4048                 break;
4049 
4050         case ZPOOL_STATUS_CORRUPT_DATA:
4051                 (void) printf(gettext("status: One or more devices has "
4052                     "experienced an error resulting in data\n\tcorruption.  "
4053                     "Applications may be affected.\n"));
4054                 (void) printf(gettext("action: Restore the file in question "
4055                     "if possible.  Otherwise restore the\n\tentire pool from "
4056                     "backup.\n"));
4057                 break;
4058 
4059         case ZPOOL_STATUS_CORRUPT_POOL:
4060                 (void) printf(gettext("status: The pool metadata is corrupted "
4061                     "and the pool cannot be opened.\n"));
4062                 zpool_explain_recover(zpool_get_handle(zhp),
4063                     zpool_get_name(zhp), reason, config);
4064                 break;
4065 
4066         case ZPOOL_STATUS_VERSION_OLDER:
4067                 (void) printf(gettext("status: The pool is formatted using a "
4068                     "legacy on-disk format.  The pool can\n\tstill be used, "
4069                     "but some features are unavailable.\n"));
4070                 (void) printf(gettext("action: Upgrade the pool using 'zpool "
4071                     "upgrade'.  Once this is done, the\n\tpool will no longer "
4072                     "be accessible on software that does not support feature\n"
4073                     "\tflags.\n"));
4074                 break;
4075 
4076         case ZPOOL_STATUS_VERSION_NEWER:
4077                 (void) printf(gettext("status: The pool has been upgraded to a "
4078                     "newer, incompatible on-disk version.\n\tThe pool cannot "
4079                     "be accessed on this system.\n"));
4080                 (void) printf(gettext("action: Access the pool from a system "
4081                     "running more recent software, or\n\trestore the pool from "
4082                     "backup.\n"));
4083                 break;
4084 
4085         case ZPOOL_STATUS_FEAT_DISABLED:
4086                 (void) printf(gettext("status: Some supported features are not "
4087                     "enabled on the pool. The pool can\n\tstill be used, but "
4088                     "some features are unavailable.\n"));
4089                 (void) printf(gettext("action: Enable all features using "
4090                     "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4091                     "longer be accessible by software that does not support\n\t"
4092                     "the features. See zpool-features(5) for details.\n"));
4093                 break;
4094 
4095         case ZPOOL_STATUS_UNSUP_FEAT_READ:
4096                 (void) printf(gettext("status: The pool cannot be accessed on "
4097                     "this system because it uses the\n\tfollowing feature(s) "
4098                     "not supported on this system:\n"));
4099                 zpool_print_unsup_feat(config);
4100                 (void) printf("\n");
4101                 (void) printf(gettext("action: Access the pool from a system "
4102                     "that supports the required feature(s),\n\tor restore the "
4103                     "pool from backup.\n"));
4104                 break;
4105 
4106         case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4107                 (void) printf(gettext("status: The pool can only be accessed "
4108                     "in read-only mode on this system. It\n\tcannot be "
4109                     "accessed in read-write mode because it uses the "
4110                     "following\n\tfeature(s) not supported on this system:\n"));
4111                 zpool_print_unsup_feat(config);
4112                 (void) printf("\n");
4113                 (void) printf(gettext("action: The pool cannot be accessed in "
4114                     "read-write mode. Import the pool with\n"
4115                     "\t\"-o readonly=on\", access the pool from a system that "
4116                     "supports the\n\trequired feature(s), or restore the "
4117                     "pool from backup.\n"));
4118                 break;
4119 
4120         case ZPOOL_STATUS_FAULTED_DEV_R:
4121                 (void) printf(gettext("status: One or more devices are "
4122                     "faulted in response to persistent errors.\n\tSufficient "
4123                     "replicas exist for the pool to continue functioning "
4124                     "in a\n\tdegraded state.\n"));
4125                 (void) printf(gettext("action: Replace the faulted device, "
4126                     "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4127                 break;
4128 
4129         case ZPOOL_STATUS_FAULTED_DEV_NR:
4130                 (void) printf(gettext("status: One or more devices are "
4131                     "faulted in response to persistent errors.  There are "
4132                     "insufficient replicas for the pool to\n\tcontinue "
4133                     "functioning.\n"));
4134                 (void) printf(gettext("action: Destroy and re-create the pool "
4135                     "from a backup source.  Manually marking the device\n"
4136                     "\trepaired using 'zpool clear' may allow some data "
4137                     "to be recovered.\n"));
4138                 break;
4139 
4140         case ZPOOL_STATUS_IO_FAILURE_WAIT:
4141         case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4142                 (void) printf(gettext("status: One or more devices are "
4143                     "faulted in response to IO failures.\n"));
4144                 (void) printf(gettext("action: Make sure the affected devices "
4145                     "are connected, then run 'zpool clear'.\n"));
4146                 break;
4147 
4148         case ZPOOL_STATUS_BAD_LOG:
4149                 (void) printf(gettext("status: An intent log record "
4150                     "could not be read.\n"
4151                     "\tWaiting for adminstrator intervention to fix the "
4152                     "faulted pool.\n"));
4153                 (void) printf(gettext("action: Either restore the affected "
4154                     "device(s) and run 'zpool online',\n"
4155                     "\tor ignore the intent log records by running "
4156                     "'zpool clear'.\n"));
4157                 break;
4158 
4159         default:
4160                 /*
4161                  * The remaining errors can't actually be generated, yet.
4162                  */
4163                 assert(reason == ZPOOL_STATUS_OK);
4164         }
4165 
4166         if (msgid != NULL)
4167                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
4168                     msgid);
4169 
4170         if (config != NULL) {
4171                 int namewidth;
4172                 uint64_t nerr;
4173                 nvlist_t **spares, **l2cache;
4174                 uint_t nspares, nl2cache;
4175                 pool_scan_stat_t *ps = NULL;
4176 
4177                 (void) nvlist_lookup_uint64_array(nvroot,
4178                     ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4179                 print_scan_status(ps);
4180 
4181                 namewidth = max_width(zhp, nvroot, 0, 0);
4182                 if (namewidth < 10)
4183                         namewidth = 10;
4184 
4185                 (void) printf(gettext("config:\n\n"));
4186                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
4187                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
4188                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4189                     namewidth, 0, B_FALSE);
4190 
4191                 if (num_logs(nvroot) > 0)
4192                         print_logs(zhp, nvroot, namewidth, B_TRUE);
4193                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4194                     &l2cache, &nl2cache) == 0)
4195                         print_l2cache(zhp, l2cache, nl2cache, namewidth);
4196 
4197                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4198                     &spares, &nspares) == 0)
4199                         print_spares(zhp, spares, nspares, namewidth);
4200 
4201                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4202                     &nerr) == 0) {
4203                         nvlist_t *nverrlist = NULL;
4204 
4205                         /*
4206                          * If the approximate error count is small, get a
4207                          * precise count by fetching the entire log and
4208                          * uniquifying the results.
4209                          */
4210                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4211                             zpool_get_errlog(zhp, &nverrlist) == 0) {
4212                                 nvpair_t *elem;
4213 
4214                                 elem = NULL;
4215                                 nerr = 0;
4216                                 while ((elem = nvlist_next_nvpair(nverrlist,
4217                                     elem)) != NULL) {
4218                                         nerr++;
4219                                 }
4220                         }
4221                         nvlist_free(nverrlist);
4222 
4223                         (void) printf("\n");
4224 
4225                         if (nerr == 0)
4226                                 (void) printf(gettext("errors: No known data "
4227                                     "errors\n"));
4228                         else if (!cbp->cb_verbose)
4229                                 (void) printf(gettext("errors: %llu data "
4230                                     "errors, use '-v' for a list\n"),
4231                                     (u_longlong_t)nerr);
4232                         else
4233                                 print_error_log(zhp);
4234                 }
4235 
4236                 if (cbp->cb_dedup_stats)
4237                         print_dedup_stats(config);
4238         } else {
4239                 (void) printf(gettext("config: The configuration cannot be "
4240                     "determined.\n"));
4241         }
4242 
4243         return (0);
4244 }
4245 
4246 /*
4247  * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4248  *
4249  *      -v      Display complete error logs
4250  *      -x      Display only pools with potential problems
4251  *      -D      Display dedup status (undocumented)
4252  *      -T      Display a timestamp in date(1) or Unix format
4253  *
4254  * Describes the health status of all pools or some subset.
4255  */
4256 int
4257 zpool_do_status(int argc, char **argv)
4258 {
4259         int c;
4260         int ret;
4261         unsigned long interval = 0, count = 0;
4262         status_cbdata_t cb = { 0 };
4263 
4264         /* check options */
4265         while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4266                 switch (c) {
4267                 case 'v':
4268                         cb.cb_verbose = B_TRUE;
4269                         break;
4270                 case 'x':
4271                         cb.cb_explain = B_TRUE;
4272                         break;
4273                 case 'D':
4274                         cb.cb_dedup_stats = B_TRUE;
4275                         break;
4276                 case 'T':
4277                         get_timestamp_arg(*optarg);
4278                         break;
4279                 case '?':
4280                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4281                             optopt);
4282                         usage(B_FALSE);
4283                 }
4284         }
4285 
4286         argc -= optind;
4287         argv += optind;
4288 
4289         get_interval_count(&argc, argv, &interval, &count);
4290 
4291         if (argc == 0)
4292                 cb.cb_allpools = B_TRUE;
4293 
4294         cb.cb_first = B_TRUE;
4295 
4296         for (;;) {
4297                 if (timestamp_fmt != NODATE)
4298                         print_timestamp(timestamp_fmt);
4299 
4300                 ret = for_each_pool(argc, argv, B_TRUE, NULL,
4301                     status_callback, &cb);
4302 
4303                 if (argc == 0 && cb.cb_count == 0)
4304                         (void) printf(gettext("no pools available\n"));
4305                 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
4306                         (void) printf(gettext("all pools are healthy\n"));
4307 
4308                 if (ret != 0)
4309                         return (ret);
4310 
4311                 if (interval == 0)
4312                         break;
4313 
4314                 if (count != 0 && --count == 0)
4315                         break;
4316 
4317                 (void) sleep(interval);
4318         }
4319 
4320         return (0);
4321 }
4322 
4323 typedef struct upgrade_cbdata {
4324         int     cb_first;
4325         int     cb_argc;
4326         uint64_t cb_version;
4327         char    **cb_argv;
4328 } upgrade_cbdata_t;
4329 
4330 static int
4331 upgrade_version(zpool_handle_t *zhp, uint64_t version)
4332 {
4333         int ret;
4334         nvlist_t *config;
4335         uint64_t oldversion;
4336 
4337         config = zpool_get_config(zhp, NULL);
4338         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4339             &oldversion) == 0);
4340 
4341         assert(SPA_VERSION_IS_SUPPORTED(oldversion));
4342         assert(oldversion < version);
4343 
4344         ret = zpool_upgrade(zhp, version);
4345         if (ret != 0)
4346                 return (ret);
4347 
4348         if (version >= SPA_VERSION_FEATURES) {
4349                 (void) printf(gettext("Successfully upgraded "
4350                     "'%s' from version %llu to feature flags.\n"),
4351                     zpool_get_name(zhp), oldversion);
4352         } else {
4353                 (void) printf(gettext("Successfully upgraded "
4354                     "'%s' from version %llu to version %llu.\n"),
4355                     zpool_get_name(zhp), oldversion, version);
4356         }
4357 
4358         return (0);
4359 }
4360 
4361 static int
4362 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4363 {
4364         int i, ret, count;
4365         boolean_t firstff = B_TRUE;
4366         nvlist_t *enabled = zpool_get_features(zhp);
4367 
4368         count = 0;
4369         for (i = 0; i < SPA_FEATURES; i++) {
4370                 const char *fname = spa_feature_table[i].fi_uname;
4371                 const char *fguid = spa_feature_table[i].fi_guid;
4372                 if (!nvlist_exists(enabled, fguid)) {
4373                         char *propname;
4374                         verify(-1 != asprintf(&propname, "feature@%s", fname));
4375                         ret = zpool_set_prop(zhp, propname,
4376                             ZFS_FEATURE_ENABLED);
4377                         if (ret != 0) {
4378                                 free(propname);
4379                                 return (ret);
4380                         }
4381                         count++;
4382 
4383                         if (firstff) {
4384                                 (void) printf(gettext("Enabled the "
4385                                     "following features on '%s':\n"),
4386                                     zpool_get_name(zhp));
4387                                 firstff = B_FALSE;
4388                         }
4389                         (void) printf(gettext("  %s\n"), fname);
4390                         free(propname);
4391                 }
4392         }
4393 
4394         if (countp != NULL)
4395                 *countp = count;
4396         return (0);
4397 }
4398 
4399 static int
4400 upgrade_cb(zpool_handle_t *zhp, void *arg)
4401 {
4402         upgrade_cbdata_t *cbp = arg;
4403         nvlist_t *config;
4404         uint64_t version;
4405         boolean_t printnl = B_FALSE;
4406         int ret;
4407 
4408         config = zpool_get_config(zhp, NULL);
4409         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4410             &version) == 0);
4411 
4412         assert(SPA_VERSION_IS_SUPPORTED(version));
4413 
4414         if (version < cbp->cb_version) {
4415                 cbp->cb_first = B_FALSE;
4416                 ret = upgrade_version(zhp, cbp->cb_version);
4417                 if (ret != 0)
4418                         return (ret);
4419                 printnl = B_TRUE;
4420 
4421                 /*
4422                  * If they did "zpool upgrade -a", then we could
4423                  * be doing ioctls to different pools.  We need
4424                  * to log this history once to each pool, and bypass
4425                  * the normal history logging that happens in main().
4426                  */
4427                 (void) zpool_log_history(g_zfs, history_str);
4428                 log_history = B_FALSE;
4429         }
4430 
4431         if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4432                 int count;
4433                 ret = upgrade_enable_all(zhp, &count);
4434                 if (ret != 0)
4435                         return (ret);
4436 
4437                 if (count > 0) {
4438                         cbp->cb_first = B_FALSE;
4439                         printnl = B_TRUE;
4440                 }
4441         }
4442 
4443         if (printnl) {
4444                 (void) printf(gettext("\n"));
4445         }
4446 
4447         return (0);
4448 }
4449 
4450 static int
4451 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
4452 {
4453         upgrade_cbdata_t *cbp = arg;
4454         nvlist_t *config;
4455         uint64_t version;
4456 
4457         config = zpool_get_config(zhp, NULL);
4458         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4459             &version) == 0);
4460 
4461         assert(SPA_VERSION_IS_SUPPORTED(version));
4462 
4463         if (version < SPA_VERSION_FEATURES) {
4464                 if (cbp->cb_first) {
4465                         (void) printf(gettext("The following pools are "
4466                             "formatted with legacy version numbers and can\n"
4467                             "be upgraded to use feature flags.  After "
4468                             "being upgraded, these pools\nwill no "
4469                             "longer be accessible by software that does not "
4470                             "support feature\nflags.\n\n"));
4471                         (void) printf(gettext("VER  POOL\n"));
4472                         (void) printf(gettext("---  ------------\n"));
4473                         cbp->cb_first = B_FALSE;
4474                 }
4475 
4476                 (void) printf("%2llu   %s\n", (u_longlong_t)version,
4477                     zpool_get_name(zhp));
4478         }
4479 
4480         return (0);
4481 }
4482 
4483 static int
4484 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
4485 {
4486         upgrade_cbdata_t *cbp = arg;
4487         nvlist_t *config;
4488         uint64_t version;
4489 
4490         config = zpool_get_config(zhp, NULL);
4491         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4492             &version) == 0);
4493 
4494         if (version >= SPA_VERSION_FEATURES) {
4495                 int i;
4496                 boolean_t poolfirst = B_TRUE;
4497                 nvlist_t *enabled = zpool_get_features(zhp);
4498 
4499                 for (i = 0; i < SPA_FEATURES; i++) {
4500                         const char *fguid = spa_feature_table[i].fi_guid;
4501                         const char *fname = spa_feature_table[i].fi_uname;
4502                         if (!nvlist_exists(enabled, fguid)) {
4503                                 if (cbp->cb_first) {
4504                                         (void) printf(gettext("\nSome "
4505                                             "supported features are not "
4506                                             "enabled on the following pools. "
4507                                             "Once a\nfeature is enabled the "
4508                                             "pool may become incompatible with "
4509                                             "software\nthat does not support "
4510                                             "the feature. See "
4511                                             "zpool-features(5) for "
4512                                             "details.\n\n"));
4513                                         (void) printf(gettext("POOL  "
4514                                             "FEATURE\n"));
4515                                         (void) printf(gettext("------"
4516                                             "---------\n"));
4517                                         cbp->cb_first = B_FALSE;
4518                                 }
4519 
4520                                 if (poolfirst) {
4521                                         (void) printf(gettext("%s\n"),
4522                                             zpool_get_name(zhp));
4523                                         poolfirst = B_FALSE;
4524                                 }
4525 
4526                                 (void) printf(gettext("      %s\n"), fname);
4527                         }
4528                 }
4529         }
4530 
4531         return (0);
4532 }
4533 
4534 /* ARGSUSED */
4535 static int
4536 upgrade_one(zpool_handle_t *zhp, void *data)
4537 {
4538         boolean_t printnl = B_FALSE;
4539         upgrade_cbdata_t *cbp = data;
4540         uint64_t cur_version;
4541         int ret;
4542 
4543         if (strcmp("log", zpool_get_name(zhp)) == 0) {
4544                 (void) printf(gettext("'log' is now a reserved word\n"
4545                     "Pool 'log' must be renamed using export and import"
4546                     " to upgrade.\n"));
4547                 return (1);
4548         }
4549 
4550         cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
4551         if (cur_version > cbp->cb_version) {
4552                 (void) printf(gettext("Pool '%s' is already formatted "
4553                     "using more current version '%llu'.\n\n"),
4554                     zpool_get_name(zhp), cur_version);
4555                 return (0);
4556         }
4557 
4558         if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
4559                 (void) printf(gettext("Pool '%s' is already formatted "
4560                     "using version %llu.\n\n"), zpool_get_name(zhp),
4561                     cbp->cb_version);
4562                 return (0);
4563         }
4564 
4565         if (cur_version != cbp->cb_version) {
4566                 printnl = B_TRUE;
4567                 ret = upgrade_version(zhp, cbp->cb_version);
4568                 if (ret != 0)
4569                         return (ret);
4570         }
4571 
4572         if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4573                 int count = 0;
4574                 ret = upgrade_enable_all(zhp, &count);
4575                 if (ret != 0)
4576                         return (ret);
4577 
4578                 if (count != 0) {
4579                         printnl = B_TRUE;
4580                 } else if (cur_version == SPA_VERSION) {
4581                         (void) printf(gettext("Pool '%s' already has all "
4582                             "supported features enabled.\n"),
4583                             zpool_get_name(zhp));
4584                 }
4585         }
4586 
4587         if (printnl) {
4588                 (void) printf(gettext("\n"));
4589         }
4590 
4591         return (0);
4592 }
4593 
4594 /*
4595  * zpool upgrade
4596  * zpool upgrade -v
4597  * zpool upgrade [-V version] <-a | pool ...>
4598  *
4599  * With no arguments, display downrev'd ZFS pool available for upgrade.
4600  * Individual pools can be upgraded by specifying the pool, and '-a' will
4601  * upgrade all pools.
4602  */
4603 int
4604 zpool_do_upgrade(int argc, char **argv)
4605 {
4606         int c;
4607         upgrade_cbdata_t cb = { 0 };
4608         int ret = 0;
4609         boolean_t showversions = B_FALSE;
4610         boolean_t upgradeall = B_FALSE;
4611         char *end;
4612 
4613 
4614         /* check options */
4615         while ((c = getopt(argc, argv, ":avV:")) != -1) {
4616                 switch (c) {
4617                 case 'a':
4618                         upgradeall = B_TRUE;
4619                         break;
4620                 case 'v':
4621                         showversions = B_TRUE;
4622                         break;
4623                 case 'V':
4624                         cb.cb_version = strtoll(optarg, &end, 10);
4625                         if (*end != '\0' ||
4626                             !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
4627                                 (void) fprintf(stderr,
4628                                     gettext("invalid version '%s'\n"), optarg);
4629                                 usage(B_FALSE);
4630                         }
4631                         break;
4632                 case ':':
4633                         (void) fprintf(stderr, gettext("missing argument for "
4634                             "'%c' option\n"), optopt);
4635                         usage(B_FALSE);
4636                         break;
4637                 case '?':
4638                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4639                             optopt);
4640                         usage(B_FALSE);
4641                 }
4642         }
4643 
4644         cb.cb_argc = argc;
4645         cb.cb_argv = argv;
4646         argc -= optind;
4647         argv += optind;
4648 
4649         if (cb.cb_version == 0) {
4650                 cb.cb_version = SPA_VERSION;
4651         } else if (!upgradeall && argc == 0) {
4652                 (void) fprintf(stderr, gettext("-V option is "
4653                     "incompatible with other arguments\n"));
4654                 usage(B_FALSE);
4655         }
4656 
4657         if (showversions) {
4658                 if (upgradeall || argc != 0) {
4659                         (void) fprintf(stderr, gettext("-v option is "
4660                             "incompatible with other arguments\n"));
4661                         usage(B_FALSE);
4662                 }
4663         } else if (upgradeall) {
4664                 if (argc != 0) {
4665                         (void) fprintf(stderr, gettext("-a option should not "
4666                             "be used along with a pool name\n"));
4667                         usage(B_FALSE);
4668                 }
4669         }
4670 
4671         (void) printf(gettext("This system supports ZFS pool feature "
4672             "flags.\n\n"));
4673         if (showversions) {
4674                 int i;
4675 
4676                 (void) printf(gettext("The following features are "
4677                     "supported:\n\n"));
4678                 (void) printf(gettext("FEAT DESCRIPTION\n"));
4679                 (void) printf("----------------------------------------------"
4680                     "---------------\n");
4681                 for (i = 0; i < SPA_FEATURES; i++) {
4682                         zfeature_info_t *fi = &spa_feature_table[i];
4683                         const char *ro = fi->fi_can_readonly ?
4684                             " (read-only compatible)" : "";
4685 
4686                         (void) printf("%-37s%s\n", fi->fi_uname, ro);
4687                         (void) printf("     %s\n", fi->fi_desc);
4688                 }
4689                 (void) printf("\n");
4690 
4691                 (void) printf(gettext("The following legacy versions are also "
4692                     "supported:\n\n"));
4693                 (void) printf(gettext("VER  DESCRIPTION\n"));
4694                 (void) printf("---  -----------------------------------------"
4695                     "---------------\n");
4696                 (void) printf(gettext(" 1   Initial ZFS version\n"));
4697                 (void) printf(gettext(" 2   Ditto blocks "
4698                     "(replicated metadata)\n"));
4699                 (void) printf(gettext(" 3   Hot spares and double parity "
4700                     "RAID-Z\n"));
4701                 (void) printf(gettext(" 4   zpool history\n"));
4702                 (void) printf(gettext(" 5   Compression using the gzip "
4703                     "algorithm\n"));
4704                 (void) printf(gettext(" 6   bootfs pool property\n"));
4705                 (void) printf(gettext(" 7   Separate intent log devices\n"));
4706                 (void) printf(gettext(" 8   Delegated administration\n"));
4707                 (void) printf(gettext(" 9   refquota and refreservation "
4708                     "properties\n"));
4709                 (void) printf(gettext(" 10  Cache devices\n"));
4710                 (void) printf(gettext(" 11  Improved scrub performance\n"));
4711                 (void) printf(gettext(" 12  Snapshot properties\n"));
4712                 (void) printf(gettext(" 13  snapused property\n"));
4713                 (void) printf(gettext(" 14  passthrough-x aclinherit\n"));
4714                 (void) printf(gettext(" 15  user/group space accounting\n"));
4715                 (void) printf(gettext(" 16  stmf property support\n"));
4716                 (void) printf(gettext(" 17  Triple-parity RAID-Z\n"));
4717                 (void) printf(gettext(" 18  Snapshot user holds\n"));
4718                 (void) printf(gettext(" 19  Log device removal\n"));
4719                 (void) printf(gettext(" 20  Compression using zle "
4720                     "(zero-length encoding)\n"));
4721                 (void) printf(gettext(" 21  Deduplication\n"));
4722                 (void) printf(gettext(" 22  Received properties\n"));
4723                 (void) printf(gettext(" 23  Slim ZIL\n"));
4724                 (void) printf(gettext(" 24  System attributes\n"));
4725                 (void) printf(gettext(" 25  Improved scrub stats\n"));
4726                 (void) printf(gettext(" 26  Improved snapshot deletion "
4727                     "performance\n"));
4728                 (void) printf(gettext(" 27  Improved snapshot creation "
4729                     "performance\n"));
4730                 (void) printf(gettext(" 28  Multiple vdev replacements\n"));
4731                 (void) printf(gettext("\nFor more information on a particular "
4732                     "version, including supported releases,\n"));
4733                 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
4734         } else if (argc == 0 && upgradeall) {
4735                 cb.cb_first = B_TRUE;
4736                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
4737                 if (ret == 0 && cb.cb_first) {
4738                         if (cb.cb_version == SPA_VERSION) {
4739                                 (void) printf(gettext("All pools are already "
4740                                     "formatted using feature flags.\n\n"));
4741                                 (void) printf(gettext("Every feature flags "
4742                                     "pool already has all supported features "
4743                                     "enabled.\n"));
4744                         } else {
4745                                 (void) printf(gettext("All pools are already "
4746                                     "formatted with version %llu or higher.\n"),
4747                                     cb.cb_version);
4748                         }
4749                 }
4750         } else if (argc == 0) {
4751                 cb.cb_first = B_TRUE;
4752                 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
4753                 assert(ret == 0);
4754 
4755                 if (cb.cb_first) {
4756                         (void) printf(gettext("All pools are formatted "
4757                             "using feature flags.\n\n"));
4758                 } else {
4759                         (void) printf(gettext("\nUse 'zpool upgrade -v' "
4760                             "for a list of available legacy versions.\n"));
4761                 }
4762 
4763                 cb.cb_first = B_TRUE;
4764                 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
4765                 assert(ret == 0);
4766 
4767                 if (cb.cb_first) {
4768                         (void) printf(gettext("Every feature flags pool has "
4769                             "all supported features enabled.\n"));
4770                 } else {
4771                         (void) printf(gettext("\n"));
4772                 }
4773         } else {
4774                 ret = for_each_pool(argc, argv, B_FALSE, NULL,
4775                     upgrade_one, &cb);
4776         }
4777 
4778         return (ret);
4779 }
4780 
4781 typedef struct hist_cbdata {
4782         boolean_t first;
4783         boolean_t longfmt;
4784         boolean_t internal;
4785 } hist_cbdata_t;
4786 
4787 /*
4788  * Print out the command history for a specific pool.
4789  */
4790 static int
4791 get_history_one(zpool_handle_t *zhp, void *data)
4792 {
4793         nvlist_t *nvhis;
4794         nvlist_t **records;
4795         uint_t numrecords;
4796         int ret, i;
4797         hist_cbdata_t *cb = (hist_cbdata_t *)data;
4798 
4799         cb->first = B_FALSE;
4800 
4801         (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
4802 
4803         if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
4804                 return (ret);
4805 
4806         verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
4807             &records, &numrecords) == 0);
4808         for (i = 0; i < numrecords; i++) {
4809                 nvlist_t *rec = records[i];
4810                 char tbuf[30] = "";
4811 
4812                 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
4813                         time_t tsec;
4814                         struct tm t;
4815 
4816                         tsec = fnvlist_lookup_uint64(records[i],
4817                             ZPOOL_HIST_TIME);
4818                         (void) localtime_r(&tsec, &t);
4819                         (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
4820                 }
4821 
4822                 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
4823                         (void) printf("%s %s", tbuf,
4824                             fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
4825                 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
4826                         int ievent =
4827                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
4828                         if (!cb->internal)
4829                                 continue;
4830                         if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
4831                                 (void) printf("%s unrecognized record:\n",
4832                                     tbuf);
4833                                 dump_nvlist(rec, 4);
4834                                 continue;
4835                         }
4836                         (void) printf("%s [internal %s txg:%lld] %s", tbuf,
4837                             zfs_history_event_names[ievent],
4838                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
4839                             fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
4840                 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
4841                         if (!cb->internal)
4842                                 continue;
4843                         (void) printf("%s [txg:%lld] %s", tbuf,
4844                             fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
4845                             fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
4846                         if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
4847                                 (void) printf(" %s (%llu)",
4848                                     fnvlist_lookup_string(rec,
4849                                     ZPOOL_HIST_DSNAME),
4850                                     fnvlist_lookup_uint64(rec,
4851                                     ZPOOL_HIST_DSID));
4852                         }
4853                         (void) printf(" %s", fnvlist_lookup_string(rec,
4854                             ZPOOL_HIST_INT_STR));
4855                 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
4856                         if (!cb->internal)
4857                                 continue;
4858                         (void) printf("%s ioctl %s\n", tbuf,
4859                             fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
4860                         if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
4861                                 (void) printf("    input:\n");
4862                                 dump_nvlist(fnvlist_lookup_nvlist(rec,
4863                                     ZPOOL_HIST_INPUT_NVL), 8);
4864                         }
4865                         if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
4866                                 (void) printf("    output:\n");
4867                                 dump_nvlist(fnvlist_lookup_nvlist(rec,
4868                                     ZPOOL_HIST_OUTPUT_NVL), 8);
4869                         }
4870                 } else {
4871                         if (!cb->internal)
4872                                 continue;
4873                         (void) printf("%s unrecognized record:\n", tbuf);
4874                         dump_nvlist(rec, 4);
4875                 }
4876 
4877                 if (!cb->longfmt) {
4878                         (void) printf("\n");
4879                         continue;
4880                 }
4881                 (void) printf(" [");
4882                 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
4883                         uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
4884                         struct passwd *pwd = getpwuid(who);
4885                         (void) printf("user %d ", (int)who);
4886                         if (pwd != NULL)
4887                                 (void) printf("(%s) ", pwd->pw_name);
4888                 }
4889                 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
4890                         (void) printf("on %s",
4891                             fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
4892                 }
4893                 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
4894                         (void) printf(":%s",
4895                             fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
4896                 }
4897                 (void) printf("]");
4898                 (void) printf("\n");
4899         }
4900         (void) printf("\n");
4901         nvlist_free(nvhis);
4902 
4903         return (ret);
4904 }
4905 
4906 /*
4907  * zpool history <pool>
4908  *
4909  * Displays the history of commands that modified pools.
4910  */
4911 int
4912 zpool_do_history(int argc, char **argv)
4913 {
4914         hist_cbdata_t cbdata = { 0 };
4915         int ret;
4916         int c;
4917 
4918         cbdata.first = B_TRUE;
4919         /* check options */
4920         while ((c = getopt(argc, argv, "li")) != -1) {
4921                 switch (c) {
4922                 case 'l':
4923                         cbdata.longfmt = B_TRUE;
4924                         break;
4925                 case 'i':
4926                         cbdata.internal = B_TRUE;
4927                         break;
4928                 case '?':
4929                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4930                             optopt);
4931                         usage(B_FALSE);
4932                 }
4933         }
4934         argc -= optind;
4935         argv += optind;
4936 
4937         ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
4938             &cbdata);
4939 
4940         if (argc == 0 && cbdata.first == B_TRUE) {
4941                 (void) printf(gettext("no pools available\n"));
4942                 return (0);
4943         }
4944 
4945         return (ret);
4946 }
4947 
4948 static int
4949 get_callback(zpool_handle_t *zhp, void *data)
4950 {
4951         zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
4952         char value[MAXNAMELEN];
4953         zprop_source_t srctype;
4954         zprop_list_t *pl;
4955 
4956         for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
4957 
4958                 /*
4959                  * Skip the special fake placeholder. This will also skip
4960                  * over the name property when 'all' is specified.
4961                  */
4962                 if (pl->pl_prop == ZPOOL_PROP_NAME &&
4963                     pl == cbp->cb_proplist)
4964                         continue;
4965 
4966                 if (pl->pl_prop == ZPROP_INVAL &&
4967                     (zpool_prop_feature(pl->pl_user_prop) ||
4968                     zpool_prop_unsupported(pl->pl_user_prop))) {
4969                         srctype = ZPROP_SRC_LOCAL;
4970 
4971                         if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
4972                             value, sizeof (value)) == 0) {
4973                                 zprop_print_one_property(zpool_get_name(zhp),
4974                                     cbp, pl->pl_user_prop, value, srctype,
4975                                     NULL, NULL);
4976                         }
4977                 } else {
4978                         if (zpool_get_prop(zhp, pl->pl_prop, value,
4979                             sizeof (value), &srctype) != 0)
4980                                 continue;
4981 
4982                         zprop_print_one_property(zpool_get_name(zhp), cbp,
4983                             zpool_prop_to_name(pl->pl_prop), value, srctype,
4984                             NULL, NULL);
4985                 }
4986         }
4987         return (0);
4988 }
4989 
4990 int
4991 zpool_do_get(int argc, char **argv)
4992 {
4993         zprop_get_cbdata_t cb = { 0 };
4994         zprop_list_t fake_name = { 0 };
4995         int ret;
4996 
4997         if (argc < 2) {
4998                 (void) fprintf(stderr, gettext("missing property "
4999                     "argument\n"));
5000                 usage(B_FALSE);
5001         }
5002 
5003         cb.cb_first = B_TRUE;
5004         cb.cb_sources = ZPROP_SRC_ALL;
5005         cb.cb_columns[0] = GET_COL_NAME;
5006         cb.cb_columns[1] = GET_COL_PROPERTY;
5007         cb.cb_columns[2] = GET_COL_VALUE;
5008         cb.cb_columns[3] = GET_COL_SOURCE;
5009         cb.cb_type = ZFS_TYPE_POOL;
5010 
5011         if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
5012             ZFS_TYPE_POOL) != 0)
5013                 usage(B_FALSE);
5014 
5015         if (cb.cb_proplist != NULL) {
5016                 fake_name.pl_prop = ZPOOL_PROP_NAME;
5017                 fake_name.pl_width = strlen(gettext("NAME"));
5018                 fake_name.pl_next = cb.cb_proplist;
5019                 cb.cb_proplist = &fake_name;
5020         }
5021 
5022         ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
5023             get_callback, &cb);
5024 
5025         if (cb.cb_proplist == &fake_name)
5026                 zprop_free_list(fake_name.pl_next);
5027         else
5028                 zprop_free_list(cb.cb_proplist);
5029 
5030         return (ret);
5031 }
5032 
5033 typedef struct set_cbdata {
5034         char *cb_propname;
5035         char *cb_value;
5036         boolean_t cb_any_successful;
5037 } set_cbdata_t;
5038 
5039 int
5040 set_callback(zpool_handle_t *zhp, void *data)
5041 {
5042         int error;
5043         set_cbdata_t *cb = (set_cbdata_t *)data;
5044 
5045         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5046 
5047         if (!error)
5048                 cb->cb_any_successful = B_TRUE;
5049 
5050         return (error);
5051 }
5052 
5053 int
5054 zpool_do_set(int argc, char **argv)
5055 {
5056         set_cbdata_t cb = { 0 };
5057         int error;
5058 
5059         if (argc > 1 && argv[1][0] == '-') {
5060                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5061                     argv[1][1]);
5062                 usage(B_FALSE);
5063         }
5064 
5065         if (argc < 2) {
5066                 (void) fprintf(stderr, gettext("missing property=value "
5067                     "argument\n"));
5068                 usage(B_FALSE);
5069         }
5070 
5071         if (argc < 3) {
5072                 (void) fprintf(stderr, gettext("missing pool name\n"));
5073                 usage(B_FALSE);
5074         }
5075 
5076         if (argc > 3) {
5077                 (void) fprintf(stderr, gettext("too many pool names\n"));
5078                 usage(B_FALSE);
5079         }
5080 
5081         cb.cb_propname = argv[1];
5082         cb.cb_value = strchr(cb.cb_propname, '=');
5083         if (cb.cb_value == NULL) {
5084                 (void) fprintf(stderr, gettext("missing value in "
5085                     "property=value argument\n"));
5086                 usage(B_FALSE);
5087         }
5088 
5089         *(cb.cb_value) = '\0';
5090         cb.cb_value++;
5091 
5092         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5093             set_callback, &cb);
5094 
5095         return (error);
5096 }
5097 
5098 static int
5099 find_command_idx(char *command, int *idx)
5100 {
5101         int i;
5102 
5103         for (i = 0; i < NCOMMAND; i++) {
5104                 if (command_table[i].name == NULL)
5105                         continue;
5106 
5107                 if (strcmp(command, command_table[i].name) == 0) {
5108                         *idx = i;
5109                         return (0);
5110                 }
5111         }
5112         return (1);
5113 }
5114 
5115 int
5116 main(int argc, char **argv)
5117 {
5118         int ret;
5119         int i;
5120         char *cmdname;
5121 
5122         (void) setlocale(LC_ALL, "");
5123         (void) textdomain(TEXT_DOMAIN);
5124 
5125         if ((g_zfs = libzfs_init()) == NULL) {
5126                 (void) fprintf(stderr, gettext("internal error: failed to "
5127                     "initialize ZFS library\n"));
5128                 return (1);
5129         }
5130 
5131         libzfs_print_on_error(g_zfs, B_TRUE);
5132 
5133         opterr = 0;
5134 
5135         /*
5136          * Make sure the user has specified some command.
5137          */
5138         if (argc < 2) {
5139                 (void) fprintf(stderr, gettext("missing command\n"));
5140                 usage(B_FALSE);
5141         }
5142 
5143         cmdname = argv[1];
5144 
5145         /*
5146          * Special case '-?'
5147          */
5148         if (strcmp(cmdname, "-?") == 0)
5149                 usage(B_TRUE);
5150 
5151         zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
5152 
5153         /*
5154          * Run the appropriate command.
5155          */
5156         if (find_command_idx(cmdname, &i) == 0) {
5157                 current_command = &command_table[i];
5158                 ret = command_table[i].func(argc - 1, argv + 1);
5159         } else if (strchr(cmdname, '=')) {
5160                 verify(find_command_idx("set", &i) == 0);
5161                 current_command = &command_table[i];
5162                 ret = command_table[i].func(argc, argv);
5163         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5164                 /*
5165                  * 'freeze' is a vile debugging abomination, so we treat
5166                  * it as such.
5167                  */
5168                 char buf[16384];
5169                 int fd = open(ZFS_DEV, O_RDWR);
5170                 (void) strcpy((void *)buf, argv[2]);
5171                 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
5172         } else {
5173                 (void) fprintf(stderr, gettext("unrecognized "
5174                     "command '%s'\n"), cmdname);
5175                 usage(B_FALSE);
5176         }
5177 
5178         if (ret == 0 && log_history)
5179                 (void) zpool_log_history(g_zfs, history_str);
5180 
5181         libzfs_fini(g_zfs);
5182 
5183         /*
5184          * The 'ZFS_ABORT' environment variable causes us to dump core on exit
5185          * for the purposes of running ::findleaks.
5186          */
5187         if (getenv("ZFS_ABORT") != NULL) {
5188                 (void) printf("dumping core by request\n");
5189                 abort();
5190         }
5191 
5192         return (ret);
5193 }