Print this page
NEX-6088 ZFS scrub/resilver take excessively long due to issuing lots of random IO
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-5284 need to document and update default for import -t option
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
NEX-5795 Rename 'wrc' as 'wbc' in the source and in the tech docs
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5745 WBC: Sometimes disabled instance never finish migration
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-5750 Time values for aggregated NFS server kstats should be normalized
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-5562 Trim timestamps incorrectly shown in UTC instead of local time
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-5064 On-demand trim should store operation start and stop time (lint fix)
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
NEX-5064 On-demand trim should store operation start and stop time
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5163 backport illumos 6027 EOL zulu (XVR-4000)
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
6027 EOL zulu (XVR-4000)
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-5162 backport illumos 6507 i386 makecontext(3c) needs to 16-byte align the stack
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
6507 i386 makecontext(3c) needs to 16-byte align the stack
Reviewed by: Gordon Ross <gordon.w.ross@gmail.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-5207 attempt to activate spare cores fmd
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-4934 Add capability to remove special vdev
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-4776 zpool(1M) coredumps on status when trimming a pool with log devices
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
6328 Fix cstyle errors in zfs codebase (fix studio)
6328 Fix cstyle errors in zfs codebase
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Jorgen Lundman <lundman@lundman.net>
Approved by: Robert Mustacchi <rm@joyent.com>
6047 SPARC boot should support feature@embedded_data
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5959 clean up per-dataset feature count code
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
5669 altroot not set in zpool create when specified with -o
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5767 fix several problems with zfs test suite
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Approved by: Gordon Ross <gwr@nexenta.com>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-4336 zpool vdev-get with an unsuported prop name core dumps
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3984 On-demand TRIM
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Conflicts:
        usr/src/common/zfs/zpool_prop.c
        usr/src/uts/common/sys/fs/zfs.h
NEX-3558 KRRP Integration
NEX-3165 need some dedup improvements
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
OS-195 itadm needs an easily parsable output mode
OS-207 SUP-817 causes lint warnings in zpool_main.c
Reviewed by: Alek Pinchuk <alek.pinchuk@nexena.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Albert Lee <albert.lee@nexenta.com>
OS-199 keep your tree clean (lint zpool_main.c)
SUP-817 Removed references to special device from man and help
Revert "SUP-817 Removed references to special device"
This reverts commit f8970e28f0d8bd6b69711722f341e3e1d0e1babf.
SUP-817 Removed references to special device
OS-132 zpool(1m) in scripting mode returns wrong exit code if no pools available
OS-103 handle CoS descriptor persistent references across vdev operations
OS-102 add man page info and tests for vdev/CoS properties and ZFS meta features
SUP-647 Long failover times dominated by zpool import times trigger client-side errors
Fix up some merges where we wanted the upstream version.
Make special vdev subtree topology the same as regular vdev subtree to simplify testcase setup
Fixup merge issues
Issue #26: partial scrub
Added partial scrub options:
-M for MOS only scrub
-m for metadata scrub
Issue #9: Support for persistent CoS/vdev attributes with feature flags
          Support for feature flags for special tier
          Contributors: Daniil Lunev, Boris Protopopov
Fixup merge results
re 13748 added zpool export -c option
zpool export -c command exports specified pool while keeping its latest
configuration in the cache file for subsequent zpool import -c.
re #13594 rb4488 Lint complaints fix
re #10054 #13409 rb4387 added parallel unmount for zpool export
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (fix lint -courtesy of Yuri Pankov)
re #12584 rb4049 zfsxx latest code merge (fix lint - courtesy of Yuri Pankov)
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (Opened code)
re #8346 rb2639 KT disk failures
ZFS plus work: special vdevs, cos, cos/vdev properties (fix lint)
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties
re #6853 rb1787 remove references to sun.com


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
  25  * Copyright (c) 2012 by Frederik Wessels. All rights reserved.

  26  * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
  27  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
  28  * Copyright 2016 Nexenta Systems, Inc.
  29  * Copyright (c) 2017 Datto Inc.
  30  */
  31 
  32 #include <assert.h>
  33 #include <ctype.h>
  34 #include <dirent.h>
  35 #include <errno.h>
  36 #include <fcntl.h>
  37 #include <libgen.h>
  38 #include <libintl.h>
  39 #include <libuutil.h>
  40 #include <locale.h>
  41 #include <stdio.h>
  42 #include <stdlib.h>
  43 #include <string.h>
  44 #include <strings.h>
  45 #include <unistd.h>
  46 #include <priv.h>
  47 #include <pwd.h>
  48 #include <zone.h>
  49 #include <zfs_prop.h>
  50 #include <sys/fs/zfs.h>
  51 #include <sys/stat.h>
  52 
  53 #include <libzfs.h>
  54 
  55 #include "zpool_util.h"
  56 #include "zfs_comutil.h"
  57 #include "zfeature_common.h"
  58 
  59 #include "statcommon.h"
  60 




  61 static int zpool_do_create(int, char **);
  62 static int zpool_do_destroy(int, char **);
  63 
  64 static int zpool_do_add(int, char **);
  65 static int zpool_do_remove(int, char **);
  66 static int zpool_do_labelclear(int, char **);
  67 
  68 static int zpool_do_list(int, char **);
  69 static int zpool_do_iostat(int, char **);
  70 static int zpool_do_status(int, char **);
  71 
  72 static int zpool_do_online(int, char **);
  73 static int zpool_do_offline(int, char **);
  74 static int zpool_do_clear(int, char **);
  75 static int zpool_do_reopen(int, char **);
  76 
  77 static int zpool_do_reguid(int, char **);
  78 
  79 static int zpool_do_attach(int, char **);
  80 static int zpool_do_detach(int, char **);
  81 static int zpool_do_replace(int, char **);
  82 static int zpool_do_split(int, char **);
  83 
  84 static int zpool_do_scrub(int, char **);

  85 
  86 static int zpool_do_import(int, char **);
  87 static int zpool_do_export(int, char **);
  88 
  89 static int zpool_do_upgrade(int, char **);
  90 
  91 static int zpool_do_history(int, char **);
  92 
  93 static int zpool_do_get(int, char **);
  94 static int zpool_do_set(int, char **);
  95 











  96 /*
  97  * These libumem hooks provide a reasonable set of defaults for the allocator's
  98  * debugging facilities.
  99  */
 100 
 101 #ifdef DEBUG
 102 const char *
 103 _umem_debug_init(void)
 104 {
 105         return ("default,verbose"); /* $UMEM_DEBUG setting */
 106 }
 107 
 108 const char *
 109 _umem_logging_init(void)
 110 {
 111         return ("fail,contents"); /* $UMEM_LOGGING setting */
 112 }
 113 #endif
 114 
 115 typedef enum {
 116         HELP_ADD,
 117         HELP_ATTACH,
 118         HELP_CLEAR,
 119         HELP_CREATE,
 120         HELP_DESTROY,
 121         HELP_DETACH,
 122         HELP_EXPORT,
 123         HELP_HISTORY,
 124         HELP_IMPORT,
 125         HELP_IOSTAT,
 126         HELP_LABELCLEAR,
 127         HELP_LIST,
 128         HELP_OFFLINE,
 129         HELP_ONLINE,
 130         HELP_REPLACE,
 131         HELP_REMOVE,
 132         HELP_SCRUB,

 133         HELP_STATUS,
 134         HELP_UPGRADE,
 135         HELP_GET,
 136         HELP_SET,
 137         HELP_SPLIT,
 138         HELP_REGUID,
 139         HELP_REOPEN







 140 } zpool_help_t;
 141 
 142 
 143 typedef struct zpool_command {
 144         const char      *name;
 145         int             (*func)(int, char **);
 146         zpool_help_t    usage;
 147 } zpool_command_t;
 148 
 149 /*
 150  * Master command table.  Each ZFS command has a name, associated function, and
 151  * usage message.  The usage messages need to be internationalized, so we have
 152  * to have a function to return the usage message based on a command index.
 153  *
 154  * These commands are organized according to how they are displayed in the usage
 155  * message.  An empty command (one with a NULL name) indicates an empty line in
 156  * the generic usage message.
 157  */
 158 static zpool_command_t command_table[] = {
 159         { "create",     zpool_do_create,        HELP_CREATE             },


 163         { "remove",     zpool_do_remove,        HELP_REMOVE             },
 164         { NULL },
 165         { "labelclear", zpool_do_labelclear,    HELP_LABELCLEAR         },
 166         { NULL },
 167         { "list",       zpool_do_list,          HELP_LIST               },
 168         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
 169         { "status",     zpool_do_status,        HELP_STATUS             },
 170         { NULL },
 171         { "online",     zpool_do_online,        HELP_ONLINE             },
 172         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
 173         { "clear",      zpool_do_clear,         HELP_CLEAR              },
 174         { "reopen",     zpool_do_reopen,        HELP_REOPEN             },
 175         { NULL },
 176         { "attach",     zpool_do_attach,        HELP_ATTACH             },
 177         { "detach",     zpool_do_detach,        HELP_DETACH             },
 178         { "replace",    zpool_do_replace,       HELP_REPLACE            },
 179         { "split",      zpool_do_split,         HELP_SPLIT              },
 180         { NULL },
 181         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
 182         { NULL },


 183         { "import",     zpool_do_import,        HELP_IMPORT             },
 184         { "export",     zpool_do_export,        HELP_EXPORT             },
 185         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 186         { "reguid",     zpool_do_reguid,        HELP_REGUID             },
 187         { NULL },
 188         { "history",    zpool_do_history,       HELP_HISTORY            },
 189         { "get",        zpool_do_get,           HELP_GET                },
 190         { "set",        zpool_do_set,           HELP_SET                },







 191 };
 192 
 193 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 194 
 195 static zpool_command_t *current_command;
 196 static char history_str[HIS_MAX_RECORD_LEN];
 197 static boolean_t log_history = B_TRUE;
 198 static uint_t timestamp_fmt = NODATE;
 199 
 200 static const char *
 201 get_usage(zpool_help_t idx)
 202 {
 203         switch (idx) {
 204         case HELP_ADD:
 205                 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
 206         case HELP_ATTACH:
 207                 return (gettext("\tattach [-f] <pool> <device> "
 208                     "<new-device>\n"));
 209         case HELP_CLEAR:
 210                 return (gettext("\tclear [-nF] <pool> [device]\n"));
 211         case HELP_CREATE:
 212                 return (gettext("\tcreate [-fnd] [-B] "
 213                     "[-o property=value] ... \n"
 214                     "\t    [-O file-system-property=value] ... \n"
 215                     "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
 216         case HELP_DESTROY:
 217                 return (gettext("\tdestroy [-f] <pool>\n"));
 218         case HELP_DETACH:
 219                 return (gettext("\tdetach <pool> <device>\n"));
 220         case HELP_EXPORT:
 221                 return (gettext("\texport [-f] <pool> ...\n"));
 222         case HELP_HISTORY:
 223                 return (gettext("\thistory [-il] [<pool>] ...\n"));
 224         case HELP_IMPORT:
 225                 return (gettext("\timport [-d dir] [-D]\n"
 226                     "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
 227                     "\timport [-o mntopts] [-o property=value] ... \n"
 228                     "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
 229                     "[-R root] [-F [-n]] -a\n"
 230                     "\timport [-o mntopts] [-o property=value] ... \n"
 231                     "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
 232                     "[-R root] [-F [-n]]\n"
 233                     "\t    <pool | id> [newpool]\n"));
 234         case HELP_IOSTAT:
 235                 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
 236                     "[count]]\n"));
 237         case HELP_LABELCLEAR:
 238                 return (gettext("\tlabelclear [-f] <vdev>\n"));
 239         case HELP_LIST:
 240                 return (gettext("\tlist [-Hp] [-o property[,...]] "
 241                     "[-T d|u] [pool] ... [interval [count]]\n"));
 242         case HELP_OFFLINE:
 243                 return (gettext("\toffline [-t] <pool> <device> ...\n"));
 244         case HELP_ONLINE:
 245                 return (gettext("\tonline <pool> <device> ...\n"));
 246         case HELP_REPLACE:
 247                 return (gettext("\treplace [-f] <pool> <device> "
 248                     "[new-device]\n"));
 249         case HELP_REMOVE:
 250                 return (gettext("\tremove [-nps] <pool> <device> ...\n"));
 251         case HELP_REOPEN:
 252                 return (gettext("\treopen <pool>\n"));
 253         case HELP_SCRUB:
 254                 return (gettext("\tscrub [-s | -p] <pool> ...\n"));


 255         case HELP_STATUS:
 256                 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
 257                     "[count]]\n"));
 258         case HELP_UPGRADE:
 259                 return (gettext("\tupgrade\n"
 260                     "\tupgrade -v\n"
 261                     "\tupgrade [-V version] <-a | pool ...>\n"));
 262         case HELP_GET:
 263                 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
 264                     "<\"all\" | property[,...]> <pool> ...\n"));
 265         case HELP_SET:
 266                 return (gettext("\tset <property=value> <pool> \n"));
 267         case HELP_SPLIT:
 268                 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
 269                     "\t    [-o property=value] <pool> <newpool> "
 270                     "[<device> ...]\n"));
 271         case HELP_REGUID:
 272                 return (gettext("\treguid <pool>\n"));


















 273         }
 274 
 275         abort();
 276         /* NOTREACHED */
 277 }














 278 
 279 
 280 /*
 281  * Callback routine that will print out a pool property value.
 282  */
 283 static int
 284 print_prop_cb(int prop, void *cb)
 285 {
 286         FILE *fp = cb;
 287 
 288         (void) fprintf(fp, "\t%-15s  ", zpool_prop_to_name(prop));
 289 
 290         if (zpool_prop_readonly(prop))
 291                 (void) fprintf(fp, "  NO   ");
 292         else
 293                 (void) fprintf(fp, " YES   ");
 294 
 295         if (zpool_prop_values(prop) == NULL)
 296                 (void) fprintf(fp, "-\n");
 297         else
 298                 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
 299 


 394 
 395 static boolean_t
 396 prop_list_contains_feature(nvlist_t *proplist)
 397 {
 398         nvpair_t *nvp;
 399         for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
 400             nvp = nvlist_next_nvpair(proplist, nvp)) {
 401                 if (zpool_prop_feature(nvpair_name(nvp)))
 402                         return (B_TRUE);
 403         }
 404         return (B_FALSE);
 405 }
 406 
 407 /*
 408  * Add a property pair (name, string-value) into a property nvlist.
 409  */
 410 static int
 411 add_prop_list(const char *propname, char *propval, nvlist_t **props,
 412     boolean_t poolprop)
 413 {
 414         zpool_prop_t prop = ZPOOL_PROP_INVAL;
 415         zfs_prop_t fprop;
 416         nvlist_t *proplist;
 417         const char *normnm;
 418         char *strval;
 419 
 420         if (*props == NULL &&
 421             nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
 422                 (void) fprintf(stderr,
 423                     gettext("internal error: out of memory\n"));
 424                 return (1);
 425         }
 426 
 427         proplist = *props;
 428 
 429         if (poolprop) {
 430                 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
 431 
 432                 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
 433                     !zpool_prop_feature(propname)) {
 434                         (void) fprintf(stderr, gettext("property '%s' is "
 435                             "not a valid pool property\n"), propname);
 436                         return (2);
 437                 }
 438 
 439                 /*
 440                  * feature@ properties and version should not be specified
 441                  * at the same time.
 442                  */
 443                 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
 444                     nvlist_exists(proplist, vname)) ||
 445                     (prop == ZPOOL_PROP_VERSION &&
 446                     prop_list_contains_feature(proplist))) {
 447                         (void) fprintf(stderr, gettext("'feature@' and "
 448                             "'version' properties cannot be specified "
 449                             "together\n"));
 450                         return (2);
 451                 }
 452 
 453 
 454                 if (zpool_prop_feature(propname))
 455                         normnm = propname;
 456                 else
 457                         normnm = zpool_prop_to_name(prop);
 458         } else {
 459                 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
 460                         normnm = zfs_prop_to_name(fprop);
 461                 } else {
 462                         normnm = propname;
 463                 }
 464         }
 465 
 466         if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
 467             prop != ZPOOL_PROP_CACHEFILE) {
 468                 (void) fprintf(stderr, gettext("property '%s' "
 469                     "specified multiple times\n"), propname);
 470                 return (2);
 471         }
 472 
 473         if (nvlist_add_string(proplist, normnm, propval) != 0) {
 474                 (void) fprintf(stderr, gettext("internal "
 475                     "error: out of memory\n"));
 476                 return (1);
 477         }
 478 
 479         return (0);
 480 }
 481 
 482 /*


































































 483  * zpool add [-fn] <pool> <vdev> ...
 484  *
 485  *      -f      Force addition of devices, even if they appear in use
 486  *      -n      Do not add the devices, but display the resulting layout if
 487  *              they were to be added.
 488  *
 489  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
 490  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
 491  * libzfs.
 492  */
 493 int
 494 zpool_do_add(int argc, char **argv)
 495 {
 496         boolean_t force = B_FALSE;
 497         boolean_t dryrun = B_FALSE;
 498         int c;
 499         nvlist_t *nvroot;
 500         char *poolname;
 501         zpool_boot_label_t boot_type;
 502         uint64_t boot_size;


 580                         print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
 581                         print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
 582                 } else if (num_logs(nvroot) > 0) {
 583                         print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
 584                 }
 585 
 586                 ret = 0;
 587         } else {
 588                 ret = (zpool_add(zhp, nvroot) != 0);
 589         }
 590 
 591         nvlist_free(nvroot);
 592         zpool_close(zhp);
 593 
 594         return (ret);
 595 }
 596 
 597 /*
 598  * zpool remove  <pool> <vdev> ...
 599  *
 600  * Removes the given vdev from the pool.

 601  */
 602 int
 603 zpool_do_remove(int argc, char **argv)
 604 {
 605         char *poolname;
 606         int i, ret = 0;
 607         zpool_handle_t *zhp;
 608         boolean_t stop = B_FALSE;
 609         boolean_t noop = B_FALSE;
 610         boolean_t parsable = B_FALSE;
 611         char c;
 612 
 613         /* check options */
 614         while ((c = getopt(argc, argv, "nps")) != -1) {
 615                 switch (c) {
 616                 case 'n':
 617                         noop = B_TRUE;
 618                         break;
 619                 case 'p':
 620                         parsable = B_TRUE;
 621                         break;
 622                 case 's':
 623                         stop = B_TRUE;
 624                         break;
 625                 case '?':
 626                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 627                             optopt);
 628                         usage(B_FALSE);
 629                 }
 630         }
 631 
 632         argc -= optind;
 633         argv += optind;
 634 
 635         /* get pool name and check number of arguments */
 636         if (argc < 1) {
 637                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
 638                 usage(B_FALSE);
 639         }




 640 
 641         poolname = argv[0];
 642 
 643         if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
 644                 return (1);
 645 
 646         if (stop && noop) {
 647                 (void) fprintf(stderr, gettext("stop request ignored\n"));
 648                 return (0);
 649         }
 650 
 651         if (stop) {
 652                 if (argc > 1) {
 653                         (void) fprintf(stderr, gettext("too many arguments\n"));
 654                         usage(B_FALSE);
 655                 }
 656                 if (zpool_vdev_remove_cancel(zhp) != 0)
 657                         ret = 1;
 658         } else {
 659                 if (argc < 2) {
 660                         (void) fprintf(stderr, gettext("missing device\n"));
 661                         usage(B_FALSE);
 662                 }
 663 
 664                 for (i = 1; i < argc; i++) {
 665                         if (noop) {
 666                                 uint64_t size;
 667 
 668                                 if (zpool_vdev_indirect_size(zhp, argv[i],
 669                                     &size) != 0) {
 670                                         ret = 1;
 671                                         break;
 672                                 }
 673                                 if (parsable) {
 674                                         (void) printf("%s %llu\n",
 675                                             argv[i], size);
 676                                 } else {
 677                                         char valstr[32];
 678                                         zfs_nicenum(size, valstr,
 679                                             sizeof (valstr));
 680                                         (void) printf("Memory that will be "
 681                                             "used after removing %s: %s\n",
 682                                             argv[i], valstr);
 683                                 }
 684                         } else {
 685                                 if (zpool_vdev_remove(zhp, argv[i]) != 0)
 686                                         ret = 1;
 687                         }
 688                 }
 689         }
 690 
 691         return (ret);
 692 }
 693 
 694 /*
 695  * zpool labelclear [-f] <vdev>
 696  *
 697  *      -f      Force clearing the label for the vdevs which are members of
 698  *              the exported or foreign pools.
 699  *
 700  * Verifies that the vdev is not active and zeros out the label information
 701  * on the device.
 702  */
 703 int
 704 zpool_do_labelclear(int argc, char **argv)
 705 {
 706         char vdev[MAXPATHLEN];
 707         char *name = NULL;
 708         struct stat st;
 709         int c, fd, ret = 0;


1247                 usage(B_FALSE);
1248         }
1249         if (argc > 1) {
1250                 (void) fprintf(stderr, gettext("too many arguments\n"));
1251                 usage(B_FALSE);
1252         }
1253 
1254         pool = argv[0];
1255 
1256         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1257                 /*
1258                  * As a special case, check for use of '/' in the name, and
1259                  * direct the user to use 'zfs destroy' instead.
1260                  */
1261                 if (strchr(pool, '/') != NULL)
1262                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1263                             "destroy a dataset\n"));
1264                 return (1);
1265         }
1266 




















1267         if (zpool_disable_datasets(zhp, force) != 0) {
1268                 (void) fprintf(stderr, gettext("could not destroy '%s': "
1269                     "could not unmount datasets\n"), zpool_get_name(zhp));
1270                 return (1);
1271         }
1272 
1273         /* The history must be logged as part of the export */
1274         log_history = B_FALSE;
1275 
1276         ret = (zpool_destroy(zhp, history_str) != 0);
1277 
1278         zpool_close(zhp);
1279 
1280         return (ret);
1281 }
1282 
1283 /*
1284  * zpool export [-f] <pool> ...
1285  *
1286  *      -f      Forcefully unmount datasets
1287  *
1288  * Export the given pools.  By default, the command will attempt to cleanly
1289  * unmount any active datasets within the pool.  If the '-f' flag is specified,
1290  * then the datasets will be forcefully unmounted.
1291  */
1292 int
1293 zpool_do_export(int argc, char **argv)
1294 {
1295         boolean_t force = B_FALSE;
1296         boolean_t hardforce = B_FALSE;

1297         int c;

1298         zpool_handle_t *zhp;
1299         int ret;
1300         int i;
1301 
1302         /* check options */
1303         while ((c = getopt(argc, argv, "fF")) != -1) {
1304                 switch (c) {
1305                 case 'f':
1306                         force = B_TRUE;
1307                         break;
1308                 case 'F':
1309                         hardforce = B_TRUE;
1310                         break;






1311                 case '?':
1312                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1313                             optopt);
1314                         usage(B_FALSE);






1315                 }
1316         }
1317 
1318         argc -= optind;
1319         argv += optind;
1320 
1321         /* check arguments */
1322         if (argc < 1) {
1323                 (void) fprintf(stderr, gettext("missing pool argument\n"));
1324                 usage(B_FALSE);
1325         }
1326 
1327         ret = 0;
1328         for (i = 0; i < argc; i++) {
1329                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1330                         ret = 1;
1331                         continue;
1332                 }
1333 
1334                 if (zpool_disable_datasets(zhp, force) != 0) {












1335                         ret = 1;








1336                         zpool_close(zhp);
1337                         continue;
1338                 }
1339 
1340                 /* The history must be logged as part of the export */
1341                 log_history = B_FALSE;
1342 
1343                 if (hardforce) {
1344                         if (zpool_export_force(zhp, history_str) != 0)

1345                                 ret = 1;
1346                 } else if (zpool_export(zhp, force, history_str) != 0) {

1347                         ret = 1;
1348                 }
1349 
1350                 zpool_close(zhp);
1351         }
1352 
1353         return (ret);
1354 }
1355 
1356 /*
1357  * Given a vdev configuration, determine the maximum width needed for the device
1358  * name column.
1359  */
1360 static int
1361 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1362 {
1363         char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1364         nvlist_t **child;
1365         uint_t c, children;
1366         int ret;


1442         zpool_close(zhp);
1443         return (0);
1444 }
1445 
1446 /*
1447  * Print out configuration state as requested by status_callback.
1448  */
1449 void
1450 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1451     int namewidth, int depth, boolean_t isspare)
1452 {
1453         nvlist_t **child;
1454         uint_t c, children;
1455         pool_scan_stat_t *ps = NULL;
1456         vdev_stat_t *vs;
1457         char rbuf[6], wbuf[6], cbuf[6];
1458         char *vname;
1459         uint64_t notpresent;
1460         spare_cbdata_t cb;
1461         const char *state;
1462         char *type;
1463 
1464         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1465             &child, &children) != 0)
1466                 children = 0;
1467 
1468         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1469             (uint64_t **)&vs, &c) == 0);
1470 
1471         verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1472 
1473         if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1474                 return;
1475 
1476         state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1477         if (isspare) {
1478                 /*
1479                  * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1480                  * online drives.
1481                  */
1482                 if (vs->vs_aux == VDEV_AUX_SPARED)
1483                         state = "INUSE";
1484                 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1485                         state = "AVAIL";
1486         }
1487 
1488         (void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
1489             name, state);
1490 
1491         if (!isspare) {
1492                 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1493                 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1494                 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1495                 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);


1545                 case VDEV_AUX_ERR_EXCEEDED:
1546                         (void) printf(gettext("too many errors"));
1547                         break;
1548 
1549                 case VDEV_AUX_IO_FAILURE:
1550                         (void) printf(gettext("experienced I/O failures"));
1551                         break;
1552 
1553                 case VDEV_AUX_BAD_LOG:
1554                         (void) printf(gettext("bad intent log"));
1555                         break;
1556 
1557                 case VDEV_AUX_EXTERNAL:
1558                         (void) printf(gettext("external device fault"));
1559                         break;
1560 
1561                 case VDEV_AUX_SPLIT_POOL:
1562                         (void) printf(gettext("split into new pool"));
1563                         break;
1564 
1565                 case VDEV_AUX_CHILDREN_OFFLINE:
1566                         (void) printf(gettext("all children offline"));
1567                         break;
1568 
1569                 default:
1570                         (void) printf(gettext("corrupted data"));
1571                         break;
1572                 }
1573         }
1574 
1575         (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1576             (uint64_t **)&ps, &c);
1577 
1578         if (ps && ps->pss_state == DSS_SCANNING &&
1579             vs->vs_scan_processed != 0 && children == 0) {

1580                 (void) printf(gettext("  (%s)"),
1581                     (ps->pss_func == POOL_SCAN_RESILVER) ?
1582                     "resilvering" : "repairing");
1583         }
1584 
1585         (void) printf("\n");
1586 
1587         for (c = 0; c < children; c++) {
1588                 uint64_t islog = B_FALSE, ishole = B_FALSE;
1589 
1590                 /* Don't print logs or holes here */
1591                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1592                     &islog);
1593                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1594                     &ishole);
1595                 if (islog || ishole)


1596                         continue;
1597                 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1598                 print_status_config(zhp, vname, child[c],
1599                     namewidth, depth + 2, isspare);
1600                 free(vname);
1601         }
1602 }
1603 
1604 
1605 /*
1606  * Print the configuration of an exported pool.  Iterate over all vdevs in the
1607  * pool, printing out the name and status for each one.
1608  */
1609 void
1610 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1611 {
1612         nvlist_t **child;
1613         uint_t c, children;
1614         vdev_stat_t *vs;
1615         char *type, *vname;


1636                 case VDEV_AUX_BAD_GUID_SUM:
1637                         (void) printf(gettext("missing device"));
1638                         break;
1639 
1640                 case VDEV_AUX_NO_REPLICAS:
1641                         (void) printf(gettext("insufficient replicas"));
1642                         break;
1643 
1644                 case VDEV_AUX_VERSION_NEWER:
1645                         (void) printf(gettext("newer version"));
1646                         break;
1647 
1648                 case VDEV_AUX_UNSUP_FEAT:
1649                         (void) printf(gettext("unsupported feature(s)"));
1650                         break;
1651 
1652                 case VDEV_AUX_ERR_EXCEEDED:
1653                         (void) printf(gettext("too many errors"));
1654                         break;
1655 
1656                 case VDEV_AUX_CHILDREN_OFFLINE:
1657                         (void) printf(gettext("all children offline"));
1658                         break;
1659 
1660                 default:
1661                         (void) printf(gettext("corrupted data"));
1662                         break;
1663                 }
1664         }
1665         (void) printf("\n");
1666 
1667         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1668             &child, &children) != 0)
1669                 return;
1670 
1671         for (c = 0; c < children; c++) {
1672                 uint64_t is_log = B_FALSE;
1673 
1674                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1675                     &is_log);
1676                 if (is_log)


1677                         continue;
1678 
1679                 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1680                 print_import_config(vname, child[c], namewidth, depth + 2);
1681                 free(vname);
1682         }
1683 
1684         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1685             &child, &children) == 0) {
1686                 (void) printf(gettext("\tcache\n"));
1687                 for (c = 0; c < children; c++) {
1688                         vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1689                         (void) printf("\t  %s\n", vname);
1690                         free(vname);
1691                 }
1692         }
1693 
1694         if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1695             &child, &children) == 0) {
1696                 (void) printf(gettext("\tspares\n"));


1724 
1725         for (c = 0; c < children; c++) {
1726                 uint64_t is_log = B_FALSE;
1727                 char *name;
1728 
1729                 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1730                     &is_log);
1731                 if (!is_log)
1732                         continue;
1733                 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1734                 if (verbose)
1735                         print_status_config(zhp, name, child[c], namewidth,
1736                             2, B_FALSE);
1737                 else
1738                         print_import_config(name, child[c], namewidth, 2);
1739                 free(name);
1740         }
1741 }
1742 
1743 /*







































1744  * Display the status for the given pool.
1745  */
1746 static void
1747 show_import(nvlist_t *config)
1748 {
1749         uint64_t pool_state;
1750         vdev_stat_t *vs;
1751         char *name;
1752         uint64_t guid;
1753         char *msgid;
1754         nvlist_t *nvroot;
1755         int reason;
1756         const char *health;
1757         uint_t vsc;
1758         int namewidth;
1759         char *comment;
1760 
1761         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1762             &name) == 0);
1763         verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,


1938                 if (pool_state == POOL_STATE_DESTROYED)
1939                         (void) printf(gettext("\tThe pool was destroyed, "
1940                             "but can be imported using the '-Df' flags.\n"));
1941                 else if (pool_state != POOL_STATE_EXPORTED)
1942                         (void) printf(gettext("\tThe pool may be active on "
1943                             "another system, but can be imported using\n\t"
1944                             "the '-f' flag.\n"));
1945         }
1946 
1947         if (msgid != NULL)
1948                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
1949                     msgid);
1950 
1951         (void) printf(gettext(" config:\n\n"));
1952 
1953         namewidth = max_width(NULL, nvroot, 0, 0);
1954         if (namewidth < 10)
1955                 namewidth = 10;
1956 
1957         print_import_config(name, nvroot, namewidth, 0);



1958         if (num_logs(nvroot) > 0)
1959                 print_logs(NULL, nvroot, namewidth, B_FALSE);
1960 
1961         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1962                 (void) printf(gettext("\n\tAdditional devices are known to "
1963                     "be part of this pool, though their\n\texact "
1964                     "configuration cannot be determined.\n"));
1965         }
1966 }
1967 
1968 /*
1969  * Perform the import for the given configuration.  This passes the heavy
1970  * lifting off to zpool_import_props(), and then mounts the datasets contained
1971  * within the pool.
1972  */
1973 static int
1974 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1975     nvlist_t *props, int flags)
1976 {
1977         zpool_handle_t *zhp;
1978         char *name;
1979         uint64_t state;
1980         uint64_t version;
1981 
1982         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1983             &name) == 0);
1984 
1985         verify(nvlist_lookup_uint64(config,
1986             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1987         verify(nvlist_lookup_uint64(config,
1988             ZPOOL_CONFIG_VERSION, &version) == 0);
1989         if (!SPA_VERSION_IS_SUPPORTED(version)) {
1990                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1991                     "is formatted using an unsupported ZFS version\n"), name);
1992                 return (1);
1993         } else if (state != POOL_STATE_EXPORTED &&
1994             !(flags & ZFS_IMPORT_ANY_HOST)) {
1995                 uint64_t hostid;


2019                 } else {
2020                         (void) fprintf(stderr, gettext("cannot import '%s': "
2021                             "pool may be in use from other system\n"), name);
2022                         (void) fprintf(stderr, gettext("use '-f' to import "
2023                             "anyway\n"));
2024                         return (1);
2025                 }
2026         }
2027 
2028         if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2029                 return (1);
2030 
2031         if (newname != NULL)
2032                 name = (char *)newname;
2033 
2034         if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2035                 return (1);
2036 
2037         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2038             !(flags & ZFS_IMPORT_ONLY) &&
2039             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2040                 zpool_close(zhp);
2041                 return (1);
2042         }
2043 
2044         zpool_close(zhp);
2045         return (0);
2046 }
2047 
2048 /*
2049  * zpool import [-d dir] [-D]
2050  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2051  *              [-d dir | -c cachefile] [-f] -a
2052  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2053  *              [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2054  *
2055  *       -c     Read pool information from a cachefile instead of searching
2056  *              devices.
2057  *
2058  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
2059  *              one directory can be specified using multiple '-d' options.
2060  *
2061  *       -D     Scan for previously destroyed pools or import all or only
2062  *              specified destroyed pools.
2063  *
2064  *       -R     Temporarily import the pool, with all mountpoints relative to
2065  *              the given root.  The pool will remain exported when the machine
2066  *              is rebooted.
2067  *
2068  *       -V     Import even in the presence of faulted vdevs.  This is an
2069  *              intentionally undocumented option for testing purposes, and
2070  *              treats the pool configuration as complete, leaving any bad
2071  *              vdevs in the FAULTED state. In other words, it does verbatim
2072  *              import.
2073  *
2074  *       -f     Force import, even if it appears that the pool is active.
2075  *
2076  *       -F     Attempt rewind if necessary.
2077  *
2078  *       -n     See if rewind would work, but don't actually rewind.
2079  *
2080  *       -N     Import the pool but don't mount datasets.
2081  *


2082  *       -T     Specify a starting txg to use for import. This option is
2083  *              intentionally undocumented option for testing purposes.
2084  *
2085  *       -a     Import all pools found.
2086  *
2087  *       -o     Set property=value and/or temporary mount options (without '=').
2088  *
2089  * The import command scans for pools to import, and import pools based on pool
2090  * name and GUID.  The pool can also be renamed as part of the import process.
2091  */
2092 int
2093 zpool_do_import(int argc, char **argv)
2094 {
2095         char **searchdirs = NULL;
2096         int nsearch = 0;
2097         int c;
2098         int err = 0;
2099         nvlist_t *pools = NULL;
2100         boolean_t do_all = B_FALSE;
2101         boolean_t do_destroyed = B_FALSE;
2102         char *mntopts = NULL;
2103         nvpair_t *elem;
2104         nvlist_t *config;
2105         uint64_t searchguid = 0;
2106         char *searchname = NULL;
2107         char *propval;
2108         nvlist_t *found_config;
2109         nvlist_t *policy = NULL;
2110         nvlist_t *props = NULL;
2111         boolean_t first;
2112         int flags = ZFS_IMPORT_NORMAL;
2113         uint32_t rewind_policy = ZPOOL_NO_REWIND;
2114         boolean_t dryrun = B_FALSE;
2115         boolean_t do_rewind = B_FALSE;
2116         boolean_t xtreme_rewind = B_FALSE;
2117         uint64_t pool_state, txg = -1ULL;
2118         char *cachefile = NULL;
2119         importargs_t idata = { 0 };

2120         char *endptr;
2121 
2122         /* check options */
2123         while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) {
2124                 switch (c) {
2125                 case 'a':
2126                         do_all = B_TRUE;
2127                         break;
2128                 case 'c':
2129                         cachefile = optarg;
2130                         break;
2131                 case 'd':
2132                         if (searchdirs == NULL) {
2133                                 searchdirs = safe_malloc(sizeof (char *));
2134                         } else {
2135                                 char **tmp = safe_malloc((nsearch + 1) *
2136                                     sizeof (char *));
2137                                 bcopy(searchdirs, tmp, nsearch *
2138                                     sizeof (char *));
2139                                 free(searchdirs);
2140                                 searchdirs = tmp;
2141                         }
2142                         searchdirs[nsearch++] = optarg;
2143                         break;


2165                                 propval++;
2166                                 if (add_prop_list(optarg, propval,
2167                                     &props, B_TRUE))
2168                                         goto error;
2169                         } else {
2170                                 mntopts = optarg;
2171                         }
2172                         break;
2173                 case 'R':
2174                         if (add_prop_list(zpool_prop_to_name(
2175                             ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2176                                 goto error;
2177                         if (nvlist_lookup_string(props,
2178                             zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2179                             &propval) == 0)
2180                                 break;
2181                         if (add_prop_list(zpool_prop_to_name(
2182                             ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2183                                 goto error;
2184                         break;









2185                 case 'T':
2186                         errno = 0;
2187                         txg = strtoull(optarg, &endptr, 0);
2188                         if (errno != 0 || *endptr != '\0') {
2189                                 (void) fprintf(stderr,
2190                                     gettext("invalid txg value\n"));
2191                                 usage(B_FALSE);
2192                         }
2193                         rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2194                         break;
2195                 case 'V':
2196                         flags |= ZFS_IMPORT_VERBATIM;
2197                         break;
2198                 case 'X':
2199                         xtreme_rewind = B_TRUE;
2200                         break;
2201                 case ':':
2202                         (void) fprintf(stderr, gettext("missing argument for "
2203                             "'%c' option\n"), optopt);
2204                         usage(B_FALSE);


2287                 errno = 0;
2288                 searchguid = strtoull(argv[0], &endptr, 10);
2289                 if (errno != 0 || *endptr != '\0') {
2290                         searchname = argv[0];
2291                         searchguid = 0;
2292                 }
2293                 found_config = NULL;
2294 
2295                 /*
2296                  * User specified a name or guid.  Ensure it's unique.
2297                  */
2298                 idata.unique = B_TRUE;
2299         }
2300 
2301 
2302         idata.path = searchdirs;
2303         idata.paths = nsearch;
2304         idata.poolname = searchname;
2305         idata.guid = searchguid;
2306         idata.cachefile = cachefile;
2307         idata.policy = policy;
2308 
2309         pools = zpool_search_import(g_zfs, &idata);
2310 
2311         if (pools != NULL && idata.exists &&
2312             (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2313                 (void) fprintf(stderr, gettext("cannot import '%s': "
2314                     "a pool with that name already exists\n"),
2315                     argv[0]);
2316                 (void) fprintf(stderr, gettext("use the form '%s "
2317                     "<pool | id> <newpool>' to give it a new name\n"),
2318                     "zpool import");
2319                 err = 1;
2320         } else if (pools == NULL && idata.exists) {
2321                 (void) fprintf(stderr, gettext("cannot import '%s': "
2322                     "a pool with that name is already created/imported,\n"),
2323                     argv[0]);
2324                 (void) fprintf(stderr, gettext("and no additional pools "
2325                     "with that name were found\n"));
2326                 err = 1;
2327         } else if (pools == NULL) {


2352                 verify(nvpair_value_nvlist(elem, &config) == 0);
2353 
2354                 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2355                     &pool_state) == 0);
2356                 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2357                         continue;
2358                 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2359                         continue;
2360 
2361                 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2362                     policy) == 0);
2363 
2364                 if (argc == 0) {
2365                         if (first)
2366                                 first = B_FALSE;
2367                         else if (!do_all)
2368                                 (void) printf("\n");
2369 
2370                         if (do_all) {
2371                                 err |= do_import(config, NULL, mntopts,
2372                                     props, flags);
2373                         } else {
2374                                 show_import(config);
2375                         }
2376                 } else if (searchname != NULL) {
2377                         char *name;
2378 
2379                         /*
2380                          * We are searching for a pool based on name.
2381                          */
2382                         verify(nvlist_lookup_string(config,
2383                             ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2384 
2385                         if (strcmp(name, searchname) == 0) {
2386                                 if (found_config != NULL) {
2387                                         (void) fprintf(stderr, gettext(
2388                                             "cannot import '%s': more than "
2389                                             "one matching pool\n"), searchname);
2390                                         (void) fprintf(stderr, gettext(
2391                                             "import by numeric ID instead\n"));
2392                                         err = B_TRUE;


2401                          */
2402                         verify(nvlist_lookup_uint64(config,
2403                             ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2404 
2405                         if (guid == searchguid)
2406                                 found_config = config;
2407                 }
2408         }
2409 
2410         /*
2411          * If we were searching for a specific pool, verify that we found a
2412          * pool, and then do the import.
2413          */
2414         if (argc != 0 && err == 0) {
2415                 if (found_config == NULL) {
2416                         (void) fprintf(stderr, gettext("cannot import '%s': "
2417                             "no such pool available\n"), argv[0]);
2418                         err = B_TRUE;
2419                 } else {
2420                         err |= do_import(found_config, argc == 1 ? NULL :
2421                             argv[1], mntopts, props, flags);
2422                 }
2423         }
2424 
2425         /*
2426          * If we were just looking for pools, report an error if none were
2427          * found.
2428          */
2429         if (argc == 0 && first)
2430                 (void) fprintf(stderr,
2431                     gettext("no pools available to import\n"));
2432 
2433 error:
2434         nvlist_free(props);
2435         nvlist_free(pools);
2436         nvlist_free(policy);
2437         free(searchdirs);
2438 
2439         return (err ? 1 : 0);
2440 }
2441 
2442 typedef struct iostat_cbdata {
2443         boolean_t cb_verbose;
2444         int cb_namewidth;
2445         int cb_iteration;
2446         zpool_list_t *cb_list;
2447 } iostat_cbdata_t;
2448 
2449 static void
2450 print_iostat_separator(iostat_cbdata_t *cb)
2451 {
2452         int i = 0;
2453 
2454         for (i = 0; i < cb->cb_namewidth; i++)
2455                 (void) printf("-");
2456         (void) printf("  -----  -----  -----  -----  -----  -----\n");

2457 }
2458 
2459 static void
2460 print_iostat_header(iostat_cbdata_t *cb)
2461 {
2462         (void) printf("%*s     capacity     operations    bandwidth\n",
2463             cb->cb_namewidth, "");
2464         (void) printf("%-*s  alloc   free   read  write   read  write\n",
2465             cb->cb_namewidth, "pool");
2466         print_iostat_separator(cb);
2467 }
2468 
2469 /*
2470  * Display a single statistic.
2471  */
2472 static void
2473 print_one_stat(uint64_t value)
2474 {
2475         char buf[64];
2476 
2477         zfs_nicenum(value, buf, sizeof (buf));
2478         (void) printf("  %5s", buf);
2479 }
2480 
2481 /*



















2482  * Print out all the statistics for the given vdev.  This can either be the
2483  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2484  * is a verbose output, and we don't want to display the toplevel pool stats.
2485  */
2486 void
2487 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2488     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2489 {
2490         nvlist_t **oldchild, **newchild;
2491         uint_t c, children;
2492         vdev_stat_t *oldvs, *newvs;
2493         vdev_stat_t zerovs = { 0 };
2494         uint64_t tdelta;
2495         double scale;
2496         char *vname;
2497 
2498         if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2499                 return;
2500 
2501         if (oldnv != NULL) {
2502                 verify(nvlist_lookup_uint64_array(oldnv,
2503                     ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2504         } else {
2505                 oldvs = &zerovs;
2506         }
2507 
2508         verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2509             (uint64_t **)&newvs, &c) == 0);
2510 
2511         if (strlen(name) + depth > cb->cb_namewidth)
2512                 (void) printf("%*s%s", depth, "", name);
2513         else
2514                 (void) printf("%*s%s%*s", depth, "", name,
2515                     (int)(cb->cb_namewidth - strlen(name) - depth), "");
2516 
2517         tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2518 
2519         if (tdelta == 0)
2520                 scale = 1.0;


2524         /* only toplevel vdevs have capacity stats */
2525         if (newvs->vs_space == 0) {
2526                 (void) printf("      -      -");
2527         } else {
2528                 print_one_stat(newvs->vs_alloc);
2529                 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2530         }
2531 
2532         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2533             oldvs->vs_ops[ZIO_TYPE_READ])));
2534 
2535         print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2536             oldvs->vs_ops[ZIO_TYPE_WRITE])));
2537 
2538         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2539             oldvs->vs_bytes[ZIO_TYPE_READ])));
2540 
2541         print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2542             oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2543 













2544         (void) printf("\n");
2545 
2546         if (!cb->cb_verbose)
2547                 return;
2548 
2549         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2550             &newchild, &children) != 0)
2551                 return;
2552 
2553         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2554             &oldchild, &c) != 0)
2555                 return;
2556 
2557         for (c = 0; c < children; c++) {
2558                 uint64_t ishole = B_FALSE, islog = B_FALSE;
2559 
2560                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2561                     &ishole);
2562 
2563                 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2564                     &islog);
2565 
2566                 if (ishole || islog)



2567                         continue;
2568 
2569                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2570                 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2571                     newchild[c], cb, depth + 2);
2572                 free(vname);
2573         }
2574 
2575         /*
2576          * Log device section
2577          */
2578 
2579         if (num_logs(newnv) > 0) {
2580                 (void) printf("%-*s      -      -      -      -      -      "
2581                     "-\n", cb->cb_namewidth, "logs");
2582 
2583                 for (c = 0; c < children; c++) {
2584                         uint64_t islog = B_FALSE;
2585                         (void) nvlist_lookup_uint64(newchild[c],
2586                             ZPOOL_CONFIG_IS_LOG, &islog);
2587 
2588                         if (islog) {
2589                                 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2590                                     B_FALSE);
2591                                 print_vdev_stats(zhp, vname, oldnv ?
2592                                     oldchild[c] : NULL, newchild[c],
2593                                     cb, depth + 2);
2594                                 free(vname);
2595                         }
2596                 }

2597 




















2598         }


2599 
2600         /*
2601          * Include level 2 ARC devices in iostat output
2602          */
2603         if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2604             &newchild, &children) != 0)
2605                 return;
2606 
2607         if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2608             &oldchild, &c) != 0)
2609                 return;
2610 
2611         if (children > 0) {
2612                 (void) printf("%-*s      -      -      -      -      -      "
2613                     "-\n", cb->cb_namewidth, "cache");
2614                 for (c = 0; c < children; c++) {
2615                         vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2616                             B_FALSE);
2617                         print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2618                             newchild[c], cb, depth + 2);


3087 void
3088 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3089     list_cbdata_t *cb, int depth)
3090 {
3091         nvlist_t **child;
3092         vdev_stat_t *vs;
3093         uint_t c, children;
3094         char *vname;
3095         boolean_t scripted = cb->cb_scripted;
3096         uint64_t islog = B_FALSE;
3097         boolean_t haslog = B_FALSE;
3098         char *dashes = "%-*s      -      -      -         -      -      -\n";
3099 
3100         verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3101             (uint64_t **)&vs, &c) == 0);
3102 
3103         if (name != NULL) {
3104                 boolean_t toplevel = (vs->vs_space != 0);
3105                 uint64_t cap;
3106 
3107                 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3108                         return;
3109 
3110                 if (scripted)
3111                         (void) printf("\t%s", name);
3112                 else if (strlen(name) + depth > cb->cb_namewidth)
3113                         (void) printf("%*s%s", depth, "", name);
3114                 else
3115                         (void) printf("%*s%s%*s", depth, "", name,
3116                             (int)(cb->cb_namewidth - strlen(name) - depth), "");
3117 
3118                 /*
3119                  * Print the properties for the individual vdevs. Some
3120                  * properties are only applicable to toplevel vdevs. The
3121                  * 'toplevel' boolean value is passed to the print_one_column()
3122                  * to indicate that the value is valid.
3123                  */
3124                 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3125                     toplevel);
3126                 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3127                     toplevel);
3128                 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3129                     scripted, toplevel);


3221 }
3222 
3223 /*
3224  * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3225  *
3226  *      -H      Scripted mode.  Don't display headers, and separate properties
3227  *              by a single tab.
3228  *      -o      List of properties to display.  Defaults to
3229  *              "name,size,allocated,free,expandsize,fragmentation,capacity,"
3230  *              "dedupratio,health,altroot"
3231  *      -p      Diplay values in parsable (exact) format.
3232  *      -T      Display a timestamp in date(1) or Unix format
3233  *
3234  * List all pools in the system, whether or not they're healthy.  Output space
3235  * statistics for each one, as well as health status summary.
3236  */
3237 int
3238 zpool_do_list(int argc, char **argv)
3239 {
3240         int c;
3241         int ret;
3242         list_cbdata_t cb = { 0 };
3243         static char default_props[] =
3244             "name,size,allocated,free,expandsize,fragmentation,capacity,"
3245             "dedupratio,health,altroot";
3246         char *props = default_props;
3247         unsigned long interval = 0, count = 0;
3248         zpool_list_t *list;
3249         boolean_t first = B_TRUE;
3250 
3251         /* check options */
3252         while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3253                 switch (c) {
3254                 case 'H':
3255                         cb.cb_scripted = B_TRUE;
3256                         break;
3257                 case 'o':
3258                         props = optarg;
3259                         break;
3260                 case 'p':
3261                         cb.cb_literal = B_TRUE;


3965 int
3966 scrub_callback(zpool_handle_t *zhp, void *data)
3967 {
3968         scrub_cbdata_t *cb = data;
3969         int err;
3970 
3971         /*
3972          * Ignore faulted pools.
3973          */
3974         if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
3975                 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
3976                     "currently unavailable\n"), zpool_get_name(zhp));
3977                 return (1);
3978         }
3979 
3980         err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
3981 
3982         return (err != 0);
3983 }
3984 

























3985 /*
3986  * zpool scrub [-s | -p] <pool> ...
3987  *
3988  *      -s      Stop.  Stops any in-progress scrub.
3989  *      -p      Pause. Pause in-progress scrub.
3990  */
3991 int
3992 zpool_do_scrub(int argc, char **argv)
3993 {
3994         int c;
3995         scrub_cbdata_t cb;
3996 
3997         cb.cb_type = POOL_SCAN_SCRUB;
3998         cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
3999 
4000         /* check options */
4001         while ((c = getopt(argc, argv, "sp")) != -1) {
4002                 switch (c) {
4003                 case 's':





4004                         cb.cb_type = POOL_SCAN_NONE;
4005                         break;
















4006                 case 'p':
4007                         cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4008                         break;
4009                 case '?':
4010                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4011                             optopt);
4012                         usage(B_FALSE);
4013                 }
4014         }
4015 
4016         if (cb.cb_type == POOL_SCAN_NONE &&
4017             cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4018                 (void) fprintf(stderr, gettext("invalid option combination: "
4019                     "-s and -p are mutually exclusive\n"));
4020                 usage(B_FALSE);
4021         }
4022 
4023         cb.cb_argc = argc;
4024         cb.cb_argv = argv;
4025         argc -= optind;
4026         argv += optind;
4027 
4028         if (argc < 1) {
4029                 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4030                 usage(B_FALSE);
4031         }
4032 
4033         return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4034 }
4035 














































4036 typedef struct status_cbdata {
4037         int             cb_count;
4038         boolean_t       cb_allpools;
4039         boolean_t       cb_verbose;
4040         boolean_t       cb_explain;
4041         boolean_t       cb_first;
4042         boolean_t       cb_dedup_stats;
4043 } status_cbdata_t;
4044 
4045 /*
4046  * Print out detailed scrub status.
4047  */
4048 static void
4049 print_scan_status(pool_scan_stat_t *ps)
4050 {
4051         time_t start, end, pause;
4052         uint64_t elapsed, mins_left, hours_left;
4053         uint64_t pass_exam, examined, total;
4054         uint_t rate;
4055         double fraction_done;
4056         char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];

4057 
4058         (void) printf(gettext("  scan: "));
4059 
4060         /* If there's never been a scan, there's not much to say. */
4061         if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4062             ps->pss_func >= POOL_SCAN_FUNCS) {
4063                 (void) printf(gettext("none requested\n"));
4064                 return;
4065         }
4066 
4067         start = ps->pss_start_time;
4068         end = ps->pss_end_time;
4069         pause = ps->pss_pass_scrub_pause;
4070         zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4071 
4072         assert(ps->pss_func == POOL_SCAN_SCRUB ||
4073             ps->pss_func == POOL_SCAN_RESILVER);


4074         /*
4075          * Scan is finished or canceled.
4076          */
4077         if (ps->pss_state == DSS_FINISHED) {
4078                 uint64_t minutes_taken = (end - start) / 60;
4079                 char *fmt = NULL;
4080 
4081                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4082                         fmt = gettext("scrub repaired %s in %lluh%um with "
4083                             "%llu errors on %s");






4084                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4085                         fmt = gettext("resilvered %s in %lluh%um with "
4086                             "%llu errors on %s");
4087                 }
4088                 /* LINTED */
4089                 (void) printf(fmt, processed_buf,
4090                     (u_longlong_t)(minutes_taken / 60),
4091                     (uint_t)(minutes_taken % 60),
4092                     (u_longlong_t)ps->pss_errors,
4093                     ctime((time_t *)&end));
4094                 return;
4095         } else if (ps->pss_state == DSS_CANCELED) {
4096                 if (ps->pss_func == POOL_SCAN_SCRUB) {
4097                         (void) printf(gettext("scrub canceled on %s"),
4098                             ctime(&end));






4099                 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4100                         (void) printf(gettext("resilver canceled on %s"),
4101                             ctime(&end));
4102                 }
4103                 return;
4104         }
4105 
4106         assert(ps->pss_state == DSS_SCANNING);
4107 
4108         /*
4109          * Scan is in progress.
4110          */
4111         if (ps->pss_func == POOL_SCAN_SCRUB) {
4112                 if (pause == 0) {
4113                         (void) printf(gettext("scrub in progress since %s"),
4114                             ctime(&start));
4115                 } else {
4116                         char buf[32];
4117                         struct tm *p = localtime(&pause);
4118                         (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4119                         (void) printf(gettext("scrub paused since %s\n"), buf);
4120                         (void) printf(gettext("\tscrub started on   %s"),
4121                             ctime(&start));
4122                 }






4123         } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4124                 (void) printf(gettext("resilver in progress since %s"),
4125                     ctime(&start));
4126         }
4127 
4128         examined = ps->pss_examined ? ps->pss_examined : 1;
4129         total = ps->pss_to_examine;
4130         fraction_done = (double)examined / total;
4131 
4132         /* elapsed time for this pass */
4133         elapsed = time(NULL) - ps->pss_pass_start;
4134         elapsed -= ps->pss_pass_scrub_spent_paused;
4135         elapsed = elapsed ? elapsed : 1;
4136         pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
4137         rate = pass_exam / elapsed;
4138         rate = rate ? rate : 1;
4139         mins_left = ((total - examined) / rate) / 60;






4140         hours_left = mins_left / 60;
4141 
4142         zfs_nicenum(examined, examined_buf, sizeof (examined_buf));

4143         zfs_nicenum(total, total_buf, sizeof (total_buf));

4144 



















4145         /*
4146          * do not print estimated time if hours_left is more than 30 days
4147          * or we have a paused scrub
4148          */
4149         if (pause == 0) {
4150                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4151                 (void) printf(gettext("\t%s scanned out of %s at %s/s"),
4152                     examined_buf, total_buf, rate_buf);
4153                 if (hours_left < (30 * 24)) {
4154                         (void) printf(gettext(", %lluh%um to go\n"),
4155                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4156                 } else {
4157                         (void) printf(gettext(
4158                             ", (scan is slow, no estimated time)\n"));
4159                 }
4160         } else {
4161                 (void) printf(gettext("\t%s scanned out of %s\n"),
4162                     examined_buf, total_buf);
4163         }
4164 
4165         if (ps->pss_func == POOL_SCAN_RESILVER) {
4166                 (void) printf(gettext("    %s resilvered, %.2f%% done\n"),
4167                     processed_buf, 100 * fraction_done);
4168         } else if (ps->pss_func == POOL_SCAN_SCRUB) {
4169                 (void) printf(gettext("    %s repaired, %.2f%% done\n"),
4170                     processed_buf, 100 * fraction_done);
4171         }
4172 }
4173 
4174 /*
4175  * Print out detailed removal status.
4176  */
4177 static void
4178 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)

4179 {
4180         char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4181         time_t start, end;
4182         nvlist_t *config, *nvroot;
4183         nvlist_t **child;
4184         uint_t children;
4185         char *vdev_name;
4186 
4187         if (prs == NULL || prs->prs_state == DSS_NONE)
4188                 return;
4189 
4190         /*
4191          * Determine name of vdev.
4192          */
4193         config = zpool_get_config(zhp, NULL);
4194         nvroot = fnvlist_lookup_nvlist(config,
4195             ZPOOL_CONFIG_VDEV_TREE);
4196         verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4197             &child, &children) == 0);
4198         assert(prs->prs_removing_vdev < children);
4199         vdev_name = zpool_vdev_name(g_zfs, zhp,
4200             child[prs->prs_removing_vdev], B_TRUE);
4201 
4202         (void) printf(gettext("remove: "));
4203 
4204         start = prs->prs_start_time;
4205         end = prs->prs_end_time;
4206         zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4207 
4208         /*
4209          * Removal is finished or canceled.
4210          */
4211         if (prs->prs_state == DSS_FINISHED) {
4212                 uint64_t minutes_taken = (end - start) / 60;
4213 
4214                 (void) printf(gettext("Removal of vdev %llu copied %s "
4215                     "in %lluh%um, completed on %s"),
4216                     (longlong_t)prs->prs_removing_vdev,
4217                     copied_buf,
4218                     (u_longlong_t)(minutes_taken / 60),
4219                     (uint_t)(minutes_taken % 60),
4220                     ctime((time_t *)&end));
4221         } else if (prs->prs_state == DSS_CANCELED) {
4222                 (void) printf(gettext("Removal of %s canceled on %s"),
4223                     vdev_name, ctime(&end));
4224         } else {
4225                 uint64_t copied, total, elapsed, mins_left, hours_left;
4226                 double fraction_done;
4227                 uint_t rate;
4228 
4229                 assert(prs->prs_state == DSS_SCANNING);
4230 
4231                 /*
4232                  * Removal is in progress.

4233                  */
4234                 (void) printf(gettext(
4235                     "Evacuation of %s in progress since %s"),
4236                     vdev_name, ctime(&start));

4237 
4238                 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4239                 total = prs->prs_to_copy;
4240                 fraction_done = (double)copied / total;
4241 
4242                 /* elapsed time for this pass */
4243                 elapsed = time(NULL) - prs->prs_start_time;
4244                 elapsed = elapsed > 0 ? elapsed : 1;
4245                 rate = copied / elapsed;
4246                 rate = rate > 0 ? rate : 1;
4247                 mins_left = ((total - copied) / rate) / 60;
4248                 hours_left = mins_left / 60;
4249 
4250                 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4251                 zfs_nicenum(total, total_buf, sizeof (total_buf));
4252                 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4253 
4254                 /*
4255                  * do not print estimated time if hours_left is more than
4256                  * 30 days
4257                  */
4258                 (void) printf(gettext("    %s copied out of %s at %s/s, "
4259                     "%.2f%% done"),
4260                     examined_buf, total_buf, rate_buf, 100 * fraction_done);
4261                 if (hours_left < (30 * 24)) {
4262                         (void) printf(gettext(", %lluh%um to go\n"),
4263                             (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4264                 } else {
4265                         (void) printf(gettext(
4266                             ", (copy is slow, no estimated time)\n"));



4267                 }



4268         }
4269 
4270         if (prs->prs_mapping_memory > 0) {
4271                 char mem_buf[7];
4272                 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4273                 (void) printf(gettext("    %s memory used for "
4274                     "removed device mappings\n"),
4275                     mem_buf);
4276         }
4277 }
4278 
4279 static void
4280 print_error_log(zpool_handle_t *zhp)
4281 {
4282         nvlist_t *nverrlist = NULL;
4283         nvpair_t *elem;
4284         char *pathname;
4285         size_t len = MAXPATHLEN * 2;
4286 
4287         if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4288                 (void) printf("errors: List of errors unavailable "
4289                     "(insufficient privileges)\n");
4290                 return;
4291         }
4292 
4293         (void) printf("errors: Permanent errors have been "
4294             "detected in the following files:\n\n");
4295 


4371         (void) printf("\n");
4372         (void) printf(gettext(" dedup: "));
4373         if (ddo->ddo_count == 0) {
4374                 (void) printf(gettext("no DDT entries\n"));
4375                 return;
4376         }
4377 
4378         (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4379             (u_longlong_t)ddo->ddo_count,
4380             (u_longlong_t)ddo->ddo_dspace,
4381             (u_longlong_t)ddo->ddo_mspace);
4382 
4383         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4384             (uint64_t **)&dds, &c) == 0);
4385         verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4386             (uint64_t **)&ddh, &c) == 0);
4387         zpool_dump_ddt(dds, ddh);
4388 }
4389 
4390 /*





































4391  * Display a summary of pool status.  Displays a summary such as:
4392  *
4393  *        pool: tank
4394  *      status: DEGRADED
4395  *      reason: One or more devices ...
4396  *         see: http://illumos.org/msg/ZFS-xxxx-01
4397  *      config:
4398  *              mirror          DEGRADED
4399  *                c1t0d0        OK
4400  *                c2t0d0        UNAVAIL
4401  *
4402  * When given the '-v' option, we print out the complete config.  If the '-e'
4403  * option is specified, then we print out error rate information as well.
4404  */
4405 int
4406 status_callback(zpool_handle_t *zhp, void *data)
4407 {
4408         status_cbdata_t *cbp = data;
4409         nvlist_t *config, *nvroot;
4410         char *msgid;


4423          * problems.
4424          */
4425         if (cbp->cb_explain &&
4426             (reason == ZPOOL_STATUS_OK ||
4427             reason == ZPOOL_STATUS_VERSION_OLDER ||
4428             reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4429                 if (!cbp->cb_allpools) {
4430                         (void) printf(gettext("pool '%s' is healthy\n"),
4431                             zpool_get_name(zhp));
4432                         if (cbp->cb_first)
4433                                 cbp->cb_first = B_FALSE;
4434                 }
4435                 return (0);
4436         }
4437 
4438         if (cbp->cb_first)
4439                 cbp->cb_first = B_FALSE;
4440         else
4441                 (void) printf("\n");
4442 
4443         nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);

4444         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4445             (uint64_t **)&vs, &c) == 0);
4446         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4447 
4448         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4449         (void) printf(gettext(" state: %s\n"), health);
4450 
4451         switch (reason) {
4452         case ZPOOL_STATUS_MISSING_DEV_R:
4453                 (void) printf(gettext("status: One or more devices could not "
4454                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
4455                     "continue functioning in a degraded state.\n"));
4456                 (void) printf(gettext("action: Attach the missing device and "
4457                     "online it using 'zpool online'.\n"));
4458                 break;
4459 
4460         case ZPOOL_STATUS_MISSING_DEV_NR:
4461                 (void) printf(gettext("status: One or more devices could not "
4462                     "be opened.  There are insufficient\n\treplicas for the "
4463                     "pool to continue functioning.\n"));


4631                     "'zpool clear'.\n"));
4632                 break;
4633 
4634         default:
4635                 /*
4636                  * The remaining errors can't actually be generated, yet.
4637                  */
4638                 assert(reason == ZPOOL_STATUS_OK);
4639         }
4640 
4641         if (msgid != NULL)
4642                 (void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
4643                     msgid);
4644 
4645         if (config != NULL) {
4646                 int namewidth;
4647                 uint64_t nerr;
4648                 nvlist_t **spares, **l2cache;
4649                 uint_t nspares, nl2cache;
4650                 pool_scan_stat_t *ps = NULL;
4651                 pool_removal_stat_t *prs = NULL;
4652 
4653                 (void) nvlist_lookup_uint64_array(nvroot,
4654                     ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4655                 print_scan_status(ps);
4656 
4657                 (void) nvlist_lookup_uint64_array(nvroot,
4658                     ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
4659                 print_removal_status(zhp, prs);














4660 
4661                 namewidth = max_width(zhp, nvroot, 0, 0);
4662                 if (namewidth < 10)
4663                         namewidth = 10;
4664 
4665                 (void) printf(gettext("config:\n\n"));
4666                 (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
4667                     "NAME", "STATE", "READ", "WRITE", "CKSUM");
4668                 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4669                     namewidth, 0, B_FALSE);
4670 


4671                 if (num_logs(nvroot) > 0)
4672                         print_logs(zhp, nvroot, namewidth, B_TRUE);
4673                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4674                     &l2cache, &nl2cache) == 0)
4675                         print_l2cache(zhp, l2cache, nl2cache, namewidth);
4676 
4677                 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4678                     &spares, &nspares) == 0)
4679                         print_spares(zhp, spares, nspares, namewidth);
4680 
4681                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4682                     &nerr) == 0) {
4683                         nvlist_t *nverrlist = NULL;
4684 
4685                         /*
4686                          * If the approximate error count is small, get a
4687                          * precise count by fetching the entire log and
4688                          * uniquifying the results.
4689                          */
4690                         if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&


4830                     "'%s' from version %llu to feature flags.\n"),
4831                     zpool_get_name(zhp), oldversion);
4832         } else {
4833                 (void) printf(gettext("Successfully upgraded "
4834                     "'%s' from version %llu to version %llu.\n"),
4835                     zpool_get_name(zhp), oldversion, version);
4836         }
4837 
4838         return (0);
4839 }
4840 
4841 static int
4842 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4843 {
4844         int i, ret, count;
4845         boolean_t firstff = B_TRUE;
4846         nvlist_t *enabled = zpool_get_features(zhp);
4847 
4848         count = 0;
4849         for (i = 0; i < SPA_FEATURES; i++) {
4850                 const char *fname = spa_feature_table[i].fi_uname;
4851                 const char *fguid = spa_feature_table[i].fi_guid;

4852                 if (!nvlist_exists(enabled, fguid)) {
4853                         char *propname;








4854                         verify(-1 != asprintf(&propname, "feature@%s", fname));
4855                         ret = zpool_set_prop(zhp, propname,
4856                             ZFS_FEATURE_ENABLED);
4857                         if (ret != 0) {
4858                                 free(propname);
4859                                 return (ret);
4860                         }
4861                         count++;
4862 
4863                         if (firstff) {
4864                                 (void) printf(gettext("Enabled the "
4865                                     "following features on '%s':\n"),
4866                                     zpool_get_name(zhp));
4867                                 firstff = B_FALSE;
4868                         }
4869                         (void) printf(gettext("  %s\n"), fname);
4870                         free(propname);
4871                 }
4872         }
4873 


5591 
5592         if (cb.cb_proplist != NULL) {
5593                 fake_name.pl_prop = ZPOOL_PROP_NAME;
5594                 fake_name.pl_width = strlen(gettext("NAME"));
5595                 fake_name.pl_next = cb.cb_proplist;
5596                 cb.cb_proplist = &fake_name;
5597         }
5598 
5599         ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5600             get_callback, &cb);
5601 
5602         if (cb.cb_proplist == &fake_name)
5603                 zprop_free_list(fake_name.pl_next);
5604         else
5605                 zprop_free_list(cb.cb_proplist);
5606 
5607         return (ret);
5608 }
5609 
5610 typedef struct set_cbdata {
5611         char *cb_propname;
5612         char *cb_value;
5613         boolean_t cb_any_successful;
5614 } set_cbdata_t;
5615 
5616 int
5617 set_callback(zpool_handle_t *zhp, void *data)
5618 {
5619         int error;
5620         set_cbdata_t *cb = (set_cbdata_t *)data;
5621 
5622         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5623 
5624         if (!error)
5625                 cb->cb_any_successful = B_TRUE;
5626 
5627         return (error);
5628 }
5629 










































5630 int
5631 zpool_do_set(int argc, char **argv)
5632 {
5633         set_cbdata_t cb = { 0 };
5634         int error;
5635 
5636         if (argc > 1 && argv[1][0] == '-') {
5637                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5638                     argv[1][1]);
5639                 usage(B_FALSE);
5640         }
5641 
5642         if (argc < 2) {
5643                 (void) fprintf(stderr, gettext("missing property=value "
5644                     "argument\n"));
5645                 usage(B_FALSE);
5646         }
5647 
5648         if (argc < 3) {
5649                 (void) fprintf(stderr, gettext("missing pool name\n"));
5650                 usage(B_FALSE);
5651         }
5652 
5653         if (argc > 3) {
5654                 (void) fprintf(stderr, gettext("too many pool names\n"));
5655                 usage(B_FALSE);
5656         }
5657 
5658         cb.cb_propname = argv[1];
5659         cb.cb_value = strchr(cb.cb_propname, '=');
5660         if (cb.cb_value == NULL) {
5661                 (void) fprintf(stderr, gettext("missing value in "
5662                     "property=value argument\n"));






















































5663                 usage(B_FALSE);
5664         }
5665 
5666         *(cb.cb_value) = '\0';
5667         cb.cb_value++;


5668 
5669         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5670             set_callback, &cb);


5671 























5672         return (error);
5673 }
5674 




































































































































































5675 static int





































































































































































































5676 find_command_idx(char *command, int *idx)
5677 {
5678         int i;
5679 
5680         for (i = 0; i < NCOMMAND; i++) {
5681                 if (command_table[i].name == NULL)
5682                         continue;
5683 
5684                 if (strcmp(command, command_table[i].name) == 0) {
5685                         *idx = i;
5686                         return (0);
5687                 }
5688         }
5689         return (1);
5690 }
5691 
5692 int
5693 main(int argc, char **argv)
5694 {
5695         int ret = 0;


5709 
5710         opterr = 0;
5711 
5712         /*
5713          * Make sure the user has specified some command.
5714          */
5715         if (argc < 2) {
5716                 (void) fprintf(stderr, gettext("missing command\n"));
5717                 usage(B_FALSE);
5718         }
5719 
5720         cmdname = argv[1];
5721 
5722         /*
5723          * Special case '-?'
5724          */
5725         if (strcmp(cmdname, "-?") == 0)
5726                 usage(B_TRUE);
5727 
5728         zfs_save_arguments(argc, argv, history_str, sizeof (history_str));

5729 
5730         /*
5731          * Run the appropriate command.
5732          */
5733         if (find_command_idx(cmdname, &i) == 0) {
5734                 current_command = &command_table[i];
5735                 ret = command_table[i].func(argc - 1, argv + 1);
5736         } else if (strchr(cmdname, '=')) {
5737                 verify(find_command_idx("set", &i) == 0);
5738                 current_command = &command_table[i];
5739                 ret = command_table[i].func(argc, argv);
5740         } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5741                 /*
5742                  * 'freeze' is a vile debugging abomination, so we treat
5743                  * it as such.
5744                  */
5745                 char buf[16384];
5746                 int fd = open(ZFS_DEV, O_RDWR);
5747                 (void) strcpy((void *)buf, argv[2]);
5748                 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));




   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             },


 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 


 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;


 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;


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;


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);


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;


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"));


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,


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;


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;


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);


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) {


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;


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;


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);


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);


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;


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 


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;


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"));


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 &&


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 


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;


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));