@@ -99,6 +99,30 @@ xfs_scrub_walk_agfl(
return 0;
}
+/* Does this AG extent cover the AG headers? */
+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;
+}
+
/* Superblock */
#define XFS_SCRUB_SB_CHECK(fs_ok) \
@@ -452,6 +476,9 @@ xfs_scrub_agfl_block(
XFS_SCRUB_AGFL_CHECK(agbno < mp->m_sb.sb_agblocks);
XFS_SCRUB_AGFL_CHECK(agbno < sagfl->eoag);
+ /* Cross-reference with the AG headers. */
+ XFS_SCRUB_AGFL_CHECK(!xfs_scrub_extent_covers_ag_head(mp, agbno, 1));
+
/* Cross-reference with the bnobt. */
if (sc->sa.bno_cur) {
err2 = xfs_alloc_has_record(sc->sa.bno_cur, agbno,
@@ -70,6 +70,10 @@ xfs_scrub_allocbt_helper(
if (error)
goto out;
+ /* Make sure we don't cover the AG headers. */
+ XFS_SCRUB_BTREC_CHECK(bs,
+ !xfs_scrub_extent_covers_ag_head(mp, bno, len));
+
psa = &bs->sc->sa;
/*
* Ensure there's a corresponding cntbt/bnobt record matching
@@ -121,6 +121,11 @@ xfs_scrub_bmap_extent(
XFS_SCRUB_BMAP_OP_ERROR_GOTO(out);
}
+ /* Make sure we don't cover the AG headers. */
+ if (!info->is_rt)
+ XFS_SCRUB_BMAP_CHECK(!xfs_scrub_extent_covers_ag_head(mp,
+ bno, irec->br_blockcount));
+
/* Cross-reference with the bnobt. */
if (sa.bno_cur) {
err2 = xfs_alloc_has_record(sa.bno_cur, bno,
@@ -203,6 +203,9 @@ int xfs_scrub_walk_agfl(struct xfs_scrub_context *sc,
int (*fn)(struct xfs_scrub_context *, xfs_agblock_t bno,
void *),
void *priv);
+bool xfs_scrub_extent_covers_ag_head(struct xfs_mount *mp, xfs_agblock_t agbno,
+ xfs_extlen_t len);
+
/* Metadata scrubbers */
int xfs_scrub_superblock(struct xfs_scrub_context *sc);
@@ -76,6 +76,10 @@ xfs_scrub_iallocbt_chunk(
goto out;
}
+ /* Make sure we don't cover the AG headers. */
+ XFS_SCRUB_BTREC_CHECK(bs,
+ !xfs_scrub_extent_covers_ag_head(mp, bno, len));
+
psa = &bs->sc->sa;
/* Cross-reference with the bnobt. */
if (psa->bno_cur) {
@@ -76,6 +76,10 @@ xfs_scrub_refcountbt_helper(
if (error)
goto out;
+ /* Make sure we don't cover the AG headers. */
+ XFS_SCRUB_BTREC_CHECK(bs, !xfs_scrub_extent_covers_ag_head(mp,
+ irec.rc_startblock, irec.rc_blockcount));
+
psa = &bs->sc->sa;
/* Cross-reference with the bnobt. */
if (psa->bno_cur) {
@@ -106,6 +106,11 @@ xfs_scrub_rmapbt_helper(
if (error)
goto out;
+ /* Make sure only the AG header owner maps to the AG header. */
+ XFS_SCRUB_BTREC_CHECK(bs, irec.rm_owner == XFS_RMAP_OWN_FS ||
+ !xfs_scrub_extent_covers_ag_head(mp, irec.rm_startblock,
+ irec.rm_blockcount));
+
psa = &bs->sc->sa;
/* check there's no record in freesp btrees */
if (psa->bno_cur) {
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/repair/agheader.c | 27 +++++++++++++++++++++++++++ fs/xfs/repair/alloc.c | 4 ++++ fs/xfs/repair/bmap.c | 5 +++++ fs/xfs/repair/common.h | 3 +++ fs/xfs/repair/ialloc.c | 4 ++++ fs/xfs/repair/refcount.c | 4 ++++ fs/xfs/repair/rmap.c | 5 +++++ 7 files changed, 52 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html