diff options
| author | Jinjie Ruan <ruanjinjie@huawei.com> | 2026-09-02 15:48:05 +0800 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2026-10-08 11:07:33 -0400 |
| commit | 4a87cfb9b45ae07cd28bdc1ab9059ea73eab312e (patch) | |
| tree | 14aa0b40d8e328632ac756fd6fd47e726a9a381b | |
| parent | b067d3c1f90b536e9aa9f48b19580475a0b34f0f (diff) | |
ext4: convert group-count barrier protocol to acquire/release
During an online resize, reading s_groups_count and s_blockfile_groups
requires strict ordering against subsequent initialized block group
metadata.
Replace the historical smp_wmb()/smp_rmb() pairs with smp_store_release()
and smp_load_acquire(). This formalizes the publish-subscribe pattern
and allows weakly-ordered architectures (e.g., arm64) to utilize native
STLR/LDAR instructions instead of full DMB fences.
Update the documentation in resize.c and ext4.h accordingly.
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: Baokun Li <libaokun@linux.alibaba.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Cc: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
Cc: Zhang Yi <yi.zhang@huawei.com>
Assisted-by: Gemini:Gemini-3.1
Assisted-by: DeepSeek:DeepSeek-V3
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Link: https://patch.msgid.link/20260902074805.398540-9-ruanjinjie@huawei.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
| -rw-r--r-- | fs/ext4/ext4.h | 10 | ||||
| -rw-r--r-- | fs/ext4/mballoc.c | 6 | ||||
| -rw-r--r-- | fs/ext4/resize.c | 19 |
3 files changed, 16 insertions, 19 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 1edc4a94bb7d..9d06ddd865d4 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -3542,16 +3542,12 @@ static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size) } /* - * Reading s_groups_count requires using smp_rmb() afterwards. See - * the locking protocol documented in the comments of ext4_group_add() - * in resize.c + * Reading s_groups_count uses acquire semantics. */ static inline ext4_group_t ext4_get_groups_count(struct super_block *sb) { - ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; - - smp_rmb(); - return ngroups; + /* Pairs with smp_store_release() in ext4_update_super() */ + return smp_load_acquire(&EXT4_SB(sb)->s_groups_count); } static inline ext4_group_t ext4_flex_group(struct ext4_sb_info *sbi, diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 06171a11db12..a15285224cdf 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -899,10 +899,8 @@ static ext4_group_t ext4_get_allocation_groups_count( /* non-extent files are limited to low blocks/groups */ if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS))) - ngroups = EXT4_SB(ac->ac_sb)->s_blockfile_groups; - - /* Pairs with smp_wmb() in ext4_update_super() */ - smp_rmb(); + /* Pairs with smp_store_release() in ext4_update_super() */ + ngroups = smp_load_acquire(&EXT4_SB(ac->ac_sb)->s_blockfile_groups); return ngroups; } diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 2c5b851c552a..5e3ad8393cf8 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1462,11 +1462,11 @@ static void ext4_update_super(struct super_block *sb, * * The precise rules we use are: * - * * Writers must perform a smp_wmb() after updating all - * dependent data and before modifying the groups count + * * Writers must use a release store when updating the groups count + * after all dependent data has been updated * - * * Readers must perform an smp_rmb() after reading the groups - * count and before reading any dependent data. + * * Readers must use an acquire load when reading the groups + * count before reading any dependent data. * * NB. These rules can be relaxed when checking the group count * while freeing data, as we can only allocate from a block @@ -1474,12 +1474,15 @@ static void ext4_update_super(struct super_block *sb, * only then free after serialising in turn against that * allocation. */ - smp_wmb(); /* Update the global fs size fields */ - sbi->s_groups_count += flex_gd->count; - sbi->s_blockfile_groups = min(sbi->s_groups_count, - (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb))); + /* Pairs with smp_load_acquire() in ext4_get_groups_count() */ + smp_store_release(&sbi->s_groups_count, + sbi->s_groups_count + flex_gd->count); + /* Pairs with smp_load_acquire() in ext4_get_allocation_groups_count() */ + smp_store_release(&sbi->s_blockfile_groups, + min(sbi->s_groups_count, + (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)))); /* Update the reserved block counts only once the new group is * active. */ |
