summaryrefslogtreecommitdiff
path: root/fs/xfs/scrub
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:17:58 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-12-15 17:29:17 -0800
commitcb351ea02f1345892ffb86282ddf3341783ed695 (patch)
treeb7c38b756e17af2b81976b2bc855f8728efa7aa8 /fs/xfs/scrub
parentd6728f80177eeba6037bf2d9880a00aea8ca9c98 (diff)
xfs: scan rt rmap when we're doing an intense rmap check
Teach the bmbt scrubber how to perform a comprehensive check that the rmapbt does not contain /any/ mappings that are not described by bmbt records when it's dealing with a realtime file. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/scrub')
-rw-r--r--fs/xfs/scrub/bmap.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 558ab424a46b..84d50c207e10 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -19,6 +19,8 @@
#include "xfs_bmap_btree.h"
#include "xfs_rmap.h"
#include "xfs_rmap_btree.h"
+#include "xfs_rtalloc.h"
+#include "xfs_rtrmap_btree.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/btree.h"
@@ -597,12 +599,18 @@ xchk_bmap_check_rmap(
*/
check_rec = *rec;
while (have_map) {
+ xfs_fsblock_t startblock;
+
if (irec.br_startoff != check_rec.rm_offset)
xchk_fblock_set_corrupt(sc, sbcri->whichfork,
check_rec.rm_offset);
- if (irec.br_startblock != XFS_AGB_TO_FSB(sc->mp,
- cur->bc_ag.pag->pag_agno,
- check_rec.rm_startblock))
+ if (cur->bc_btnum == XFS_BTNUM_RMAP)
+ startblock = XFS_AGB_TO_FSB(sc->mp,
+ cur->bc_ag.pag->pag_agno,
+ check_rec.rm_startblock);
+ else
+ startblock = check_rec.rm_startblock;
+ if (irec.br_startblock != startblock)
xchk_fblock_set_corrupt(sc, sbcri->whichfork,
check_rec.rm_offset);
if (irec.br_blockcount > check_rec.rm_blockcount)
@@ -656,6 +664,29 @@ xchk_bmap_check_ag_rmaps(
return error;
}
+/* Make sure each rt rmap has a corresponding bmbt entry. */
+STATIC int
+xchk_bmap_check_rt_rmaps(
+ struct xfs_scrub *sc)
+{
+ struct xchk_bmap_check_rmap_info sbcri;
+ struct xfs_btree_cur *cur;
+ int error;
+
+ xfs_rtlock(NULL, sc->mp, XFS_RTLOCK_RMAP);
+ cur = xfs_rtrmapbt_init_cursor(sc->mp, sc->tp, sc->mp->m_rrmapip);
+
+ sbcri.sc = sc;
+ sbcri.whichfork = XFS_DATA_FORK;
+ error = xfs_rmap_query_all(cur, xchk_bmap_check_rmap, &sbcri);
+ if (error == -ECANCELED)
+ error = 0;
+
+ xfs_btree_del_cursor(cur, error);
+ xfs_rtunlock(sc->mp, XFS_RTLOCK_RMAP);
+ return error;
+}
+
/* Make sure each rmap has a corresponding bmbt entry. */
STATIC int
xchk_bmap_check_rmaps(
@@ -673,10 +704,6 @@ xchk_bmap_check_rmaps(
(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
return 0;
- /* Don't support realtime rmap checks yet. */
- if (xfs_ifork_is_realtime(sc->ip, whichfork))
- return 0;
-
ASSERT(XFS_IFORK_PTR(sc->ip, whichfork) != NULL);
/*
@@ -696,6 +723,9 @@ xchk_bmap_check_rmaps(
(zero_size || ifp->if_nextents > 0))
return 0;
+ if (xfs_ifork_is_realtime(sc->ip, whichfork))
+ return xchk_bmap_check_rt_rmaps(sc);
+
for_each_perag(sc->mp, agno, pag) {
error = xchk_bmap_check_ag_rmaps(sc, whichfork, pag);
if (error)