summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2023-04-11 19:00:26 -0700
committerDarrick J. Wong <djwong@kernel.org>2023-04-11 19:00:26 -0700
commit1e59fdb7d6157ff685a250e0873a015a2b16a4f2 (patch)
tree551c11e030cb8d29a8a07f4b1aa6cf34ba9c7f59
parente8882f69b941b20704ea509ebfca2d8a123ad6e3 (diff)
xfs: don't call xchk_bmap_check_rmaps for btree-format file forksscrub-merge-bmap-records-6.4_2023-04-12scrub-merge-bmap-records-6.4_2023-04-11
The logic at the end of xchk_bmap_want_check_rmaps tries to detect a file fork that has been zapped by what will become the online inode repair code. Zapped forks are in FMT_EXTENTS with zero extents, and some sort of hint that there's supposed to be data somewhere in the filesystem. Unfortunately, the inverted logic here is confusing and has the effect that we always call xchk_bmap_check_rmaps for FMT_BTREE forks. This is horribly inefficient and unnecessary, so invert the logic to get rid of this performance problem. This has caused 8h delays in generic/333 and generic/334. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com>
-rw-r--r--fs/xfs/scrub/bmap.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 64ed5b6585d5..87ab9f95a487 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -645,7 +645,6 @@ xchk_bmap_want_check_rmaps(
{
struct xfs_scrub *sc = info->sc;
struct xfs_ifork *ifp;
- bool zero_size;
if (!xfs_has_rmapbt(sc->mp))
return false;
@@ -659,24 +658,23 @@ xchk_bmap_want_check_rmaps(
return false;
/*
- * Only do this for complex maps that are in btree format, or for
- * situations where we would seem to have a size but zero extents.
- * The inode repair code can zap broken iforks, which means we have
- * to flag this bmap as corrupt if there are rmaps that need to be
- * reattached.
+ * The inode repair code zaps broken inode forks by resetting them back
+ * to EXTENTS format and zero extent records. If we encounter a fork
+ * in this state along with evidence that the fork isn't supposed to be
+ * empty, we need to scan the reverse mappings to decide if we're going
+ * to rebuild the fork. Data forks with nonzero file size are scanned.
+ * xattr forks are never empty of content, so they are always scanned.
*/
-
- if (info->whichfork == XFS_DATA_FORK)
- zero_size = i_size_read(VFS_I(sc->ip)) == 0;
- else
- zero_size = false;
-
ifp = xfs_ifork_ptr(sc->ip, info->whichfork);
- if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
- (zero_size || ifp->if_nextents > 0))
- return false;
+ if (ifp->if_format == XFS_DINODE_FMT_EXTENTS && ifp->if_nextents == 0) {
+ if (info->whichfork == XFS_DATA_FORK &&
+ i_size_read(VFS_I(sc->ip)) == 0)
+ return false;
- return true;
+ return true;
+ }
+
+ return false;
}
/* Make sure each rmap has a corresponding bmbt entry. */