Serialize access to spa->spa_feat_stats nvlist

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
This commit is contained in:
Ned Bass 2015-04-23 12:32:59 -07:00 committed by Brian Behlendorf
parent 7008109646
commit 4eb30c6864
3 changed files with 9 additions and 1 deletions

View File

@ -236,6 +236,7 @@ struct spa {
uint64_t spa_feat_for_read_obj; /* required to read from pool */ uint64_t spa_feat_for_read_obj; /* required to read from pool */
uint64_t spa_feat_desc_obj; /* Feature descriptions */ uint64_t spa_feat_desc_obj; /* Feature descriptions */
uint64_t spa_feat_enabled_txg_obj; /* Feature enabled txg */ 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 */ nvlist_t *spa_feat_stats; /* Cache of enabled features */
/* cache feature refcounts */ /* cache feature refcounts */
uint64_t spa_feat_refcount_cache[SPA_FEATURES]; uint64_t spa_feat_refcount_cache[SPA_FEATURES];

View File

@ -3264,10 +3264,13 @@ spa_feature_stats_from_cache(spa_t *spa, nvlist_t *features)
static void static void
spa_add_feature_stats(spa_t *spa, nvlist_t *config) 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)); ASSERT(spa_config_held(spa, SCL_CONFIG, RW_READER));
mutex_enter(&spa->spa_feat_stats_lock);
features = spa->spa_feat_stats;
if (features != NULL) { if (features != NULL) {
spa_feature_stats_from_cache(spa, features); spa_feature_stats_from_cache(spa, features);
} else { } else {
@ -3278,6 +3281,8 @@ spa_add_feature_stats(spa_t *spa, nvlist_t *config)
VERIFY0(nvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS, VERIFY0(nvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
features)); features));
mutex_exit(&spa->spa_feat_stats_lock);
} }
int int

View 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_scrub_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&spa->spa_suspend_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_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_async_cv, NULL, CV_DEFAULT, NULL);
cv_init(&spa->spa_proc_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_scrub_lock);
mutex_destroy(&spa->spa_suspend_lock); mutex_destroy(&spa->spa_suspend_lock);
mutex_destroy(&spa->spa_vdev_top_lock); mutex_destroy(&spa->spa_vdev_top_lock);
mutex_destroy(&spa->spa_feat_stats_lock);
kmem_free(spa, sizeof (spa_t)); kmem_free(spa, sizeof (spa_t));
} }