[PATCH] minix: don't re-dirty the superblock buffer after a write failure

From: Nguyen Ngoc Thang

Date: Mon Oct 12 2026 - 12:46:34 EST


minix keeps the superblock buffer head (sbi->s_sbh) pinned for the
lifetime of the mount and modifies it in place. If a write to the
backing device fails, end_buffer_write_sync() clears BH_Uptodate on
that buffer. minix_put_super() and minix_reconfigure() then call
mark_buffer_dirty() on it unconditionally and trip:

WARNING: fs/buffer.c:991 at mark_buffer_dirty+0x299/0x410
!buffer_uptodate(bh)
Call Trace:
minix_put_super+0x16d/0x460 fs/minix/inode.c:70
generic_shutdown_super+0x13d/0x2d0 fs/super.c:751
kill_block_super+0x44/0xa0 fs/super.c:1903
deactivate_locked_super+0xbe/0x110 fs/super.c:586
cleanup_mnt+0x204/0x2a0 fs/namespace.c:1392

Reproduced by mounting a minix image on a loop device, making all
writes to it fail with fail_make_request, and unmounting.

Skip the s_state update and the dirtying in minix_put_super() when the
buffer is no longer uptodate, and fail a state-changing remount with
-EIO, the same way hfs handles its MDB buffers.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: syzbot+bffc332f376fdab5cef0@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=bffc332f376fdab5cef0
Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@xxxxxxxxx>
---
fs/minix/inode.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index daf83e4ff25c..5c0ad33b85e0 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -64,7 +64,8 @@ static void minix_put_super(struct super_block *sb)
int i;
struct minix_sb_info *sbi = minix_sb(sb);

- if (!sb_rdonly(sb)) {
+ /* a failed write clears uptodate; don't re-dirty the stale buffer */
+ if (!sb_rdonly(sb) && buffer_uptodate(sbi->s_sbh)) {
if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
sbi->s_ms->s_state = sbi->s_mount_state;
mark_buffer_dirty(sbi->s_sbh);
@@ -146,6 +147,8 @@ static int minix_reconfigure(struct fs_context *fc)
ms = sbi->s_ms;
if ((bool)(fc->sb_flags & SB_RDONLY) == sb_rdonly(sb))
return 0;
+ if (!buffer_uptodate(sbi->s_sbh))
+ return -EIO;
if (fc->sb_flags & SB_RDONLY) {
if (ms->s_state & MINIX_VALID_FS ||
!(sbi->s_mount_state & MINIX_VALID_FS))
--
2.43.0