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
Subject: [PATCH 32/39] xfs_repair: check the refcount btree against our observed reference counts when -n
Date: Tue, 25 Oct 2016 16:07:01 -0700	[thread overview]
Message-ID: <147743682152.11035.17051192159697748623.stgit@birch.djwong.org> (raw)
In-Reply-To: <147743661772.11035.560864407573832590.stgit@birch.djwong.org>

Check the observed reference counts against whatever's in the refcount
btree for discrepancies.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/libxfs_api_defs.h |    4 +
 repair/phase4.c          |   19 +++++++
 repair/rmap.c            |  126 ++++++++++++++++++++++++++++++++++++++++++++++
 repair/rmap.h            |    5 ++
 repair/scan.c            |    3 +
 5 files changed, 156 insertions(+), 1 deletion(-)


diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index b30228d..8c15b75 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -138,4 +138,8 @@
 #define xfs_dinode_good_version		libxfs_dinode_good_version
 #define xfs_free_extent			libxfs_free_extent
 
+#define xfs_refcountbt_init_cursor	libxfs_refcountbt_init_cursor
+#define xfs_refcount_lookup_le		libxfs_refcount_lookup_le
+#define xfs_refcount_get_rec		libxfs_refcount_get_rec
+
 #endif /* __LIBXFS_API_DEFS_H__ */
diff --git a/repair/phase4.c b/repair/phase4.c
index 2c2d611..e59464b 100644
--- a/repair/phase4.c
+++ b/repair/phase4.c
@@ -223,6 +223,21 @@ _("%s while fixing inode reflink flags.\n"),
 }
 
 static void
+check_refcount_btrees(
+	work_queue_t	*wq,
+	xfs_agnumber_t	agno,
+	void		*arg)
+{
+	int		error;
+
+	error = check_refcounts(wq->mp, agno);
+	if (error)
+		do_error(
+_("%s while checking reference counts"),
+			 strerror(-error));
+}
+
+static void
 process_rmap_data(
 	struct xfs_mount	*mp)
 {
@@ -246,8 +261,10 @@ process_rmap_data(
 	destroy_work_queue(&wq);
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
 		queue_work(&wq, process_inode_reflink_flags, i, NULL);
+		queue_work(&wq, check_refcount_btrees, i, NULL);
+	}
 	destroy_work_queue(&wq);
 }
 
diff --git a/repair/rmap.c b/repair/rmap.c
index 4ef9051..849b788 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -47,6 +47,7 @@ struct xfs_ag_rmap {
 
 static struct xfs_ag_rmap *ag_rmaps;
 static bool rmapbt_suspect;
+static bool refcbt_suspect;
 
 /*
  * Compare rmap observations for array sorting.
@@ -1242,6 +1243,131 @@ _("Unable to fix reflink flag on inode %"PRIu64".\n"),
 }
 
 /*
+ * Return the number of refcount objects for an AG.
+ */
+size_t
+refcount_record_count(
+	struct xfs_mount		*mp,
+	xfs_agnumber_t		agno)
+{
+	return slab_count(ag_rmaps[agno].ar_refcount_items);
+}
+
+/*
+ * Return a slab cursor that will return refcount objects in order.
+ */
+int
+init_refcount_cursor(
+	xfs_agnumber_t		agno,
+	struct xfs_slab_cursor	**cur)
+{
+	return init_slab_cursor(ag_rmaps[agno].ar_refcount_items, NULL, cur);
+}
+
+/*
+ * Disable the refcount btree check.
+ */
+void
+refcount_avoid_check(void)
+{
+	refcbt_suspect = true;
+}
+
+/*
+ * Compare the observed reference counts against what's in the ag btree.
+ */
+int
+check_refcounts(
+	struct xfs_mount	*mp,
+	xfs_agnumber_t		agno)
+{
+	struct xfs_slab_cursor	*rl_cur;
+	struct xfs_btree_cur	*bt_cur = NULL;
+	int			error;
+	int			have;
+	int			i;
+	struct xfs_buf		*agbp = NULL;
+	struct xfs_refcount_irec	*rl_rec;
+	struct xfs_refcount_irec	tmp;
+	struct xfs_perag	*pag;		/* per allocation group data */
+
+	if (!xfs_sb_version_hasreflink(&mp->m_sb))
+		return 0;
+	if (refcbt_suspect) {
+		if (no_modify && agno == 0)
+			do_warn(_("would rebuild corrupt refcount btrees.\n"));
+		return 0;
+	}
+
+	/* Create cursors to refcount structures */
+	error = init_refcount_cursor(agno, &rl_cur);
+	if (error)
+		return error;
+
+	error = -libxfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
+	if (error)
+		goto err;
+
+	/* Leave the per-ag data "uninitialized" since we rewrite it later */
+	pag = libxfs_perag_get(mp, agno);
+	pag->pagf_init = 0;
+	libxfs_perag_put(pag);
+
+	bt_cur = libxfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL);
+	if (!bt_cur) {
+		error = -ENOMEM;
+		goto err;
+	}
+
+	rl_rec = pop_slab_cursor(rl_cur);
+	while (rl_rec) {
+		/* Look for a refcount record in the btree */
+		error = -libxfs_refcount_lookup_le(bt_cur,
+				rl_rec->rc_startblock, &have);
+		if (error)
+			goto err;
+		if (!have) {
+			do_warn(
+_("Missing reference count record for (%u/%u) len %u count %u\n"),
+				agno, rl_rec->rc_startblock,
+				rl_rec->rc_blockcount, rl_rec->rc_refcount);
+			goto next_loop;
+		}
+
+		error = -libxfs_refcount_get_rec(bt_cur, &tmp, &i);
+		if (error)
+			goto err;
+		if (!i) {
+			do_warn(
+_("Missing reference count record for (%u/%u) len %u count %u\n"),
+				agno, rl_rec->rc_startblock,
+				rl_rec->rc_blockcount, rl_rec->rc_refcount);
+			goto next_loop;
+		}
+
+		/* Compare each refcount observation against the btree's */
+		if (tmp.rc_startblock != rl_rec->rc_startblock ||
+		    tmp.rc_blockcount < rl_rec->rc_blockcount ||
+		    tmp.rc_refcount < rl_rec->rc_refcount)
+			do_warn(
+_("Incorrect reference count: saw (%u/%u) len %u nlinks %u; should be (%u/%u) len %u nlinks %u\n"),
+				agno, tmp.rc_startblock, tmp.rc_blockcount,
+				tmp.rc_refcount, agno, rl_rec->rc_startblock,
+				rl_rec->rc_blockcount, rl_rec->rc_refcount);
+next_loop:
+		rl_rec = pop_slab_cursor(rl_cur);
+	}
+
+err:
+	if (bt_cur)
+		libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
+	if (agbp)
+		libxfs_putbuf(agbp);
+	free_slab_cursor(&rl_cur);
+	return 0;
+}
+
+/*
  * Regenerate the AGFL so that we don't run out of it while rebuilding the
  * rmap btree.  If skip_rmapbt is true, don't update the rmapbt (most probably
  * because we're updating the rmapbt).
diff --git a/repair/rmap.h b/repair/rmap.h
index 266448f..752ece8 100644
--- a/repair/rmap.h
+++ b/repair/rmap.h
@@ -50,6 +50,11 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec,
 		struct xfs_rmap_irec *key);
 
 extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t);
+extern size_t refcount_record_count(struct xfs_mount *, xfs_agnumber_t);
+extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **);
+extern void refcount_avoid_check(void);
+extern int check_refcounts(struct xfs_mount *, xfs_agnumber_t);
+
 extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *,
 	xfs_agnumber_t, xfs_agino_t, xfs_ino_t);
 extern int fix_inode_reflink_flags(struct xfs_mount *, xfs_agnumber_t);
diff --git a/repair/scan.c b/repair/scan.c
index d3a1a82..1c60784 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -1370,6 +1370,8 @@ _("%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
 		}
 	}
 out:
+	if (suspect)
+		refcount_avoid_check();
 	return;
 }
 
@@ -2173,6 +2175,7 @@ validate_agf(
 		} else  {
 			do_warn(_("bad agbno %u for refcntbt root, agno %d\n"),
 				bno, agno);
+			refcount_avoid_check();
 		}
 	}
 


  parent reply	other threads:[~2016-10-25 23:07 UTC|newest]

Thread overview: 85+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-25 23:03 [PATCH v10 00/39] xfsprogs: add reflink and dedupe support Darrick J. Wong
2016-10-25 23:03 ` [PATCH 01/39] xfs: convert RUI log formats to use variable length arrays Darrick J. Wong
2016-10-26 10:21   ` Christoph Hellwig
2016-10-25 23:03 ` [PATCH 02/39] xfs_buflock: handling parsing errors more gracefully Darrick J. Wong
2016-10-26 10:22   ` Christoph Hellwig
2016-10-25 23:03 ` [PATCH 03/39] xfs: define the on-disk refcount btree format Darrick J. Wong
2016-10-26 10:23   ` Christoph Hellwig
2016-10-25 23:04 ` [PATCH 04/39] xfs: add refcount btree operations Darrick J. Wong
2016-10-26 10:23   ` Christoph Hellwig
2016-10-25 23:04 ` [PATCH 05/39] xfs: connect refcount adjust functions to upper layers Darrick J. Wong
2016-10-26 10:24   ` Christoph Hellwig
2016-10-26 18:06     ` Darrick J. Wong
2016-10-25 23:04 ` [PATCH 06/39] xfs: implement deferred bmbt map/unmap operations Darrick J. Wong
2016-10-25 23:04 ` [PATCH 07/39] xfs: introduce the CoW fork Darrick J. Wong
2016-10-26 10:25   ` Christoph Hellwig
2016-10-26 17:59     ` Darrick J. Wong
2016-10-25 23:04 ` [PATCH 08/39] xfs: create a separate cow extent size hint for the allocator Darrick J. Wong
2016-10-25 23:04 ` [PATCH 09/39] xfs_db: dump refcount btree data Darrick J. Wong
2016-10-26 10:28   ` Christoph Hellwig
2016-10-26 17:52     ` Darrick J. Wong
2016-10-25 23:04 ` [PATCH 10/39] xfs_db: add support for checking the refcount btree Darrick J. Wong
2016-10-26  0:49   ` Dave Chinner
2016-10-26  1:13     ` Darrick J. Wong
2016-10-26  3:26       ` Dave Chinner
2016-10-26  6:29         ` Darrick J. Wong
2016-10-25 23:04 ` [PATCH 11/39] xfs_db: metadump should copy the refcount btree too Darrick J. Wong
2016-10-26 10:29   ` Christoph Hellwig
2016-10-26 16:33     ` Darrick J. Wong
2016-10-25 23:04 ` [PATCH 12/39] xfs_db: deal with the CoW extent size hint Darrick J. Wong
2016-10-26 10:28   ` Christoph Hellwig
2016-10-25 23:04 ` [PATCH 13/39] xfs_db: print one array element per line Darrick J. Wong
2016-10-26  0:51   ` Dave Chinner
2016-10-26  1:13     ` Darrick J. Wong
2016-10-26  3:23       ` Dave Chinner
2016-10-26  3:34         ` Darrick J. Wong
2016-10-26  5:48           ` Dave Chinner
2016-10-25 23:05 ` [PATCH 14/39] xfs_growfs: report the presence of the reflink feature Darrick J. Wong
2016-10-26 10:31   ` Christoph Hellwig
2016-10-25 23:05 ` [PATCH 15/39] xfs_io: bmap should support querying CoW fork, shared blocks Darrick J. Wong
2016-10-25 23:05 ` [PATCH 16/39] libxfs: add configure option to override system header fsxattr Darrick J. Wong
2016-10-26  0:56   ` Dave Chinner
2016-10-26  1:16     ` Darrick J. Wong
2016-10-26 10:32   ` Christoph Hellwig
2016-10-26 19:04     ` Darrick J. Wong
2016-10-25 23:05 ` [PATCH 17/39] xfs_io: get and set the CoW extent size hint Darrick J. Wong
2016-10-26  1:06   ` Dave Chinner
2016-10-25 23:05 ` [PATCH 18/39] xfs_io: add refcount+bmap error injection types Darrick J. Wong
2016-10-26 10:33   ` Christoph Hellwig
2016-10-25 23:05 ` [PATCH 19/39] xfs_io: support injecting the 'per-AG reservation critically low' error Darrick J. Wong
2016-10-26 10:33   ` Christoph Hellwig
2016-10-25 23:05 ` [PATCH 20/39] xfs_io: provide long-format help for falloc Darrick J. Wong
2016-10-26 10:34   ` Christoph Hellwig
2016-10-26 16:37     ` Darrick J. Wong
2016-10-25 23:05 ` [PATCH 21/39] xfs_io: try to unshare copy-on-write blocks via fallocate Darrick J. Wong
2016-10-26 10:34   ` Christoph Hellwig
2016-10-25 23:05 ` [PATCH 22/39] xfs_logprint: support cowextsize reporting in log contents Darrick J. Wong
2016-10-26 10:34   ` Christoph Hellwig
2016-10-25 23:06 ` [PATCH 23/39] xfs_logprint: support refcount redo items Darrick J. Wong
2016-10-26 10:37   ` Christoph Hellwig
2016-10-26 17:31     ` Darrick J. Wong
2016-10-25 23:06 ` [PATCH 24/39] xfs_logprint: support bmap " Darrick J. Wong
2016-10-26 10:38   ` Christoph Hellwig
2016-10-25 23:06 ` [PATCH 25/39] man: document the inode cowextsize flags & fields Darrick J. Wong
2016-10-26 10:39   ` Christoph Hellwig
2016-10-26 17:20     ` Darrick J. Wong
2016-10-25 23:06 ` [PATCH 26/39] xfs_repair: fix get_agino_buf to avoid corrupting inodes Darrick J. Wong
2016-10-26 10:48   ` Christoph Hellwig
2016-10-25 23:06 ` [PATCH 27/39] xfs_repair: check the existing refcount btree Darrick J. Wong
2016-10-26 10:49   ` Christoph Hellwig
2016-10-25 23:06 ` [PATCH 28/39] xfs_repair: handle multiple owners of data blocks Darrick J. Wong
2016-10-26 10:57   ` Christoph Hellwig
2016-10-26 17:15     ` Darrick J. Wong
2016-10-26 21:15       ` Dave Chinner
2016-10-26 21:59         ` Darrick J. Wong
2016-10-25 23:06 ` [PATCH 29/39] xfs_repair: process reverse-mapping data into refcount data Darrick J. Wong
2016-10-25 23:06 ` [PATCH 30/39] xfs_repair: record reflink inode state Darrick J. Wong
2016-10-25 23:06 ` [PATCH 31/39] xfs_repair: fix inode reflink flags Darrick J. Wong
2016-10-25 23:07 ` Darrick J. Wong [this message]
2016-10-25 23:07 ` [PATCH 33/39] xfs_repair: rebuild the refcount btree Darrick J. Wong
2016-10-25 23:07 ` [PATCH 34/39] xfs_repair: complain about copy-on-write leftovers Darrick J. Wong
2016-10-25 23:07 ` [PATCH 35/39] xfs_repair: check the CoW extent size hint Darrick J. Wong
2016-10-25 23:07 ` [PATCH 36/39] xfs_repair: use range query when while checking rmaps Darrick J. Wong
2016-10-25 23:07 ` [PATCH 37/39] xfs_repair: check for mergeable refcount records Darrick J. Wong
2016-10-25 23:07 ` [PATCH 38/39] xfs_repair: use thread pools to sort rmap data Darrick J. Wong
2016-10-25 23:07 ` [PATCH 39/39] mkfs.xfs: format reflink enabled filesystems 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=147743682152.11035.17051192159697748623.stgit@birch.djwong.org \
    --to=darrick.wong@oracle.com \
    --cc=david@fromorbit.com \
    --cc=linux-xfs@vger.kernel.org \
    /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.