From: Javier Tia <javier@peridio.com>
To: Carlos Maiolino <cem@kernel.org>
Cc: "Darrick J . Wong" <djwong@kernel.org>,
Dave Chinner <dchinner@redhat.com>,
Allison Henderson <allison.henderson@oracle.com>,
Andrey Albershteyn <aalbersh@kernel.org>,
linux-xfs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 3/5] xfs: report the error that made deferred work shut down the fs
Date: Sat, 8 Aug 2026 17:40:20 -0600 [thread overview]
Message-ID: <20260808234016.246054-10-floss@jetm.me> (raw)
In-Reply-To: <20260808234016.246054-7-floss@jetm.me>
When xfs_defer_finish_one() fails with anything other than -EAGAIN,
xfs_defer_finish_noroll() shuts the filesystem down from a generic
out_shutdown: label. SHUTDOWN_CORRUPT_INCORE makes that surface as
"Corruption of in-memory data (0x8) detected at
xfs_defer_finish_noroll+0x29a/0x4b0 (fs/xfs/libxfs/xfs_defer.c:721)",
naming neither the errno nor the deferred op that produced it. Any
error from any deferred work item lands on that one line, so the report
is equally consistent with a transient -ENOSPC, an -EIO on a metadata
buffer, or genuine in-core corruption, and there is no way to tell
which from the log.
trace_xfs_defer_finish_error() records the errno, but it is called
after xfs_force_shutdown(). With fs.xfs.panic_mask carrying
XFS_PTAG_SHUTDOWN_CORRUPT (16), the first shutdown reaches
_xfs_alert_tag(), which BUGs, so the tracepoint does not fire for it.
Later racers do reach it, because xfs_do_force_shutdown() returns early
once xfs_set_shutdown() has fired, but by then the errno belongs to a
secondary failure. The informative one is lost, and that is the
configuration used to capture a crash dump: recovering the errno from a
vmcore means an ORC unwind of the xfs_defer_finish_noroll frame to read
the callee-saved %rbp that happens to still hold the value.
Move the tracepoint ahead of xfs_force_shutdown() so it is reachable
for the first failure, and report the same information through the log,
because the systems that hit this do not have tracing armed in advance.
Report t_blk_res as well as the errno: how much of the reservation is
left separates a transaction that ran out of blocks from one that never
came close, which is the difference between suspecting whichever
xfs_*_space_res() fed it and moving the search to the allocator or to
the buffer that returned the error. It cannot say more than that,
since xfs_trans_dup() hands each rolled transaction the unused
remainder, so a small value is also what a correctly sized reservation
looks like several rolls in. t_blk_res_used is not worth printing
beside it: the new transaction starts at zero because xfs_trans_dup()
allocates it with kmem_cache_zalloc(), so it reads zero on the roll
paths and counts only the current segment on the others.
Take the op name in a local read before the call rather than from dfp
afterwards. dfp is freed once its work list drains, so the name has to
be captured while the item is known live, and it has to outlive the
item to be available at out_shutdown for the paths that do not come
from xfs_defer_finish_one() at all. dfp_ops points into a static const
table, so the string itself outlives everything.
Clear the attribution once an item finishes. Three of the four paths to
out_shutdown - the create_intents failure and both trans_roll failures -
are reached at the top of a later loop iteration, before any item has
been picked, so a name left over from an item that already succeeded
would blame it for a log commit that failed afterwards. That is worse
than the generic message this replaces, because it invents a lead where
there was none. An -EAGAIN item keeps its name, since the roll that
follows is part of completing it.
Skip the alert once the filesystem is already down. Only the first
failure is informative; everything after it is a consequence, and
xfs_do_force_shutdown() suppresses its own message for exactly that
reason. Testing xfs_is_shutdown() rather than rate-limiting keeps the
first report unconditionally and drops the ones that follow, instead of
a token bucket that could spend itself on another mount's failures and
discard the one that mattered.
Signed-off-by: Javier Tia <floss@jetm.me>
---
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..bbf2f4ca3c2e 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 = "deferred";
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 = "deferred";
}
/* 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,
+ "%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
next prev parent reply other threads:[~2026-08-08 23:40 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-08 23:40 [PATCH 0/5] xfs: fix filesystem shutdown from parent pointer reservation underflow Javier Tia
2026-08-08 23:40 ` [PATCH 1/5] xfs: initialise error in xfs_defer_finish_one() Javier Tia
2026-08-09 18:48 ` Darrick J. Wong
2026-08-08 23:40 ` [PATCH 2/5] xfs: give the deferred barrier op type a name Javier Tia
2026-08-09 18:49 ` Darrick J. Wong
2026-08-08 23:40 ` Javier Tia [this message]
2026-08-08 23:40 ` [PATCH 4/5] xfs: correct the parent pointer space reservation comment Javier Tia
2026-08-09 18:55 ` Darrick J. Wong
2026-08-08 23:40 ` [PATCH 5/5] xfs: initialise args->total for parent pointer updates Javier Tia
2026-08-09 19:02 ` Darrick J. Wong
2026-08-10 16:43 ` [PATCH v2 0/6] xfs: fix filesystem shutdown from parent pointer reservation underflow Javier Tia
2026-08-10 16:43 ` [PATCH v2 1/6] xfs: initialise error in xfs_defer_finish_one() Javier Tia
2026-08-10 16:43 ` [PATCH v2 2/6] xfs: give the deferred barrier op type a name Javier Tia
2026-08-10 16:43 ` [PATCH v2 3/6] xfs: report the error that made deferred work shut down the fs Javier Tia
2026-08-10 18:47 ` Darrick J. Wong
2026-08-10 16:43 ` [PATCH v2 4/6] xfs: correct the parent pointer space reservation comment Javier Tia
2026-08-10 16:43 ` [PATCH v2 5/6] xfs: initialise args->total for parent pointer updates Javier Tia
2026-08-10 18:08 ` Darrick J. Wong
2026-08-10 18:39 ` Javier Tia
2026-08-10 18:47 ` Darrick J. Wong
2026-08-10 16:43 ` [PATCH v2 6/6] xfs: assert the reservation covers each da fork growth Javier Tia
2026-08-10 18:07 ` Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260808234016.246054-10-floss@jetm.me \
--to=javier@peridio.com \
--cc=aalbersh@kernel.org \
--cc=allison.henderson@oracle.com \
--cc=cem@kernel.org \
--cc=dchinner@redhat.com \
--cc=djwong@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.