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