All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: linux-xfs@vger.kernel.org
Cc: Dave Chinner <david@fromorbit.com>
Subject: [PATCH v3 16/21] xfs: cross-reference inode btrees during scrub
Date: Tue, 16 Jan 2018 15:23:22 -0800	[thread overview]
Message-ID: <20180116232322.GA5602@magnolia> (raw)
In-Reply-To: <151398987068.18741.4829286717637372866.stgit@magnolia>

From: Darrick J. Wong <darrick.wong@oracle.com>

Cross-reference the inode btrees with the other metadata when we
scrub the filesystem.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
v3: fix some indenting craziness, clean up helpers per dave's suggestion
v2: streamline scrubber arguments, remove stack allocated objects
---
 fs/xfs/scrub/agheader.c |   27 +++++++++++++++++
 fs/xfs/scrub/alloc.c    |    1 +
 fs/xfs/scrub/bmap.c     |    1 +
 fs/xfs/scrub/ialloc.c   |   73 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/scrub/inode.c    |   49 ++++++++++++++++++++++++++++++++
 fs/xfs/scrub/refcount.c |    1 +
 fs/xfs/scrub/rmap.c     |    4 +++
 fs/xfs/scrub/scrub.h    |    4 +++
 8 files changed, 160 insertions(+)

diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
index 1aba7c0..13ec76b 100644
--- a/fs/xfs/scrub/agheader.c
+++ b/fs/xfs/scrub/agheader.c
@@ -122,6 +122,7 @@ xfs_scrub_superblock_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(sc, agbno, 1);
+	xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
 
 	/* scrub teardown will take care of sc->sa for us */
 }
@@ -507,6 +508,7 @@ xfs_scrub_agf_xref(
 	xfs_scrub_xref_is_used_space(sc, agbno, 1);
 	xfs_scrub_agf_xref_freeblks(sc);
 	xfs_scrub_agf_xref_cntbt(sc);
+	xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
 
 	/* scrub teardown will take care of sc->sa for us */
 }
@@ -612,6 +614,7 @@ xfs_scrub_agfl_block_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(sc, agbno, 1);
+	xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
 }
 
 /* Scrub an AGFL block. */
@@ -666,6 +669,7 @@ xfs_scrub_agfl_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(sc, agbno, 1);
+	xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
 
 	/*
 	 * Scrub teardown will take care of sc->sa for us.  Leave sc->sa
@@ -740,6 +744,27 @@ xfs_scrub_agfl(
 
 /* AGI */
 
+/* Check agi_count/agi_freecount */
+static inline void
+xfs_scrub_agi_xref_icounts(
+	struct xfs_scrub_context	*sc)
+{
+	struct xfs_agi			*agi = XFS_BUF_TO_AGI(sc->sa.agi_bp);
+	xfs_agino_t			icount;
+	xfs_agino_t			freecount;
+	int				error;
+
+	if (!sc->sa.ino_cur)
+		return;
+
+	error = xfs_ialloc_count_inodes(sc->sa.ino_cur, &icount, &freecount);
+	if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.ino_cur))
+		return;
+	if (be32_to_cpu(agi->agi_count) != icount ||
+	    be32_to_cpu(agi->agi_freecount) != freecount)
+		xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agi_bp);
+}
+
 /* Cross-reference with the other btrees. */
 STATIC void
 xfs_scrub_agi_xref(
@@ -759,6 +784,8 @@ xfs_scrub_agi_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(sc, agbno, 1);
+	xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
+	xfs_scrub_agi_xref_icounts(sc);
 
 	/* scrub teardown will take care of sc->sa for us */
 }
diff --git a/fs/xfs/scrub/alloc.c b/fs/xfs/scrub/alloc.c
index 836b3c3..0031014 100644
--- a/fs/xfs/scrub/alloc.c
+++ b/fs/xfs/scrub/alloc.c
@@ -104,6 +104,7 @@ xfs_scrub_allocbt_xref(
 		return;
 
 	xfs_scrub_allocbt_xref_other(sc, agbno, len);
+	xfs_scrub_xref_is_not_inode_chunk(sc, agbno, len);
 }
 
 /* Scrub a bnobt/cntbt record. */
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 7e8e239..6f1d145 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -138,6 +138,7 @@ xfs_scrub_bmap_extent_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(info->sc, agbno, len);
+	xfs_scrub_xref_is_not_inode_chunk(info->sc, agbno, len);
 
 	xfs_scrub_ag_free(info->sc, &info->sc->sa);
 }
diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c
index 4526894..bd7ba16 100644
--- a/fs/xfs/scrub/ialloc.c
+++ b/fs/xfs/scrub/ialloc.c
@@ -58,6 +58,35 @@ xfs_scrub_setup_ag_iallocbt(
 
 /* Inode btree scrubber. */
 
+/*
+ * If we're checking the finobt, cross-reference with the inobt.
+ * Otherwise we're checking the inobt; if there is an finobt, make sure
+ * we have a record or not depending on freecount.
+ */
+static inline void
+xfs_scrub_iallocbt_chunk_xref_other(
+	struct xfs_scrub_context	*sc,
+	struct xfs_inobt_rec_incore	*irec,
+	xfs_agino_t			agino)
+{
+	struct xfs_btree_cur		**pcur;
+	bool				has_irec;
+	int				error;
+
+	if (sc->sm->sm_type == XFS_SCRUB_TYPE_FINOBT)
+		pcur = &sc->sa.ino_cur;
+	else
+		pcur = &sc->sa.fino_cur;
+	if (!(*pcur))
+		return;
+	error = xfs_ialloc_has_inode_record(*pcur, agino, agino, &has_irec);
+	if (!xfs_scrub_should_check_xref(sc, &error, pcur))
+		return;
+	if (((irec->ir_freecount > 0 && !has_irec) ||
+	     (irec->ir_freecount == 0 && has_irec)))
+		xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
+}
+
 /* Cross-reference with the other btrees. */
 STATIC void
 xfs_scrub_iallocbt_chunk_xref(
@@ -71,6 +100,7 @@ xfs_scrub_iallocbt_chunk_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(sc, agbno, len);
+	xfs_scrub_iallocbt_chunk_xref_other(sc, irec, agino);
 }
 
 /* Is this chunk worth checking? */
@@ -352,3 +382,46 @@ xfs_scrub_finobt(
 {
 	return xfs_scrub_iallocbt(sc, XFS_BTNUM_FINO);
 }
+
+/* See if an inode btree has (or doesn't have) an inode chunk record. */
+static inline void
+xfs_scrub_xref_inode_check(
+	struct xfs_scrub_context	*sc,
+	xfs_agblock_t			agbno,
+	xfs_extlen_t			len,
+	struct xfs_btree_cur		**icur,
+	bool				should_have_inodes)
+{
+	bool				has_inodes;
+	int				error;
+
+	if (!(*icur))
+		return;
+
+	error = xfs_ialloc_has_inodes_at_extent(*icur, agbno, len, &has_inodes);
+	if (!xfs_scrub_should_check_xref(sc, &error, icur))
+		return;
+	if (has_inodes != should_have_inodes)
+		xfs_scrub_btree_xref_set_corrupt(sc, *icur, 0);
+}
+
+/* xref check that the extent is not covered by inodes */
+void
+xfs_scrub_xref_is_not_inode_chunk(
+	struct xfs_scrub_context	*sc,
+	xfs_agblock_t			agbno,
+	xfs_extlen_t			len)
+{
+	xfs_scrub_xref_inode_check(sc, agbno, len, &sc->sa.ino_cur, false);
+	xfs_scrub_xref_inode_check(sc, agbno, len, &sc->sa.fino_cur, false);
+}
+
+/* xref check that the extent is covered by inodes */
+void
+xfs_scrub_xref_is_inode_chunk(
+	struct xfs_scrub_context	*sc,
+	xfs_agblock_t			agbno,
+	xfs_extlen_t			len)
+{
+	xfs_scrub_xref_inode_check(sc, agbno, len, &sc->sa.ino_cur, true);
+}
diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
index be9cf19..b48d5fb 100644
--- a/fs/xfs/scrub/inode.c
+++ b/fs/xfs/scrub/inode.c
@@ -39,6 +39,7 @@
 #include "scrub/xfs_scrub.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
+#include "scrub/btree.h"
 #include "scrub/trace.h"
 
 /*
@@ -577,6 +578,53 @@ xfs_scrub_inode_map_raw(
 	return error;
 }
 
+/*
+ * Make sure the finobt doesn't think this inode is free.
+ * We don't have to check the inobt ourselves because we got the inode via
+ * IGET_UNTRUSTED, which checks the inobt for us.
+ */
+static void
+xfs_scrub_inode_xref_finobt(
+	struct xfs_scrub_context	*sc,
+	xfs_ino_t			ino)
+{
+	struct xfs_inobt_rec_incore	rec;
+	xfs_agino_t			agino;
+	int				has_record;
+	int				error;
+
+	if (!sc->sa.fino_cur)
+		return;
+
+	agino = XFS_INO_TO_AGINO(sc->mp, ino);
+
+	/*
+	 * Try to get the finobt record.  If we can't get it, then we're
+	 * in good shape.
+	 */
+	error = xfs_inobt_lookup(sc->sa.fino_cur, agino, XFS_LOOKUP_LE,
+			&has_record);
+	if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
+	    !has_record)
+		return;
+
+	error = xfs_inobt_get_rec(sc->sa.fino_cur, &rec, &has_record);
+	if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
+	    !has_record)
+		return;
+
+	/*
+	 * Otherwise, make sure this record either doesn't cover this inode,
+	 * or that it does but it's marked present.
+	 */
+	if (rec.ir_startino > agino ||
+	    rec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
+		return;
+
+	if (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino))
+		xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.fino_cur, 0);
+}
+
 /* Cross-reference with the other btrees. */
 STATIC void
 xfs_scrub_inode_xref(
@@ -599,6 +647,7 @@ xfs_scrub_inode_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(sc, agbno, 1);
+	xfs_scrub_inode_xref_finobt(sc, ino);
 
 	xfs_scrub_ag_free(sc, &sc->sa);
 }
diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c
index 09a04ae..af54590 100644
--- a/fs/xfs/scrub/refcount.c
+++ b/fs/xfs/scrub/refcount.c
@@ -62,6 +62,7 @@ xfs_scrub_refcountbt_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(sc, agbno, len);
+	xfs_scrub_xref_is_not_inode_chunk(sc, agbno, len);
 }
 
 /* Scrub a refcountbt record. */
diff --git a/fs/xfs/scrub/rmap.c b/fs/xfs/scrub/rmap.c
index 54b0eac..6e937ef 100644
--- a/fs/xfs/scrub/rmap.c
+++ b/fs/xfs/scrub/rmap.c
@@ -64,6 +64,10 @@ xfs_scrub_rmapbt_xref(
 		return;
 
 	xfs_scrub_xref_is_used_space(sc, agbno, len);
+	if (irec->rm_owner == XFS_RMAP_OWN_INODES)
+		xfs_scrub_xref_is_inode_chunk(sc, agbno, len);
+	else
+		xfs_scrub_xref_is_not_inode_chunk(sc, agbno, len);
 }
 
 /* Scrub an rmapbt record. */
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index cbc6363..9b0033b 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -126,5 +126,9 @@ xfs_scrub_quota(struct xfs_scrub_context *sc)
 /* cross-referencing helpers */
 void xfs_scrub_xref_is_used_space(struct xfs_scrub_context *sc,
 		xfs_agblock_t agbno, xfs_extlen_t len);
+void xfs_scrub_xref_is_not_inode_chunk(struct xfs_scrub_context *sc,
+		xfs_agblock_t agbno, xfs_extlen_t len);
+void xfs_scrub_xref_is_inode_chunk(struct xfs_scrub_context *sc,
+		xfs_agblock_t agbno, xfs_extlen_t len);
 
 #endif	/* __XFS_SCRUB_SCRUB_H__ */

  parent reply	other threads:[~2018-01-16 23:23 UTC|newest]

Thread overview: 94+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-23  0:42 [PATCH v11 00/21] xfs: online scrub xref support Darrick J. Wong
2017-12-23  0:42 ` [PATCH 01/21] xfs: ignore agfl read errors when not scrubbing agfl Darrick J. Wong
2018-01-05  1:12   ` Dave Chinner
2017-12-23  0:43 ` [PATCH 02/21] xfs: catch a few more error codes when scrubbing secondary sb Darrick J. Wong
2018-01-05  1:17   ` Dave Chinner
2018-01-05  1:24     ` Darrick J. Wong
2018-01-05  2:10       ` Dave Chinner
2017-12-23  0:43 ` [PATCH 03/21] xfs: xfs_scrub_bmap should use for_each_xfs_iext Darrick J. Wong
2018-01-05  1:17   ` Dave Chinner
2017-12-23  0:43 ` [PATCH 04/21] xfs: always grab transaction when scrubbing inode Darrick J. Wong
2018-01-05  1:18   ` Dave Chinner
2017-12-23  0:43 ` [PATCH 05/21] xfs: distinguish between corrupt inode and invalid inum in xfs_scrub_get_inode Darrick J. Wong
2018-01-05  1:23   ` Dave Chinner
2017-12-23  0:43 ` [PATCH 06/21] xfs: add scrub cross-referencing helpers for the free space btrees Darrick J. Wong
2018-01-05  1:29   ` Dave Chinner
2017-12-23  0:43 ` [PATCH 07/21] xfs: add scrub cross-referencing helpers for the inode btrees Darrick J. Wong
2018-01-05  1:36   ` Dave Chinner
2018-01-05  2:19     ` Darrick J. Wong
2018-01-05 21:51   ` [PATCH v2 " Darrick J. Wong
2018-01-16 23:05     ` Darrick J. Wong
2018-01-17  0:36       ` Dave Chinner
2017-12-23  0:43 ` [PATCH 08/21] xfs: add scrub cross-referencing helpers for the rmap btrees Darrick J. Wong
2018-01-05  1:40   ` Dave Chinner
2018-01-05  2:49     ` Darrick J. Wong
2018-01-05  3:38       ` Dave Chinner
2018-01-05 21:53   ` [PATCH v2 " Darrick J. Wong
2018-01-06 20:46     ` Dave Chinner
2017-12-23  0:43 ` [PATCH 09/21] xfs: add scrub cross-referencing helpers for the refcount btrees Darrick J. Wong
2018-01-05  1:41   ` Dave Chinner
2017-12-23  0:43 ` [PATCH 10/21] xfs: set up scrub cross-referencing helpers Darrick J. Wong
2018-01-05  2:08   ` Dave Chinner
2018-01-05  3:05     ` Darrick J. Wong
2018-01-05 21:54   ` [PATCH v2 " Darrick J. Wong
2018-01-16 23:06     ` Darrick J. Wong
2018-01-17  0:41     ` Dave Chinner
2017-12-23  0:44 ` [PATCH 11/21] xfs: fix a few erroneous process_error calls in the scrubbers Darrick J. Wong
2018-01-05  2:11   ` Dave Chinner
2017-12-23  0:44 ` [PATCH 12/21] xfs: check btree block ownership with bnobt/rmapbt when scrubbing btree Darrick J. Wong
2018-01-05  2:24   ` Dave Chinner
2018-01-05  2:53     ` Darrick J. Wong
2018-01-05  3:39       ` Dave Chinner
2017-12-23  0:44 ` [PATCH 13/21] xfs: introduce scrubber cross-referencing stubs Darrick J. Wong
2018-01-08 23:36   ` Dave Chinner
2018-01-08 23:59     ` Darrick J. Wong
2018-01-09 21:00   ` [PATCH v2 " Darrick J. Wong
2018-01-10  0:12     ` Dave Chinner
2017-12-23  0:44 ` [PATCH 14/21] xfs: cross-reference with the bnobt Darrick J. Wong
2018-01-08 23:51   ` Dave Chinner
2018-01-09  0:34     ` Darrick J. Wong
2018-01-09  0:57       ` Dave Chinner
2018-01-09 21:15   ` [PATCH v2 " Darrick J. Wong
2018-01-10  0:15     ` Dave Chinner
2017-12-23  0:44 ` [PATCH 15/21] xfs: cross-reference bnobt records with cntbt Darrick J. Wong
2018-01-08 23:55   ` Dave Chinner
2018-01-09  0:37     ` Darrick J. Wong
2018-01-09 21:20   ` [PATCH v2 " Darrick J. Wong
2018-01-10  0:19     ` Dave Chinner
2017-12-23  0:44 ` [PATCH 16/21] xfs: cross-reference inode btrees during scrub Darrick J. Wong
2018-01-09 21:22   ` [PATCH v2 " Darrick J. Wong
2018-01-15 22:17     ` Dave Chinner
2018-01-16  6:30       ` Darrick J. Wong
2018-01-16 23:23   ` Darrick J. Wong [this message]
2018-01-17  0:44     ` [PATCH v3 " Dave Chinner
2017-12-23  0:44 ` [PATCH 17/21] xfs: cross-reference reverse-mapping btree Darrick J. Wong
2018-01-09 21:24   ` [PATCH v2 " Darrick J. Wong
2018-01-15 23:04     ` Dave Chinner
2018-01-16  6:38       ` Darrick J. Wong
2018-01-16 23:25   ` [PATCH v3 " Darrick J. Wong
2018-01-17  0:52     ` Dave Chinner
2017-12-23  0:44 ` [PATCH 18/21] xfs: cross-reference the rmapbt data with the refcountbt Darrick J. Wong
2018-01-09 21:25   ` [PATCH v2 " Darrick J. Wong
2018-01-15 23:49     ` Dave Chinner
2018-01-16  6:49       ` Darrick J. Wong
2018-01-16 19:47         ` Darrick J. Wong
2018-01-16 23:26   ` [PATCH v3 " Darrick J. Wong
2018-01-17  1:00     ` Dave Chinner
2018-01-17  1:11       ` Darrick J. Wong
2017-12-23  0:44 ` [PATCH 19/21] xfs: cross-reference refcount btree during scrub Darrick J. Wong
2018-01-09 21:25   ` [PATCH v2 " Darrick J. Wong
2018-01-16  2:44     ` Dave Chinner
2018-01-16  6:52       ` Darrick J. Wong
2018-01-16 20:26         ` Darrick J. Wong
2018-01-16 23:27   ` [PATCH v3 " Darrick J. Wong
2018-01-17  1:02     ` Dave Chinner
2017-12-23  0:44 ` [PATCH 20/21] xfs: cross-reference the realtime bitmap Darrick J. Wong
2018-01-09 21:26   ` [PATCH v2 " Darrick J. Wong
2018-01-16  2:57     ` Dave Chinner
2018-01-16  6:55       ` Darrick J. Wong
2018-01-16 23:27   ` [PATCH v3 " Darrick J. Wong
2018-01-17  1:03     ` Dave Chinner
2017-12-23  0:45 ` [PATCH 21/21] xfs: cross-reference the block mappings when possible Darrick J. Wong
2018-01-09 21:26   ` [PATCH v2 " Darrick J. Wong
2018-01-16  2:58     ` Dave Chinner
2018-01-16  6:55       ` 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=20180116232322.GA5602@magnolia \
    --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.