diff options
-rw-r--r-- | fs/xfs/scrub/agheader.c | 20 | ||||
-rw-r--r-- | fs/xfs/scrub/agheader_repair.c | 13 |
2 files changed, 33 insertions, 0 deletions
diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c index 1a6733aa05c6..b460e07cd865 100644 --- a/fs/xfs/scrub/agheader.c +++ b/fs/xfs/scrub/agheader.c @@ -781,6 +781,25 @@ xchk_agi_xref_icounts( xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp); } +/* Check agi_fino_blocks against tree size */ +static inline void +xchk_agi_xref_finoblks( + struct xfs_scrub *sc) +{ + struct xfs_agi *agi = XFS_BUF_TO_AGI(sc->sa.agi_bp); + xfs_agblock_t blocks; + int error; + + if (!sc->sa.fino_cur || !xfs_sb_version_hasfinobtblocks(&sc->mp->m_sb)) + return; + + error = xfs_btree_count_blocks(sc->sa.fino_cur, &blocks); + if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur)) + return; + if (blocks != be32_to_cpu(agi->agi_fino_blocks)) + xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp); +} + /* Cross-reference with the other btrees. */ STATIC void xchk_agi_xref( @@ -804,6 +823,7 @@ xchk_agi_xref( xchk_agi_xref_icounts(sc); xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); xchk_xref_is_not_shared(sc, agbno, 1); + xchk_agi_xref_finoblks(sc); /* scrub teardown will take care of sc->sa for us */ } diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c index 7a1a38b636a9..16bb0668cc8c 100644 --- a/fs/xfs/scrub/agheader_repair.c +++ b/fs/xfs/scrub/agheader_repair.c @@ -813,6 +813,7 @@ xrep_agi_calc_from_btrees( struct xfs_btree_cur *cur; struct xfs_agi *agi = XFS_BUF_TO_AGI(agi_bp); struct xfs_mount *mp = sc->mp; + xfs_agblock_t blocks; xfs_agino_t count; xfs_agino_t freecount; int error; @@ -826,6 +827,18 @@ xrep_agi_calc_from_btrees( agi->agi_count = cpu_to_be32(count); agi->agi_freecount = cpu_to_be32(freecount); + + /* Update the AGI counters from the finobt. */ + if (xfs_sb_version_hasfinobtblocks(&mp->m_sb)) { + cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp, sc->sa.agno, + XFS_BTNUM_FINO); + error = xfs_btree_count_blocks(cur, &blocks); + if (error) + goto err; + xfs_btree_del_cursor(cur, error); + agi->agi_fino_blocks = cpu_to_be32(blocks); + } + return 0; err: xfs_btree_del_cursor(cur, error); |