]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: check inode btree block counters in AGI
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 20 Nov 2020 22:03:27 +0000 (17:03 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Fri, 20 Nov 2020 22:03:27 +0000 (17:03 -0500)
Make sure that both inode btree block counters in the AGI are correct.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
repair/scan.c

index 42b299f75067ab4b85057d08cdf2b7b350423350..a1d1ec941a8811b25c25916fcab28b5cf7e1cc10 100644 (file)
@@ -1948,6 +1948,12 @@ _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
        return suspect;
 }
 
+struct ino_priv {
+       struct aghdr_cnts       *agcnts;
+       uint32_t                ino_blocks;
+       uint32_t                fino_blocks;
+};
+
 /*
  * this one walks the inode btrees sucking the info there into
  * the incore avl tree.  We try and rescue corrupted btree records
@@ -1976,7 +1982,8 @@ scan_inobt(
        void                    *priv,
        const struct xfs_buf_ops *ops)
 {
-       struct aghdr_cnts       *agcnts = priv;
+       struct ino_priv         *ipriv = priv;
+       struct aghdr_cnts       *agcnts = ipriv->agcnts;
        char                    *name;
        xfs_agino_t             lastino = 0;
        int                     i;
@@ -1994,10 +2001,12 @@ scan_inobt(
        case XFS_FIBT_MAGIC:
        case XFS_FIBT_CRC_MAGIC:
                name = "fino";
+               ipriv->fino_blocks++;
                break;
        case XFS_IBT_MAGIC:
        case XFS_IBT_CRC_MAGIC:
                name = "ino";
+               ipriv->ino_blocks++;
                break;
        default:
                name = "(unknown)";
@@ -2347,6 +2356,9 @@ validate_agi(
        xfs_agnumber_t          agno,
        struct aghdr_cnts       *agcnts)
 {
+       struct ino_priv         priv = {
+               .agcnts = agcnts,
+       };
        xfs_agblock_t           bno;
        int                     i;
        uint32_t                magic;
@@ -2356,7 +2368,7 @@ validate_agi(
                magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_IBT_CRC_MAGIC
                                                         : XFS_IBT_MAGIC;
                scan_sbtree(bno, be32_to_cpu(agi->agi_level),
-                           agno, 0, scan_inobt, 1, magic, agcnts,
+                           agno, 0, scan_inobt, 1, magic, &priv,
                            &xfs_inobt_buf_ops);
        } else {
                do_warn(_("bad agbno %u for inobt root, agno %d\n"),
@@ -2369,7 +2381,7 @@ validate_agi(
                        magic = xfs_sb_version_hascrc(&mp->m_sb) ?
                                        XFS_FIBT_CRC_MAGIC : XFS_FIBT_MAGIC;
                        scan_sbtree(bno, be32_to_cpu(agi->agi_free_level),
-                                   agno, 0, scan_inobt, 1, magic, agcnts,
+                                   agno, 0, scan_inobt, 1, magic, &priv,
                                    &xfs_finobt_buf_ops);
                } else {
                        do_warn(_("bad agbno %u for finobt root, agno %d\n"),
@@ -2377,6 +2389,17 @@ validate_agi(
                }
        }
 
+       if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+               if (be32_to_cpu(agi->agi_iblocks) != priv.ino_blocks)
+                       do_warn(_("bad inobt block count %u, saw %u\n"),
+                                       be32_to_cpu(agi->agi_iblocks),
+                                       priv.ino_blocks);
+               if (be32_to_cpu(agi->agi_fblocks) != priv.fino_blocks)
+                       do_warn(_("bad finobt block count %u, saw %u\n"),
+                                       be32_to_cpu(agi->agi_fblocks),
+                                       priv.fino_blocks);
+       }
+
        if (be32_to_cpu(agi->agi_count) != agcnts->agicount) {
                do_warn(_("agi_count %u, counted %u in ag %u\n"),
                         be32_to_cpu(agi->agi_count), agcnts->agicount, agno);