summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-05-21 17:08:10 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-08-10 09:58:09 -0700
commit0274226e7e8e45d2f42e730e31c303b72423cbdf (patch)
tree72e2ee1c0483c3e948432872422f7b31824c73d2
parentb3fb130b0df35eefd1df8ca7fc65db87d1c51a08 (diff)
xfs: cross-reference the realtime rmapbtrealtime-rmap_2019-08-10
When we're scrubbing the realtime metadata, cross-reference the rtrmapt. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/scrub/bmap.c19
-rw-r--r--fs/xfs/scrub/common.c22
-rw-r--r--fs/xfs/scrub/common.h1
-rw-r--r--fs/xfs/scrub/rmap.c16
-rw-r--r--fs/xfs/scrub/rtbitmap.c30
-rw-r--r--fs/xfs/scrub/scrub.h12
6 files changed, 86 insertions, 14 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 1894fb2d80c1..4b5460709587 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -241,11 +241,30 @@ xchk_bmap_rt_extent_xref(
struct xfs_btree_cur *cur,
struct xfs_bmbt_irec *irec)
{
+ struct xfs_mount *mp = info->sc->mp;
+ int error;
+
if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
return;
+ xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
+ if (mp->m_rrmapip)
+ xfs_ilock(mp->m_rrmapip, XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM);
+
+ error = xchk_rt_init(info->sc, &info->sc->sa);
+ if (!xchk_fblock_process_error(info->sc, info->whichfork,
+ irec->br_startoff, &error))
+ goto out_unlock;
+
xchk_xref_is_used_rt_space(info->sc, irec->br_startblock,
irec->br_blockcount);
+ xchk_bmap_xref_rmap(info, irec, irec->br_startblock);
+
+ xchk_ag_free(info->sc, &info->sc->sa);
+out_unlock:
+ if (mp->m_rrmapip)
+ xfs_iunlock(mp->m_rrmapip, XFS_ILOCK_EXCL);
+ xfs_iunlock(mp->m_rbmip, XFS_ILOCK_EXCL);
}
/* Cross-reference a single datadev extent record. */
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index c825239dd2a3..385d4a509a71 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -26,6 +26,7 @@
#include "xfs_trans_priv.h"
#include "xfs_attr.h"
#include "xfs_reflink.h"
+#include "xfs_rtrmap_btree.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"
@@ -584,6 +585,27 @@ xchk_perag_get(
sa->pag = xfs_perag_get(mp, sa->agno);
}
+/*
+ * For scrubbing a realtime file, grab the rtrmapt. We follow the same
+ * resource release rules as xfs_scrub_ag_init.
+ */
+int
+xchk_rt_init(
+ struct xfs_scrub *sc,
+ struct xchk_ag *sa)
+{
+ memset(sa, 0, sizeof(*sa));
+ sa->agno = NULLAGNUMBER;
+ if (xfs_sb_version_hasrmapbt(&sc->mp->m_sb)) {
+ ASSERT(xfs_isilocked(sc->mp->m_rrmapip,
+ XFS_ILOCK_EXCL | XFS_ILOCK_SHARED));
+ sa->rmap_cur = xfs_rtrmapbt_init_cursor(sc->mp, sc->tp,
+ sc->mp->m_rrmapip);
+ }
+
+ return 0;
+}
+
/* Per-scrubber setup functions */
/*
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 0ded5c606ca3..fa08ca38c23d 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -114,6 +114,7 @@ xchk_setup_quota(struct xfs_scrub *sc, struct xfs_inode *ip)
#endif
int xchk_setup_fscounters(struct xfs_scrub *sc, struct xfs_inode *ip);
+int xchk_rt_init(struct xfs_scrub *sc, struct xchk_ag *sa);
void xchk_ag_free(struct xfs_scrub *sc, struct xchk_ag *sa);
int xchk_ag_init(struct xfs_scrub *sc, xfs_agnumber_t agno,
struct xchk_ag *sa);
diff --git a/fs/xfs/scrub/rmap.c b/fs/xfs/scrub/rmap.c
index b50604b7f87d..4580061ca862 100644
--- a/fs/xfs/scrub/rmap.c
+++ b/fs/xfs/scrub/rmap.c
@@ -177,8 +177,8 @@ xchk_rmapbt(
static inline void
xchk_xref_check_owner(
struct xfs_scrub *sc,
- xfs_agblock_t bno,
- xfs_extlen_t len,
+ xfs_fsblock_t bno,
+ xfs_filblks_t len,
const struct xfs_owner_info *oinfo,
bool should_have_rmap)
{
@@ -200,8 +200,8 @@ xchk_xref_check_owner(
void
xchk_xref_is_owned_by(
struct xfs_scrub *sc,
- xfs_agblock_t bno,
- xfs_extlen_t len,
+ xfs_fsblock_t bno,
+ xfs_filblks_t len,
const struct xfs_owner_info *oinfo)
{
xchk_xref_check_owner(sc, bno, len, oinfo, true);
@@ -211,8 +211,8 @@ xchk_xref_is_owned_by(
void
xchk_xref_is_not_owned_by(
struct xfs_scrub *sc,
- xfs_agblock_t bno,
- xfs_extlen_t len,
+ xfs_fsblock_t bno,
+ xfs_filblks_t len,
const struct xfs_owner_info *oinfo)
{
xchk_xref_check_owner(sc, bno, len, oinfo, false);
@@ -222,8 +222,8 @@ xchk_xref_is_not_owned_by(
void
xchk_xref_has_no_owner(
struct xfs_scrub *sc,
- xfs_agblock_t bno,
- xfs_extlen_t len)
+ xfs_fsblock_t bno,
+ xfs_filblks_t len)
{
bool has_rmap;
int error;
diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c
index 6cbd3f6413e0..ca17df198cb2 100644
--- a/fs/xfs/scrub/rtbitmap.c
+++ b/fs/xfs/scrub/rtbitmap.c
@@ -9,12 +9,16 @@
#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_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
@@ -32,11 +36,31 @@ xchk_setup_rt(
sc->ip = sc->mp->m_rbmip;
xfs_ilock(sc->ip, sc->ilock_flags);
+ if (xfs_sb_version_hasrmapbt(&sc->mp->m_sb)) {
+ unsigned int lockmode = XFS_ILOCK_EXCL;
+
+ xfs_ilock(sc->mp->m_rrmapip, lockmode);
+ xfs_trans_ijoin(sc->tp, sc->mp->m_rrmapip, lockmode);
+ }
+
return 0;
}
/* 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_owner(sc, startblock, blockcount);
+}
+
/* Scrub a free extent record from the realtime bitmap. */
STATIC int
xchk_rtbitmap_rec(
@@ -55,6 +79,8 @@ xchk_rtbitmap_rec(
!xfs_verify_rtbno(sc->mp, startblock) ||
!xfs_verify_rtbno(sc->mp, startblock + blockcount - 1))
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
+
+ xchk_rtbitmap_xref(sc, startblock, blockcount);
return 0;
}
@@ -70,6 +96,10 @@ xchk_rtbitmap(
if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
return error;
+ error = xchk_rt_init(sc, &sc->sa);
+ if (error)
+ return error;
+
error = xfs_rtalloc_query_all(sc->tp, xchk_rtbitmap_rec, sc);
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
goto out;
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index fb5f0f371cd8..6c435341ad68 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -152,12 +152,12 @@ void xchk_xref_is_not_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
xfs_extlen_t len);
void xchk_xref_is_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
xfs_extlen_t len);
-void xchk_xref_is_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
- xfs_extlen_t len, const struct xfs_owner_info *oinfo);
-void xchk_xref_is_not_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
- xfs_extlen_t len, const struct xfs_owner_info *oinfo);
-void xchk_xref_has_no_owner(struct xfs_scrub *sc, xfs_agblock_t agbno,
- xfs_extlen_t len);
+void xchk_xref_is_owned_by(struct xfs_scrub *sc, xfs_fsblock_t bno,
+ xfs_filblks_t len, const struct xfs_owner_info *oinfo);
+void xchk_xref_is_not_owned_by(struct xfs_scrub *sc, xfs_fsblock_t bno,
+ xfs_filblks_t len, const struct xfs_owner_info *oinfo);
+void xchk_xref_has_no_owner(struct xfs_scrub *sc, xfs_fsblock_t bno,
+ xfs_filblks_t len);
void xchk_xref_is_cow_staging(struct xfs_scrub *sc, xfs_agblock_t bno,
xfs_extlen_t len);
void xchk_xref_is_not_shared(struct xfs_scrub *sc, xfs_agblock_t bno,