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>

@@ -18,11 +18,11 @@
  *
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/zfs_context.h>
 #include <sys/spa_impl.h>

@@ -46,10 +46,11 @@
 #include <sys/fs/zfs.h>
 #include <sys/metaslab_impl.h>
 #include <sys/arc.h>
 #include <sys/ddt.h>
 #include "zfs_prop.h"
+#include "zfeature_common.h"
 
 /*
  * SPA locking
  *
  * There are four basic locks for managing spa_t structures:

@@ -214,11 +215,11 @@
  *
  * vdev state is protected by spa_vdev_state_enter() / spa_vdev_state_exit().
  * Like spa_vdev_enter/exit, these are convenience wrappers -- the actual
  * locking is, always, based on spa_namespace_lock and spa_config_lock[].
  *
- * spa_rename() is also implemented within this file since is requires
+ * spa_rename() is also implemented within this file since it requires
  * manipulation of the namespace.
  */
 
 static avl_tree_t spa_namespace_avl;
 kmutex_t spa_namespace_lock;

@@ -481,13 +482,27 @@
         list_insert_head(&spa->spa_config_list, dp);
 
         VERIFY(nvlist_alloc(&spa->spa_load_info, NV_UNIQUE_NAME,
             KM_SLEEP) == 0);
 
-        if (config != NULL)
+        if (config != NULL) {
+                nvlist_t *features;
+
+                if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURES_FOR_READ,
+                    &features) == 0) {
+                        VERIFY(nvlist_dup(features, &spa->spa_label_features,
+                            0) == 0);
+                }
+
                 VERIFY(nvlist_dup(config, &spa->spa_config, 0) == 0);
+        }
 
+        if (spa->spa_label_features == NULL) {
+                VERIFY(nvlist_alloc(&spa->spa_label_features, NV_UNIQUE_NAME,
+                    KM_SLEEP) == 0);
+        }
+
         return (spa);
 }
 
 /*
  * Removes a spa_t from the namespace, freeing up any memory used.  Requires

@@ -519,10 +534,11 @@
                 kmem_free(dp, sizeof (spa_config_dirent_t));
         }
 
         list_destroy(&spa->spa_config_list);
 
+        nvlist_free(spa->spa_label_features);
         nvlist_free(spa->spa_load_info);
         spa_config_set(spa, NULL);
 
         refcount_destroy(&spa->spa_refcount);
 

@@ -1027,10 +1043,24 @@
  * ==========================================================================
  * Miscellaneous functions
  * ==========================================================================
  */
 
+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);
+}
+
+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);
+}
+
 /*
  * Rename a spa_t.
  */
 int
 spa_rename(const char *name, const char *newname)

@@ -1177,16 +1207,26 @@
 }
 
 void
 sprintf_blkptr(char *buf, const blkptr_t *bp)
 {
-        char *type = NULL;
+        char type[256];
         char *checksum = NULL;
         char *compress = NULL;
 
         if (bp != NULL) {
-                type = dmu_ot[BP_GET_TYPE(bp)].ot_name;
+                if (BP_GET_TYPE(bp) & DMU_OT_NEWTYPE) {
+                        dmu_object_byteswap_t bswap =
+                            DMU_OT_BYTESWAP(BP_GET_TYPE(bp));
+                        (void) snprintf(type, sizeof (type), "bswap %s %s",
+                            DMU_OT_IS_METADATA(BP_GET_TYPE(bp)) ?
+                            "metadata" : "data",
+                            dmu_ot_byteswap[bswap].ob_name);
+                } else {
+                        (void) strlcpy(type, dmu_ot[BP_GET_TYPE(bp)].ot_name,
+                            sizeof (type));
+                }
                 checksum = zio_checksum_table[BP_GET_CHECKSUM(bp)].ci_name;
                 compress = zio_compress_table[BP_GET_COMPRESS(bp)].ci_name;
         }
 
         SPRINTF_BLKPTR(snprintf, ' ', buf, bp, type, checksum, compress);

@@ -1264,10 +1304,16 @@
 spa_get_dsl(spa_t *spa)
 {
         return (spa->spa_dsl_pool);
 }
 
+boolean_t
+spa_is_initializing(spa_t *spa)
+{
+        return (spa->spa_is_initializing);
+}
+
 blkptr_t *
 spa_get_rootblkptr(spa_t *spa)
 {
         return (&spa->spa_ubsync.ub_rootbp);
 }

@@ -1547,10 +1593,11 @@
         dmu_init();
         zil_init();
         vdev_cache_stat_init();
         zfs_prop_init();
         zpool_prop_init();
+        zpool_feature_init();
         spa_config_load();
         l2arc_start();
 }
 
 void