mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
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 <dgc@kernel.org> Signed-off-by: Ravi Singh <ravising@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
parent
0344a9492e
commit
bde0010631
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user