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