Check the realtime reverse mapping btree against the rtbitmap, and
modify the rtbitmap scrub to check against the rtrmapbt.
Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
fs/xfs/libxfs/xfs_fs.h | 3 +
fs/xfs/xfs_scrub.c | 103 +++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 90 insertions(+), 16 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index f273e76..d1accde 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -551,7 +551,8 @@ struct xfs_scrub_metadata {
#define XFS_SCRUB_TYPE_BMBTC 13 /* CoW fork block mapping */
#define XFS_SCRUB_TYPE_RTBITMAP 14 /* realtime bitmap */
#define XFS_SCRUB_TYPE_RTSUM 15 /* realtime summary */
-#define XFS_SCRUB_TYPE_MAX 15
+#define XFS_SCRUB_TYPE_RTRMAPBT 16 /* realtime reverse mapping
btree */
+#define XFS_SCRUB_TYPE_MAX 16
#define XFS_SCRUB_FLAGS_ALL 0x0 /* no flags yet */
diff --git a/fs/xfs/xfs_scrub.c b/fs/xfs/xfs_scrub.c
index 590bef8..f1f4a2f 100644
--- a/fs/xfs/xfs_scrub.c
+++ b/fs/xfs/xfs_scrub.c
@@ -42,6 +42,7 @@
#include "xfs_refcount_btree.h"
#include "xfs_rmap.h"
#include "xfs_rmap_btree.h"
+#include "xfs_rtrmap_btree.h"
#include "xfs_rtalloc.h"
#include "xfs_icache.h"
#include "xfs_itable.h"
@@ -128,6 +129,7 @@ static const char * const btree_types[] = {
[XFS_BTNUM_BNO] = "bnobt",
[XFS_BTNUM_CNT] = "cntbt",
[XFS_BTNUM_RMAP] = "rmapbt",
+ [XFS_BTNUM_RTRMAP] = "rtrmapbt",
[XFS_BTNUM_BMAP] = "bmapbt",
[XFS_BTNUM_INO] = "inobt",
[XFS_BTNUM_FINO] = "finobt",
@@ -925,6 +927,7 @@ xfs_scrub_sb(
XFS_SCRUB_SB_FEAT(rmapbt);
XFS_SCRUB_SB_FEAT(reflink);
XFS_SCRUB_SB_FEAT(realtime);
+ XFS_SCRUB_SB_FEAT(rtrmapbt);
#undef XFS_SCRUB_SB_FEAT
if (error)
@@ -1912,12 +1915,12 @@ xfs_scrub_rmapbt(
/* Reference count btree scrubber. */
-struct xfs_refcountbt_scrub_fragment {
+struct xfs_scrub_refcountbt_fragment {
struct xfs_rmap_irec rm;
struct list_head list;
};
-struct xfs_refcountbt_scrub_rmap_check_info {
+struct xfs_scrub_refcountbt_rmap_check_info {
struct xfs_scrub_btree *bs;
xfs_nlink_t nr;
struct xfs_refcount_irec rc;
@@ -1932,13 +1935,13 @@ struct xfs_refcountbt_scrub_rmap_check_info {
* fragments as the refcountbt says we should have.
*/
STATIC int
-xfs_refcountbt_scrub_rmap_check(
+xfs_scrub_refcountbt_rmap_check(
struct xfs_btree_cur *cur,
struct xfs_rmap_irec *rec,
void *priv)
{
- struct xfs_refcountbt_scrub_rmap_check_info *rsrci = priv;
- struct xfs_refcountbt_scrub_fragment *frag;
+ struct xfs_scrub_refcountbt_rmap_check_info *rsrci = priv;
+ struct xfs_scrub_refcountbt_fragment *frag;
xfs_agblock_t rm_last;
xfs_agblock_t rc_last;
@@ -1949,7 +1952,7 @@ xfs_refcountbt_scrub_rmap_check(
if (rec->rm_startblock <= rsrci->rc.rc_startblock && rm_last >= rc_last)
rsrci->nr++;
else {
- frag = kmem_zalloc(sizeof(struct xfs_refcountbt_scrub_fragment),
+ frag = kmem_zalloc(sizeof(struct xfs_scrub_refcountbt_fragment),
KM_SLEEP);
frag->rm = *rec;
list_add_tail(&frag->list, &rsrci->fragments);
@@ -1968,11 +1971,11 @@ xfs_refcountbt_scrub_rmap_check(
STATIC void
xfs_refcountbt_process_rmap_fragments(
struct xfs_mount *mp,
- struct xfs_refcountbt_scrub_rmap_check_info *rsrci)
+ struct xfs_scrub_refcountbt_rmap_check_info *rsrci)
{
struct list_head worklist;
- struct xfs_refcountbt_scrub_fragment *cur;
- struct xfs_refcountbt_scrub_fragment *n;
+ struct xfs_scrub_refcountbt_fragment *cur;
+ struct xfs_scrub_refcountbt_fragment *n;
xfs_agblock_t bno;
xfs_agblock_t rbno;
xfs_agblock_t next_rbno;
@@ -2059,13 +2062,13 @@ fail:
/* Delete fragments and work list. */
while (!list_empty(&worklist)) {
cur = list_first_entry(&worklist,
- struct xfs_refcountbt_scrub_fragment, list);
+ struct xfs_scrub_refcountbt_fragment, list);
list_del(&cur->list);
kmem_free(cur);
}
while (!list_empty(&rsrci->fragments)) {
cur = list_first_entry(&rsrci->fragments,
- struct xfs_refcountbt_scrub_fragment, list);
+ struct xfs_scrub_refcountbt_fragment, list);
list_del(&cur->list);
kmem_free(cur);
}
@@ -2082,8 +2085,8 @@ xfs_scrub_refcountbt_helper(
struct xfs_refcount_irec irec;
struct xfs_rmap_irec low;
struct xfs_rmap_irec high;
- struct xfs_refcountbt_scrub_rmap_check_info rsrci;
- struct xfs_refcountbt_scrub_fragment *cur;
+ struct xfs_scrub_refcountbt_rmap_check_info rsrci;
+ struct xfs_scrub_refcountbt_fragment *cur;
xfs_agblock_t eoag;
bool is_freesp;
bool has_inodes;
@@ -2144,7 +2147,7 @@ xfs_scrub_refcountbt_helper(
rsrci.rc = irec;
INIT_LIST_HEAD(&rsrci.fragments);
err2 = xfs_rmap_query_range(bs->rmap_cur, &low, &high,
- &xfs_refcountbt_scrub_rmap_check, &rsrci);
+ &xfs_scrub_refcountbt_rmap_check, &rsrci);
if (err2 == 0) {
xfs_refcountbt_process_rmap_fragments(mp, &rsrci);
XFS_BTREC_SCRUB_CHECK(bs, irec.rc_refcount == rsrci.nr);
@@ -2152,7 +2155,7 @@ xfs_scrub_refcountbt_helper(
while (!list_empty(&rsrci.fragments)) {
cur = list_first_entry(&rsrci.fragments,
- struct xfs_refcountbt_scrub_fragment,
+ struct xfs_scrub_refcountbt_fragment,
list);
list_del(&cur->list);
kmem_free(cur);
@@ -2646,6 +2649,7 @@ xfs_scrub_bmap(
case XFS_DINODE_FMT_UUID:
case XFS_DINODE_FMT_DEV:
case XFS_DINODE_FMT_LOCAL:
+ case XFS_DINODE_FMT_RMAP:
/* No mappings to check. */
goto out_unlock;
case XFS_DINODE_FMT_EXTENTS:
@@ -2831,6 +2835,74 @@ xfs_scrub_rtsummary(
return -ENOENT;
}
+/* Realtime reverse mapping. */
+
+/* Scrub a realtime rmapbt record. */
+STATIC int
+xfs_scrub_rtrmapbt_helper(
+ struct xfs_scrub_btree *bs,
+ union xfs_btree_rec *rec)
+{
+ struct xfs_mount *mp = bs->cur->bc_mp;
+ struct xfs_rmap_irec irec;
+ bool non_inode;
+ bool is_bmbt;
+ bool is_attr;
+ int error;
+
+ error = xfs_rmap_btrec_to_irec(bs->cur, rec, &irec);
+ if (error)
+ return error;
+
+ XFS_BTREC_SCRUB_CHECK(bs, irec.rm_startblock < mp->m_sb.sb_rblocks)
+ XFS_BTREC_SCRUB_CHECK(bs, irec.rm_startblock < irec.rm_startblock +
+ irec.rm_blockcount);
+ XFS_BTREC_SCRUB_CHECK(bs, irec.rm_startblock + irec.rm_blockcount <=
+ mp->m_sb.sb_rblocks)
+
+ non_inode = XFS_RMAP_NON_INODE_OWNER(irec.rm_owner);
+ is_bmbt = irec.rm_flags & XFS_RMAP_BMBT_BLOCK;
+ is_attr = irec.rm_flags & XFS_RMAP_ATTR_FORK;
+
+ XFS_BTREC_SCRUB_CHECK(bs, !is_bmbt);
+ XFS_BTREC_SCRUB_CHECK(bs, !non_inode);
+ XFS_BTREC_SCRUB_CHECK(bs, !is_attr);
+
+ return error;
+}
+
+/* Scrub the realtime rmap btree. */
+STATIC int
+xfs_scrub_rtrmapbt(
+ struct xfs_inode *ip,
+ struct xfs_scrub_metadata *sm)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ struct xfs_scrub_btree bs;
+ int error;
+
+ if (sm->control || sm->flags)
+ return -EINVAL;
+
+ xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
+ xfs_ilock(mp->m_rrmapip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
+
+ bs.cur = xfs_rtrmapbt_init_cursor(mp, NULL, mp->m_rrmapip);
+ bs.scrub_rec = xfs_scrub_rtrmapbt_helper;
+ xfs_rmap_ino_bmbt_owner(&bs.oinfo, mp->m_sb.sb_rrmapino, XFS_DATA_FORK);
+ error = xfs_scrub_btree(&bs);
+ xfs_btree_del_cursor(bs.cur,
+ error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+
+ xfs_iunlock(mp->m_rrmapip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
+ xfs_iunlock(mp->m_rbmip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
+
+ if (!error && bs.error)
+ error = bs.error;
+
+ return error;
+}
+
/* Scrubbing dispatch. */
struct xfs_scrub_meta_fns {
@@ -2855,6 +2927,7 @@ static const struct xfs_scrub_meta_fns meta_scrub_fns[] =
{
{xfs_scrub_bmap_cow, NULL},
{xfs_scrub_rtbitmap, xfs_sb_version_hasrealtime},
{xfs_scrub_rtsummary, xfs_sb_version_hasrealtime},
+ {xfs_scrub_rtrmapbt, xfs_sb_version_hasrtrmapbt},
};
/* Dispatch metadata scrubbing. */
|