[PATCH] xfs: fix dead loop when do mount with IO fault injection
From: Ye Bin
Date: Thu Oct 10 2024 - 05:24:12 EST
From: Ye Bin <yebin10@xxxxxxxxxx>
When do IO fault injection, mount maybe hung:
blk_update_request: I/O error, dev dm-4, sector 2128216 op 0x0:(READ)
flags 0x1000 phys_seg 1 prio class 0
XFS (dm-4): metadata I/O error in "xfs_btree_read_buf_block.constprop.
0+0x190/0x200 [xfs]" at daddr 0x207958 len 8 error 5
blk_update_request: I/O error, dev dm-4, sector 2108042 op 0x1:(WRITE)
flags 0x29800 phys_seg 1 prio class 0
XFS (dm-4): log I/O error -5
XFS (dm-4): Metadata I/O Error (0x1) detected at xfs_trans_read_buf_map
+0x2b6/0x510 [xfs] (fs/xfs/xfs_trans_buf.c:296). Shutting down filesystem.
sd 6:0:0:3: [sdh] Synchronizing SCSI cache
XFS (dm-4): Please unmount the filesystem and rectify the problem(s)
XFS (dm-4): Failed to recover intents
XFS (dm-4): Ending recovery (logdev: internal)
xfs_buftarg_drain+0x53a/0x740
xfs_log_mount_finish+0x2be/0x550
xfs_mountfs+0x16ba/0x2220
xfs_fs_fill_super+0x1376/0x1f10
get_tree_bdev+0x44a/0x770
vfs_get_tree+0x8d/0x350
path_mount+0x1228/0x1cc0
do_mount+0xf7/0x110
__x64_sys_mount+0x193/0x230
do_syscall_64+0x39/0xb0
entry_SYSCALL_64_after_hwframe+0x63/0xcd
Above issue hapnens as xfs_buf log item is in AIL list, but xlog is already
shutdown, so xfs_log_worker() will not wakeup xfsaild to submit AIL list.
Then the last 'b_hold' will no chance to be decreased. Then
xfs_buftarg_drain() will dead loop to free xfs_buf.
To solve above issue there is need to push AIL list before call
xfs_buftarg_drain(). As xfs_log_mount_finish() return error, xfs_mountfs()
will call xfs_log_mount_cancel() to clean AIL list, and call
xfs_buftarg_drain() to make sure all xfs_buf has been reclaimed. So what we
need to do is call xfs_wait_buftarg() when 'error == 0' in
xfs_log_mount_finish().
Signed-off-by: Ye Bin <yebin10@xxxxxxxxxx>
---
fs/xfs/xfs_log.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 817ea7e0a8ab..b91892733b78 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -765,7 +765,9 @@ xfs_log_mount_finish(
} else {
xfs_info(mp, "Ending clean mount");
}
- xfs_buftarg_drain(mp->m_ddev_targp);
+
+ if (!error)
+ xfs_buftarg_drain(mp->m_ddev_targp);
clear_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate);
--
2.31.1