mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-01-12 08:12:04 +03:00
Synchronize the update of feature refcount
The concurrent execution of feature_sync() can lead to a panic due to an unprotected update of the feature refcount. Resolve this by using the spa->spa_feat_stats_lock to synchronize the update of the refcount. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Youzhong Yang <yyang@mathworks.com> Closes #17184 Closes #17632
This commit is contained in:
parent
9f2cbea1dc
commit
8e7a310860
@ -363,10 +363,12 @@ feature_incr_sync(void *arg, dmu_tx_t *tx)
|
||||
zfeature_info_t *feature = arg;
|
||||
uint64_t refcount;
|
||||
|
||||
mutex_enter(&spa->spa_feat_stats_lock);
|
||||
VERIFY0(feature_get_refcount_from_disk(spa, feature, &refcount));
|
||||
feature_sync(spa, feature, refcount + 1, tx);
|
||||
spa_history_log_internal(spa, "zhack feature incr", tx,
|
||||
"name=%s", feature->fi_guid);
|
||||
mutex_exit(&spa->spa_feat_stats_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -376,10 +378,12 @@ feature_decr_sync(void *arg, dmu_tx_t *tx)
|
||||
zfeature_info_t *feature = arg;
|
||||
uint64_t refcount;
|
||||
|
||||
mutex_enter(&spa->spa_feat_stats_lock);
|
||||
VERIFY0(feature_get_refcount_from_disk(spa, feature, &refcount));
|
||||
feature_sync(spa, feature, refcount - 1, tx);
|
||||
spa_history_log_internal(spa, "zhack feature decr", tx,
|
||||
"name=%s", feature->fi_guid);
|
||||
mutex_exit(&spa->spa_feat_stats_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@ -308,6 +308,7 @@ feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount,
|
||||
ASSERT(VALID_FEATURE_OR_NONE(feature->fi_feature));
|
||||
uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
|
||||
ASSERT(MUTEX_HELD(&spa->spa_feat_stats_lock));
|
||||
VERIFY0(zap_update(spa->spa_meta_objset, zapobj, feature->fi_guid,
|
||||
sizeof (uint64_t), 1, &refcount, tx));
|
||||
|
||||
@ -360,7 +361,9 @@ feature_enable_sync(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
|
||||
feature->fi_guid, 1, strlen(feature->fi_desc) + 1,
|
||||
feature->fi_desc, tx));
|
||||
|
||||
mutex_enter(&spa->spa_feat_stats_lock);
|
||||
feature_sync(spa, feature, initial_refcount, tx);
|
||||
mutex_exit(&spa->spa_feat_stats_lock);
|
||||
|
||||
if (spa_feature_is_enabled(spa, SPA_FEATURE_ENABLED_TXG)) {
|
||||
uint64_t enabling_txg = dmu_tx_get_txg(tx);
|
||||
@ -416,6 +419,7 @@ feature_do_action(spa_t *spa, spa_feature_t fid, feature_action_t action,
|
||||
ASSERT(dmu_tx_is_syncing(tx));
|
||||
ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
|
||||
|
||||
mutex_enter(&spa->spa_feat_stats_lock);
|
||||
VERIFY3U(feature_get_refcount(spa, feature, &refcount), !=, ENOTSUP);
|
||||
|
||||
switch (action) {
|
||||
@ -433,6 +437,7 @@ feature_do_action(spa_t *spa, spa_feature_t fid, feature_action_t action,
|
||||
}
|
||||
|
||||
feature_sync(spa, feature, refcount, tx);
|
||||
mutex_exit(&spa->spa_feat_stats_lock);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Loading…
Reference in New Issue
Block a user