From bde0010631a207511308dc8407f34595dac13ad5 Mon Sep 17 00:00:00 2001 From: Ravi Singh Date: Wed, 21 Oct 2026 08:33:29 +0200 Subject: [PATCH] xfs: mark i_mode=0 and shut down on attr fork inactivation failure xfs_attr_inactive() can fail on an I/O error reading the attribute fork's btree blocks, for example from fault injection such as the dm-flakey errors used by xfstests generic/475. On failure, xfs_ifork_zap_attr() zeros af_nextents without freeing the attribute blocks or decrementing i_nblocks, leaving the inode in an inconsistent in-memory state. The inode is marked XFS_IRECLAIMABLE and remains in the cache. If a concurrent operation (e.g., XFS_IOC_FSBULKSTAT) calls xfs_iget() on this inode, xfs_iget_check_free_state() will allow recycling if i_mode != 0. The recycled inode reuses the stale in-memory state (af_nextents=0, i_nblocks=1). When the recycled inode is queued for inactivation again, xfs_attr_inactive() sees af_nextents=0 and skips truncation, leaving i_nblocks non-zero. This triggers the assertion in xfs_ifree(): XFS: Assertion failed: ip->i_nblocks == 0 Clear i_mode so the stale inode cannot be recycled, and force a shutdown so log recovery frees the still-unlinked inode on the next mount. Suggested-by: Dave Chinner Signed-off-by: Ravi Singh Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_inode.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 05a14da28031..fceedb699bcf 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1481,8 +1481,17 @@ xfs_inactive( */ if (xfs_inode_has_attr_fork(ip)) { error = xfs_attr_inactive(ip); - if (error) + if (error) { + /* + * Attr teardown failed, leaking blocks with no in-core + * record. Clear i_mode to block xfs_iget() recycling, + * then shut down so recovery cleans up the inode. + */ + VFS_I(ip)->i_mode = 0; + if (!xfs_is_shutdown(mp)) + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); goto out; + } } ASSERT(ip->i_forkoff == 0);