All of lore.kernel.org
 help / color / mirror / Atom feed
From: ThangNN99 <ngocthang2710.1999@gmail.com>
To: Mark Fasheh <mark@fasheh.com>, Joel Becker <jlbec@evilplan.org>,
	Joseph Qi <joseph.qi@linux.alibaba.com>,
	Heming Zhao <heming.zhao@suse.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Su Yue <glass.su@suse.com>,
	ocfs2-devel@lists.linux.dev, linux-kernel@vger.kernel.org,
	ThangNN99 <ngocthang2710.1999@gmail.com>,
	syzbot+73d1166b94ed9875af54@syzkaller.appspotmail.com,
	stable@vger.kernel.org
Subject: [PATCH] ocfs2: fix ABBA deadlock in suballocator reclaim
Date: Sun,  6 Sep 2026 20:31:12 +0700	[thread overview]
Message-ID: <20260906133112.73343-1-ngocthang2710.1999@gmail.com> (raw)

_ocfs2_reclaim_suballoc_to_main() runs inside an already-started
transaction (j_trans_barrier held) and locks the global bitmap inode
to return clusters to it. Every other allocation path takes that
inode lock *before* starting a transaction, so this reverses the
order and can deadlock:

  CPU0                          CPU1
  rlock(j_trans_barrier)
                                lock(sb_internal)
                                lock(j_trans_barrier)
  lock(GLOBAL_BITMAP inode)

Since reclaim is best-effort (its caller already ignores the return
value), fix it by acquiring the global bitmap inode with trylock,
before mutating anything, and bailing out to skip reclaim on a busy
lock instead of blocking in the wrong order.

Reproduced with the syzbot C repro under QEMU: the unpatched kernel
hits the lockdep splat on the very first mount+mkdir+rmdir cycle
(~10s in); the patched kernel ran the same cycle 169 times with zero
splats, and instrumentation confirmed reclaim keeps running (trylock
succeeds) rather than being silently skipped.

Reported-by: syzbot+73d1166b94ed9875af54@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=73d1166b94ed9875af54
Fixes: 4a54331616b3 ("ocfs2: give ocfs2 the ability to reclaim suballocator free bg")
Cc: stable@vger.kernel.org
Signed-off-by: ThangNN99 <ngocthang2710.1999@gmail.com>
---
 fs/ocfs2/suballoc.c | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 20c3aec6b987..085af9ba38ab 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -2716,18 +2716,39 @@ static int _ocfs2_reclaim_suballoc_to_main(handle_t *handle,
 	idx = le16_to_cpu(group->bg_chain);
 	rec = &(cl->cl_recs[idx]);
 
+	/*
+	 * We already hold j_trans_barrier, while everywhere else locks the
+	 * allocator inode before starting a transaction. Trylock here, before
+	 * mutating anything, so a busy lock skips this best-effort reclaim
+	 * instead of inverting that order into an ABBA deadlock.
+	 */
+	main_bm_inode = ocfs2_get_system_file_inode(osb,
+						    GLOBAL_BITMAP_SYSTEM_INODE,
+						    OCFS2_INVALID_SLOT);
+	if (!main_bm_inode)
+		goto bail; /* ignore the error in reclaim path */
+
+	if (!inode_trylock(main_bm_inode)) {
+		iput(main_bm_inode);
+		goto bail; /* ignore the error in reclaim path */
+	}
+
+	status = ocfs2_try_inode_lock(main_bm_inode, &main_bm_bh, 1);
+	if (status < 0)
+		goto free_bm_inode; /* ignore the error in reclaim path */
+
 	status = ocfs2_extend_trans(handle,
 				ocfs2_calc_group_alloc_credits(osb->sb,
 						 le16_to_cpu(cl->cl_cpg)));
 	if (status) {
 		mlog_errno(status);
-		goto bail;
+		goto free_bm_bh;
 	}
 	status = ocfs2_journal_access_di(handle, INODE_CACHE(alloc_inode),
 					 alloc_bh, OCFS2_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
 		mlog_errno(status);
-		goto bail;
+		goto free_bm_bh;
 	}
 
 	/*
@@ -2795,18 +2816,6 @@ static int _ocfs2_reclaim_suballoc_to_main(handle_t *handle,
 	memset(group, 0, sizeof(struct ocfs2_group_desc));
 
 	/* prepare job for reclaim clusters */
-	main_bm_inode = ocfs2_get_system_file_inode(osb,
-						    GLOBAL_BITMAP_SYSTEM_INODE,
-						    OCFS2_INVALID_SLOT);
-	if (!main_bm_inode)
-		goto bail; /* ignore the error in reclaim path */
-
-	inode_lock(main_bm_inode);
-
-	status = ocfs2_inode_lock(main_bm_inode, &main_bm_bh, 1);
-	if (status < 0)
-		goto free_bm_inode; /* ignore the error in reclaim path */
-
 	ocfs2_block_to_cluster_group(main_bm_inode, start_blk, &bg_blkno,
 				     &start_bit);
 	fe = (struct ocfs2_dinode *) main_bm_bh->b_data;
-- 
2.43.0


             reply	other threads:[~2026-09-06 13:31 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-06 13:31 ThangNN99 [this message]
2026-09-06 14:18 ` [PATCH] ocfs2: fix ABBA deadlock in suballocator reclaim Joseph Qi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260906133112.73343-1-ngocthang2710.1999@gmail.com \
    --to=ngocthang2710.1999@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=glass.su@suse.com \
    --cc=heming.zhao@suse.com \
    --cc=jlbec@evilplan.org \
    --cc=joseph.qi@linux.alibaba.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark@fasheh.com \
    --cc=ocfs2-devel@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=syzbot+73d1166b94ed9875af54@syzkaller.appspotmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.