Author: delphij
Date: Wed Mar 19 23:38:23 2014
New Revision: 263391
URL: http://svnweb.freebsd.org/changeset/base/263391

Log:
  MFC r259813 + r259816: MFV r258374:
  
  4171 clean up spa_feature_*() interfaces
  
  4172 implement extensible_dataset feature for use by other zpool
  features
  
  illumos/illumos-gate@2acef22db7808606888f8f92715629ff3ba555b9

Modified:
  stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c
  stable/9/cddl/contrib/opensolaris/cmd/zhack/zhack.c
  stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7
  stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_impl.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfeature.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
Directory Properties:
  stable/9/cddl/contrib/opensolaris/   (props changed)
  stable/9/cddl/contrib/opensolaris/cmd/zpool/   (props changed)
  stable/9/cddl/contrib/opensolaris/lib/libzfs/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)

Modified: stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c     Wed Mar 19 23:36:12 
2014        (r263390)
+++ stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c     Wed Mar 19 23:38:23 
2014        (r263391)
@@ -559,16 +559,20 @@ get_metaslab_refcount(vdev_t *vd)
 static int
 verify_spacemap_refcounts(spa_t *spa)
 {
-       int expected_refcount, actual_refcount;
+       uint64_t expected_refcount = 0;
+       uint64_t actual_refcount;
 
-       expected_refcount = spa_feature_get_refcount(spa,
-           &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM]);
+       (void) feature_get_refcount(spa,
+           &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM],
+           &expected_refcount);
        actual_refcount = get_dtl_refcount(spa->spa_root_vdev);
        actual_refcount += get_metaslab_refcount(spa->spa_root_vdev);
 
        if (expected_refcount != actual_refcount) {
-               (void) printf("space map refcount mismatch: expected %d != "
-                   "actual %d\n", expected_refcount, actual_refcount);
+               (void) printf("space map refcount mismatch: expected %lld != "
+                   "actual %lld\n",
+                   (longlong_t)expected_refcount,
+                   (longlong_t)actual_refcount);
                return (2);
        }
        return (0);
@@ -670,8 +674,7 @@ dump_metaslab(metaslab_t *msp)
        }
 
        if (dump_opt['m'] > 1 && sm != NULL &&
-           spa_feature_is_active(spa,
-           &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM])) {
+           spa_feature_is_active(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
                /*
                 * The space map histogram represents free space in chunks
                 * of sm_shift (i.e. bucket 0 refers to 2^sm_shift).
@@ -2417,8 +2420,7 @@ dump_block_stats(spa_t *spa)
                (void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
                    count_block_cb, &zcb, NULL);
        }
-       if (spa_feature_is_active(spa,
-           &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
+       if (spa_feature_is_active(spa, SPA_FEATURE_ASYNC_DESTROY)) {
                VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
                    spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
                    &zcb, NULL));
@@ -2719,7 +2721,7 @@ dump_zpool(spa_t *spa)
                        }
 
                        if (spa_feature_is_active(spa,
-                           &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
+                           SPA_FEATURE_ASYNC_DESTROY)) {
                                dump_bptree(spa->spa_meta_objset,
                                    spa->spa_dsl_pool->dp_bptree_obj,
                                    "Pool dataset frees");

Modified: stable/9/cddl/contrib/opensolaris/cmd/zhack/zhack.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zhack/zhack.c Wed Mar 19 23:36:12 
2014        (r263390)
+++ stable/9/cddl/contrib/opensolaris/cmd/zhack/zhack.c Wed Mar 19 23:38:23 
2014        (r263391)
@@ -283,12 +283,13 @@ zhack_do_feature_stat(int argc, char **a
 }
 
 static void
-feature_enable_sync(void *arg, dmu_tx_t *tx)
+zhack_feature_enable_sync(void *arg, dmu_tx_t *tx)
 {
        spa_t *spa = dmu_tx_pool(tx)->dp_spa;
        zfeature_info_t *feature = arg;
 
-       spa_feature_enable(spa, feature, tx);
+       feature_enable_sync(spa, feature, tx);
+
        spa_history_log_internal(spa, "zhack enable feature", tx,
            "name=%s can_readonly=%u",
            feature->fi_guid, feature->fi_can_readonly);
@@ -302,7 +303,7 @@ zhack_do_feature_enable(int argc, char *
        spa_t *spa;
        objset_t *mos;
        zfeature_info_t feature;
-       zfeature_info_t *nodeps[] = { NULL };
+       spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
 
        /*
         * Features are not added to the pool's label until their refcounts
@@ -349,14 +350,14 @@ zhack_do_feature_enable(int argc, char *
        zhack_spa_open(target, B_FALSE, FTAG, &spa);
        mos = spa->spa_meta_objset;
 
-       if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
+       if (zfeature_is_supported(feature.fi_guid))
                fatal(spa, FTAG, "'%s' is a real feature, will not enable");
        if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid))
                fatal(spa, FTAG, "feature already enabled: %s",
                    feature.fi_guid);
 
        VERIFY0(dsl_sync_task(spa_name(spa), NULL,
-           feature_enable_sync, &feature, 5));
+           zhack_feature_enable_sync, &feature, 5));
 
        spa_close(spa, FTAG);
 
@@ -368,8 +369,10 @@ feature_incr_sync(void *arg, dmu_tx_t *t
 {
        spa_t *spa = dmu_tx_pool(tx)->dp_spa;
        zfeature_info_t *feature = arg;
+       uint64_t refcount;
 
-       spa_feature_incr(spa, feature, tx);
+       VERIFY0(feature_get_refcount(spa, feature, &refcount));
+       feature_sync(spa, feature, refcount + 1, tx);
        spa_history_log_internal(spa, "zhack feature incr", tx,
            "name=%s", feature->fi_guid);
 }
@@ -379,8 +382,10 @@ feature_decr_sync(void *arg, dmu_tx_t *t
 {
        spa_t *spa = dmu_tx_pool(tx)->dp_spa;
        zfeature_info_t *feature = arg;
+       uint64_t refcount;
 
-       spa_feature_decr(spa, feature, tx);
+       VERIFY0(feature_get_refcount(spa, feature, &refcount));
+       feature_sync(spa, feature, refcount - 1, tx);
        spa_history_log_internal(spa, "zhack feature decr", tx,
            "name=%s", feature->fi_guid);
 }
@@ -394,7 +399,7 @@ zhack_do_feature_ref(int argc, char **ar
        spa_t *spa;
        objset_t *mos;
        zfeature_info_t feature;
-       zfeature_info_t *nodeps[] = { NULL };
+       spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
 
        /*
         * fi_desc does not matter here because it was written to disk
@@ -437,9 +442,10 @@ zhack_do_feature_ref(int argc, char **ar
        zhack_spa_open(target, B_FALSE, FTAG, &spa);
        mos = spa->spa_meta_objset;
 
-       if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
-               fatal(spa, FTAG, "'%s' is a real feature, will not change "
-                   "refcount");
+       if (zfeature_is_supported(feature.fi_guid)) {
+               fatal(spa, FTAG,
+                   "'%s' is a real feature, will not change refcount");
+       }
 
        if (0 == zap_contains(mos, spa->spa_feat_for_read_obj,
            feature.fi_guid)) {
@@ -451,9 +457,14 @@ zhack_do_feature_ref(int argc, char **ar
                fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid);
        }
 
-       if (decr && !spa_feature_is_active(spa, &feature))
-               fatal(spa, FTAG, "feature refcount already 0: %s",
-                   feature.fi_guid);
+       if (decr) {
+               uint64_t count;
+               if (feature_get_refcount(spa, &feature, &count) == 0 &&
+                   count != 0) {
+                       fatal(spa, FTAG, "feature refcount already 0: %s",
+                           feature.fi_guid);
+               }
+       }
 
        VERIFY0(dsl_sync_task(spa_name(spa), NULL,
            decr ? feature_decr_sync : feature_incr_sync, &feature, 5));

Modified: stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7        Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7        Wed Mar 
19 23:38:23 2014        (r263391)
@@ -269,6 +269,23 @@ an existing space map is upgraded to the
 Once the feature is
 .Sy active ,
 it will remain in that state until the pool is destroyed.
+.It Sy extensible_dataset
+.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:extensible_dataset"
+.It GUID Ta com.delphix:extensible_dataset
+.It READ\-ONLY COMPATIBLE Ta no
+.It DEPENDENCIES Ta none
+.El
+.Pp
+This feature allows more flexible use of internal ZFS data structures,
+and exists for other features to depend on.
+.Pp
+This feature will be
+.Sy active
+when the first dependent feature uses it,
+and will be returned to the
+.Sy enabled
+state when all datasets that use
+this feature are destroyed.
 .El
 .Sh SEE ALSO
 .Xr zpool 8

Modified: stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c    Wed Mar 19 
23:36:12 2014        (r263390)
+++ stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c    Wed Mar 19 
23:38:23 2014        (r263391)
@@ -22,7 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
  * Copyright (c) 2012 Martin Matuska <m...@freebsd.org>. All rights reserved.
  */
@@ -1002,7 +1002,7 @@ zpool_do_create(int argc, char **argv)
                 * Hand off to libzfs.
                 */
                if (enable_all_pool_feat) {
-                       int i;
+                       spa_feature_t i;
                        for (i = 0; i < SPA_FEATURES; i++) {
                                char propname[MAXPATHLEN];
                                zfeature_info_t *feat = &spa_feature_table[i];

Modified: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c   Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c   Wed Mar 
19 23:38:23 2014        (r263391)
@@ -22,7 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  */
 
@@ -443,10 +443,9 @@ zpool_valid_proplist(libzfs_handle_t *hd
                prop = zpool_name_to_prop(propname);
                if (prop == ZPROP_INVAL && zpool_prop_feature(propname)) {
                        int err;
-                       zfeature_info_t *feature;
                        char *fname = strchr(propname, '@') + 1;
 
-                       err = zfeature_lookup_name(fname, &feature);
+                       err = zfeature_lookup_name(fname, NULL);
                        if (err != 0) {
                                ASSERT3U(err, ==, ENOENT);
                                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -839,14 +838,14 @@ zpool_prop_get_feature(zpool_handle_t *z
         */
        if (supported) {
                int ret;
-               zfeature_info_t *fi;
+               spa_feature_t fid;
 
-               ret = zfeature_lookup_name(feature, &fi);
+               ret = zfeature_lookup_name(feature, &fid);
                if (ret != 0) {
                        (void) strlcpy(buf, "-", len);
                        return (ENOTSUP);
                }
-               feature = fi->fi_guid;
+               feature = spa_feature_table[fid].fi_guid;
        }
 
        if (nvlist_lookup_uint64(features, feature, &refcount) == 0)

Modified: stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c  Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c  Wed Mar 
19 23:38:23 2014        (r263391)
@@ -91,32 +91,22 @@ zfeature_is_supported(const char *guid)
        if (zfeature_checks_disable)
                return (B_TRUE);
 
-       return (0 == zfeature_lookup_guid(guid, NULL));
-}
-
-int
-zfeature_lookup_guid(const char *guid, zfeature_info_t **res)
-{
-       for (int i = 0; i < SPA_FEATURES; i++) {
+       for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
                zfeature_info_t *feature = &spa_feature_table[i];
-               if (strcmp(guid, feature->fi_guid) == 0) {
-                       if (res != NULL)
-                               *res = feature;
-                       return (0);
-               }
+               if (strcmp(guid, feature->fi_guid) == 0)
+                       return (B_TRUE);
        }
-
-       return (ENOENT);
+       return (B_FALSE);
 }
 
 int
-zfeature_lookup_name(const char *name, zfeature_info_t **res)
+zfeature_lookup_name(const char *name, spa_feature_t *res)
 {
-       for (int i = 0; i < SPA_FEATURES; i++) {
+       for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
                zfeature_info_t *feature = &spa_feature_table[i];
                if (strcmp(name, feature->fi_uname) == 0) {
                        if (res != NULL)
-                               *res = feature;
+                               *res = i;
                        return (0);
                }
        }
@@ -125,11 +115,12 @@ zfeature_lookup_name(const char *name, z
 }
 
 static void
-zfeature_register(int fid, const char *guid, const char *name, const char 
*desc,
-    boolean_t readonly, boolean_t mos, zfeature_info_t **deps)
+zfeature_register(spa_feature_t fid, const char *guid, const char *name,
+    const char *desc, boolean_t readonly, boolean_t mos,
+    const spa_feature_t *deps)
 {
        zfeature_info_t *feature = &spa_feature_table[fid];
-       static zfeature_info_t *nodeps[] = { NULL };
+       static spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
 
        ASSERT(name != NULL);
        ASSERT(desc != NULL);
@@ -140,6 +131,7 @@ zfeature_register(int fid, const char *g
        if (deps == NULL)
                deps = nodeps;
 
+       feature->fi_feature = fid;
        feature->fi_guid = guid;
        feature->fi_uname = name;
        feature->fi_desc = desc;
@@ -166,4 +158,8 @@ zpool_feature_init(void)
        zfeature_register(SPA_FEATURE_SPACEMAP_HISTOGRAM,
            "com.delphix:spacemap_histogram", "spacemap_histogram",
            "Spacemaps maintain space histograms.", B_TRUE, B_FALSE, NULL);
+       zfeature_register(SPA_FEATURE_EXTENSIBLE_DATASET,
+           "com.delphix:extensible_dataset", "extensible_dataset",
+           "Enhanced dataset functionality, used by other features.",
+           B_FALSE, B_FALSE, NULL);
 }

Modified: stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h  Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h  Wed Mar 
19 23:38:23 2014        (r263391)
@@ -37,35 +37,38 @@ extern "C" {
 
 struct zfeature_info;
 
+typedef enum spa_feature {
+       SPA_FEATURE_NONE = -1,
+       SPA_FEATURE_ASYNC_DESTROY,
+       SPA_FEATURE_EMPTY_BPOBJ,
+       SPA_FEATURE_LZ4_COMPRESS,
+       SPA_FEATURE_MULTI_VDEV_CRASH_DUMP,
+       SPA_FEATURE_SPACEMAP_HISTOGRAM,
+       SPA_FEATURE_EXTENSIBLE_DATASET,
+       SPA_FEATURES
+} spa_feature_t;
+
 typedef struct zfeature_info {
+       spa_feature_t fi_feature;
        const char *fi_uname;   /* User-facing feature name */
        const char *fi_guid;    /* On-disk feature identifier */
        const char *fi_desc;    /* Feature description */
        boolean_t fi_can_readonly; /* Can open pool readonly w/o support? */
        boolean_t fi_mos;       /* Is the feature necessary to read the MOS? */
-       struct zfeature_info **fi_depends; /* array; null terminated */
+       /* array of dependencies, terminated by SPA_FEATURE_NONE */
+       const spa_feature_t *fi_depends;
 } zfeature_info_t;
 
 typedef int (zfeature_func_t)(zfeature_info_t *fi, void *arg);
 
 #define        ZFS_FEATURE_DEBUG
 
-static enum spa_feature {
-       SPA_FEATURE_ASYNC_DESTROY,
-       SPA_FEATURE_EMPTY_BPOBJ,
-       SPA_FEATURE_LZ4_COMPRESS,
-       SPA_FEATURE_MULTI_VDEV_CRASH_DUMP,
-       SPA_FEATURE_SPACEMAP_HISTOGRAM,
-       SPA_FEATURES
-} spa_feature_t;
-
 extern zfeature_info_t spa_feature_table[SPA_FEATURES];
 
 extern boolean_t zfeature_is_valid_guid(const char *);
 
 extern boolean_t zfeature_is_supported(const char *);
-extern int zfeature_lookup_guid(const char *, zfeature_info_t **res);
-extern int zfeature_lookup_name(const char *, zfeature_info_t **res);
+extern int zfeature_lookup_name(const char *name, spa_feature_t *res);
 
 extern void zpool_feature_init(void);
 

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c     Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c     Wed Mar 
19 23:38:23 2014        (r263391)
@@ -36,13 +36,11 @@
 uint64_t
 bpobj_alloc_empty(objset_t *os, int blocksize, dmu_tx_t *tx)
 {
-       zfeature_info_t *empty_bpobj_feat =
-           &spa_feature_table[SPA_FEATURE_EMPTY_BPOBJ];
        spa_t *spa = dmu_objset_spa(os);
        dsl_pool_t *dp = dmu_objset_pool(os);
 
-       if (spa_feature_is_enabled(spa, empty_bpobj_feat)) {
-               if (!spa_feature_is_active(spa, empty_bpobj_feat)) {
+       if (spa_feature_is_enabled(spa, SPA_FEATURE_EMPTY_BPOBJ)) {
+               if (!spa_feature_is_active(spa, SPA_FEATURE_EMPTY_BPOBJ)) {
                        ASSERT0(dp->dp_empty_bpobj);
                        dp->dp_empty_bpobj =
                            bpobj_alloc(os, SPA_MAXBLOCKSIZE, tx);
@@ -51,7 +49,7 @@ bpobj_alloc_empty(objset_t *os, int bloc
                            DMU_POOL_EMPTY_BPOBJ, sizeof (uint64_t), 1,
                            &dp->dp_empty_bpobj, tx) == 0);
                }
-               spa_feature_incr(spa, empty_bpobj_feat, tx);
+               spa_feature_incr(spa, SPA_FEATURE_EMPTY_BPOBJ, tx);
                ASSERT(dp->dp_empty_bpobj != 0);
                return (dp->dp_empty_bpobj);
        } else {
@@ -62,12 +60,11 @@ bpobj_alloc_empty(objset_t *os, int bloc
 void
 bpobj_decr_empty(objset_t *os, dmu_tx_t *tx)
 {
-       zfeature_info_t *empty_bpobj_feat =
-           &spa_feature_table[SPA_FEATURE_EMPTY_BPOBJ];
        dsl_pool_t *dp = dmu_objset_pool(os);
 
-       spa_feature_decr(dmu_objset_spa(os), empty_bpobj_feat, tx);
-       if (!spa_feature_is_active(dmu_objset_spa(os), empty_bpobj_feat)) {
+       spa_feature_decr(dmu_objset_spa(os), SPA_FEATURE_EMPTY_BPOBJ, tx);
+       if (!spa_feature_is_active(dmu_objset_spa(os),
+           SPA_FEATURE_EMPTY_BPOBJ)) {
                VERIFY3U(0, ==, zap_remove(dp->dp_meta_objset,
                    DMU_POOL_DIRECTORY_OBJECT,
                    DMU_POOL_EMPTY_BPOBJ, tx));
@@ -265,6 +262,7 @@ bpobj_iterate_impl(bpobj_t *bpo, bpobj_i
                mutex_exit(&bpo->bpo_lock);
                return (err);
        }
+       ASSERT3U(doi.doi_type, ==, DMU_OT_BPOBJ_SUBOBJ);
        epb = doi.doi_data_block_size / sizeof (uint64_t);
 
        for (i = bpo->bpo_phys->bpo_num_subobjs - 1; i >= 0; i--) {

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c        
Wed Mar 19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c        
Wed Mar 19 23:38:23 2014        (r263391)
@@ -27,6 +27,8 @@
 #include <sys/dmu_objset.h>
 #include <sys/dmu_tx.h>
 #include <sys/dnode.h>
+#include <sys/zap.h>
+#include <sys/zfeature.h>
 
 uint64_t
 dmu_object_alloc(objset_t *os, dmu_object_type_t ot, int blocksize,
@@ -195,3 +197,54 @@ dmu_object_next(objset_t *os, uint64_t *
 
        return (error);
 }
+
+/*
+ * Turn this object from old_type into DMU_OTN_ZAP_METADATA, and bump the
+ * refcount on SPA_FEATURE_EXTENSIBLE_DATASET.
+ *
+ * Only for use from syncing context, on MOS objects.
+ */
+void
+dmu_object_zapify(objset_t *mos, uint64_t object, dmu_object_type_t old_type,
+    dmu_tx_t *tx)
+{
+       dnode_t *dn;
+
+       ASSERT(dmu_tx_is_syncing(tx));
+
+       VERIFY0(dnode_hold(mos, object, FTAG, &dn));
+       if (dn->dn_type == DMU_OTN_ZAP_METADATA) {
+               dnode_rele(dn, FTAG);
+               return;
+       }
+       ASSERT3U(dn->dn_type, ==, old_type);
+       ASSERT0(dn->dn_maxblkid);
+       dn->dn_next_type[tx->tx_txg & TXG_MASK] = dn->dn_type =
+           DMU_OTN_ZAP_METADATA;
+       dnode_setdirty(dn, tx);
+       dnode_rele(dn, FTAG);
+
+       mzap_create_impl(mos, object, 0, 0, tx);
+
+       spa_feature_incr(dmu_objset_spa(mos),
+           SPA_FEATURE_EXTENSIBLE_DATASET, tx);
+}
+
+void
+dmu_object_free_zapified(objset_t *mos, uint64_t object, dmu_tx_t *tx)
+{
+       dnode_t *dn;
+       dmu_object_type_t t;
+
+       ASSERT(dmu_tx_is_syncing(tx));
+
+       VERIFY0(dnode_hold(mos, object, FTAG, &dn));
+       t = dn->dn_type;
+       dnode_rele(dn, FTAG);
+
+       if (t == DMU_OTN_ZAP_METADATA) {
+               spa_feature_decr(dmu_objset_spa(mos),
+                   SPA_FEATURE_EXTENSIBLE_DATASET, tx);
+       }
+       VERIFY0(dmu_object_free(mos, object, tx));
+}

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c      
Wed Mar 19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c      
Wed Mar 19 23:38:23 2014        (r263391)
@@ -605,7 +605,7 @@ traverse_pool(spa_t *spa, uint64_t txg_s
                        continue;
                }
 
-               if (doi.doi_type == DMU_OT_DSL_DATASET) {
+               if (doi.doi_bonus_type == DMU_OT_DSL_DATASET) {
                        dsl_dataset_t *ds;
                        uint64_t txg = txg_start;
 

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c        
Wed Mar 19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c        
Wed Mar 19 23:38:23 2014        (r263391)
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -577,7 +577,12 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
            BP_GET_LSIZE(&dnp->dn_blkptr[0]) ==
            dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
 
-       if (dn->dn_next_blksz[txgoff]) {
+       if (dn->dn_next_type[txgoff] != 0) {
+               dnp->dn_type = dn->dn_type;
+               dn->dn_next_type[txgoff] = 0;
+       }
+
+       if (dn->dn_next_blksz[txgoff] != 0) {
                ASSERT(P2PHASE(dn->dn_next_blksz[txgoff],
                    SPA_MINBLOCKSIZE) == 0);
                ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[0]) ||
@@ -590,7 +595,7 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
                dn->dn_next_blksz[txgoff] = 0;
        }
 
-       if (dn->dn_next_bonuslen[txgoff]) {
+       if (dn->dn_next_bonuslen[txgoff] != 0) {
                if (dn->dn_next_bonuslen[txgoff] == DN_ZERO_BONUSLEN)
                        dnp->dn_bonuslen = 0;
                else
@@ -599,7 +604,7 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
                dn->dn_next_bonuslen[txgoff] = 0;
        }
 
-       if (dn->dn_next_bonustype[txgoff]) {
+       if (dn->dn_next_bonustype[txgoff] != 0) {
                ASSERT(DMU_OT_IS_VALID(dn->dn_next_bonustype[txgoff]));
                dnp->dn_bonustype = dn->dn_next_bonustype[txgoff];
                dn->dn_next_bonustype[txgoff] = 0;
@@ -617,7 +622,7 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
                dn->dn_rm_spillblk[txgoff] = 0;
        }
 
-       if (dn->dn_next_indblkshift[txgoff]) {
+       if (dn->dn_next_indblkshift[txgoff] != 0) {
                ASSERT(dnp->dn_nlevels == 1);
                dnp->dn_indblkshift = dn->dn_next_indblkshift[txgoff];
                dn->dn_next_indblkshift[txgoff] = 0;

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c       
Wed Mar 19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c       
Wed Mar 19 23:38:23 2014        (r263391)
@@ -358,7 +358,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uin
 
        /* Make sure dsobj has the correct object type. */
        dmu_object_info_from_db(dbuf, &doi);
-       if (doi.doi_type != DMU_OT_DSL_DATASET) {
+       if (doi.doi_bonus_type != DMU_OT_DSL_DATASET) {
                dmu_buf_rele(dbuf, tag);
                return (SET_ERROR(EINVAL));
        }
@@ -3053,3 +3053,11 @@ dsl_dataset_is_before(dsl_dataset_t *lat
        dsl_dataset_rele(origin, FTAG);
        return (ret);
 }
+
+
+void
+dsl_dataset_zapify(dsl_dataset_t *ds, dmu_tx_t *tx)
+{
+       objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
+       dmu_object_zapify(mos, ds->ds_object, DMU_OT_DSL_DATASET, tx);
+}

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c       
Wed Mar 19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c       
Wed Mar 19 23:38:23 2014        (r263391)
@@ -38,6 +38,7 @@
 #include <sys/zfeature.h>
 #include <sys/zfs_ioctl.h>
 #include <sys/dsl_deleg.h>
+#include <sys/dmu_impl.h>
 
 typedef struct dmu_snapshots_destroy_arg {
        nvlist_t *dsda_snaps;
@@ -448,7 +449,7 @@ dsl_destroy_snapshot_sync_impl(dsl_datas
                VERIFY0(zap_destroy(mos, ds->ds_phys->ds_userrefs_obj, tx));
        dsl_dir_rele(ds->ds_dir, ds);
        ds->ds_dir = NULL;
-       VERIFY0(dmu_object_free(mos, obj, tx));
+       dmu_object_free_zapified(mos, obj, tx);
 }
 
 static void
@@ -671,7 +672,7 @@ dsl_dir_destroy_sync(uint64_t ddobj, dmu
            dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx));
 
        dsl_dir_rele(dd, FTAG);
-       VERIFY0(dmu_object_free(mos, ddobj, tx));
+       dmu_object_free_zapified(mos, ddobj, tx);
 }
 
 void
@@ -724,10 +725,6 @@ dsl_destroy_head_sync_impl(dsl_dataset_t
                ds->ds_prev->ds_phys->ds_num_children--;
        }
 
-       zfeature_info_t *async_destroy =
-           &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY];
-       objset_t *os;
-
        /*
         * Destroy the deadlist.  Unless it's a clone, the
         * deadlist should be empty.  (If it's a clone, it's
@@ -738,9 +735,10 @@ dsl_destroy_head_sync_impl(dsl_dataset_t
        dmu_buf_will_dirty(ds->ds_dbuf, tx);
        ds->ds_phys->ds_deadlist_obj = 0;
 
+       objset_t *os;
        VERIFY0(dmu_objset_from_ds(ds, &os));
 
-       if (!spa_feature_is_enabled(dp->dp_spa, async_destroy)) {
+       if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY)) {
                old_synchronous_dataset_destroy(ds, tx);
        } else {
                /*
@@ -751,10 +749,11 @@ dsl_destroy_head_sync_impl(dsl_dataset_t
 
                zil_destroy_sync(dmu_objset_zil(os), tx);
 
-               if (!spa_feature_is_active(dp->dp_spa, async_destroy)) {
+               if (!spa_feature_is_active(dp->dp_spa,
+                   SPA_FEATURE_ASYNC_DESTROY)) {
                        dsl_scan_t *scn = dp->dp_scan;
-
-                       spa_feature_incr(dp->dp_spa, async_destroy, tx);
+                       spa_feature_incr(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY,
+                           tx);
                        dp->dp_bptree_obj = bptree_alloc(mos, tx);
                        VERIFY0(zap_add(mos,
                            DMU_POOL_DIRECTORY_OBJECT,
@@ -814,7 +813,7 @@ dsl_destroy_head_sync_impl(dsl_dataset_t
        ASSERT0(ds->ds_phys->ds_userrefs_obj);
        dsl_dir_rele(ds->ds_dir, ds);
        ds->ds_dir = NULL;
-       VERIFY0(dmu_object_free(mos, obj, tx));
+       dmu_object_free_zapified(mos, obj, tx);
 
        dsl_dir_destroy_sync(ddobj, tx);
 
@@ -870,8 +869,7 @@ dsl_destroy_head(const char *name)
        error = spa_open(name, &spa, FTAG);
        if (error != 0)
                return (error);
-       isenabled = spa_feature_is_enabled(spa,
-           &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY]);
+       isenabled = spa_feature_is_enabled(spa, SPA_FEATURE_ASYNC_DESTROY);
        spa_close(spa, FTAG);
 
        ddha.ddha_name = name;

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c   Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c   Wed Mar 
19 23:38:23 2014        (r263391)
@@ -33,6 +33,7 @@
 #include <sys/dsl_prop.h>
 #include <sys/dsl_synctask.h>
 #include <sys/dsl_deleg.h>
+#include <sys/dmu_impl.h>
 #include <sys/spa.h>
 #include <sys/metaslab.h>
 #include <sys/zap.h>
@@ -93,7 +94,7 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_
        {
                dmu_object_info_t doi;
                dmu_object_info_from_db(dbuf, &doi);
-               ASSERT3U(doi.doi_type, ==, DMU_OT_DSL_DIR);
+               ASSERT3U(doi.doi_bonus_type, ==, DMU_OT_DSL_DIR);
                ASSERT3U(doi.doi_bonus_size, >=, sizeof (dsl_dir_phys_t));
        }
 #endif
@@ -1363,3 +1364,10 @@ dsl_dir_snap_cmtime_update(dsl_dir_t *dd
        dd->dd_snap_cmtime = t;
        mutex_exit(&dd->dd_lock);
 }
+
+void
+dsl_dir_zapify(dsl_dir_t *dd, dmu_tx_t *tx)
+{
+       objset_t *mos = dd->dd_pool->dp_meta_objset;
+       dmu_object_zapify(mos, dd->dd_object, DMU_OT_DSL_DIR, tx);
+}

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c  Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c  Wed Mar 
19 23:38:23 2014        (r263391)
@@ -278,8 +278,7 @@ dsl_pool_open(dsl_pool_t *dp)
                    dp->dp_meta_objset, obj));
        }
 
-       if (spa_feature_is_active(dp->dp_spa,
-           &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
+       if (spa_feature_is_active(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY)) {
                err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
                    DMU_POOL_BPTREE_OBJ, sizeof (uint64_t), 1,
                    &dp->dp_bptree_obj);
@@ -287,8 +286,7 @@ dsl_pool_open(dsl_pool_t *dp)
                        goto out;
        }
 
-       if (spa_feature_is_active(dp->dp_spa,
-           &spa_feature_table[SPA_FEATURE_EMPTY_BPOBJ])) {
+       if (spa_feature_is_active(dp->dp_spa, SPA_FEATURE_EMPTY_BPOBJ)) {
                err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
                    DMU_POOL_EMPTY_BPOBJ, sizeof (uint64_t), 1,
                    &dp->dp_empty_bpobj);

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c  Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c  Wed Mar 
19 23:38:23 2014        (r263391)
@@ -132,7 +132,7 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t t
         */
        ASSERT(!scn->scn_async_destroying);
        scn->scn_async_destroying = spa_feature_is_active(dp->dp_spa,
-           &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY]);
+           SPA_FEATURE_ASYNC_DESTROY);
 
        err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
            "scrub_func", sizeof (uint64_t), 1, &f);
@@ -1387,7 +1387,6 @@ dsl_scan_active(dsl_scan_t *scn)
                return (B_FALSE);
        if (spa_shutting_down(spa))
                return (B_FALSE);
-
        if (scn->scn_phys.scn_state == DSS_SCANNING ||
            scn->scn_async_destroying)
                return (B_TRUE);
@@ -1446,7 +1445,7 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *
                VERIFY3U(0, ==, zio_wait(scn->scn_zio_root));
 
                if (err == 0 && spa_feature_is_active(spa,
-                   &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
+                   SPA_FEATURE_ASYNC_DESTROY)) {
                        ASSERT(scn->scn_async_destroying);
                        scn->scn_is_bptree = B_TRUE;
                        scn->scn_zio_root = zio_root(dp->dp_spa, NULL,
@@ -1457,11 +1456,11 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *
                        VERIFY0(zio_wait(scn->scn_zio_root));
 
                        if (err == 0) {
-                               zfeature_info_t *feat = &spa_feature_table
-                                   [SPA_FEATURE_ASYNC_DESTROY];
                                /* finished; deactivate async destroy feature */
-                               spa_feature_decr(spa, feat, tx);
-                               ASSERT(!spa_feature_is_active(spa, feat));
+                               spa_feature_decr(spa, SPA_FEATURE_ASYNC_DESTROY,
+                                   tx);
+                               ASSERT(!spa_feature_is_active(spa,
+                                   SPA_FEATURE_ASYNC_DESTROY));
                                VERIFY0(zap_remove(dp->dp_meta_objset,
                                    DMU_POOL_DIRECTORY_OBJECT,
                                    DMU_POOL_BPTREE_OBJ, tx));

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c       Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c       Wed Mar 
19 23:38:23 2014        (r263391)
@@ -2352,14 +2352,12 @@ spa_load_impl(spa_t *spa, uint64_t pool_
                enabled_feat = fnvlist_alloc();
                unsup_feat = fnvlist_alloc();
 
-               if (!feature_is_supported(spa->spa_meta_objset,
-                   spa->spa_feat_for_read_obj, spa->spa_feat_desc_obj,
+               if (!spa_features_check(spa, B_FALSE,
                    unsup_feat, enabled_feat))
                        missing_feat_read = B_TRUE;
 
                if (spa_writeable(spa) || state == SPA_LOAD_TRYIMPORT) {
-                       if (!feature_is_supported(spa->spa_meta_objset,
-                           spa->spa_feat_for_write_obj, spa->spa_feat_desc_obj,
+                       if (!spa_features_check(spa, B_TRUE,
                            unsup_feat, enabled_feat)) {
                                missing_feat_write = B_TRUE;
                        }
@@ -6233,7 +6231,7 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
                zpool_prop_t prop;
                const char *propname;
                zprop_type_t proptype;
-               zfeature_info_t *feature;
+               spa_feature_t fid;
 
                switch (prop = zpool_name_to_prop(nvpair_name(elem))) {
                case ZPROP_INVAL:
@@ -6243,9 +6241,9 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
                        ASSERT(zpool_prop_feature(nvpair_name(elem)));
 
                        fname = strchr(nvpair_name(elem), '@') + 1;
-                       VERIFY0(zfeature_lookup_name(fname, &feature));
+                       VERIFY0(zfeature_lookup_name(fname, &fid));
 
-                       spa_feature_enable(spa, feature, tx);
+                       spa_feature_enable(spa, fid, tx);
                        spa_history_log_internal(spa, "set", tx,
                            "%s=enabled", nvpair_name(elem));
                        break;

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c  Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c  Wed Mar 
19 23:38:23 2014        (r263391)
@@ -1195,15 +1195,17 @@ spa_vdev_state_exit(spa_t *spa, vdev_t *
 void
 spa_activate_mos_feature(spa_t *spa, const char *feature)
 {
-       (void) nvlist_add_boolean(spa->spa_label_features, feature);
-       vdev_config_dirty(spa->spa_root_vdev);
+       if (!nvlist_exists(spa->spa_label_features, feature)) {
+               fnvlist_add_boolean(spa->spa_label_features, feature);
+               vdev_config_dirty(spa->spa_root_vdev);
+       }
 }
 
 void
 spa_deactivate_mos_feature(spa_t *spa, const char *feature)
 {
-       (void) nvlist_remove_all(spa->spa_label_features, feature);
-       vdev_config_dirty(spa->spa_root_vdev);
+       if (nvlist_remove_all(spa->spa_label_features, feature) == 0)
+               vdev_config_dirty(spa->spa_root_vdev);
 }
 
 /*

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c Wed Mar 
19 23:38:23 2014        (r263391)
@@ -474,8 +474,6 @@ space_map_truncate(space_map_t *sm, dmu_
 {
        objset_t *os = sm->sm_os;
        spa_t *spa = dmu_objset_spa(os);
-       zfeature_info_t *space_map_histogram =
-           &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM];
        dmu_object_info_t doi;
        int bonuslen;
 
@@ -485,7 +483,7 @@ space_map_truncate(space_map_t *sm, dmu_
        VERIFY0(dmu_free_range(os, space_map_object(sm), 0, -1ULL, tx));
        dmu_object_info_from_db(sm->sm_dbuf, &doi);
 
-       if (spa_feature_is_enabled(spa, space_map_histogram)) {
+       if (spa_feature_is_enabled(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
                bonuslen = sizeof (space_map_phys_t);
                ASSERT3U(bonuslen, <=, dmu_bonus_max());
        } else {
@@ -525,13 +523,11 @@ uint64_t
 space_map_alloc(objset_t *os, dmu_tx_t *tx)
 {
        spa_t *spa = dmu_objset_spa(os);
-       zfeature_info_t *space_map_histogram =
-           &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM];
        uint64_t object;
        int bonuslen;
 
-       if (spa_feature_is_enabled(spa, space_map_histogram)) {
-               spa_feature_incr(spa, space_map_histogram, tx);
+       if (spa_feature_is_enabled(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
+               spa_feature_incr(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM, tx);
                bonuslen = sizeof (space_map_phys_t);
                ASSERT3U(bonuslen, <=, dmu_bonus_max());
        } else {
@@ -549,20 +545,20 @@ void
 space_map_free(space_map_t *sm, dmu_tx_t *tx)
 {
        spa_t *spa;
-       zfeature_info_t *space_map_histogram =
-           &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM];
 
        if (sm == NULL)
                return;
 
        spa = dmu_objset_spa(sm->sm_os);
-       if (spa_feature_is_enabled(spa, space_map_histogram)) {
+       if (spa_feature_is_enabled(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
                dmu_object_info_t doi;
 
                dmu_object_info_from_db(sm->sm_dbuf, &doi);
                if (doi.doi_bonus_size != SPACE_MAP_SIZE_V0) {
-                       VERIFY(spa_feature_is_active(spa, space_map_histogram));
-                       spa_feature_decr(spa, space_map_histogram, tx);
+                       VERIFY(spa_feature_is_active(spa,
+                           SPA_FEATURE_SPACEMAP_HISTOGRAM));
+                       spa_feature_decr(spa,
+                           SPA_FEATURE_SPACEMAP_HISTOGRAM, tx);
                }
        }
 

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_impl.h
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_impl.h      
Wed Mar 19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_impl.h      
Wed Mar 19 23:38:23 2014        (r263391)
@@ -301,6 +301,8 @@ typedef struct dmu_sendarg {
        uint64_t dsa_last_data_offset;
 } dmu_sendarg_t;
 
+void dmu_object_zapify(objset_t *, uint64_t, dmu_object_type_t, dmu_tx_t *);
+void dmu_object_free_zapified(objset_t *, uint64_t, dmu_tx_t *);
 
 #ifdef __cplusplus
 }

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h Wed Mar 
19 23:38:23 2014        (r263391)
@@ -178,6 +178,7 @@ typedef struct dnode {
        uint16_t dn_datablkszsec;       /* in 512b sectors */
        uint32_t dn_datablksz;          /* in bytes */
        uint64_t dn_maxblkid;
+       uint8_t dn_next_type[TXG_SIZE];
        uint8_t dn_next_nblkptr[TXG_SIZE];
        uint8_t dn_next_nlevels[TXG_SIZE];
        uint8_t dn_next_indblkshift[TXG_SIZE];

Modified: 
stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h   
Wed Mar 19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h   
Wed Mar 19 23:38:23 2014        (r263391)
@@ -49,9 +49,9 @@ struct dsl_pool;
 #define        DS_FLAG_INCONSISTENT    (1ULL<<0)
 #define        DS_IS_INCONSISTENT(ds)  \
        ((ds)->ds_phys->ds_flags & DS_FLAG_INCONSISTENT)
+
 /*
- * Note: nopromote can not yet be set, but we want support for it in this
- * on-disk version, so that we don't need to upgrade for it later.
+ * Do not allow this dataset to be promoted.
  */
 #define        DS_FLAG_NOPROMOTE       (1ULL<<1)
 
@@ -71,6 +71,11 @@ struct dsl_pool;
        ((ds)->ds_phys->ds_flags & DS_FLAG_DEFER_DESTROY)
 
 /*
+ * DS_FIELD_* are strings that are used in the "extensified" dataset zap 
object.
+ * They should be of the format <reverse-dns>:<field>.
+ */
+
+/*
  * DS_FLAG_CI_DATASET is set if the dataset contains a file system whose
  * name lookups should be performed case-insensitively.
  */

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h   Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h   Wed Mar 
19 23:38:23 2014        (r263391)
@@ -141,6 +141,12 @@ uint64_t zap_create_link(objset_t *os, d
     uint64_t parent_obj, const char *name, dmu_tx_t *tx);
 
 /*
+ * Initialize an already-allocated object.
+ */
+void mzap_create_impl(objset_t *os, uint64_t obj, int normflags,
+    zap_flags_t flags, dmu_tx_t *tx);
+
+/*
  * Create a new zapobj with no attributes from the given (unallocated)
  * object number.
  */

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfeature.h
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfeature.h      
Wed Mar 19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfeature.h      
Wed Mar 19 23:38:23 2014        (r263391)
@@ -27,6 +27,7 @@
 #define        _SYS_ZFEATURE_H
 
 #include <sys/nvpair.h>
+#include <sys/txg.h>
 #include "zfeature_common.h"
 
 #ifdef __cplusplus
@@ -37,17 +38,25 @@ struct spa;
 struct dmu_tx;
 struct objset;
 
-extern boolean_t feature_is_supported(struct objset *os, uint64_t obj,
-    uint64_t desc_obj, nvlist_t *unsup_feat, nvlist_t *enabled_feat);
-
 extern void spa_feature_create_zap_objects(struct spa *, struct dmu_tx *);
-extern void spa_feature_enable(struct spa *, zfeature_info_t *,
+extern void spa_feature_enable(struct spa *, spa_feature_t,
+    struct dmu_tx *);
+extern void spa_feature_incr(struct spa *, spa_feature_t, struct dmu_tx *);
+extern void spa_feature_decr(struct spa *, spa_feature_t, struct dmu_tx *);
+extern boolean_t spa_feature_is_enabled(struct spa *, spa_feature_t);
+extern boolean_t spa_feature_is_active(struct spa *, spa_feature_t);
+extern uint64_t spa_feature_refcount(spa_t *, spa_feature_t, uint64_t);
+extern boolean_t spa_features_check(spa_t *, boolean_t, nvlist_t *, nvlist_t 
*);
+
+/*
+ * These functions are only exported for zhack and zdb; normal callers should
+ * use the above interfaces.
+ */
+extern int feature_get_refcount(struct spa *, zfeature_info_t *, uint64_t *);
+extern void feature_enable_sync(struct spa *, zfeature_info_t *,
+    struct dmu_tx *);
+extern void feature_sync(struct spa *, zfeature_info_t *, uint64_t,
     struct dmu_tx *);
-extern void spa_feature_incr(struct spa *, zfeature_info_t *, struct dmu_tx *);
-extern void spa_feature_decr(struct spa *, zfeature_info_t *, struct dmu_tx *);
-extern boolean_t spa_feature_is_enabled(struct spa *, zfeature_info_t *);
-extern boolean_t spa_feature_is_active(struct spa *, zfeature_info_t *);
-extern int spa_feature_get_refcount(struct spa *, zfeature_info_t *);
 
 #ifdef __cplusplus
 }

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c Wed Mar 
19 23:36:12 2014        (r263390)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c Wed Mar 
19 23:38:23 2014        (r263391)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to