diff options
author | Darrick J. Wong <djwong@kernel.org> | 2022-07-14 11:05:49 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2022-10-14 14:16:31 -0700 |
commit | 47fb57ea54df3f219aaa4abc08ff0ec70fbd74eb (patch) | |
tree | 70b8830fc48ba63994f298b98eaf42b04ced7af3 /fs | |
parent | e4544093f3db5c429684fe09e3ff39e520d89462 (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.c | 27 |
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 |