[PATCH] gfs2: fix kernel BUG in __gfs2_ail_flush during withdraw

From: Morduan Zang

Date: Thu Apr 02 2026 - 03:44:44 EST


From: Zhan Jun <zhanjun@xxxxxxxxxxxxx>

When __gfs2_ail_flush() finds an AIL buffer in unexpected state
(dirty/pinned/locked) and fsync is false, it calls gfs2_ail_error(),
which withdraws the filesystem.

However, the code then falls through and still calls
gfs2_trans_add_revoke(). That function asserts that bd->bd_list must be
empty:

BUG_ON(!list_empty(&bd->bd_list));

During withdraw this can be false because the same bufdata may still be
on a transaction buffer list, which triggers the reported BUG at
fs/gfs2/trans.c:321.

Fix this by skipping revoke addition after gfs2_ail_error(). Also avoid
asserting gl_ail_count==0 once the filesystem is withdrawn, because
buffers skipped for revoke can legitimately remain on the AIL list.

Reported-by: syzbot+b17a83b050e9617376f0@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=b17a83b050e9617376f0
Cc: Andreas Gruenbacher <agruenba@xxxxxxxxxx>
Cc: gfs2@xxxxxxxxxxxxxxx
Signed-off-by: Zhan Jun <zhanjun@xxxxxxxxxxxxx>
---
fs/gfs2/glops.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index ba61649368bf..70c998b80e86 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -74,11 +74,13 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
if (fsync)
continue;
gfs2_ail_error(gl, bh);
+ continue;
}
gfs2_trans_add_revoke(sdp, bd);
nr_revokes--;
}
- GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
+ GLOCK_BUG_ON(gl, !fsync && !gfs2_withdrawn(sdp) &&
+ atomic_read(&gl->gl_ail_count));
spin_unlock(&sdp->sd_ail_lock);
gfs2_log_unlock(sdp);
}
--
2.50.1