Author: mav
Date: Thu Apr 25 15:31:35 2019
New Revision: 346676
URL: https://svnweb.freebsd.org/changeset/base/346676

Log:
  MFC r337594 (by mmacy):
  ZFS/MFV:    Use cached feature info in spa_add_feature_stats()
  
  commit 417104bdd3c7ce07ec58674dd078f9891c3bc780
  Author: Ned Bass <ba...@llnl.gov>
  Date:   Thu Feb 26 12:24:11 2015 -0800
  
      Use cached feature info in spa_add_feature_stats()
  
      Avoid issuing I/O to the pool when retrieving feature flags information.
      Trying to read the ZAPs from disk means that zpool clear would hang if
      the pool is suspended and recovery would require a reboot. To keep the
      feature stats resident in memory, we hang a cached nvlist off of the
      spa.  It is built up from disk the first time spa_add_feature_stats() is
      called, and refreshed thereafter using the cached feature reference
      counts. spa_add_feature_stats() gets called at pool import time so we
      can be sure the cached nvlist will be available if the pool is later
      suspended.
  
      Signed-off-by: Ned Bass <ba...@llnl.gov>
      Signed-off-by: Brian Behlendorf <behlendo...@llnl.gov>
      Closes #3082

Modified:
  stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
  stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
  stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
  stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
==============================================================================
--- stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c      Thu Apr 
25 15:09:21 2019        (r346675)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c      Thu Apr 
25 15:31:35 2019        (r346676)
@@ -4372,18 +4372,14 @@ spa_add_l2cache(spa_t *spa, nvlist_t *config)
 }
 
 static void
-spa_add_feature_stats(spa_t *spa, nvlist_t *config)
+spa_feature_stats_from_disk(spa_t *spa, nvlist_t *features)
 {
-       nvlist_t *features;
        zap_cursor_t zc;
        zap_attribute_t za;
 
-       ASSERT(spa_config_held(spa, SCL_CONFIG, RW_READER));
-       VERIFY(nvlist_alloc(&features, NV_UNIQUE_NAME, KM_SLEEP) == 0);
-
        /* We may be unable to read features if pool is suspended. */
        if (spa_suspended(spa))
-               goto out;
+               return;
 
        if (spa->spa_feat_for_read_obj != 0) {
                for (zap_cursor_init(&zc, spa->spa_meta_objset,
@@ -4392,7 +4388,7 @@ spa_add_feature_stats(spa_t *spa, nvlist_t *config)
                    zap_cursor_advance(&zc)) {
                        ASSERT(za.za_integer_length == sizeof (uint64_t) &&
                            za.za_num_integers == 1);
-                       VERIFY3U(0, ==, nvlist_add_uint64(features, za.za_name,
+                       VERIFY0(nvlist_add_uint64(features, za.za_name,
                            za.za_first_integer));
                }
                zap_cursor_fini(&zc);
@@ -4405,16 +4401,62 @@ spa_add_feature_stats(spa_t *spa, nvlist_t *config)
                    zap_cursor_advance(&zc)) {
                        ASSERT(za.za_integer_length == sizeof (uint64_t) &&
                            za.za_num_integers == 1);
-                       VERIFY3U(0, ==, nvlist_add_uint64(features, za.za_name,
+                       VERIFY0(nvlist_add_uint64(features, za.za_name,
                            za.za_first_integer));
                }
                zap_cursor_fini(&zc);
        }
+}
 
-out:
-       VERIFY(nvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
-           features) == 0);
-       nvlist_free(features);
+static void
+spa_feature_stats_from_cache(spa_t *spa, nvlist_t *features)
+{
+       int i;
+
+       for (i = 0; i < SPA_FEATURES; i++) {
+               zfeature_info_t feature = spa_feature_table[i];
+               uint64_t refcount;
+
+               if (feature_get_refcount(spa, &feature, &refcount) != 0)
+                       continue;
+
+               VERIFY0(nvlist_add_uint64(features, feature.fi_guid, refcount));
+       }
+}
+
+/*
+ * Store a list of pool features and their reference counts in the
+ * config.
+ *
+ * The first time this is called on a spa, allocate a new nvlist, fetch
+ * the pool features and reference counts from disk, then save the list
+ * in the spa. In subsequent calls on the same spa use the saved nvlist
+ * and refresh its values from the cached reference counts.  This
+ * ensures we don't block here on I/O on a suspended pool so 'zpool
+ * clear' can resume the pool.
+ */
+static void
+spa_add_feature_stats(spa_t *spa, nvlist_t *config)
+{
+       nvlist_t *features;
+
+       ASSERT(spa_config_held(spa, SCL_CONFIG, RW_READER));
+
+       mutex_enter(&spa->spa_feat_stats_lock);
+       features = spa->spa_feat_stats;
+
+       if (features != NULL) {
+               spa_feature_stats_from_cache(spa, features);
+       } else {
+               VERIFY0(nvlist_alloc(&features, NV_UNIQUE_NAME, KM_SLEEP));
+               spa->spa_feat_stats = features;
+               spa_feature_stats_from_disk(spa, features);
+       }
+
+       VERIFY0(nvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
+           features));
+
+       mutex_exit(&spa->spa_feat_stats_lock);
 }
 
 int

Modified: stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
==============================================================================
--- stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c Thu Apr 
25 15:09:21 2019        (r346675)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c Thu Apr 
25 15:31:35 2019        (r346676)
@@ -716,6 +716,7 @@ spa_add(const char *name, nvlist_t *config, const char
        mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&spa->spa_feat_stats_lock, NULL, MUTEX_DEFAULT, NULL);
 
        cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL);
        cv_init(&spa->spa_evicting_os_cv, NULL, CV_DEFAULT, NULL);
@@ -889,6 +890,7 @@ spa_remove(spa_t *spa)
 
        nvlist_free(spa->spa_label_features);
        nvlist_free(spa->spa_load_info);
+       nvlist_free(spa->spa_feat_stats);
        spa_config_set(spa, NULL);
 
 #ifdef illumos
@@ -930,6 +932,7 @@ spa_remove(spa_t *spa)
        mutex_destroy(&spa->spa_scrub_lock);
        mutex_destroy(&spa->spa_suspend_lock);
        mutex_destroy(&spa->spa_vdev_top_lock);
+       mutex_destroy(&spa->spa_feat_stats_lock);
 
        kmem_free(spa, sizeof (spa_t));
 }

Modified: 
stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
==============================================================================
--- stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h     
Thu Apr 25 15:09:21 2019        (r346675)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h     
Thu Apr 25 15:31:35 2019        (r346676)
@@ -360,6 +360,8 @@ struct spa {
        uint64_t        spa_feat_for_read_obj;  /* required to read from pool */
        uint64_t        spa_feat_desc_obj;      /* Feature descriptions */
        uint64_t        spa_feat_enabled_txg_obj; /* Feature enabled txg */
+       kmutex_t        spa_feat_stats_lock;    /* protects spa_feat_stats */
+       nvlist_t        *spa_feat_stats;        /* Cache of enabled features */
        /* cache feature refcounts */
        uint64_t        spa_feat_refcount_cache[SPA_FEATURES];
 #ifdef illumos

Modified: stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c
==============================================================================
--- stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c Thu Apr 
25 15:09:21 2019        (r346675)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c Thu Apr 
25 15:31:35 2019        (r346676)
@@ -220,7 +220,7 @@ spa_features_check(spa_t *spa, boolean_t for_write,
  *
  * Note: well-designed features will not need to use this; they should
  * use spa_feature_is_enabled() and spa_feature_is_active() instead.
- * However, this is non-static for zdb and zhack.
+ * However, this is non-static for zdb, zhack, and spa_add_feature_stats().
  */
 int
 feature_get_refcount(spa_t *spa, zfeature_info_t *feature, uint64_t *res)
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to