summaryrefslogtreecommitdiffstats
path: root/fs/xfs/scrub/parent.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2023-12-15 19:03:37 +0100
committerDarrick J. Wong <djwong@kernel.org>2023-12-15 19:03:37 +0100
commit6c7289528d3c91855d78c56bb35fa360ed9a40bd (patch)
tree93edc842db6462f2a98ec8c0b72d4d55284373ea /fs/xfs/scrub/parent.c
parentxfs: zap broken inode forks (diff)
downloadlinux-6c7289528d3c91855d78c56bb35fa360ed9a40bd.tar.xz
linux-6c7289528d3c91855d78c56bb35fa360ed9a40bd.zip
xfs: abort directory parent scrub scans if we encounter a zapped directory
In a previous patch, we added some code to perform sufficient repairs to an ondisk inode record such that the inode cache would be willing to load the inode. If the broken inode was a shortform directory, it will reset the directory to something plausible, which is to say an empty subdirectory of the root. The telltale signs that something is seriously wrong is the broken link count. Such directories look clean, but they shouldn't participate in a filesystem scan to find or confirm a directory parent pointer. Create a predicate that identifies such directories and abort the scrub. Found by fuzzing xfs/1554 with multithreaded xfs_scrub enabled and u3.bmx[0].startblock = zeroes. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/scrub/parent.c')
-rw-r--r--fs/xfs/scrub/parent.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
index e6155d86f791..7db873672146 100644
--- a/fs/xfs/scrub/parent.c
+++ b/fs/xfs/scrub/parent.c
@@ -156,6 +156,16 @@ xchk_parent_validate(
goto out_rele;
}
+ /*
+ * We cannot yet validate this parent pointer if the directory looks as
+ * though it has been zapped by the inode record repair code.
+ */
+ if (xchk_dir_looks_zapped(dp)) {
+ error = -EBUSY;
+ xchk_set_incomplete(sc);
+ goto out_unlock;
+ }
+
/* Look for a directory entry in the parent pointing to the child. */
error = xchk_dir_walk(sc, dp, xchk_parent_actor, &spc);
if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
@@ -217,6 +227,13 @@ xchk_parent(
*/
error = xchk_parent_validate(sc, parent_ino);
} while (error == -EAGAIN);
+ if (error == -EBUSY) {
+ /*
+ * We could not scan a directory, so we marked the check
+ * incomplete. No further error return is necessary.
+ */
+ return 0;
+ }
return error;
}