]> granicus.if.org Git - zfs/commitdiff
Serialize access to spa->spa_feat_stats nvlist
authorNed Bass <bass6@llnl.gov>
Thu, 23 Apr 2015 19:32:59 +0000 (12:32 -0700)
committerNed Bass <bass6@llnl.gov>
Tue, 23 Jun 2015 01:14:46 +0000 (18:14 -0700)
The function spa_add_feature_stats() manipulates the shared nvlist
spa->spa_feat_stats in an unsafe concurrent manner. Add a mutex to
protect the list.

Signed-off-by: Ned Bass <bass6@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3335

include/sys/spa_impl.h
module/zfs/spa.c
module/zfs/spa_misc.c

index 72e04e8cfe3572a42eba3078edc28c0b1ecdf089..19ba1153741f93af4f776c54520571fb23194ed8 100644 (file)
@@ -236,6 +236,7 @@ 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];
index 8bee15094685ce5be1bd03cfca93d0f09605f537..998ec3e543f9e0931be5adf4048c88459b079fa7 100644 (file)
@@ -3264,10 +3264,13 @@ spa_feature_stats_from_cache(spa_t *spa, nvlist_t *features)
 static void
 spa_add_feature_stats(spa_t *spa, nvlist_t *config)
 {
-       nvlist_t *features = spa->spa_feat_stats;
+       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 {
@@ -3278,6 +3281,8 @@ spa_add_feature_stats(spa_t *spa, nvlist_t *config)
 
        VERIFY0(nvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
            features));
+
+       mutex_exit(&spa->spa_feat_stats_lock);
 }
 
 int
index ec0c0195947c0c2841ce49ef19e0a07d62685e1b..7a96ea18bfc580b8be8336649385f546a33d8ea7 100644 (file)
@@ -531,6 +531,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
        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_proc_cv, NULL, CV_DEFAULT, NULL);
@@ -668,6 +669,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));
 }