* [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount
@ 2026-06-10 19:19 Mikhail Lobanov
2026-06-10 19:19 ` [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount Mikhail Lobanov
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Mikhail Lobanov @ 2026-06-10 19:19 UTC (permalink / raw)
To: cem
Cc: m.lobanov, djwong, david, hch, hch, linux-xfs, linux-kernel, lvc-project
XFS already declines to inactivate inodes on a shut down mount, but only
at queue time: xfs_inode_mark_reclaimable() calls
xfs_inode_needs_inactive(), which returns false when the mount is shut
down ("If the log isn't running, push inodes straight to reclaim"), and
then drops the dquots and marks the inode reclaimable directly.
An inode that was queued for background inactivation while the mount was
still live is not covered by that check: the inodegc worker still calls
xfs_inactive() on it even after the mount has been shut down in the
meantime. Inactivation modifies persistent metadata and runs
transactions that cannot complete on a shut down mount, and it relies on
subsystems (e.g. quota) that a torn down, or never fully set up, mount
may not have available.
Honour the same invariant in xfs_inactive() itself: if the mount is shut
down, return early before doing any inactivation work. The dquots
attached to the inode are released by the existing xfs_qm_dqdetach() at
the out: label, so references are not leaked, and the caller then makes
the inode reclaimable exactly as before.
On its own this is a consistency fix with the existing queue-time
behaviour; it is also a prerequisite for shutting the mount down in the
xfs_mountfs() failure path in the following patch.
Fixes: ab23a7768739 ("xfs: per-cpu deferred inode inactivation queues")
Signed-off-by: Mikhail Lobanov <m.lobanov@rosa.ru>
---
v5: per Christoph's review of v4, move the shutdown check into
xfs_inactive() itself - an early "goto out" after initialising mp at
declaration - instead of guarding the call in
xfs_inodegc_inactivate(). The attached dquots are then released by
the existing xfs_qm_dqdetach() at the out: label, which also removes
the empty else branch that v4 had to brace to silence -Wempty-body
without CONFIG_XFS_QUOTA. Christoph's other comment - a potential
NULL deref in xfs_qm_dqdetach() when the quota subsystem is gone - is
discussed separately in-thread; I could not find a path that reaches
it in the current tree, so it is not folded into this series.
v4: brace both branches of the if/else. Without CONFIG_XFS_QUOTA
xfs_qm_dqdetach() expands to nothing, leaving the else with an empty
body, which trips -Wempty-body on a W=1 build (i386-allnoconfig,
reported by the kernel test robot).
v3: split out of the v2 single patch as a prep patch, and additionally
drop the attached dquots in the shutdown branch to avoid leaking
references when an inode queued while the mount was live is processed
after a (normal) shutdown - spotted in review of v2.
v2: https://lore.kernel.org/linux-xfs/aiKA7vVQ_RxT_YOr@infradead.org/T/#t
v1: https://lore.kernel.org/linux-xfs/ah6BIsvEitNW5Edb@infradead.org/
fs/xfs/xfs_inode.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index beaa26ec62da..658da1e5fd42 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1386,7 +1386,7 @@ int
xfs_inactive(
xfs_inode_t *ip)
{
- struct xfs_mount *mp;
+ struct xfs_mount *mp = ip->i_mount;
int error = 0;
int truncate = 0;
@@ -1399,7 +1399,20 @@ xfs_inactive(
goto out;
}
- mp = ip->i_mount;
+ /*
+ * If the filesystem has been shut down - for example a mount that
+ * failed after background inactivation was enabled - do not
+ * inactivate the inode. Inactivation modifies persistent metadata,
+ * its transactions cannot complete on a shut down mount, and the
+ * subsystems it relies on (e.g. quota, mp->m_quotainfo) may not be
+ * set up. The attached dquots are dropped at the out: label and the
+ * inode then goes straight to reclaim, the same way
+ * xfs_inode_needs_inactive() already declines to inactivate on a shut
+ * down mount at queue time.
+ */
+ if (xfs_is_shutdown(mp))
+ goto out;
+
ASSERT(!xfs_iflags_test(ip, XFS_IRECOVERY));
xfs_inactive_health(ip);
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount
2026-06-10 19:19 [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount Mikhail Lobanov
@ 2026-06-10 19:19 ` Mikhail Lobanov
2026-06-11 14:00 ` Christoph Hellwig
2026-06-13 8:13 ` Zhang Cen
2026-06-11 13:59 ` [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount Christoph Hellwig
2026-06-12 8:36 ` Carlos Maiolino
2 siblings, 2 replies; 8+ messages in thread
From: Mikhail Lobanov @ 2026-06-10 19:19 UTC (permalink / raw)
To: cem
Cc: m.lobanov, djwong, david, hch, hch, linux-xfs, linux-kernel, lvc-project
A corrupt/crafted XFS image can make mount fail after background inode
inactivation has already been enabled. xfs_mountfs() turns on inodegc
(xfs_inodegc_start()) right after log recovery, but the quota subsystem
(mp->m_quotainfo) is only allocated much later, in xfs_qm_newmount() /
xfs_qm_mount_quotas(). The quota accounting flags in mp->m_qflags are
parsed from the mount options before xfs_mountfs() even runs.
If the mount then aborts in between - e.g. xfs_rtmount_inodes() failing
with "failed to read RT inodes" - the unwind path flushes the inodegc
queue, which inactivates the inodes that are still queued, and
xfs_inactive() calls xfs_qm_dqattach(). That path trusts
XFS_IS_QUOTA_ON() (the flag is set) and dereferences the not yet
allocated mp->m_quotainfo:
XFS (loop0): failed to read RT inodes
Oops: general protection fault, probably for non-canonical address
0xdffffc000000002a: 0000 [#1] PREEMPT SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000150-0x0000000000000157]
Workqueue: xfs-inodegc/loop0 xfs_inodegc_worker
RIP: 0010:__mutex_lock+0xfe/0x930
Call Trace:
xfs_qm_dqget_cache_lookup+0x63/0x7f0
xfs_qm_dqget_inode+0x336/0x860
xfs_qm_dqattach_one+0x232/0x4e0
xfs_qm_dqattach_locked+0x2c6/0x470
xfs_qm_dqattach+0x46/0x70
xfs_inactive+0x988/0xe80
xfs_inodegc_worker+0x27c/0x730
The NULL m_quotainfo deref is only one symptom. The deeper problem is
that a failed mount should not be inactivating inodes at all: it must
not write to the (possibly corrupt, only partially set up) persistent
metadata of a filesystem we just refused to mount, and the subsystems
inactivation relies on may not be initialised.
Mark the filesystem shut down before flushing the inodegc queue in the
xfs_mountfs() failure path. With the preceding patch a shut down mount
no longer inactivates the queued inodes: xfs_inactive() returns early so
they are dropped straight to reclaim instead. They are still pulled down
so reclaim can free them (which is why the flush was added in commit
ab23a7768739 ("xfs: per-cpu deferred inode inactivation queues")), but
without touching the on-disk structures - matching that comment's own
"pull down all the state and flee" intent.
Use SHUTDOWN_META_IO_ERROR for the shutdown: it is the generic "cannot
safely touch metadata" reason already used elsewhere in this file and in
the xfs_ifree() failure path, and unlike SHUTDOWN_FORCE_UMOUNT it does
not log a misleading "User initiated shutdown received". A failed mount
is not necessarily on-disk corruption (it can be a transient I/O or
resource error), so SHUTDOWN_CORRUPT_ONDISK would not be accurate either.
Found by fuzzing XFS with syzkaller (corrupt image mount); reproduced and
verified under QEMU/KASAN.
Fixes: ab23a7768739 ("xfs: per-cpu deferred inode inactivation queues")
Signed-off-by: Mikhail Lobanov <m.lobanov@rosa.ru>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
v5: no change to this patch's diff; carry Christoph's Reviewed-by. v5 of
patch 1/2 moves the shutdown check into xfs_inactive(), so the body
here now refers to xfs_inactive() returning early rather than to
xfs_inodegc_inactivate().
v4: no change to this patch; resent as part of the series. v4 of patch
1/2 braces the if/else to silence a -Wempty-body W=1 warning.
v3: depend on the preceding "skip inode inactivation on a shut down
mount" prep patch instead of doing both changes in one patch; use
SHUTDOWN_META_IO_ERROR instead of SHUTDOWN_FORCE_UMOUNT (no
misleading "User initiated shutdown" message, no message special
casing); reflow the comment to stay within 80 columns.
v2: https://lore.kernel.org/linux-xfs/aiKA7vVQ_RxT_YOr@infradead.org/T/#t
v1: https://lore.kernel.org/linux-xfs/ah6BIsvEitNW5Edb@infradead.org/
fs/xfs/xfs_mount.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index b24195f570cd..37fb69165502 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1243,11 +1243,19 @@ xfs_mountfs(
xfs_irele(mp->m_metadirip);
/*
- * Inactivate all inodes that might still be in memory after a log
- * intent recovery failure so that reclaim can free them. Metadata
- * inodes and the root directory shouldn't need inactivation, but the
- * mount failed for some reason, so pull down all the state and flee.
+ * The mount has failed. Mark the filesystem shut down so that any
+ * inodes still queued for background inactivation are dropped
+ * straight to reclaim instead of being inactivated: a failed mount
+ * must not write to the (possibly corrupt, only partially set up)
+ * persistent metadata, and parts of the mount it would need - e.g.
+ * the quota subsystem (mp->m_quotainfo) - may never have been
+ * initialised.
+ *
+ * Flush the queue so that those inodes are pulled down and reclaim
+ * can free them; with the fs shut down xfs_inodegc_inactivate()
+ * turns each one reclaimable without touching the on-disk structures.
*/
+ xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
xfs_inodegc_flush(mp);
/*
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount
2026-06-10 19:19 [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount Mikhail Lobanov
2026-06-10 19:19 ` [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount Mikhail Lobanov
@ 2026-06-11 13:59 ` Christoph Hellwig
2026-06-12 8:36 ` Carlos Maiolino
2 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2026-06-11 13:59 UTC (permalink / raw)
To: Mikhail Lobanov
Cc: cem, djwong, david, hch, hch, linux-xfs, linux-kernel, lvc-project
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount
2026-06-10 19:19 ` [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount Mikhail Lobanov
@ 2026-06-11 14:00 ` Christoph Hellwig
2026-06-13 8:13 ` Zhang Cen
1 sibling, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2026-06-11 14:00 UTC (permalink / raw)
To: Mikhail Lobanov
Cc: cem, djwong, david, hch, hch, linux-xfs, linux-kernel, lvc-project
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount
2026-06-10 19:19 [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount Mikhail Lobanov
2026-06-10 19:19 ` [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount Mikhail Lobanov
2026-06-11 13:59 ` [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount Christoph Hellwig
@ 2026-06-12 8:36 ` Carlos Maiolino
2 siblings, 0 replies; 8+ messages in thread
From: Carlos Maiolino @ 2026-06-12 8:36 UTC (permalink / raw)
To: Mikhail Lobanov
Cc: djwong, david, hch, hch, linux-xfs, linux-kernel, lvc-project
On Wed, 10 Jun 2026 22:19:03 +0300, Mikhail Lobanov wrote:
> XFS already declines to inactivate inodes on a shut down mount, but only
> at queue time: xfs_inode_mark_reclaimable() calls
> xfs_inode_needs_inactive(), which returns false when the mount is shut
> down ("If the log isn't running, push inodes straight to reclaim"), and
> then drops the dquots and marks the inode reclaimable directly.
>
> An inode that was queued for background inactivation while the mount was
> still live is not covered by that check: the inodegc worker still calls
> xfs_inactive() on it even after the mount has been shut down in the
> meantime. Inactivation modifies persistent metadata and runs
> transactions that cannot complete on a shut down mount, and it relies on
> subsystems (e.g. quota) that a torn down, or never fully set up, mount
> may not have available.
>
> [...]
Applied to for-next, thanks!
[1/2] xfs: skip inode inactivation on a shut down mount
commit: 07e2939ddab876d68d661ebad6c4eedec98193b8
[2/2] xfs: shut down the filesystem on a failed mount
commit: 804826eac53cff44f88f42989fcc601c2612c0ed
Best regards,
--
Carlos Maiolino <cem@kernel.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount
2026-06-10 19:19 ` [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount Mikhail Lobanov
2026-06-11 14:00 ` Christoph Hellwig
@ 2026-06-13 8:13 ` Zhang Cen
2026-06-15 7:24 ` Carlos Maiolino
1 sibling, 1 reply; 8+ messages in thread
From: Zhang Cen @ 2026-06-13 8:13 UTC (permalink / raw)
To: Mikhail Lobanov
Cc: Carlos Maiolino, Darrick J . Wong, Dave Chinner,
Christoph Hellwig, Christoph Hellwig, linux-xfs, linux-kernel,
lvc-project, Zhang Cen
Hi Mikhail and Christoph,
Sorry for the delayed follow-up. I was tied up with other work recently and
did not get a chance to continue following up on this issue.
This series appears to address the same mount-failure inodegc/quota teardown
race that I reported earlier here:
https://lore.kernel.org/linux-xfs/20260528053554.3047829-1-rollkingzzc@gmail.com/
Could you please carry the following tags?
Reported-by: Zhang Cen <rollkingzzc@gmail.com>
Closes: https://lore.kernel.org/linux-xfs/20260528053554.3047829-1-rollkingzzc@gmail.com/
Thanks,
Zhang Cen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount
2026-06-13 8:13 ` Zhang Cen
@ 2026-06-15 7:24 ` Carlos Maiolino
2026-06-15 7:28 ` Cen Zhang
0 siblings, 1 reply; 8+ messages in thread
From: Carlos Maiolino @ 2026-06-15 7:24 UTC (permalink / raw)
To: Zhang Cen
Cc: Mikhail Lobanov, Darrick J . Wong, Dave Chinner,
Christoph Hellwig, Christoph Hellwig, linux-xfs, linux-kernel,
lvc-project
On Sat, Jun 13, 2026 at 04:13:22PM +0800, Zhang Cen wrote:
> Hi Mikhail and Christoph,
>
> Sorry for the delayed follow-up. I was tied up with other work recently and
> did not get a chance to continue following up on this issue.
>
> This series appears to address the same mount-failure inodegc/quota teardown
> race that I reported earlier here:
>
> https://lore.kernel.org/linux-xfs/20260528053554.3047829-1-rollkingzzc@gmail.com/
>
> Could you please carry the following tags?
>
> Reported-by: Zhang Cen <rollkingzzc@gmail.com>
> Closes: https://lore.kernel.org/linux-xfs/20260528053554.3047829-1-rollkingzzc@gmail.com/
Too late.
>
> Thanks,
> Zhang Cen
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount
2026-06-15 7:24 ` Carlos Maiolino
@ 2026-06-15 7:28 ` Cen Zhang
0 siblings, 0 replies; 8+ messages in thread
From: Cen Zhang @ 2026-06-15 7:28 UTC (permalink / raw)
To: Carlos Maiolino
Cc: Mikhail Lobanov, Darrick J . Wong, Dave Chinner,
Christoph Hellwig, Christoph Hellwig, linux-xfs, linux-kernel,
lvc-project
Hi Carlos,
> Too late.
Thanks for the reply. Understood.
Best regards,
Zhang Cen
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-06-15 7:28 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-10 19:19 [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount Mikhail Lobanov
2026-06-10 19:19 ` [PATCH v5 2/2] xfs: shut down the filesystem on a failed mount Mikhail Lobanov
2026-06-11 14:00 ` Christoph Hellwig
2026-06-13 8:13 ` Zhang Cen
2026-06-15 7:24 ` Carlos Maiolino
2026-06-15 7:28 ` Cen Zhang
2026-06-11 13:59 ` [PATCH v5 1/2] xfs: skip inode inactivation on a shut down mount Christoph Hellwig
2026-06-12 8:36 ` Carlos Maiolino
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®