Skip to content

Commit 1e59fdb

Browse files
author
Darrick J. Wong
committed
xfs: don't call xchk_bmap_check_rmaps for btree-format file forks
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>
1 parent e8882f6 commit 1e59fdb

1 file changed

Lines changed: 14 additions & 16 deletions

File tree

fs/xfs/scrub/bmap.c

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,6 @@ xchk_bmap_want_check_rmaps(
645645
{
646646
struct xfs_scrub *sc = info->sc;
647647
struct xfs_ifork *ifp;
648-
bool zero_size;
649648

650649
if (!xfs_has_rmapbt(sc->mp))
651650
return false;
@@ -659,24 +658,23 @@ xchk_bmap_want_check_rmaps(
659658
return false;
660659

661660
/*
662-
* Only do this for complex maps that are in btree format, or for
663-
* situations where we would seem to have a size but zero extents.
664-
* The inode repair code can zap broken iforks, which means we have
665-
* to flag this bmap as corrupt if there are rmaps that need to be
666-
* reattached.
661+
* The inode repair code zaps broken inode forks by resetting them back
662+
* to EXTENTS format and zero extent records. If we encounter a fork
663+
* in this state along with evidence that the fork isn't supposed to be
664+
* empty, we need to scan the reverse mappings to decide if we're going
665+
* to rebuild the fork. Data forks with nonzero file size are scanned.
666+
* xattr forks are never empty of content, so they are always scanned.
667667
*/
668-
669-
if (info->whichfork == XFS_DATA_FORK)
670-
zero_size = i_size_read(VFS_I(sc->ip)) == 0;
671-
else
672-
zero_size = false;
673-
674668
ifp = xfs_ifork_ptr(sc->ip, info->whichfork);
675-
if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
676-
(zero_size || ifp->if_nextents > 0))
677-
return false;
669+
if (ifp->if_format == XFS_DINODE_FMT_EXTENTS && ifp->if_nextents == 0) {
670+
if (info->whichfork == XFS_DATA_FORK &&
671+
i_size_read(VFS_I(sc->ip)) == 0)
672+
return false;
678673

679-
return true;
674+
return true;
675+
}
676+
677+
return false;
680678
}
681679

682680
/* Make sure each rmap has a corresponding bmbt entry. */

0 commit comments

Comments
 (0)