diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:17:57 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-10-22 16:41:03 -0700 |
commit | 5d4e0c5137a0687ecec89b60227734c6cb478c4c (patch) | |
tree | 34252e9df1d7a2f372bdd3ddd422e1a5deaa3efd | |
parent | 3e5217524b1bebb753de88d848fbbdc523d6307c (diff) |
xfs: cross-reference the realtime rmapbt
Teach the data fork and realtime bitmap scrubbers to cross-reference
information with the realtime rmap btree.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r-- | fs/xfs/scrub/bmap.c | 33 | ||||
-rw-r--r-- | fs/xfs/scrub/rtbitmap.c | 19 | ||||
-rw-r--r-- | fs/xfs/scrub/rtrmap.c | 20 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.h | 3 |
4 files changed, 62 insertions, 13 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index 8b7c55550b26..7412d3661fdf 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -123,15 +123,22 @@ static inline bool xchk_bmap_get_rmap( struct xchk_bmap_info *info, struct xfs_bmbt_irec *irec, - xfs_agblock_t agbno, + xfs_fsblock_t bno, uint64_t owner, struct xfs_rmap_irec *rmap) { + struct xfs_btree_cur **curp = &info->sc->sa.rmap_cur; xfs_fileoff_t offset; unsigned int rflags = 0; int has_rmap; int error; + if (xfs_ifork_is_realtime(info->sc->ip, info->whichfork)) + curp = &info->sc->sr.rmap_cur; + + if (*curp == NULL) + return false; + if (info->whichfork == XFS_ATTR_FORK) rflags |= XFS_RMAP_ATTR_FORK; if (irec->br_state == XFS_EXT_UNWRITTEN) @@ -152,13 +159,13 @@ xchk_bmap_get_rmap( * range rmap lookup to make sure we get the correct owner/offset. */ if (info->is_shared) { - error = xfs_rmap_lookup_le_range(info->sc->sa.rmap_cur, agbno, - owner, offset, rflags, rmap, &has_rmap); + error = xfs_rmap_lookup_le_range(*curp, bno, owner, offset, + rflags, rmap, &has_rmap); } else { - error = xfs_rmap_lookup_le(info->sc->sa.rmap_cur, agbno, - owner, offset, rflags, rmap, &has_rmap); + error = xfs_rmap_lookup_le(*curp, bno, owner, offset, + rflags, rmap, &has_rmap); } - if (!xchk_should_check_xref(info->sc, &error, &info->sc->sa.rmap_cur)) + if (!xchk_should_check_xref(info->sc, &error, curp)) return false; if (!has_rmap) @@ -214,13 +221,13 @@ STATIC void xchk_bmap_xref_rmap( struct xchk_bmap_info *info, struct xfs_bmbt_irec *irec, - xfs_agblock_t agbno) + xfs_fsblock_t bno) { struct xfs_rmap_irec rmap; unsigned long long rmap_end; uint64_t owner; - if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm)) + if (xchk_skip_xref(info->sc->sm)) return; if (info->whichfork == XFS_COW_FORK) @@ -229,13 +236,12 @@ xchk_bmap_xref_rmap( owner = info->sc->ip->i_ino; /* Find the rmap record for this irec. */ - if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap)) + if (!xchk_bmap_get_rmap(info, irec, bno, owner, &rmap)) return; /* Check the rmap. */ rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount; - if (rmap.rm_startblock > agbno || - agbno + irec->br_blockcount > rmap_end) + if (rmap.rm_startblock > bno || bno + irec->br_blockcount > rmap_end) xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, irec->br_startoff); @@ -284,7 +290,7 @@ xchk_bmap_xref_rmap( * Skip this for CoW fork extents because the refcount btree (and not * the inode) is the ondisk owner for those extents. */ - if (info->whichfork != XFS_COW_FORK && rmap.rm_startblock < agbno && + if (info->whichfork != XFS_COW_FORK && rmap.rm_startblock < bno && !xchk_bmap_has_prev(info, irec)) { xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, irec->br_startoff); @@ -299,7 +305,7 @@ xchk_bmap_xref_rmap( */ rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount; if (info->whichfork != XFS_COW_FORK && - rmap_end > agbno + irec->br_blockcount && + rmap_end > bno + irec->br_blockcount && !xchk_bmap_has_next(info, irec)) { xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, irec->br_startoff); @@ -318,6 +324,7 @@ xchk_bmap_rt_iextent_xref( xchk_xref_is_used_rt_space(info->sc, irec->br_startblock, irec->br_blockcount); + xchk_bmap_xref_rmap(info, irec, irec->br_startblock); xchk_rt_btcur_free(&info->sc->sr); xchk_rt_unlock(info->sc, &info->sc->sr); diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c index 1ff6014f0d3b..b7a5d0cffb0f 100644 --- a/fs/xfs/scrub/rtbitmap.c +++ b/fs/xfs/scrub/rtbitmap.c @@ -9,13 +9,17 @@ #include "xfs_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_btree.h" #include "xfs_log_format.h" #include "xfs_trans.h" #include "xfs_rtalloc.h" #include "xfs_inode.h" #include "xfs_bmap.h" +#include "xfs_rmap.h" +#include "xfs_rtrmap_btree.h" #include "scrub/scrub.h" #include "scrub/common.h" +#include "scrub/btree.h" /* Set us up with the realtime metadata locked. */ int @@ -38,6 +42,19 @@ xchk_setup_rtbitmap( /* Realtime bitmap. */ +/* Cross-reference rtbitmap entries with other metadata. */ +STATIC void +xchk_rtbitmap_xref( + struct xfs_scrub *sc, + xfs_rtblock_t startblock, + xfs_rtblock_t blockcount) +{ + if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) + return; + + xchk_xref_has_no_rt_owner(sc, startblock, blockcount); +} + /* Scrub a free extent record from the realtime bitmap. */ STATIC int xchk_rtbitmap_rec( @@ -54,6 +71,8 @@ xchk_rtbitmap_rec( if (!xfs_verify_rtext(sc->mp, startblock, blockcount)) xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0); + + xchk_rtbitmap_xref(sc, startblock, blockcount); return 0; } diff --git a/fs/xfs/scrub/rtrmap.c b/fs/xfs/scrub/rtrmap.c index 4e7b2204490a..f003ae48b3f7 100644 --- a/fs/xfs/scrub/rtrmap.c +++ b/fs/xfs/scrub/rtrmap.c @@ -112,3 +112,23 @@ xchk_rtrmapbt( return xchk_btree(sc, sc->sr.rmap_cur, xchk_rtrmapbt_rec, &oinfo, NULL); } + +/* xref check that the extent has no realtime reverse mapping at all */ +void +xchk_xref_has_no_rt_owner( + struct xfs_scrub *sc, + xfs_rtblock_t bno, + xfs_filblks_t len) +{ + bool has_rmap; + int error; + + if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm)) + return; + + error = xfs_rmap_has_record(sc->sr.rmap_cur, bno, len, &has_rmap); + if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur)) + return; + if (has_rmap) + xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); +} diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index b00891f2ac89..adb21176377d 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -215,8 +215,11 @@ void xchk_xref_is_not_shared(struct xfs_scrub *sc, xfs_agblock_t bno, #ifdef CONFIG_XFS_RT void xchk_xref_is_used_rt_space(struct xfs_scrub *sc, xfs_rtblock_t rtbno, xfs_extlen_t len); +void xchk_xref_has_no_rt_owner(struct xfs_scrub *sc, xfs_rtblock_t rtbno, + xfs_filblks_t len); #else # define xchk_xref_is_used_rt_space(sc, rtbno, len) do { } while (0) +# define xchk_xref_has_no_rt_owner(sc, rtbno, len) do { } while (0) #endif struct xchk_fscounters { |