summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-07-14 11:05:49 -0700
committerDarrick J. Wong <djwong@kernel.org>2022-10-14 14:16:31 -0700
commit47fb57ea54df3f219aaa4abc08ff0ec70fbd74eb (patch)
tree70b8830fc48ba63994f298b98eaf42b04ced7af3 /fs
parente4544093f3db5c429684fe09e3ff39e520d89462 (diff)
xfs: alert the user about data/attr fork mappings that could be merged
If the data or attr forks have mappings that could be merged, let the user know that the structure could be optimized. This isn't a filesystem corruption since the regular filesystem does not try to be smart about merging bmbt records. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/scrub/bmap.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index aaa73a2bdd17..0f5d7fb61ca1 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -390,6 +390,29 @@ xchk_bmap_dirattr_extent(
xchk_fblock_set_corrupt(info->sc, info->whichfork, off);
}
+/* Are these two mappings mergeable? */
+static inline bool
+xchk_bmap_mergeable(
+ struct xchk_bmap_info *info,
+ const struct xfs_bmbt_irec *b2)
+{
+ const struct xfs_bmbt_irec *b1 = &info->prev_rec;
+
+ /* Skip uninitialized prev_rec and COW fork extents */
+ if (b1->br_blockcount == 0)
+ return false;
+ if (info->whichfork == XFS_COW_FORK)
+ return false;
+
+ if (b1->br_startoff + b1->br_blockcount != b2->br_startoff)
+ return false;
+ if (b1->br_startblock + b1->br_blockcount != b2->br_startblock)
+ return false;
+ if (b1->br_blockcount + b2->br_blockcount > BMBT_BLOCKCOUNT_MASK)
+ return false;
+ return b1->br_state == b2->br_state;
+}
+
/* Scrub a single extent record. */
STATIC void
xchk_bmap_iextent(
@@ -441,6 +464,10 @@ xchk_bmap_iextent(
if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
return;
+ /* Notify the user of mergeable records in the data/attr forks. */
+ if (xchk_bmap_mergeable(info, irec))
+ xchk_ino_set_preen(info->sc, info->sc->ip->i_ino);
+
if (info->is_rt)
xchk_bmap_rt_iextent_xref(ip, info, irec);
else