Skip to content

Commit b6bd322

Browse files
authored
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
1 parent e7485d0 commit b6bd322

File tree

2 files changed

+9
-0
lines changed

2 files changed

+9
-0
lines changed

cmd/zhack.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,10 +363,12 @@ feature_incr_sync(void *arg, dmu_tx_t *tx)
363363
zfeature_info_t *feature = arg;
364364
uint64_t refcount;
365365

366+
mutex_enter(&spa->spa_feat_stats_lock);
366367
VERIFY0(feature_get_refcount_from_disk(spa, feature, &refcount));
367368
feature_sync(spa, feature, refcount + 1, tx);
368369
spa_history_log_internal(spa, "zhack feature incr", tx,
369370
"name=%s", feature->fi_guid);
371+
mutex_exit(&spa->spa_feat_stats_lock);
370372
}
371373

372374
static void
@@ -376,10 +378,12 @@ feature_decr_sync(void *arg, dmu_tx_t *tx)
376378
zfeature_info_t *feature = arg;
377379
uint64_t refcount;
378380

381+
mutex_enter(&spa->spa_feat_stats_lock);
379382
VERIFY0(feature_get_refcount_from_disk(spa, feature, &refcount));
380383
feature_sync(spa, feature, refcount - 1, tx);
381384
spa_history_log_internal(spa, "zhack feature decr", tx,
382385
"name=%s", feature->fi_guid);
386+
mutex_exit(&spa->spa_feat_stats_lock);
383387
}
384388

385389
static void

module/zfs/zfeature.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount,
308308
ASSERT(VALID_FEATURE_OR_NONE(feature->fi_feature));
309309
uint64_t zapobj = (feature->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
310310
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
311+
ASSERT(MUTEX_HELD(&spa->spa_feat_stats_lock));
311312
VERIFY0(zap_update(spa->spa_meta_objset, zapobj, feature->fi_guid,
312313
sizeof (uint64_t), 1, &refcount, tx));
313314

@@ -360,7 +361,9 @@ feature_enable_sync(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
360361
feature->fi_guid, 1, strlen(feature->fi_desc) + 1,
361362
feature->fi_desc, tx));
362363

364+
mutex_enter(&spa->spa_feat_stats_lock);
363365
feature_sync(spa, feature, initial_refcount, tx);
366+
mutex_exit(&spa->spa_feat_stats_lock);
364367

365368
if (spa_feature_is_enabled(spa, SPA_FEATURE_ENABLED_TXG)) {
366369
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,
416419
ASSERT(dmu_tx_is_syncing(tx));
417420
ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
418421

422+
mutex_enter(&spa->spa_feat_stats_lock);
419423
VERIFY3U(feature_get_refcount(spa, feature, &refcount), !=, ENOTSUP);
420424

421425
switch (action) {
@@ -433,6 +437,7 @@ feature_do_action(spa_t *spa, spa_feature_t fid, feature_action_t action,
433437
}
434438

435439
feature_sync(spa, feature, refcount, tx);
440+
mutex_exit(&spa->spa_feat_stats_lock);
436441
}
437442

438443
void

0 commit comments

Comments
 (0)