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@xxxxxxxxxx> --- fs/xfs/xfs_scrub.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) 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); _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs