[PATCH v3 3/6] xfs: report the error that made deferred work shut down the fs
From: Javier Tia
Date: Mon Aug 10 2026 - 19:08:26 EST
When a deferred operation fails and shuts the filesystem down,
xfs_defer_finish_noroll() reports neither the errno nor which operation
originated it, so the log cannot tell a transient -ENOSPC from real
corruption. Report the operation type, errno and remaining reservation.
trace_xfs_defer_finish_error() runs after xfs_force_shutdown(), which
BUGs under fs.xfs.panic_mask and so never fires for the first failure;
move it ahead of the shutdown and mirror it to xfs_alert() for systems
without tracing armed. Capture the op name while the item is live (dfp
is freed once its work list drains) and suppress the alert once the fs is
already down.
Signed-off-by: Javier Tia <floss@xxxxxxx>
---
fs/xfs/libxfs/xfs_defer.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 75f0d37914d5..3152acdc335d 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -656,6 +656,7 @@ xfs_defer_finish_noroll(
struct xfs_trans **tp)
{
struct xfs_defer_pending *dfp = NULL;
+ const char *what = "chain";
int error = 0;
LIST_HEAD(dop_pending);
LIST_HEAD(dop_paused);
@@ -705,9 +706,17 @@ xfs_defer_finish_noroll(
struct xfs_defer_pending, dfp_list);
if (!dfp)
break;
+ what = dfp->dfp_ops->name;
error = xfs_defer_finish_one(*tp, dfp);
if (error && error != -EAGAIN)
goto out_shutdown;
+ /*
+ * A finished item is no longer a candidate for a later
+ * failure. An -EAGAIN one is not finished, so it keeps the
+ * attribution across the roll that completes it.
+ */
+ if (!error)
+ what = "chain";
}
/* Requeue the paused items in the outgoing transaction. */
@@ -719,8 +728,12 @@ xfs_defer_finish_noroll(
out_shutdown:
list_splice_tail_init(&dop_paused, &dop_pending);
xfs_defer_trans_abort(*tp, &dop_pending);
- xfs_force_shutdown((*tp)->t_mountp, SHUTDOWN_CORRUPT_INCORE);
trace_xfs_defer_finish_error(*tp, error);
+ if (!xfs_is_shutdown((*tp)->t_mountp))
+ xfs_alert((*tp)->t_mountp,
+ "deferred %s work failed, error %d, %u blocks reserved",
+ what, error, (*tp)->t_blk_res);
+ xfs_force_shutdown((*tp)->t_mountp, SHUTDOWN_CORRUPT_INCORE);
xfs_defer_cancel_list((*tp)->t_mountp, &dop_pending);
xfs_defer_cancel(*tp);
return error;
--
Javier Tia