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
↓ 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 **);
↓ 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"));
↓ 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  
↓ 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) {
↓ 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(
↓ 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  
↓ 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           */
↓ 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);
↓ 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 "
↓ 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");
↓ 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;
↓ 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"));
↓ 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;
↓ 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");
↓ 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                   */
↓ 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:
↓ 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;
↓ 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);
↓ 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;
↓ 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"));
↓ 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  
↓ open down ↓ 170 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX