summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-05-21 17:07:56 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-08-10 09:58:06 -0700
commit22eebc103315e276e35c9102a40dd042d3893526 (patch)
tree129a3645636c641bdf0001b5a16f5fbce37bec02
parenta6ef885a916b87f0e62b322813c977d02b2c5b3d (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>
-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 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);