[RFC PATCH] xfs: Prevent umount from indefinitely waiting on XFS_IFLUSHING flag on stale inodes
From: Chandan Babu R <chandanbabu@kernel.org>
Date: 2024-09-02 07:51:00
Subsystem:
filesystems (vfs and infrastructure), the rest, xfs filesystem · Maintainers:
Alexander Viro, Christian Brauner, Linus Torvalds, Carlos Maiolino
Executing xfs/057 can lead to an unmount task to wait indefinitely for
XFS_IFLUSHING flag on some inodes to be cleared. The following timeline
describes as to how inodes can get into such a state.
Task A Task B Iclog endio processing
----------------------------------------------------------------------------
Inodes are freed
Inodes items are
added to the CIL
CIL contents are
written to iclog
iclog->ic_fail_crc
is set to true
iclog is submitted
for writing to the
disk
Last inode in the cluster
buffer is freed
XFS_[ISTALE/IFLUSHING] is
set on all inodes in the
cluster buffer
XFS_STALE is set on
the cluster buffer
iclog crc error is detected
... during endio processing
During xfs_trans_commit, Set XFS_LI_ABORTED on inode
log shutdown is detected items
XFS_LI_ABORTED is set xfs_inode_item_committed()
on xfs_buf_log_item - Unpin the inode since it
is stale and return -1
xfs_buf_log_item is freed
Inode log items are not
xfs_buf is not freed here processed further since
since b_hold has a xfs_inode_item_committed()
non-zero value returns -1
During normal operation, the stale inodes are processed by
xfs_buf_item_unpin() => xfs_buf_inode_iodone(). This ends up calling
xfs_iflush_abort() which in turn clears the XFS_IFLUSHING flag. However, in
the case of this bug, the xfs_buf_log_item is freed just before the high level
transaction is committed to the CIL.
To overcome this bug, this commit removes the check for log shutdown during
high level transaction commit operation. The log items in the high level
transaction will now be committed to the CIL despite the log being
shutdown. This will allow the CIL processing logic (i.e. xlog_cil_push_work())
to invoke xlog_cil_committed() as part of error handling. This will cause
xfs_buf log item to to be unpinned and the corresponding inodes to be aborted
and have their XFS_IFLUSHING flag cleared.
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
---
PS: I have tested this patch by executing xfs/057 in a loop for about 24 hours.
On a non-patched kernel, this issue gets recreated within 24 hours.
fs/xfs/xfs_trans.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index bdf3704dc301..b43436c8abaa 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c@@ -868,17 +868,6 @@ __xfs_trans_commit( if (!(tp->t_flags & XFS_TRANS_DIRTY)) goto out_unreserve; - /* - * We must check against log shutdown here because we cannot abort log - * items and leave them dirty, inconsistent and unpinned in memory while - * the log is active. This leaves them open to being written back to - * disk, and that will lead to on-disk corruption. - */ - if (xlog_is_shutdown(log)) { - error = -EIO; - goto out_unreserve; - } - ASSERT(tp->t_ticket != NULL); /*
--
2.43.0