summaryrefslogtreecommitdiff
path: root/fs/xfs
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-08-30 15:45:36 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-10-19 10:39:20 -0700
commitef92a592ce02a2a9840ed6ae59833e14296ecf05 (patch)
treef4dda56ad8713dc738d99b4bad5acfc537847d27 /fs/xfs
parent88e42dead2a4e81dde47bb9dc6fb777325bdd68f (diff)
xfs: scrub and repair finobt block counters
Check and repair the free inode btree block counters in the AGI. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/scrub/agheader.c20
-rw-r--r--fs/xfs/scrub/agheader_repair.c13
2 files changed, 33 insertions, 0 deletions
diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
index bf4356306e08..2bf38cf62a0e 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 f0cf205d3e73..cf95e98d6c1a 100644
--- a/fs/xfs/scrub/agheader_repair.c
+++ b/fs/xfs/scrub/agheader_repair.c
@@ -816,6 +816,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;
@@ -829,6 +830,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);