All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: david@fromorbit.com, darrick.wong@oracle.com
Cc: linux-xfs@vger.kernel.org, xfs@oss.sgi.com
Subject: [PATCH 23/25] xfs: cross-reference refcount btree during scrub
Date: Thu, 25 Aug 2016 16:42:45 -0700	[thread overview]
Message-ID: <147216856568.3108.7611118372039280000.stgit@birch.djwong.org> (raw)
In-Reply-To: <147216841262.3108.10746252464845687338.stgit@birch.djwong.org>

During metadata btree scrub, we should cross-reference with the
reference counts.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_refcount.c |   19 ++++
 fs/xfs/libxfs/xfs_refcount.h |    3 +
 fs/xfs/xfs_scrub.c           |  184 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+)


diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index 9136745..af82ea3 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -1535,3 +1535,22 @@ xfs_refcount_free_cow_extent(
 	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_FREE_COW,
 			fsb, len);
 }
+
+/* Is there a record covering a given extent? */
+int
+xfs_refcount_has_record(
+	struct xfs_btree_cur	*cur,
+	xfs_agblock_t		bno,
+	xfs_extlen_t		len,
+	bool			*exists)
+{
+	union xfs_btree_irec	low;
+	union xfs_btree_irec	high;
+
+	memset(&low, 0, sizeof(low));
+	low.rc.rc_startblock = bno;
+	memset(&high, 0xFF, sizeof(high));
+	high.rc.rc_startblock = bno + len - 1;
+
+	return xfs_btree_has_record(cur, &low, &high, exists);
+}
diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
index 105c246..a00400f 100644
--- a/fs/xfs/libxfs/xfs_refcount.h
+++ b/fs/xfs/libxfs/xfs_refcount.h
@@ -64,4 +64,7 @@ extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp,
 		struct xfs_defer_ops *dfops, xfs_fsblock_t fsb,
 		xfs_extlen_t len);
 
+extern int xfs_refcount_has_record(struct xfs_btree_cur *cur,
+		xfs_agblock_t bno, xfs_extlen_t len, bool *exists);
+
 #endif	/* __XFS_REFCOUNT_H__ */
diff --git a/fs/xfs/xfs_scrub.c b/fs/xfs/xfs_scrub.c
index 34c23f7..ff55d8c 100644
--- a/fs/xfs/xfs_scrub.c
+++ b/fs/xfs/xfs_scrub.c
@@ -867,6 +867,7 @@ xfs_scrub_sb(
 	bool				is_freesp;
 	bool				has_inodes;
 	bool				has_rmap;
+	bool				has_refcount;
 	int				error;
 	int				err2;
 
@@ -973,6 +974,17 @@ btree_xref:
 						  XFS_BTREE_NOERROR);
 	}
 
+	/* Cross-reference with the refcountbt. */
+	if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+		xcur = xfs_refcountbt_init_cursor(mp, NULL, agf_bp, agno, NULL);
+		err2 = xfs_refcount_has_record(xcur, XFS_SB_BLOCK(mp), 1,
+				&has_refcount);
+		if (!err2)
+			XFS_SCRUB_CHECK(mp, bp, "superblock", !has_refcount);
+		xfs_btree_del_cursor(xcur, err2 ? XFS_BTREE_ERROR :
+						  XFS_BTREE_NOERROR);
+	}
+
 	xfs_scrub_put_ag_headers(&agi_bp, &agf_bp);
 out:
 	xfs_buf_relse(bp);
@@ -1000,6 +1012,7 @@ xfs_scrub_agf(
 	bool				is_freesp;
 	bool				has_inodes;
 	bool				has_rmap;
+	bool				has_refcount;
 	int				error;
 	int				err2;
 
@@ -1103,6 +1116,23 @@ skip_rmap_xref:
 						  XFS_BTREE_NOERROR);
 	}
 
+	/* Cross-reference with the refcountbt. */
+	if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+		xcur = xfs_refcountbt_init_cursor(mp, NULL, agf_bp, agno, NULL);
+		err2 = xfs_refcount_has_record(xcur, XFS_AGF_BLOCK(mp), 1,
+				&has_refcount);
+		if (err2)
+			goto skip_refc_xref;
+		XFS_SCRUB_CHECK(mp, agf_bp, "AGF", !has_refcount);
+		err2 = xfs_btree_count_blocks(xcur, &blocks);
+		if (!err2)
+			XFS_SCRUB_CHECK(mp, agf_bp, "AGF", blocks ==
+					be32_to_cpu(agf->agf_refcount_blocks));
+skip_refc_xref:
+		xfs_btree_del_cursor(xcur, err2 ? XFS_BTREE_ERROR :
+						  XFS_BTREE_NOERROR);
+	}
+
 	xfs_scrub_put_ag_headers(&agi_bp, &agf_bp);
 	return error;
 }
@@ -1123,6 +1153,7 @@ xfs_scrub_agfl(
 	struct xfs_btree_cur		*icur = NULL;
 	struct xfs_btree_cur		*fcur = NULL;
 	struct xfs_btree_cur		*rcur = NULL;
+	struct xfs_btree_cur		*ccur = NULL;
 	struct xfs_owner_info		oinfo;
 	xfs_agnumber_t			agno;
 	xfs_agblock_t			agbno;
@@ -1131,6 +1162,7 @@ xfs_scrub_agfl(
 	bool				is_freesp;
 	bool				has_inodes;
 	bool				has_rmap;
+	bool				has_refcount;
 	int				i;
 	int				error;
 	int				err2;
@@ -1185,6 +1217,15 @@ xfs_scrub_agfl(
 			XFS_SCRUB_CHECK(mp, agfl_bp, "AGFL", has_rmap);
 	}
 
+	/* Set up cross-reference with refcountbt. */
+	if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+		ccur = xfs_refcountbt_init_cursor(mp, NULL, agf_bp, agno, NULL);
+		err2 = xfs_refcount_has_record(ccur, XFS_AGFL_BLOCK(mp), 1,
+				&has_refcount);
+		if (!err2)
+			XFS_SCRUB_CHECK(mp, agfl_bp, "AGFL", !has_refcount);
+	}
+
 	xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
 	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agfl_bp);
 	for (i = be32_to_cpu(agf->agf_flfirst);
@@ -1229,8 +1270,19 @@ xfs_scrub_agfl(
 			if (!err2)
 				XFS_SCRUB_CHECK(mp, agfl_bp, "AGFL", has_rmap);
 		}
+
+		/* Cross-reference with the refcountbt. */
+		if (ccur) {
+			err2 = xfs_refcount_has_record(ccur, agbno, 1,
+					&has_refcount);
+			if (!err2)
+				XFS_SCRUB_CHECK(mp, agfl_bp, "AGFL",
+						!has_refcount);
+		}
 	}
 
+	if (ccur)
+		xfs_btree_del_cursor(ccur, XFS_BTREE_ERROR);
 	if (rcur)
 		xfs_btree_del_cursor(rcur, XFS_BTREE_ERROR);
 	if (fcur)
@@ -1264,6 +1316,7 @@ xfs_scrub_agi(
 	bool				is_freesp;
 	bool				has_inodes;
 	bool				has_rmap;
+	bool				has_refcount;
 	int				error;
 	int				err2;
 
@@ -1334,6 +1387,17 @@ xfs_scrub_agi(
 						  XFS_BTREE_NOERROR);
 	}
 
+	/* Cross-reference with the refcountbt. */
+	if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+		xcur = xfs_refcountbt_init_cursor(mp, NULL, agf_bp, agno, NULL);
+		err2 = xfs_refcount_has_record(xcur, XFS_AGI_BLOCK(mp), 1,
+				&has_refcount);
+		if (!err2)
+			XFS_SCRUB_CHECK(mp, agi_bp, "AGI", !has_refcount);
+		xfs_btree_del_cursor(xcur, err2 ? XFS_BTREE_ERROR :
+						  XFS_BTREE_NOERROR);
+	}
+
 	xfs_scrub_put_ag_headers(&agi_bp, &agf_bp);
 	return error;
 }
@@ -1355,6 +1419,7 @@ xfs_scrub_allocbt_helper(
 	xfs_extlen_t			len;
 	bool				has_rmap;
 	bool				has_inodes;
+	bool				has_refcount;
 	int				has_otherrec;
 	int				error = 0;
 	int				err2;
@@ -1415,6 +1480,14 @@ skip_freesp_xref:
 			XFS_BTREC_SCRUB_CHECK(bs, !has_rmap);
 	}
 
+	/* Cross-reference with the refcountbt. */
+	if (bs->refc_cur) {
+		err2 = xfs_refcount_has_record(bs->refc_cur, bno, len,
+				&has_refcount);
+		if (!err2)
+			XFS_BTREC_SCRUB_CHECK(bs, !has_refcount);
+	}
+
 	return error;
 }
 
@@ -1488,6 +1561,7 @@ xfs_scrub_iallocbt_helper(
 	bool				is_freesp;
 	bool				has_inodes;
 	bool				has_rmap;
+	bool				has_refcount;
 	int				holecount;
 	int				i;
 	int				error = 0;
@@ -1547,6 +1621,14 @@ xfs_scrub_iallocbt_helper(
 				XFS_BTREC_SCRUB_CHECK(bs, has_rmap);
 		}
 
+		/* Cross-reference with the refcountbt. */
+		if (bs->refc_cur) {
+			err2 = xfs_refcount_has_record(bs->refc_cur, bno,
+					len, &has_refcount);
+			if (!err2)
+				XFS_BTREC_SCRUB_CHECK(bs, !has_refcount);
+		}
+
 		goto out;
 	}
 
@@ -1604,6 +1686,14 @@ xfs_scrub_iallocbt_helper(
 			if (!err2)
 				XFS_BTREC_SCRUB_CHECK(bs, has_rmap);
 		}
+
+		/* Cross-reference with the refcountbt. */
+		if (bs->refc_cur) {
+			err2 = xfs_refcount_has_record(bs->refc_cur, bno,
+					len, &has_refcount);
+			if (!err2)
+				XFS_BTREC_SCRUB_CHECK(bs, !has_refcount);
+		}
 	}
 
 	XFS_BTREC_SCRUB_CHECK(bs, holecount <= XFS_INODES_PER_CHUNK);
@@ -1674,13 +1764,17 @@ xfs_scrub_rmapbt_helper(
 	struct xfs_mount		*mp = bs->cur->bc_mp;
 	struct xfs_agf			*agf;
 	struct xfs_rmap_irec		irec;
+	struct xfs_refcount_irec	crec;
 	xfs_agblock_t			eoag;
+	xfs_agblock_t			fbno;
+	xfs_extlen_t			flen;
 	bool				is_freesp;
 	bool				non_inode;
 	bool				is_unwritten;
 	bool				is_bmbt;
 	bool				is_attr;
 	bool				has_inodes;
+	int				has_refcount;
 	int				error = 0;
 	int				err2;
 
@@ -1741,6 +1835,45 @@ xfs_scrub_rmapbt_helper(
 					!has_inodes);
 	}
 
+	/* Cross-reference with the refcount btree. */
+	if (bs->refc_cur) {
+		if (irec.rm_owner == XFS_RMAP_OWN_COW) {
+			/* Check this CoW staging extent. */
+			err2 = xfs_refcount_lookup_le(bs->refc_cur,
+					irec.rm_startblock, &has_refcount);
+			if (err2)
+				goto skip_refc_xref;
+			XFS_BTREC_SCRUB_GOTO(bs, has_refcount, skip_refc_xref);
+
+			err2 = xfs_refcount_get_rec(bs->refc_cur, &crec,
+					&has_refcount);
+			if (err2)
+				goto skip_refc_xref;
+			XFS_BTREC_SCRUB_GOTO(bs, has_refcount, skip_refc_xref);
+			XFS_BTREC_SCRUB_CHECK(bs, crec.rc_startblock <=
+					irec.rm_startblock);
+			XFS_BTREC_SCRUB_CHECK(bs, crec.rc_startblock +
+					crec.rc_blockcount >
+					crec.rc_startblock);
+			XFS_BTREC_SCRUB_CHECK(bs, crec.rc_startblock +
+					crec.rc_blockcount >=
+					irec.rm_startblock +
+					irec.rm_blockcount);
+			XFS_BTREC_SCRUB_CHECK(bs,
+					crec.rc_refcount == 1);
+		} else {
+			/* If this is shared, the inode flag must be set. */
+			err2 = xfs_refcount_find_shared(bs->refc_cur,
+					irec.rm_startblock, irec.rm_blockcount,
+					&fbno, &flen, false);
+			if (!err2)
+				XFS_BTREC_SCRUB_CHECK(bs, flen == 0 ||
+						(!non_inode && !is_attr &&
+						 !is_bmbt && !is_unwritten));
+		}
+skip_refc_xref:;
+	}
+
 	return error;
 }
 
@@ -2164,12 +2297,16 @@ xfs_scrub_bmap_extent(
 	xfs_agnumber_t			agno;
 	xfs_fsblock_t			bno;
 	struct xfs_rmap_irec		rmap;
+	struct xfs_refcount_irec	crec;
 	uint64_t			owner;
 	xfs_fileoff_t			offset;
+	xfs_agblock_t			fbno;
+	xfs_extlen_t			flen;
 	bool				is_freesp;
 	bool				has_inodes;
 	unsigned int			rflags;
 	int				has_rmap;
+	int				has_refcount;
 	int				error = 0;
 	int				err2 = 0;
 
@@ -2348,6 +2485,53 @@ skip_rmap_xref:
 						  XFS_BTREE_NOERROR);
 	}
 
+	/*
+	 * If this is a non-shared file on a reflink filesystem,
+	 * check the refcountbt to see if the flag is wrong.
+	 */
+	if (xfs_sb_version_hasreflink(&mp->m_sb) && !info->is_rt) {
+		xcur = xfs_refcountbt_init_cursor(mp, NULL, agf_bp, agno, NULL);
+
+		if (info->whichfork == XFS_COW_FORK) {
+			/* Check this CoW staging extent. */
+			err2 = xfs_refcount_lookup_le(xcur, bno, &has_refcount);
+			if (err2)
+				goto skip_refc_xref;
+			XFS_INO_SCRUB_GOTO(ip, NULL, info->type, has_refcount,
+					skip_refc_xref);
+
+			err2 = xfs_refcount_get_rec(xcur, &crec, &has_refcount);
+			if (err2)
+				goto skip_refc_xref;
+			XFS_INO_SCRUB_GOTO(ip, NULL, info->type, has_refcount,
+					skip_refc_xref);
+
+			XFS_INO_SCRUB_CHECK(ip, NULL, info->type,
+					crec.rc_startblock <= bno);
+			XFS_INO_SCRUB_CHECK(ip, NULL, info->type,
+					crec.rc_startblock +
+					crec.rc_blockcount >
+					crec.rc_startblock);
+			XFS_INO_SCRUB_CHECK(ip, NULL, info->type,
+					crec.rc_startblock +
+					crec.rc_blockcount >=
+					bno + irec->br_blockcount);
+			XFS_INO_SCRUB_CHECK(ip, NULL, info->type,
+					crec.rc_refcount == 1);
+		} else {
+			/* If this is shared, the inode flag must be set. */
+			err2 = xfs_refcount_find_shared(xcur, bno,
+					irec->br_blockcount, &fbno, &flen,
+					false);
+			if (!err2)
+				XFS_INO_SCRUB_CHECK(ip, bp, info->type,
+						flen == 0 ||
+						xfs_is_reflink_inode(ip));
+		}
+skip_refc_xref:
+		xfs_btree_del_cursor(xcur, XFS_BTREE_NOERROR);
+	}
+
 	xfs_scrub_put_ag_headers(&agi_bp, &agf_bp);
 out:
 	info->lastoff = irec->br_startoff + irec->br_blockcount;

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

  parent reply	other threads:[~2016-08-25 23:42 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-25 23:40 [PATCH v8 00/25] xfs: online scrub support Darrick J. Wong
2016-08-25 23:40 ` [PATCH 01/25] xfs: introduce the XFS_IOC_GETFSMAP ioctl Darrick J. Wong
2016-08-25 23:40 ` [PATCH 02/25] xfs: report shared extents in getfsmapx Darrick J. Wong
2016-08-25 23:40 ` [PATCH 03/25] xfs: have getfsmap fall back to the freesp btrees when rmap is not present Darrick J. Wong
2016-08-25 23:40 ` [PATCH 04/25] xfs: getfsmap should fall back to rtbitmap when rtrmapbt " Darrick J. Wong
2016-08-25 23:40 ` [PATCH 05/25] xfs: add scrub tracepoints Darrick J. Wong
2016-08-25 23:40 ` [PATCH 06/25] xfs: generic functions to scrub metadata and btrees Darrick J. Wong
2016-08-25 23:40 ` [PATCH 07/25] xfs: create an ioctl to scrub AG metadata Darrick J. Wong
2016-08-25 23:41 ` [PATCH 08/25] xfs: scrub the backup superblocks Darrick J. Wong
2016-08-25 23:41 ` [PATCH 09/25] xfs: scrub AGF and AGFL Darrick J. Wong
2016-08-25 23:41 ` [PATCH 10/25] xfs: scrub the AGI Darrick J. Wong
2016-08-25 23:41 ` [PATCH 11/25] xfs: support scrubbing free space btrees Darrick J. Wong
2016-08-25 23:41 ` [PATCH 12/25] xfs: support scrubbing inode btrees Darrick J. Wong
2016-08-25 23:41 ` [PATCH 13/25] xfs: support scrubbing rmap btree Darrick J. Wong
2016-08-25 23:41 ` [PATCH 14/25] xfs: support scrubbing refcount btree Darrick J. Wong
2016-08-25 23:41 ` [PATCH 15/25] xfs: scrub inodes Darrick J. Wong
2016-08-25 23:41 ` [PATCH 16/25] xfs: scrub inode block mappings Darrick J. Wong
2016-08-25 23:42 ` [PATCH 17/25] xfs: scrub realtime bitmap/summary Darrick J. Wong
2016-08-25 23:42 ` [PATCH 18/25] xfs: scrub should cross-reference with the bnobt Darrick J. Wong
2016-08-25 23:42 ` [PATCH 19/25] xfs: cross-reference bnobt records with cntbt Darrick J. Wong
2016-08-25 23:42 ` [PATCH 20/25] xfs: cross-reference extents with AG header Darrick J. Wong
2016-08-25 23:42 ` [PATCH 21/25] xfs: cross-reference inode btrees during scrub Darrick J. Wong
2016-08-25 23:42 ` [PATCH 22/25] xfs: cross-reference reverse-mapping btree Darrick J. Wong
2016-08-25 23:42 ` Darrick J. Wong [this message]
2016-08-25 23:42 ` [PATCH 24/25] xfs: scrub should cross-reference the realtime bitmap Darrick J. Wong
2016-08-25 23:42 ` [PATCH 25/25] xfs: query the per-AG reservation counters Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=147216856568.3108.7611118372039280000.stgit@birch.djwong.org \
    --to=darrick.wong@oracle.com \
    --cc=david@fromorbit.com \
    --cc=linux-xfs@vger.kernel.org \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.