[PATCH v2] ext4: fix race in ext4_mb_check_group_pa
rafad900 <[email protected]>
| Newsgroups | org.kernel.vger.linux-ext4,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
ext4_mb_check_group_pa drops the reference count on the previous best PA using atomic_dec(&cpa->pa_count) without holding the cpa->pa_lock. This causes race with ext4_discard_preallocations() which checks pa_count to decide whether a PA is still in use. If the pa_count is dec between the check and the discard, the PA can be freed while ext4_mb_check_group_pa() still holds a reference to it. Fix this by taking the cpa->pa_lock around the atomic_dec. Similar to pa->pa_lock which is taken outside of the ext4_mb_check_group_pa() function. The race was found while testing a change related to a Coccinelle warning from atomic_as_refcounter.cocci. The refcount conversion was found to be incorrect but the change had revealed the pre-exiting race condition. Signed-off-by: rafad900 <[email protected]> --- Changes in v2: - Identified correct race location: ext4_mb_check_group_pa rather than ext4_mb_use_preallocated (the inode PA path already holds pa_lock correctly) - Dropped refcount_t conversion — incompatible with PA lifecycle where count=0 represents an idle but reusable PA - Added spin_lock(&cpa->pa_lock) around atomic_dec in ext4_mb_check_group_pa fs/ext4/mballoc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index ed1bd00e11cd..c9a118ae4658 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4833,7 +4833,9 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block, return cpa; /* drop the previous reference */ + spin_lock(&cpa->pa_lock); atomic_dec(&cpa->pa_count); + spin_unlock(&cpa->pa_lock); atomic_inc(&pa->pa_count); return pa; } -- 2.43.0