* [PATCH] ext4: convert pa_count from atomic_t to refcount_t
@ 2026-07-20 3:44 rafad900
2026-07-20 7:25 ` [syzbot ci] " syzbot ci
0 siblings, 1 reply; 2+ messages in thread
From: rafad900 @ 2026-07-20 3:44 UTC (permalink / raw)
To: tytso, adilger.kernel, libaokun, jack; +Cc: linux-ext4, linux-kernel, rafad900
The pa_count field in struct ext4_prealloc_space is
reference counter for preallocation descriptors.
Converting it from atomic_t to refcount_t provides
underflow and overflow protection.
This was found using Coccinelle script
atomic_as_refcounter.cocci
Testing was done on a QEMU x86 VM revealing a
pre-existing race condition leading to a
use-after-free.
Signed-off-by: rafad900 <rafad900@gmail.com>
---
fs/ext4/mballoc.c | 22 +++++++++++-----------
fs/ext4/mballoc.h | 2 +-
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index ed1bd00e11cd..59b3d4abaab0 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4823,7 +4823,7 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block,
ext4_fsblk_t cur_distance, new_distance;
if (cpa == NULL) {
- atomic_inc(&pa->pa_count);
+ refcount_inc(&pa->pa_count);
return pa;
}
cur_distance = abs(goal_block - cpa->pa_pstart);
@@ -4833,8 +4833,8 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block,
return cpa;
/* drop the previous reference */
- atomic_dec(&cpa->pa_count);
- atomic_inc(&pa->pa_count);
+ refcount_dec(&cpa->pa_count);
+ refcount_inc(&pa->pa_count);
return pa;
}
@@ -4993,7 +4993,7 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
}
if (tmp_pa->pa_free && likely(ext4_mb_pa_goal_check(ac, tmp_pa))) {
- atomic_inc(&tmp_pa->pa_count);
+ refcount_inc(&tmp_pa->pa_count);
ext4_mb_use_inode_pa(ac, tmp_pa);
spin_unlock(&tmp_pa->pa_lock);
read_unlock(&ei->i_prealloc_lock);
@@ -5139,7 +5139,7 @@ static void ext4_mb_mark_pa_deleted(struct super_block *sb,
static inline void ext4_mb_pa_free(struct ext4_prealloc_space *pa)
{
BUG_ON(!pa);
- BUG_ON(atomic_read(&pa->pa_count));
+ BUG_ON(refcount_read(&pa->pa_count));
BUG_ON(pa->pa_deleted == 0);
kmem_cache_free(ext4_pspace_cachep, pa);
}
@@ -5165,7 +5165,7 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
/* in this short window concurrent discard can set pa_deleted */
spin_lock(&pa->pa_lock);
- if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) {
+ if (!refcount_dec_and_test(&pa->pa_count) || pa->pa_free != 0) {
spin_unlock(&pa->pa_lock);
return;
}
@@ -5535,7 +5535,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
list_for_each_entry_safe(pa, tmp,
&grp->bb_prealloc_list, pa_group_list) {
spin_lock(&pa->pa_lock);
- if (atomic_read(&pa->pa_count)) {
+ if (refcount_read(&pa->pa_count)) {
spin_unlock(&pa->pa_lock);
*busy = 1;
continue;
@@ -5637,7 +5637,7 @@ void ext4_discard_preallocations(struct inode *inode)
BUG_ON(pa->pa_node_lock.inode_lock != &ei->i_prealloc_lock);
spin_lock(&pa->pa_lock);
- if (atomic_read(&pa->pa_count)) {
+ if (refcount_read(&pa->pa_count)) {
/* this shouldn't happen often - nobody should
* use preallocation while we're discarding it */
spin_unlock(&pa->pa_lock);
@@ -5720,7 +5720,7 @@ static int ext4_mb_pa_alloc(struct ext4_allocation_context *ac)
pa = kmem_cache_zalloc(ext4_pspace_cachep, GFP_NOFS);
if (!pa)
return -ENOMEM;
- atomic_set(&pa->pa_count, 1);
+ refcount_set(&pa->pa_count, 1);
ac->ac_pa = pa;
return 0;
}
@@ -5731,7 +5731,7 @@ static void ext4_mb_pa_put_free(struct ext4_allocation_context *ac)
BUG_ON(!pa);
ac->ac_pa = NULL;
- WARN_ON(!atomic_dec_and_test(&pa->pa_count));
+ WARN_ON(!refcount_dec_and_test(&pa->pa_count));
/*
* current function is only called due to an error or due to
* len of found blocks < len of requested blocks hence the PA has not
@@ -5948,7 +5948,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
pa_node.lg_list,
lockdep_is_held(&lg->lg_prealloc_lock)) {
spin_lock(&pa->pa_lock);
- if (atomic_read(&pa->pa_count)) {
+ if (refcount_read(&pa->pa_count)) {
/*
* This is the pa that we just used
* for block allocation. So don't
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index 39333ce72cbd..f708d303228e 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -126,7 +126,7 @@ struct ext4_prealloc_space {
struct rcu_head pa_rcu;
} u;
spinlock_t pa_lock;
- atomic_t pa_count;
+ refcount_t pa_count;
unsigned pa_deleted;
ext4_fsblk_t pa_pstart; /* phys. block */
ext4_lblk_t pa_lstart; /* log. block */
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* [syzbot ci] Re: ext4: convert pa_count from atomic_t to refcount_t
2026-07-20 3:44 [PATCH] ext4: convert pa_count from atomic_t to refcount_t rafad900
@ 2026-07-20 7:25 ` syzbot ci
0 siblings, 0 replies; 2+ messages in thread
From: syzbot ci @ 2026-07-20 7:25 UTC (permalink / raw)
To: adilger.kernel, jack, libaokun, linux-ext4, linux-kernel,
rafad900, tytso
Cc: syzbot, syzkaller-bugs
syzbot ci has tested the following series
[v1] ext4: convert pa_count from atomic_t to refcount_t
https://lore.kernel.org/all/20260720034441.3900050-1-rafad900@gmail.com
* [PATCH] ext4: convert pa_count from atomic_t to refcount_t
and found the following issue:
WARNING: refcount bug in ext4_mb_use_preallocated
Full report is available here:
https://ci.syzbot.org/series/34fda797-e979-409c-bc2d-7af3e163df14
***
WARNING: refcount bug in ext4_mb_use_preallocated
tree: torvalds
URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
base: 1590cf0329716306e948a8fc29f1d3ee87d3989f
arch: amd64
compiler: Debian clang version 22.1.6 (++20260514074242+fc4aad7b5db3-1~exp1~20260514074407.73), Debian LLD 22.1.6
config: https://ci.syzbot.org/builds/05fa6c1d-a594-4691-ace3-ded3fc2ca4dc/config
------------[ cut here ]------------
refcount_t: addition on 0; use-after-free.
WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x9f/0x110, CPU#0: kworker/u9:2/51
Modules linked in:
CPU: 0 UID: 0 PID: 51 Comm: kworker/u9:2 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
Workqueue: writeback wb_workfn (flush-8:0)
RIP: 0010:refcount_warn_saturate+0x9f/0x110
Code: eb 66 85 db 74 3e 83 fb 01 75 4c e8 8b 73 0c fd 48 8d 3d 34 58 84 0b 67 48 0f b9 3a eb 4a e8 78 73 0c fd 48 8d 3d 31 58 84 0b <67> 48 0f b9 3a eb 37 e8 65 73 0c fd 48 8d 3d 2e 58 84 0b 67 48 0f
RSP: 0018:ffffc90000bb6590 EFLAGS: 00010293
RAX: ffffffff84b9ee08 RBX: 0000000000000002 RCX: ffff8881072a8000
RDX: 0000000000000000 RSI: ffffffff8f126800 RDI: ffffffff903e4640
RBP: ffff888112257dd0 R08: ffff8881072a8000 R09: 0000000000000005
R10: 0000000000000004 R11: 0000000000000000 R12: dffffc0000000000
R13: ffff888112257d98 R14: ffff888112257e10 R15: 0000000000000008
FS: 0000000000000000(0000) GS:ffff88818dc15000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fc831b2c080 CR3: 0000000112724000 CR4: 00000000000006f0
Call Trace:
<TASK>
ext4_mb_use_preallocated+0xaa0/0x14e0
ext4_mb_new_blocks+0x5a0/0x4560
ext4_ext_map_blocks+0x1534/0x5850
ext4_map_create_blocks+0x116/0x530
ext4_map_blocks+0x7e4/0x1240
ext4_do_writepages+0x23d3/0x47a0
ext4_writepages+0x241/0x3b0
do_writepages+0x338/0x560
__writeback_single_inode+0x12e/0xf90
writeback_sb_inodes+0x9de/0x1b00
__writeback_inodes_wb+0x114/0x240
wb_writeback+0x42f/0xad0
wb_workfn+0x980/0x10f0
process_scheduled_works+0xa8e/0x14e0
worker_thread+0xa47/0xfb0
kthread+0x388/0x470
ret_from_fork+0x514/0xb70
ret_from_fork_asm+0x1a/0x30
</TASK>
***
If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
Tested-by: syzbot@syzkaller.appspotmail.com
---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.
To test a patch for this bug, please reply with `#syz test`
(should be on a separate line).
The patch should be attached to the email.
Note: arguments like custom git repos and branches are not supported.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-20 7:25 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 3:44 [PATCH] ext4: convert pa_count from atomic_t to refcount_t rafad900
2026-07-20 7:25 ` [syzbot ci] " syzbot ci
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox