mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
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>
This commit is contained in:
parent
b067d3c1f9
commit
4a87cfb9b4
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user