xfs: support inode btree blockcounts in online repair
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 26 Aug 2020 17:48:50 +0000 (10:48 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 16 Sep 2020 03:52:40 +0000 (20:52 -0700)
Add the necessary bits to the online repair code to support logging the
inode btree counters when rebuilding the btrees, and to support fixing
the counters when rebuilding the AGI.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/scrub/agheader_repair.c

index 28b179d96812c9bf29b0e380dd6ccd1e9d783709..cc919a2ee870f09c00e579eeae95bccb98338321 100644 (file)
@@ -501,19 +501,29 @@ xfs_inobt_commit_staged_btree(
 {
        struct xfs_agi          *agi = agbp->b_addr;
        struct xbtree_afakeroot *afake = cur->bc_ag.afake;
+       int                     fields;
 
        ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
 
        if (cur->bc_btnum == XFS_BTNUM_INO) {
+               fields = XFS_AGI_ROOT | XFS_AGI_LEVEL;
                agi->agi_root = cpu_to_be32(afake->af_root);
                agi->agi_level = cpu_to_be32(afake->af_levels);
-               xfs_ialloc_log_agi(tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL);
+               if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) {
+                       agi->agi_iblocks = cpu_to_be32(afake->af_blocks);
+                       fields |= XFS_AGI_IBLOCKS;
+               }
+               xfs_ialloc_log_agi(tp, agbp, fields);
                xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_inobt_ops);
        } else {
+               fields = XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL;
                agi->agi_free_root = cpu_to_be32(afake->af_root);
                agi->agi_free_level = cpu_to_be32(afake->af_levels);
-               xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREE_ROOT |
-                                            XFS_AGI_FREE_LEVEL);
+               if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) {
+                       agi->agi_fblocks = cpu_to_be32(afake->af_blocks);
+                       fields |= XFS_AGI_IBLOCKS;
+               }
+               xfs_ialloc_log_agi(tp, agbp, fields);
                xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_finobt_ops);
        }
 }
index bca2ab1d4be9cbe040e266f0aff883d001735c84..401f71579ce6d136b36fd176d7e9baca9f1a893f 100644 (file)
@@ -810,10 +810,34 @@ xrep_agi_calc_from_btrees(
        error = xfs_ialloc_count_inodes(cur, &count, &freecount);
        if (error)
                goto err;
+       if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+               xfs_agblock_t   blocks;
+
+               error = xfs_btree_count_blocks(cur, &blocks);
+               if (error)
+                       goto err;
+               agi->agi_iblocks = cpu_to_be32(blocks);
+       }
        xfs_btree_del_cursor(cur, error);
 
        agi->agi_count = cpu_to_be32(count);
        agi->agi_freecount = cpu_to_be32(freecount);
+
+       if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
+           xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+               xfs_agblock_t   blocks;
+
+               cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp, sc->sa.agno,
+                               XFS_BTNUM_FINO);
+               if (error)
+                       goto err;
+               error = xfs_btree_count_blocks(cur, &blocks);
+               if (error)
+                       goto err;
+               xfs_btree_del_cursor(cur, error);
+               agi->agi_fblocks = cpu_to_be32(blocks);
+       }
+
        return 0;
 err:
        xfs_btree_del_cursor(cur, error);