From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: darrick.wong@oracle.com
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 13/16] xfs: cross-reference refcount btree during scrub
Date: Tue, 28 Nov 2017 17:26:44 -0800 [thread overview]
Message-ID: <151191880450.8553.15155347373871863670.stgit@magnolia> (raw)
In-Reply-To: <151191872395.8553.15627872818207535470.stgit@magnolia>
From: Darrick J. Wong <darrick.wong@oracle.com>
During metadata btree scrub, we should cross-reference with the
reference counts.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
| 14 ++++++++
fs/xfs/scrub/alloc.c | 1 +
fs/xfs/scrub/bmap.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++
fs/xfs/scrub/ialloc.c | 1 +
fs/xfs/scrub/inode.c | 1 +
fs/xfs/scrub/refcount.c | 67 ++++++++++++++++++++++++++++++++++++++++
fs/xfs/scrub/rmap.c | 40 ++++++++++++++++++++++++
fs/xfs/scrub/scrub.h | 6 ++++
8 files changed, 209 insertions(+)
--git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
index a84989cf..930a5d0 100644
--- a/fs/xfs/scrub/agheader.c
+++ b/fs/xfs/scrub/agheader.c
@@ -142,6 +142,7 @@ xfs_scrub_superblock_xref(
xfs_scrub_xref_not_inodes(sc, &sc->sa.fino_cur, bno, 1);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
xfs_scrub_xref_owned_by(sc, &sc->sa.rmap_cur, bno, 1, &oinfo);
+ xfs_scrub_xref_not_shared(sc, &sc->sa.refc_cur, bno, 1);
/* scrub teardown will take care of sc->sa for us */
}
@@ -551,6 +552,16 @@ xfs_scrub_agf_xref(
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
xfs_scrub_xref_owned_by(sc, &sc->sa.rmap_cur, bno, 1, &oinfo);
xfs_scrub_agf_xref_btreeblks(sc);
+ xfs_scrub_xref_not_shared(sc, &sc->sa.refc_cur, bno, 1);
+
+ /* Check agf_refcount_blocks against tree size */
+ pcur = &sc->sa.refc_cur;
+ if (*pcur) {
+ error = xfs_btree_count_blocks(*pcur, &blocks);
+ if (xfs_scrub_should_xref(sc, &error, pcur) &&
+ blocks != be32_to_cpu(agf->agf_refcount_blocks))
+ xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp);
+ }
/* scrub teardown will take care of sc->sa for us */
}
@@ -661,6 +672,7 @@ xfs_scrub_agfl_block_xref(
xfs_scrub_xref_not_inodes(sc, &sc->sa.ino_cur, bno, 1);
xfs_scrub_xref_not_inodes(sc, &sc->sa.fino_cur, bno, 1);
xfs_scrub_xref_owned_by(sc, &sc->sa.rmap_cur, bno, 1, oinfo);
+ xfs_scrub_xref_not_shared(sc, &sc->sa.refc_cur, bno, 1);
}
/* Scrub an AGFL block. */
@@ -720,6 +732,7 @@ xfs_scrub_agfl_xref(
xfs_scrub_xref_not_inodes(sc, &sc->sa.fino_cur, bno, 1);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
xfs_scrub_xref_owned_by(sc, &sc->sa.rmap_cur, bno, 1, &oinfo);
+ xfs_scrub_xref_not_shared(sc, &sc->sa.refc_cur, bno, 1);
/*
* Scrub teardown will take care of sc->sa for us. Leave sc->sa
@@ -831,6 +844,7 @@ xfs_scrub_agi_xref(
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
xfs_scrub_xref_owned_by(sc, &sc->sa.rmap_cur, bno, 1, &oinfo);
+ xfs_scrub_xref_not_shared(sc, &sc->sa.refc_cur, bno, 1);
/* 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 a4046c1..d1dd9b7 100644
--- a/fs/xfs/scrub/alloc.c
+++ b/fs/xfs/scrub/alloc.c
@@ -98,6 +98,7 @@ xfs_scrub_allocbt_xref(
xfs_scrub_xref_not_inodes(sc, &sc->sa.ino_cur, bno, len);
xfs_scrub_xref_not_inodes(sc, &sc->sa.fino_cur, bno, len);
xfs_scrub_xref_no_rmap(sc, &sc->sa.rmap_cur, bno, len);
+ xfs_scrub_xref_not_shared(sc, &sc->sa.refc_cur, bno, len);
}
/* Scrub a bnobt/cntbt record. */
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index f408193..2b99f06 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -37,6 +37,7 @@
#include "xfs_bmap_btree.h"
#include "xfs_rmap.h"
#include "xfs_alloc.h"
+#include "xfs_refcount.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
@@ -200,6 +201,73 @@ xfs_scrub_bmap_xref_rmap(
irec->br_startoff);
}
+/* Make sure the refcount records match this data fork extent. */
+STATIC void
+xfs_scrub_bmap_xref_refcount_data(
+ struct xfs_scrub_bmap_info *info,
+ struct xfs_scrub_ag *sa,
+ struct xfs_bmbt_irec *irec,
+ xfs_fsblock_t bno)
+{
+ xfs_agblock_t fbno;
+ xfs_extlen_t flen;
+ int error;
+
+ if (!sa->refc_cur)
+ return;
+
+ /* If this is shared, the inode flag must be set. */
+ error = xfs_refcount_find_shared(sa->refc_cur, bno,
+ irec->br_blockcount, &fbno, &flen, false);
+ if (!xfs_scrub_should_xref(info->sc, &error, &sa->refc_cur))
+ return;
+
+ if (flen != 0 && !xfs_is_reflink_inode(info->sc->ip))
+ xfs_scrub_fblock_xref_set_corrupt(info->sc, info->whichfork,
+ irec->br_startoff);
+}
+
+/* Make sure the refcount records match this attr fork extent. */
+STATIC void
+xfs_scrub_bmap_xref_refcount_attr(
+ struct xfs_scrub_bmap_info *info,
+ struct xfs_scrub_ag *sa,
+ struct xfs_bmbt_irec *irec,
+ xfs_fsblock_t bno)
+{
+ xfs_agblock_t fbno;
+ xfs_extlen_t flen;
+ int error;
+
+ if (!sa->refc_cur)
+ return;
+
+ /* No shared attr fork extents */
+ error = xfs_refcount_find_shared(sa->refc_cur, bno,
+ irec->br_blockcount, &fbno, &flen, false);
+ if (!xfs_scrub_should_xref(info->sc, &error, &sa->refc_cur))
+ return;
+
+ if (flen != 0)
+ xfs_scrub_fblock_xref_set_corrupt(info->sc, info->whichfork,
+ irec->br_startoff);
+}
+
+/* Make sure the refcount records match this CoW fork extent. */
+STATIC void
+xfs_scrub_bmap_xref_refcount_cow(
+ struct xfs_scrub_bmap_info *info,
+ struct xfs_scrub_ag *sa,
+ struct xfs_bmbt_irec *irec,
+ xfs_fsblock_t bno)
+{
+ if (!sa->refc_cur)
+ return;
+
+ xfs_scrub_xref_has_cow_staging(info->sc, &sa->refc_cur, bno,
+ irec->br_blockcount);
+}
+
/* Cross-reference a single rtdev extent record. */
STATIC void
xfs_scrub_bmap_rt_extent_xref(
@@ -238,6 +306,17 @@ xfs_scrub_bmap_extent_xref(
xfs_scrub_xref_not_inodes(info->sc, &sa.ino_cur, agbno, len);
xfs_scrub_xref_not_inodes(info->sc, &sa.fino_cur, agbno, len);
xfs_scrub_bmap_xref_rmap(info, &sa, irec, agbno);
+ switch (info->whichfork) {
+ case XFS_DATA_FORK:
+ xfs_scrub_bmap_xref_refcount_data(info, &sa, irec, agbno);
+ break;
+ case XFS_ATTR_FORK:
+ xfs_scrub_bmap_xref_refcount_attr(info, &sa, irec, agbno);
+ break;
+ case XFS_COW_FORK:
+ xfs_scrub_bmap_xref_refcount_cow(info, &sa, irec, agbno);
+ break;
+ }
xfs_scrub_ag_free(info->sc, &sa);
}
diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c
index d4b7f13..367dd5f 100644
--- a/fs/xfs/scrub/ialloc.c
+++ b/fs/xfs/scrub/ialloc.c
@@ -94,6 +94,7 @@ xfs_scrub_iallocbt_chunk_xref(
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
xfs_scrub_xref_owned_by(sc, &sc->sa.rmap_cur, bno, len, &oinfo);
+ xfs_scrub_xref_not_shared(sc, &sc->sa.refc_cur, bno, len);
}
/* Is this chunk worth checking? */
diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
index bec67f4..2939fa7 100644
--- a/fs/xfs/scrub/inode.c
+++ b/fs/xfs/scrub/inode.c
@@ -581,6 +581,7 @@ xfs_scrub_inode_xref(
xfs_scrub_xref_are_inodes(sc, &sc->sa.fino_cur, agbno, 1);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
xfs_scrub_xref_owned_by(sc, &sc->sa.rmap_cur, agbno, 1, &oinfo);
+ xfs_scrub_xref_not_shared(sc, &sc->sa.refc_cur, agbno, 1);
xfs_scrub_ag_free(sc, &sa);
}
diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c
index 6efae58..dd54435 100644
--- a/fs/xfs/scrub/refcount.c
+++ b/fs/xfs/scrub/refcount.c
@@ -31,6 +31,7 @@
#include "xfs_sb.h"
#include "xfs_alloc.h"
#include "xfs_rmap.h"
+#include "xfs_refcount.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
@@ -426,3 +427,69 @@ xfs_scrub_refcountbt(
return error;
}
+
+/* xref check that a cow staging extent is marked in the refcountbt. */
+void
+xfs_scrub_xref_has_cow_staging(
+ struct xfs_scrub_context *sc,
+ struct xfs_btree_cur **pcur,
+ xfs_agblock_t bno,
+ xfs_extlen_t len)
+{
+ struct xfs_refcount_irec rc;
+ bool has_cowflag;
+ int has_refcount;
+ int error;
+
+ if (!(*pcur))
+ return;
+
+ /* Find the CoW staging extent. */
+ error = xfs_refcount_lookup_le(*pcur, bno + XFS_REFC_COW_START,
+ &has_refcount);
+ if (!xfs_scrub_should_xref(sc, &error, pcur))
+ return;
+ if (!has_refcount) {
+ xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
+ return;
+ }
+
+ error = xfs_refcount_get_rec(*pcur, &rc, &has_refcount);
+ if (!xfs_scrub_should_xref(sc, &error, pcur))
+ return;
+ if (!has_refcount) {
+ xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
+ return;
+ }
+
+ /* CoW flag must be set, refcount must be 1. */
+ has_cowflag = (rc.rc_startblock & XFS_REFC_COW_START);
+ if (!has_cowflag || rc.rc_refcount != 1)
+ xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
+
+ /* Must be at least as long as what was passed in */
+ if (rc.rc_blockcount < len)
+ xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
+}
+
+/*
+ * xref check that the extent is not shared. Only file data blocks
+ * can have multiple owners.
+ */
+void
+xfs_scrub_xref_not_shared(
+ struct xfs_scrub_context *sc,
+ struct xfs_btree_cur **pcur,
+ xfs_agblock_t bno,
+ xfs_extlen_t len)
+{
+ bool shared;
+ int error;
+
+ if (!(*pcur))
+ return;
+
+ error = xfs_refcount_has_record(*pcur, bno, len, &shared);
+ if (xfs_scrub_should_xref(sc, &error, pcur) && shared)
+ xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
+}
diff --git a/fs/xfs/scrub/rmap.c b/fs/xfs/scrub/rmap.c
index 7970e73..fee31e9 100644
--- a/fs/xfs/scrub/rmap.c
+++ b/fs/xfs/scrub/rmap.c
@@ -32,6 +32,7 @@
#include "xfs_alloc.h"
#include "xfs_ialloc.h"
#include "xfs_rmap.h"
+#include "xfs_refcount.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
@@ -51,6 +52,43 @@ xfs_scrub_setup_ag_rmapbt(
/* Reverse-mapping scrubber. */
+/* Cross-reference a rmap against the refcount btree. */
+STATIC void
+xfs_scrub_rmapbt_xref_refc(
+ struct xfs_scrub_context *sc,
+ struct xfs_btree_cur **pcur,
+ struct xfs_rmap_irec *irec)
+{
+ xfs_agblock_t fbno;
+ xfs_extlen_t flen;
+ bool non_inode;
+ bool is_bmbt;
+ bool is_attr;
+ bool is_unwritten;
+ int error;
+
+ if (!(*pcur))
+ return;
+
+ if (irec->rm_owner == XFS_RMAP_OWN_COW) {
+ xfs_scrub_xref_has_cow_staging(sc, pcur, irec->rm_startblock,
+ irec->rm_blockcount);
+ return;
+ }
+
+ 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;
+ is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
+
+ /* If this is shared, must be a data fork extent. */
+ error = xfs_refcount_find_shared(*pcur, irec->rm_startblock,
+ irec->rm_blockcount, &fbno, &flen, false);
+ if (xfs_scrub_should_xref(sc, &error, pcur) &&
+ flen != 0 && (non_inode || is_attr || is_bmbt || is_unwritten))
+ xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
+}
+
/* Cross-reference with the other btrees. */
STATIC void
xfs_scrub_rmapbt_xref(
@@ -67,6 +105,8 @@ xfs_scrub_rmapbt_xref(
xfs_scrub_xref_not_inodes(sc, &sc->sa.ino_cur, bno, len);
xfs_scrub_xref_not_inodes(sc, &sc->sa.fino_cur, bno, len);
}
+
+ xfs_scrub_rmapbt_xref_refc(sc, &sc->sa.refc_cur, irec);
}
/* Scrub an rmapbt record. */
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index 605b1c2..3ccfff2 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -131,5 +131,11 @@ void xfs_scrub_xref_not_owned_by(struct xfs_scrub_context *sc,
void xfs_scrub_xref_no_rmap(struct xfs_scrub_context *sc,
struct xfs_btree_cur **pcur, xfs_agblock_t bno,
xfs_extlen_t len);
+void xfs_scrub_xref_has_cow_staging(struct xfs_scrub_context *sc,
+ struct xfs_btree_cur **pcur, xfs_agblock_t bno,
+ xfs_extlen_t len);
+void xfs_scrub_xref_not_shared(struct xfs_scrub_context *sc,
+ struct xfs_btree_cur **pcur, xfs_agblock_t bno,
+ xfs_extlen_t len);
#endif /* __XFS_SCRUB_SCRUB_H__ */
next prev parent reply other threads:[~2017-11-29 1:26 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-29 1:25 [PATCH v10 00/16] xfs: online scrub xref support Darrick J. Wong
2017-11-29 1:25 ` [PATCH 01/16] xfs: add scrub cross-referencing helpers for the free space btrees Darrick J. Wong
2017-11-29 1:25 ` [PATCH 02/16] xfs: add scrub cross-referencing helpers for the inode btrees Darrick J. Wong
2017-11-29 1:25 ` [PATCH 03/16] xfs: add scrub cross-referencing helpers for the rmap btrees Darrick J. Wong
2017-11-29 1:25 ` [PATCH 04/16] xfs: add scrub cross-referencing helpers for the refcount btrees Darrick J. Wong
2017-11-29 1:25 ` [PATCH 05/16] xfs: set up scrub cross-referencing helpers Darrick J. Wong
2017-11-29 1:26 ` [PATCH 06/16] xfs: check btree block ownership with bnobt/rmapbt when scrubbing btree Darrick J. Wong
2017-11-29 1:26 ` [PATCH 07/16] xfs: introduce scrubber cross-referencing stubs Darrick J. Wong
2017-11-29 1:26 ` [PATCH 08/16] xfs: scrub should cross-reference with the bnobt Darrick J. Wong
2017-11-29 1:26 ` [PATCH 09/16] xfs: cross-reference bnobt records with cntbt Darrick J. Wong
2017-11-29 1:26 ` [PATCH 10/16] xfs: cross-reference inode btrees during scrub Darrick J. Wong
2017-11-29 1:26 ` [PATCH 11/16] xfs: cross-reference reverse-mapping btree Darrick J. Wong
2017-11-29 1:26 ` [PATCH 12/16] xfs: cross-reference the rmapbt data with the refcountbt Darrick J. Wong
2017-11-29 1:26 ` Darrick J. Wong [this message]
2017-11-29 1:26 ` [PATCH 14/16] xfs: scrub should cross-reference the realtime bitmap Darrick J. Wong
2017-11-29 1:26 ` [PATCH 15/16] xfs: cross-reference the block mappings when possible Darrick J. Wong
2017-11-29 1:27 ` [PATCH 16/16] xfs: abort scrubs if the oom killer fires Darrick J. Wong
-- strict thread matches above, loose matches on Subject: below --
2017-08-11 7:10 [PATCH v9 00/16] xfs: online scrub xref support Darrick J. Wong
2017-08-11 7:11 ` [PATCH 13/16] xfs: cross-reference refcount btree during scrub 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=151191880450.8553.15155347373871863670.stgit@magnolia \
--to=darrick.wong@oracle.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).