[PATCH 18/20] xfs: scrub the realtime rmapbt

"Darrick J. Wong" <[email protected]>
Newsgroups gmane.comp.file-systems.xfs.general
Message-ID <[email protected]>
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 <[email protected]>
---
 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. */

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.