diff mbox

[20/25] xfs: cross-reference extents with AG header

Message ID 147216854170.3108.4876331933510244657.stgit@birch.djwong.org
State Superseded, archived
Headers show

Commit Message

Darrick J. Wong Aug. 25, 2016, 11:42 p.m. UTC
Ensure that none of the AG btree records overlap the AG sb/agf/agfl/agi
headers except for the XFS_RMAP_OWN_FS rmap.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/xfs_scrub.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
diff mbox

Patch

diff --git a/fs/xfs/xfs_scrub.c b/fs/xfs/xfs_scrub.c
index 66365e2..63a7434 100644
--- a/fs/xfs/xfs_scrub.c
+++ b/fs/xfs/xfs_scrub.c
@@ -434,6 +434,30 @@  xfs_scrub_put_ag_headers(
 	*agi_bpp = *agf_bpp = NULL;
 }
 
+/* Does this AG extent cover the AG headers? */
+STATIC bool
+xfs_scrub_extent_covers_ag_head(
+	struct xfs_mount	*mp,
+	xfs_agblock_t		agbno,
+	xfs_extlen_t		len)
+{
+	xfs_agblock_t		bno;
+
+	bno = XFS_SB_BLOCK(mp);
+	if (bno >= agbno && bno < agbno + len)
+		return true;
+	bno = XFS_AGF_BLOCK(mp);
+	if (bno >= agbno && bno < agbno + len)
+		return true;
+	bno = XFS_AGFL_BLOCK(mp);
+	if (bno >= agbno && bno < agbno + len)
+		return true;
+	bno = XFS_AGI_BLOCK(mp);
+	if (bno >= agbno && bno < agbno + len)
+		return true;
+	return false;
+}
+
 /*
  * For scrub, grab the AGI and the AGF headers, in that order.
  * Locking order requires us to get the AGI before the AGF.
@@ -1013,6 +1037,10 @@  xfs_scrub_agfl(
 		XFS_SCRUB_CHECK(mp, agfl_bp, "AGFL",
 				agbno < eoag);
 
+		/* Cross-reference with the AG headers. */
+		XFS_SCRUB_CHECK(mp, agfl_bp, "AGFL",
+				!xfs_scrub_extent_covers_ag_head(mp, agbno, 1));
+
 		/* Cross-reference with the bnobt. */
 		err2 = xfs_alloc_has_record(xcur, agbno, 1, &is_freesp);
 		if (!err2)
@@ -1117,6 +1145,10 @@  xfs_scrub_allocbt_helper(
 	XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <=
 			be32_to_cpu(agf->agf_length));
 
+	/* Make sure we don't cover the AG headers. */
+	XFS_BTREC_SCRUB_CHECK(bs,
+			!xfs_scrub_extent_covers_ag_head(mp, bno, len));
+
 	/*
 	 * Ensure there's a corresponding cntbt/bnobt record matching
 	 * this bnobt/cntbt record, respectively.
@@ -1233,6 +1265,10 @@  xfs_scrub_iallocbt_helper(
 		XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <=
 				eoag);
 
+		/* Make sure we don't cover the AG headers. */
+		XFS_BTREC_SCRUB_CHECK(bs,
+				!xfs_scrub_extent_covers_ag_head(mp, bno, len));
+
 		/* Cross-reference with the bnobt. */
 		err2 = xfs_alloc_has_record(bs->bno_cur, bno, len,
 				&is_freesp);
@@ -1267,6 +1303,10 @@  xfs_scrub_iallocbt_helper(
 		XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <=
 				eoag);
 
+		/* Make sure we don't cover the AG headers. */
+		XFS_BTREC_SCRUB_CHECK(bs,
+				!xfs_scrub_extent_covers_ag_head(mp, bno, len));
+
 		/* Cross-reference with the bnobt. */
 		err2 = xfs_alloc_has_record(bs->bno_cur, bno, len,
 				&is_freesp);
@@ -1378,6 +1418,11 @@  xfs_scrub_rmapbt_helper(
 	XFS_BTREC_SCRUB_CHECK(bs, !non_inode || !(is_bmbt || is_unwritten ||
 			is_attr));
 
+	/* Make sure only the AG header owner maps to the AG header. */
+	XFS_BTREC_SCRUB_CHECK(bs, irec.rm_owner == XFS_RMAP_OWN_FS ||
+			!xfs_scrub_extent_covers_ag_head(mp, irec.rm_startblock,
+				irec.rm_blockcount));
+
 	/* check there's no record in freesp btrees */
 	err2 = xfs_alloc_has_record(bs->bno_cur, irec.rm_startblock,
 			irec.rm_blockcount, &is_freesp);
@@ -1452,6 +1497,10 @@  xfs_scrub_refcountbt_helper(
 			irec.rc_blockcount <= eoag);
 	XFS_BTREC_SCRUB_CHECK(bs, irec.rc_refcount >= 1);
 
+	/* Make sure we don't cover the AG headers. */
+	XFS_BTREC_SCRUB_CHECK(bs, !xfs_scrub_extent_covers_ag_head(mp,
+			irec.rc_startblock, irec.rc_blockcount));
+
 	/* Cross-reference with the bnobt. */
 	err2 = xfs_alloc_has_record(bs->bno_cur, irec.rc_startblock,
 			irec.rc_blockcount, &is_freesp);
@@ -1639,6 +1688,11 @@  xfs_scrub_bmap_extent(
 		if (error)
 			goto out;
 
+		/* Make sure we don't cover the AG headers. */
+		XFS_INO_SCRUB_CHECK(ip, bp, info->type, info->is_rt ||
+				!xfs_scrub_extent_covers_ag_head(mp, bno,
+					irec->br_blockcount));
+
 		/* Cross-reference with the bnobt. */
 		xcur = xfs_allocbt_init_cursor(mp, NULL, agf_bp, agno,
 				XFS_BTNUM_BNO);