LCOV - code coverage report
Current view: top level - fs/xfs/scrub - agheader.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 404 497 81.3 %
Date: 2023-07-31 20:08:22 Functions: 19 19 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 2017-2023 Oracle.  All Rights Reserved.
       4             :  * Author: Darrick J. Wong <djwong@kernel.org>
       5             :  */
       6             : #include "xfs.h"
       7             : #include "xfs_fs.h"
       8             : #include "xfs_shared.h"
       9             : #include "xfs_format.h"
      10             : #include "xfs_trans_resv.h"
      11             : #include "xfs_mount.h"
      12             : #include "xfs_btree.h"
      13             : #include "xfs_sb.h"
      14             : #include "xfs_alloc.h"
      15             : #include "xfs_ialloc.h"
      16             : #include "xfs_rmap.h"
      17             : #include "xfs_ag.h"
      18             : #include "scrub/scrub.h"
      19             : #include "scrub/common.h"
      20             : 
      21             : int
      22     5694744 : xchk_setup_agheader(
      23             :         struct xfs_scrub        *sc)
      24             : {
      25     5694744 :         if (xchk_need_intent_drain(sc))
      26       77403 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      27     5694745 :         return xchk_setup_fs(sc);
      28             : }
      29             : 
      30             : /* Superblock */
      31             : 
      32             : /* Cross-reference with the other btrees. */
      33             : STATIC void
      34     1320173 : xchk_superblock_xref(
      35             :         struct xfs_scrub        *sc,
      36             :         struct xfs_buf          *bp)
      37             : {
      38     1320173 :         struct xfs_mount        *mp = sc->mp;
      39     1320173 :         xfs_agnumber_t          agno = sc->sm->sm_agno;
      40     1320173 :         xfs_agblock_t           agbno;
      41     1320173 :         int                     error;
      42             : 
      43     1320173 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
      44        6057 :                 return;
      45             : 
      46     1320192 :         agbno = XFS_SB_BLOCK(mp);
      47             : 
      48     1320192 :         error = xchk_ag_init_existing(sc, agno, &sc->sa);
      49     1322585 :         if (!xchk_xref_process_error(sc, agno, agbno, &error))
      50             :                 return;
      51             : 
      52     1315874 :         xchk_xref_is_used_space(sc, agbno, 1);
      53     1312330 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
      54     1316120 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
      55     1314332 :         xchk_xref_is_not_shared(sc, agbno, 1);
      56     1314747 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
      57             : 
      58             :         /* scrub teardown will take care of sc->sa for us */
      59             : }
      60             : 
      61             : /*
      62             :  * Scrub the filesystem superblock.
      63             :  *
      64             :  * Note: We do /not/ attempt to check AG 0's superblock.  Mount is
      65             :  * responsible for validating all the geometry information in sb 0, so
      66             :  * if the filesystem is capable of initiating online scrub, then clearly
      67             :  * sb 0 is ok and we can use its information to check everything else.
      68             :  */
      69             : int
      70     1704264 : xchk_superblock(
      71             :         struct xfs_scrub        *sc)
      72             : {
      73     1704264 :         struct xfs_mount        *mp = sc->mp;
      74     1704264 :         struct xfs_buf          *bp;
      75     1704264 :         struct xfs_dsb          *sb;
      76     1704264 :         struct xfs_perag        *pag;
      77     1704264 :         xfs_agnumber_t          agno;
      78     1704264 :         uint32_t                v2_ok;
      79     1704264 :         __be32                  features_mask;
      80     1704264 :         int                     error;
      81     1704264 :         __be16                  vernum_mask;
      82             : 
      83     1704264 :         agno = sc->sm->sm_agno;
      84     1704264 :         if (agno == 0)
      85             :                 return 0;
      86             : 
      87             :         /*
      88             :          * Grab an active reference to the perag structure.  If we can't get
      89             :          * it, we're racing with something that's tearing down the AG, so
      90             :          * signal that the AG no longer exists.
      91             :          */
      92     1320201 :         pag = xfs_perag_get(mp, agno);
      93     1323096 :         if (!pag)
      94             :                 return -ENOENT;
      95             : 
      96     1323096 :         error = xfs_sb_read_secondary(mp, sc->tp, agno, &bp);
      97             :         /*
      98             :          * The superblock verifier can return several different error codes
      99             :          * if it thinks the superblock doesn't look right.  For a mount these
     100             :          * would all get bounced back to userspace, but if we're here then the
     101             :          * fs mounted successfully, which means that this secondary superblock
     102             :          * is simply incorrect.  Treat all these codes the same way we treat
     103             :          * any corruption.
     104             :          */
     105     1321376 :         switch (error) {
     106          11 :         case -EINVAL:   /* also -EWRONGFS */
     107             :         case -ENOSYS:
     108             :         case -EFBIG:
     109          11 :                 error = -EFSCORRUPTED;
     110     1321376 :                 fallthrough;
     111             :         default:
     112     1321376 :                 break;
     113             :         }
     114     1321376 :         if (!xchk_process_error(sc, agno, XFS_SB_BLOCK(mp), &error))
     115          11 :                 goto out_pag;
     116             : 
     117     1321416 :         sb = bp->b_addr;
     118             : 
     119             :         /*
     120             :          * Verify the geometries match.  Fields that are permanently
     121             :          * set by mkfs are checked; fields that can be updated later
     122             :          * (and are not propagated to backup superblocks) are preen
     123             :          * checked.
     124             :          */
     125     1321416 :         if (sb->sb_blocksize != cpu_to_be32(mp->m_sb.sb_blocksize))
     126           0 :                 xchk_block_set_corrupt(sc, bp);
     127             : 
     128     1321416 :         if (sb->sb_dblocks != cpu_to_be64(mp->m_sb.sb_dblocks))
     129           0 :                 xchk_block_set_corrupt(sc, bp);
     130             : 
     131     1321416 :         if (sb->sb_rblocks != cpu_to_be64(mp->m_sb.sb_rblocks))
     132           0 :                 xchk_block_set_corrupt(sc, bp);
     133             : 
     134     1321416 :         if (sb->sb_rextents != cpu_to_be64(mp->m_sb.sb_rextents))
     135           0 :                 xchk_block_set_corrupt(sc, bp);
     136             : 
     137     1321416 :         if (!uuid_equal(&sb->sb_uuid, &mp->m_sb.sb_uuid))
     138           0 :                 xchk_block_set_preen(sc, bp);
     139             : 
     140     1321517 :         if (sb->sb_logstart != cpu_to_be64(mp->m_sb.sb_logstart))
     141           0 :                 xchk_block_set_corrupt(sc, bp);
     142             : 
     143     1321517 :         if (sb->sb_rootino != cpu_to_be64(mp->m_sb.sb_rootino))
     144      175382 :                 xchk_block_set_preen(sc, bp);
     145             : 
     146     1321499 :         if (sb->sb_rbmino != cpu_to_be64(mp->m_sb.sb_rbmino))
     147      435064 :                 xchk_block_set_preen(sc, bp);
     148             : 
     149     1321425 :         if (sb->sb_rsumino != cpu_to_be64(mp->m_sb.sb_rsumino))
     150      434907 :                 xchk_block_set_preen(sc, bp);
     151             : 
     152     1321554 :         if (sb->sb_rextsize != cpu_to_be32(mp->m_sb.sb_rextsize))
     153           0 :                 xchk_block_set_corrupt(sc, bp);
     154             : 
     155     1321554 :         if (sb->sb_agblocks != cpu_to_be32(mp->m_sb.sb_agblocks))
     156           0 :                 xchk_block_set_corrupt(sc, bp);
     157             : 
     158     1321554 :         if (sb->sb_agcount != cpu_to_be32(mp->m_sb.sb_agcount))
     159           0 :                 xchk_block_set_corrupt(sc, bp);
     160             : 
     161     1321554 :         if (sb->sb_rbmblocks != cpu_to_be32(mp->m_sb.sb_rbmblocks))
     162           0 :                 xchk_block_set_corrupt(sc, bp);
     163             : 
     164     1321554 :         if (sb->sb_logblocks != cpu_to_be32(mp->m_sb.sb_logblocks))
     165           0 :                 xchk_block_set_corrupt(sc, bp);
     166             : 
     167             :         /* Check sb_versionnum bits that are set at mkfs time. */
     168     1321554 :         vernum_mask = cpu_to_be16(~XFS_SB_VERSION_OKBITS |
     169             :                                   XFS_SB_VERSION_NUMBITS |
     170             :                                   XFS_SB_VERSION_ALIGNBIT |
     171             :                                   XFS_SB_VERSION_DALIGNBIT |
     172             :                                   XFS_SB_VERSION_SHAREDBIT |
     173             :                                   XFS_SB_VERSION_LOGV2BIT |
     174             :                                   XFS_SB_VERSION_SECTORBIT |
     175             :                                   XFS_SB_VERSION_EXTFLGBIT |
     176             :                                   XFS_SB_VERSION_DIRV2BIT);
     177     1321554 :         if ((sb->sb_versionnum & vernum_mask) !=
     178     1321554 :             (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask))
     179           0 :                 xchk_block_set_corrupt(sc, bp);
     180             : 
     181             :         /* Check sb_versionnum bits that can be set after mkfs time. */
     182     1321554 :         vernum_mask = cpu_to_be16(XFS_SB_VERSION_ATTRBIT |
     183             :                                   XFS_SB_VERSION_NLINKBIT |
     184             :                                   XFS_SB_VERSION_QUOTABIT);
     185     1321554 :         if ((sb->sb_versionnum & vernum_mask) !=
     186     1321554 :             (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask))
     187      353018 :                 xchk_block_set_preen(sc, bp);
     188             : 
     189     1321475 :         if (sb->sb_sectsize != cpu_to_be16(mp->m_sb.sb_sectsize))
     190           0 :                 xchk_block_set_corrupt(sc, bp);
     191             : 
     192     1321475 :         if (sb->sb_inodesize != cpu_to_be16(mp->m_sb.sb_inodesize))
     193           0 :                 xchk_block_set_corrupt(sc, bp);
     194             : 
     195     1321475 :         if (sb->sb_inopblock != cpu_to_be16(mp->m_sb.sb_inopblock))
     196           0 :                 xchk_block_set_corrupt(sc, bp);
     197             : 
     198     2642950 :         if (memcmp(sb->sb_fname, mp->m_sb.sb_fname, sizeof(sb->sb_fname)))
     199           0 :                 xchk_block_set_preen(sc, bp);
     200             : 
     201     1321475 :         if (sb->sb_blocklog != mp->m_sb.sb_blocklog)
     202           0 :                 xchk_block_set_corrupt(sc, bp);
     203             : 
     204     1321475 :         if (sb->sb_sectlog != mp->m_sb.sb_sectlog)
     205           0 :                 xchk_block_set_corrupt(sc, bp);
     206             : 
     207     1321475 :         if (sb->sb_inodelog != mp->m_sb.sb_inodelog)
     208           0 :                 xchk_block_set_corrupt(sc, bp);
     209             : 
     210     1321475 :         if (sb->sb_inopblog != mp->m_sb.sb_inopblog)
     211           0 :                 xchk_block_set_corrupt(sc, bp);
     212             : 
     213     1321475 :         if (sb->sb_agblklog != mp->m_sb.sb_agblklog)
     214           0 :                 xchk_block_set_corrupt(sc, bp);
     215             : 
     216     1321475 :         if (sb->sb_rextslog != mp->m_sb.sb_rextslog)
     217           0 :                 xchk_block_set_corrupt(sc, bp);
     218             : 
     219     1321475 :         if (sb->sb_imax_pct != mp->m_sb.sb_imax_pct)
     220           0 :                 xchk_block_set_preen(sc, bp);
     221             : 
     222             :         /*
     223             :          * Skip the summary counters since we track them in memory anyway.
     224             :          * sb_icount, sb_ifree, sb_fdblocks, sb_frexents
     225             :          */
     226             : 
     227     1321475 :         if (sb->sb_uquotino != cpu_to_be64(mp->m_sb.sb_uquotino))
     228      435140 :                 xchk_block_set_preen(sc, bp);
     229             : 
     230     1321275 :         if (sb->sb_gquotino != cpu_to_be64(mp->m_sb.sb_gquotino))
     231      434976 :                 xchk_block_set_preen(sc, bp);
     232             : 
     233             :         /*
     234             :          * Skip the quota flags since repair will force quotacheck.
     235             :          * sb_qflags
     236             :          */
     237             : 
     238     1321300 :         if (sb->sb_flags != mp->m_sb.sb_flags)
     239           0 :                 xchk_block_set_corrupt(sc, bp);
     240             : 
     241     1321300 :         if (sb->sb_shared_vn != mp->m_sb.sb_shared_vn)
     242           0 :                 xchk_block_set_corrupt(sc, bp);
     243             : 
     244     1321300 :         if (sb->sb_inoalignmt != cpu_to_be32(mp->m_sb.sb_inoalignmt))
     245           0 :                 xchk_block_set_corrupt(sc, bp);
     246             : 
     247     1321300 :         if (sb->sb_unit != cpu_to_be32(mp->m_sb.sb_unit))
     248           0 :                 xchk_block_set_preen(sc, bp);
     249             : 
     250     1321300 :         if (sb->sb_width != cpu_to_be32(mp->m_sb.sb_width))
     251         329 :                 xchk_block_set_preen(sc, bp);
     252             : 
     253     1321300 :         if (sb->sb_dirblklog != mp->m_sb.sb_dirblklog)
     254           0 :                 xchk_block_set_corrupt(sc, bp);
     255             : 
     256     1321300 :         if (sb->sb_logsectlog != mp->m_sb.sb_logsectlog)
     257           0 :                 xchk_block_set_corrupt(sc, bp);
     258             : 
     259     1321300 :         if (sb->sb_logsectsize != cpu_to_be16(mp->m_sb.sb_logsectsize))
     260           0 :                 xchk_block_set_corrupt(sc, bp);
     261             : 
     262     1321300 :         if (sb->sb_logsunit != cpu_to_be32(mp->m_sb.sb_logsunit))
     263           0 :                 xchk_block_set_corrupt(sc, bp);
     264             : 
     265             :         /* Do we see any invalid bits in sb_features2? */
     266     1321311 :         if (!xfs_sb_version_hasmorebits(&mp->m_sb)) {
     267           0 :                 if (sb->sb_features2 != 0)
     268           0 :                         xchk_block_set_corrupt(sc, bp);
     269             :         } else {
     270     1321300 :                 v2_ok = XFS_SB_VERSION2_OKBITS;
     271     1321300 :                 if (xfs_sb_is_v5(&mp->m_sb))
     272     1321167 :                         v2_ok |= XFS_SB_VERSION2_CRCBIT;
     273             : 
     274     1321300 :                 if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok)))
     275           0 :                         xchk_block_set_corrupt(sc, bp);
     276             : 
     277     1321300 :                 if (sb->sb_features2 != sb->sb_bad_features2)
     278           0 :                         xchk_block_set_preen(sc, bp);
     279             :         }
     280             : 
     281             :         /* Check sb_features2 flags that are set at mkfs time. */
     282     1321300 :         features_mask = cpu_to_be32(XFS_SB_VERSION2_LAZYSBCOUNTBIT |
     283             :                                     XFS_SB_VERSION2_PROJID32BIT |
     284             :                                     XFS_SB_VERSION2_CRCBIT |
     285             :                                     XFS_SB_VERSION2_FTYPE);
     286     1321300 :         if ((sb->sb_features2 & features_mask) !=
     287     1321300 :             (cpu_to_be32(mp->m_sb.sb_features2) & features_mask))
     288           0 :                 xchk_block_set_corrupt(sc, bp);
     289             : 
     290             :         /* Check sb_features2 flags that can be set after mkfs time. */
     291     1321300 :         features_mask = cpu_to_be32(XFS_SB_VERSION2_ATTR2BIT);
     292     1321300 :         if ((sb->sb_features2 & features_mask) !=
     293     1321300 :             (cpu_to_be32(mp->m_sb.sb_features2) & features_mask))
     294           0 :                 xchk_block_set_preen(sc, bp);
     295             : 
     296     1320422 :         if (!xfs_has_crc(mp)) {
     297             :                 /* all v5 fields must be zero */
     298          22 :                 if (memchr_inv(&sb->sb_features_compat, 0,
     299             :                                 sizeof(struct xfs_dsb) -
     300             :                                 offsetof(struct xfs_dsb, sb_features_compat)))
     301           0 :                         xchk_block_set_corrupt(sc, bp);
     302             :         } else {
     303             :                 /* compat features must match */
     304     1320411 :                 if (sb->sb_features_compat !=
     305     1320411 :                                 cpu_to_be32(mp->m_sb.sb_features_compat))
     306           0 :                         xchk_block_set_corrupt(sc, bp);
     307             : 
     308             :                 /* ro compat features must match */
     309     1320411 :                 if (sb->sb_features_ro_compat !=
     310     1320411 :                                 cpu_to_be32(mp->m_sb.sb_features_ro_compat))
     311           0 :                         xchk_block_set_corrupt(sc, bp);
     312             : 
     313             :                 /*
     314             :                  * NEEDSREPAIR is ignored on a secondary super, so we should
     315             :                  * clear it when we find it, though it's not a corruption.
     316             :                  */
     317     1320411 :                 features_mask = cpu_to_be32(XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR);
     318     1320411 :                 if ((cpu_to_be32(mp->m_sb.sb_features_incompat) ^
     319     1320411 :                                 sb->sb_features_incompat) & features_mask)
     320           0 :                         xchk_block_set_preen(sc, bp);
     321             : 
     322             :                 /* all other incompat features must match */
     323     1320411 :                 if ((cpu_to_be32(mp->m_sb.sb_features_incompat) ^
     324     1320411 :                                 sb->sb_features_incompat) & ~features_mask)
     325           0 :                         xchk_block_set_corrupt(sc, bp);
     326             : 
     327             :                 /*
     328             :                  * log incompat features protect newer log record types from
     329             :                  * older log recovery code.  Log recovery doesn't check the
     330             :                  * secondary supers, so we can clear these if needed.
     331             :                  */
     332     1320411 :                 if (sb->sb_features_log_incompat)
     333        2397 :                         xchk_block_set_preen(sc, bp);
     334             : 
     335             :                 /* Don't care about sb_crc */
     336             : 
     337     1320410 :                 if (sb->sb_spino_align != cpu_to_be32(mp->m_sb.sb_spino_align))
     338           0 :                         xchk_block_set_corrupt(sc, bp);
     339             : 
     340     1320410 :                 if (sb->sb_pquotino != cpu_to_be64(mp->m_sb.sb_pquotino))
     341      434874 :                         xchk_block_set_preen(sc, bp);
     342             : 
     343             :                 /* Don't care about sb_lsn */
     344             :         }
     345             : 
     346     1320459 :         if (xfs_has_metauuid(mp)) {
     347             :                 /* The metadata UUID must be the same for all supers */
     348          24 :                 if (!uuid_equal(&sb->sb_meta_uuid, &mp->m_sb.sb_meta_uuid))
     349           0 :                         xchk_block_set_corrupt(sc, bp);
     350             :         }
     351             : 
     352             :         /* Everything else must be zero. */
     353     1320614 :         if (memchr_inv(sb + 1, 0,
     354     1320459 :                         BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
     355           0 :                 xchk_block_set_corrupt(sc, bp);
     356             : 
     357     1320614 :         xchk_superblock_xref(sc, bp);
     358     1321010 : out_pag:
     359     1321010 :         xfs_perag_put(pag);
     360     1322591 :         return error;
     361             : }
     362             : 
     363             : /* AGF */
     364             : 
     365             : /* Tally freespace record lengths. */
     366             : STATIC int
     367  1850322239 : xchk_agf_record_bno_lengths(
     368             :         struct xfs_btree_cur            *cur,
     369             :         const struct xfs_alloc_rec_incore *rec,
     370             :         void                            *priv)
     371             : {
     372  1850322239 :         xfs_extlen_t                    *blocks = priv;
     373             : 
     374  1850322239 :         (*blocks) += rec->ar_blockcount;
     375  1850322239 :         return 0;
     376             : }
     377             : 
     378             : /* Check agf_freeblks */
     379             : static inline void
     380     1273665 : xchk_agf_xref_freeblks(
     381             :         struct xfs_scrub        *sc)
     382             : {
     383     1273665 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     384     1273665 :         xfs_extlen_t            blocks = 0;
     385     1273665 :         int                     error;
     386             : 
     387     1273665 :         if (!sc->sa.bno_cur)
     388           0 :                 return;
     389             : 
     390     1273665 :         error = xfs_alloc_query_all(sc->sa.bno_cur,
     391             :                         xchk_agf_record_bno_lengths, &blocks);
     392     1274496 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
     393             :                 return;
     394     1274026 :         if (blocks != be32_to_cpu(agf->agf_freeblks))
     395           0 :                 xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
     396             : }
     397             : 
     398             : /* Cross reference the AGF with the cntbt (freespace by length btree) */
     399             : static inline void
     400     1273886 : xchk_agf_xref_cntbt(
     401             :         struct xfs_scrub        *sc)
     402             : {
     403     1273886 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     404     1273886 :         xfs_agblock_t           agbno;
     405     1273886 :         xfs_extlen_t            blocks;
     406     1273886 :         int                     have;
     407     1273886 :         int                     error;
     408             : 
     409     1273886 :         if (!sc->sa.cnt_cur)
     410          12 :                 return;
     411             : 
     412             :         /* Any freespace at all? */
     413     1273886 :         error = xfs_alloc_lookup_le(sc->sa.cnt_cur, 0, -1U, &have);
     414     1275050 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
     415             :                 return;
     416     1274243 :         if (!have) {
     417          12 :                 if (agf->agf_freeblks != cpu_to_be32(0))
     418           0 :                         xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
     419          12 :                 return;
     420             :         }
     421             : 
     422             :         /* Check agf_longest */
     423     1274231 :         error = xfs_alloc_get_rec(sc->sa.cnt_cur, &agbno, &blocks, &have);
     424     1274190 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
     425             :                 return;
     426     1274094 :         if (!have || blocks != be32_to_cpu(agf->agf_longest))
     427          52 :                 xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
     428             : }
     429             : 
     430             : /* Check the btree block counts in the AGF against the btrees. */
     431             : STATIC void
     432     1273835 : xchk_agf_xref_btreeblks(
     433             :         struct xfs_scrub        *sc)
     434             : {
     435     1273835 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     436     1273835 :         struct xfs_mount        *mp = sc->mp;
     437     1273835 :         xfs_agblock_t           blocks;
     438     1273835 :         xfs_agblock_t           btreeblks;
     439     1273835 :         int                     error;
     440             : 
     441             :         /* agf_btreeblks didn't exist before lazysbcount */
     442     1273835 :         if (!xfs_has_lazysbcount(sc->mp))
     443          13 :                 return;
     444             : 
     445             :         /* Check agf_rmap_blocks; set up for agf_btreeblks check */
     446     1273835 :         if (sc->sa.rmap_cur) {
     447      905483 :                 error = xfs_btree_count_blocks(sc->sa.rmap_cur, &blocks);
     448      904612 :                 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     449             :                         return;
     450      904274 :                 btreeblks = blocks - 1;
     451      904274 :                 if (blocks != be32_to_cpu(agf->agf_rmap_blocks))
     452           0 :                         xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
     453             :         } else {
     454             :                 btreeblks = 0;
     455             :         }
     456             : 
     457             :         /*
     458             :          * No rmap cursor; we can't xref if we have the rmapbt feature.
     459             :          * We also can't do it if we're missing the free space btree cursors.
     460             :          */
     461     1272626 :         if ((xfs_has_rmapbt(mp) && !sc->sa.rmap_cur) ||
     462     1272626 :             !sc->sa.bno_cur || !sc->sa.cnt_cur)
     463             :                 return;
     464             : 
     465             :         /* Check agf_btreeblks */
     466     1272626 :         error = xfs_btree_count_blocks(sc->sa.bno_cur, &blocks);
     467     1274184 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
     468             :                 return;
     469     1274181 :         btreeblks += blocks - 1;
     470             : 
     471     1274181 :         error = xfs_btree_count_blocks(sc->sa.cnt_cur, &blocks);
     472     1275515 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
     473             :                 return;
     474     1275446 :         btreeblks += blocks - 1;
     475             : 
     476     1275446 :         if (btreeblks != be32_to_cpu(agf->agf_btreeblks))
     477           0 :                 xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
     478             : }
     479             : 
     480             : /* Check agf_refcount_blocks against tree size */
     481             : static inline void
     482     1273790 : xchk_agf_xref_refcblks(
     483             :         struct xfs_scrub        *sc)
     484             : {
     485     1273790 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     486     1273790 :         xfs_agblock_t           blocks;
     487     1273790 :         int                     error;
     488             : 
     489     1273790 :         if (!sc->sa.refc_cur)
     490      367755 :                 return;
     491             : 
     492      906035 :         error = xfs_btree_count_blocks(sc->sa.refc_cur, &blocks);
     493      906362 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
     494             :                 return;
     495      906409 :         if (blocks != be32_to_cpu(agf->agf_refcount_blocks))
     496           0 :                 xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
     497             : }
     498             : 
     499             : /* Cross-reference with the other btrees. */
     500             : STATIC void
     501     1274383 : xchk_agf_xref(
     502             :         struct xfs_scrub        *sc)
     503             : {
     504     1274383 :         struct xfs_mount        *mp = sc->mp;
     505     1274383 :         xfs_agblock_t           agbno;
     506             : 
     507     1274383 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     508             :                 return;
     509             : 
     510     1274383 :         agbno = XFS_AGF_BLOCK(mp);
     511             : 
     512     1274383 :         xchk_ag_btcur_init(sc, &sc->sa);
     513             : 
     514     1275568 :         xchk_xref_is_used_space(sc, agbno, 1);
     515     1273296 :         xchk_agf_xref_freeblks(sc);
     516     1273852 :         xchk_agf_xref_cntbt(sc);
     517     1273981 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
     518     1275228 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
     519     1274145 :         xchk_agf_xref_btreeblks(sc);
     520     1274903 :         xchk_xref_is_not_shared(sc, agbno, 1);
     521     1273714 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     522     1273951 :         xchk_agf_xref_refcblks(sc);
     523             : 
     524             :         /* scrub teardown will take care of sc->sa for us */
     525             : }
     526             : 
     527             : /* Scrub the AGF. */
     528             : int
     529     1298622 : xchk_agf(
     530             :         struct xfs_scrub        *sc)
     531             : {
     532     1298622 :         struct xfs_mount        *mp = sc->mp;
     533     1298622 :         struct xfs_agf          *agf;
     534     1298622 :         struct xfs_perag        *pag;
     535     1298622 :         xfs_agnumber_t          agno = sc->sm->sm_agno;
     536     1298622 :         xfs_agblock_t           agbno;
     537     1298622 :         xfs_agblock_t           eoag;
     538     1298622 :         xfs_agblock_t           agfl_first;
     539     1298622 :         xfs_agblock_t           agfl_last;
     540     1298622 :         xfs_agblock_t           agfl_count;
     541     1298622 :         xfs_agblock_t           fl_count;
     542     1298622 :         int                     level;
     543     1298622 :         int                     error = 0;
     544             : 
     545     1298622 :         error = xchk_ag_read_headers(sc, agno, &sc->sa);
     546     1298478 :         if (!xchk_process_error(sc, agno, XFS_AGF_BLOCK(sc->mp), &error))
     547       23678 :                 goto out;
     548     1274557 :         xchk_buffer_recheck(sc, sc->sa.agf_bp);
     549             : 
     550     1274009 :         agf = sc->sa.agf_bp->b_addr;
     551     1274009 :         pag = sc->sa.pag;
     552             : 
     553             :         /* Check the AG length */
     554     1274009 :         eoag = be32_to_cpu(agf->agf_length);
     555     1274009 :         if (eoag != pag->block_count)
     556           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     557             : 
     558             :         /* Check the AGF btree roots and levels */
     559     1274009 :         agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]);
     560     1274009 :         if (!xfs_verify_agbno(pag, agbno))
     561           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     562             : 
     563     1273853 :         agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]);
     564     1273853 :         if (!xfs_verify_agbno(pag, agbno))
     565           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     566             : 
     567     1273633 :         level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]);
     568     1273633 :         if (level <= 0 || level > mp->m_alloc_maxlevels)
     569           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     570             : 
     571     1273510 :         level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
     572     1273510 :         if (level <= 0 || level > mp->m_alloc_maxlevels)
     573           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     574             : 
     575     1273432 :         if (xfs_has_rmapbt(mp)) {
     576      905572 :                 agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]);
     577      905572 :                 if (!xfs_verify_agbno(pag, agbno))
     578           0 :                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     579             : 
     580      905608 :                 level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
     581      905608 :                 if (level <= 0 || level > mp->m_rmap_maxlevels)
     582           0 :                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     583             :         }
     584             : 
     585     1273468 :         if (xfs_has_reflink(mp)) {
     586      905629 :                 agbno = be32_to_cpu(agf->agf_refcount_root);
     587      905629 :                 if (!xfs_verify_agbno(pag, agbno))
     588           0 :                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     589             : 
     590      905546 :                 level = be32_to_cpu(agf->agf_refcount_level);
     591      905546 :                 if (level <= 0 || level > mp->m_refc_maxlevels)
     592           0 :                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     593             :         }
     594             : 
     595             :         /* Check the AGFL counters */
     596     1273385 :         agfl_first = be32_to_cpu(agf->agf_flfirst);
     597     1273385 :         agfl_last = be32_to_cpu(agf->agf_fllast);
     598     1273385 :         agfl_count = be32_to_cpu(agf->agf_flcount);
     599     1273385 :         if (agfl_last > agfl_first)
     600     1258366 :                 fl_count = agfl_last - agfl_first + 1;
     601             :         else
     602       15019 :                 fl_count = xfs_agfl_size(mp) - agfl_first + agfl_last + 1;
     603     1273397 :         if (agfl_count != 0 && fl_count != agfl_count)
     604           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     605             : 
     606             :         /* Do the incore counters match? */
     607     1273397 :         if (pag->pagf_freeblks != be32_to_cpu(agf->agf_freeblks))
     608           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     609     1273397 :         if (pag->pagf_flcount != be32_to_cpu(agf->agf_flcount))
     610           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     611     1273397 :         if (xfs_has_lazysbcount(sc->mp) &&
     612     1273073 :             pag->pagf_btreeblks != be32_to_cpu(agf->agf_btreeblks))
     613           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     614             : 
     615     1273397 :         xchk_agf_xref(sc);
     616     1298026 : out:
     617     1298026 :         return error;
     618             : }
     619             : 
     620             : /* AGFL */
     621             : 
     622             : struct xchk_agfl_info {
     623             :         /* Number of AGFL entries that the AGF claims are in use. */
     624             :         unsigned int            agflcount;
     625             : 
     626             :         /* Number of AGFL entries that we found. */
     627             :         unsigned int            nr_entries;
     628             : 
     629             :         /* Buffer to hold AGFL entries for extent checking. */
     630             :         xfs_agblock_t           *entries;
     631             : 
     632             :         struct xfs_buf          *agfl_bp;
     633             :         struct xfs_scrub        *sc;
     634             : };
     635             : 
     636             : /* Cross-reference with the other btrees. */
     637             : STATIC void
     638     8184330 : xchk_agfl_block_xref(
     639             :         struct xfs_scrub        *sc,
     640             :         xfs_agblock_t           agbno)
     641             : {
     642     8184330 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     643             :                 return;
     644             : 
     645     8184317 :         xchk_xref_is_used_space(sc, agbno, 1);
     646     8184256 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
     647     8190300 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG);
     648     8185225 :         xchk_xref_is_not_shared(sc, agbno, 1);
     649     8186126 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     650             : }
     651             : 
     652             : /* Scrub an AGFL block. */
     653             : STATIC int
     654     8184769 : xchk_agfl_block(
     655             :         struct xfs_mount        *mp,
     656             :         xfs_agblock_t           agbno,
     657             :         void                    *priv)
     658             : {
     659     8184769 :         struct xchk_agfl_info   *sai = priv;
     660     8184769 :         struct xfs_scrub        *sc = sai->sc;
     661             : 
     662     8184769 :         if (xfs_verify_agbno(sc->sa.pag, agbno) &&
     663     8184769 :             sai->nr_entries < sai->agflcount)
     664     8184414 :                 sai->entries[sai->nr_entries++] = agbno;
     665             :         else
     666         355 :                 xchk_block_set_corrupt(sc, sai->agfl_bp);
     667             : 
     668     8184414 :         xchk_agfl_block_xref(sc, agbno);
     669             : 
     670     8186858 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     671           0 :                 return -ECANCELED;
     672             : 
     673             :         return 0;
     674             : }
     675             : 
     676             : static int
     677    20441000 : xchk_agblock_cmp(
     678             :         const void              *pa,
     679             :         const void              *pb)
     680             : {
     681    20441000 :         const xfs_agblock_t     *a = pa;
     682    20441000 :         const xfs_agblock_t     *b = pb;
     683             : 
     684    20441000 :         return (int)*a - (int)*b;
     685             : }
     686             : 
     687             : /* Cross-reference with the other btrees. */
     688             : STATIC void
     689     1319258 : xchk_agfl_xref(
     690             :         struct xfs_scrub        *sc)
     691             : {
     692     1319258 :         struct xfs_mount        *mp = sc->mp;
     693     1319258 :         xfs_agblock_t           agbno;
     694             : 
     695     1319258 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     696             :                 return;
     697             : 
     698     1319258 :         agbno = XFS_AGFL_BLOCK(mp);
     699             : 
     700     1319258 :         xchk_ag_btcur_init(sc, &sc->sa);
     701             : 
     702     1319990 :         xchk_xref_is_used_space(sc, agbno, 1);
     703     1317310 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
     704     1319274 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
     705     1318393 :         xchk_xref_is_not_shared(sc, agbno, 1);
     706     1318842 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     707             : 
     708             :         /*
     709             :          * Scrub teardown will take care of sc->sa for us.  Leave sc->sa
     710             :          * active so that the agfl block xref can use it too.
     711             :          */
     712             : }
     713             : 
     714             : /* Scrub the AGFL. */
     715             : int
     716     1342489 : xchk_agfl(
     717             :         struct xfs_scrub        *sc)
     718             : {
     719     1342489 :         struct xchk_agfl_info   sai = {
     720             :                 .sc             = sc,
     721             :         };
     722     1342489 :         struct xfs_agf          *agf;
     723     1342489 :         xfs_agnumber_t          agno = sc->sm->sm_agno;
     724     1342489 :         unsigned int            i;
     725     1342489 :         int                     error;
     726             : 
     727             :         /* Lock the AGF and AGI so that nobody can touch this AG. */
     728     1342489 :         error = xchk_ag_read_headers(sc, agno, &sc->sa);
     729     1342902 :         if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
     730       24377 :                 return error;
     731     1317875 :         if (!sc->sa.agf_bp)
     732             :                 return -EFSCORRUPTED;
     733             : 
     734             :         /* Try to read the AGFL, and verify its structure if we get it. */
     735     1317875 :         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &sai.agfl_bp);
     736     1319697 :         if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
     737           0 :                 return error;
     738     1319533 :         xchk_buffer_recheck(sc, sai.agfl_bp);
     739             : 
     740     1319457 :         xchk_agfl_xref(sc);
     741             : 
     742     1318542 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     743           0 :                 goto out;
     744             : 
     745             :         /* Allocate buffer to ensure uniqueness of AGFL entries. */
     746     1318542 :         agf = sc->sa.agf_bp->b_addr;
     747     1318542 :         sai.agflcount = be32_to_cpu(agf->agf_flcount);
     748     1318542 :         if (sai.agflcount > xfs_agfl_size(sc->mp)) {
     749           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     750           0 :                 goto out;
     751             :         }
     752     1316480 :         sai.entries = kvcalloc(sai.agflcount, sizeof(xfs_agblock_t),
     753             :                                XCHK_GFP_FLAGS);
     754     1318843 :         if (!sai.entries) {
     755           0 :                 error = -ENOMEM;
     756           0 :                 goto out;
     757             :         }
     758             : 
     759             :         /* Check the blocks in the AGFL. */
     760     1318843 :         error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr, sai.agfl_bp,
     761             :                         xchk_agfl_block, &sai);
     762     1319314 :         if (error == -ECANCELED) {
     763           0 :                 error = 0;
     764           0 :                 goto out_free;
     765             :         }
     766     1319314 :         if (error)
     767           0 :                 goto out_free;
     768             : 
     769     1319314 :         if (sai.agflcount != sai.nr_entries) {
     770           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     771           0 :                 goto out_free;
     772             :         }
     773             : 
     774             :         /* Sort entries, check for duplicates. */
     775     1319314 :         sort(sai.entries, sai.nr_entries, sizeof(sai.entries[0]),
     776             :                         xchk_agblock_cmp, NULL);
     777     9506665 :         for (i = 1; i < sai.nr_entries; i++) {
     778     6869803 :                 if (sai.entries[i] == sai.entries[i - 1]) {
     779           0 :                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     780           0 :                         break;
     781             :                 }
     782             :         }
     783             : 
     784     1317548 : out_free:
     785     1317548 :         kvfree(sai.entries);
     786     1318001 : out:
     787     1318001 :         return error;
     788             : }
     789             : 
     790             : /* AGI */
     791             : 
     792             : /* Check agi_count/agi_freecount */
     793             : static inline void
     794     1320419 : xchk_agi_xref_icounts(
     795             :         struct xfs_scrub        *sc)
     796             : {
     797     1320419 :         struct xfs_agi          *agi = sc->sa.agi_bp->b_addr;
     798     1320419 :         xfs_agino_t             icount;
     799     1320419 :         xfs_agino_t             freecount;
     800     1320419 :         int                     error;
     801             : 
     802     1320419 :         if (!sc->sa.ino_cur)
     803           0 :                 return;
     804             : 
     805     1320419 :         error = xfs_ialloc_count_inodes(sc->sa.ino_cur, &icount, &freecount);
     806     1319901 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur))
     807             :                 return;
     808     1319608 :         if (be32_to_cpu(agi->agi_count) != icount ||
     809     1319608 :             be32_to_cpu(agi->agi_freecount) != freecount)
     810          26 :                 xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp);
     811             : }
     812             : 
     813             : /* Check agi_[fi]blocks against tree size */
     814             : static inline void
     815     1320096 : xchk_agi_xref_fiblocks(
     816             :         struct xfs_scrub        *sc)
     817             : {
     818     1320096 :         struct xfs_agi          *agi = sc->sa.agi_bp->b_addr;
     819     1320096 :         xfs_agblock_t           blocks;
     820     1320096 :         int                     error = 0;
     821             : 
     822     1320096 :         if (!xfs_has_inobtcounts(sc->mp))
     823          22 :                 return;
     824             : 
     825     1320074 :         if (sc->sa.ino_cur) {
     826     1319796 :                 error = xfs_btree_count_blocks(sc->sa.ino_cur, &blocks);
     827     1318811 :                 if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur))
     828             :                         return;
     829     1318853 :                 if (blocks != be32_to_cpu(agi->agi_iblocks))
     830           0 :                         xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp);
     831             :         }
     832             : 
     833     1319131 :         if (sc->sa.fino_cur) {
     834     1319168 :                 error = xfs_btree_count_blocks(sc->sa.fino_cur, &blocks);
     835     1320810 :                 if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur))
     836             :                         return;
     837     1320753 :                 if (blocks != be32_to_cpu(agi->agi_fblocks))
     838           0 :                         xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp);
     839             :         }
     840             : }
     841             : 
     842             : /* Cross-reference with the other btrees. */
     843             : STATIC void
     844     1319310 : xchk_agi_xref(
     845             :         struct xfs_scrub        *sc)
     846             : {
     847     1319310 :         struct xfs_mount        *mp = sc->mp;
     848     1319310 :         xfs_agblock_t           agbno;
     849             : 
     850     1319310 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     851             :                 return;
     852             : 
     853     1319310 :         agbno = XFS_AGI_BLOCK(mp);
     854             : 
     855     1319310 :         xchk_ag_btcur_init(sc, &sc->sa);
     856             : 
     857     1321000 :         xchk_xref_is_used_space(sc, agbno, 1);
     858     1318680 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
     859     1320573 :         xchk_agi_xref_icounts(sc);
     860     1318983 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
     861     1319309 :         xchk_xref_is_not_shared(sc, agbno, 1);
     862     1319800 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     863     1319700 :         xchk_agi_xref_fiblocks(sc);
     864             : 
     865             :         /* scrub teardown will take care of sc->sa for us */
     866             : }
     867             : 
     868             : /* Scrub the AGI. */
     869             : int
     870     1343496 : xchk_agi(
     871             :         struct xfs_scrub        *sc)
     872             : {
     873     1343496 :         struct xfs_mount        *mp = sc->mp;
     874     1343496 :         struct xfs_agi          *agi;
     875     1343496 :         struct xfs_perag        *pag;
     876     1343496 :         struct xfs_ino_geometry *igeo = M_IGEO(sc->mp);
     877     1343496 :         xfs_agnumber_t          agno = sc->sm->sm_agno;
     878     1343496 :         xfs_agblock_t           agbno;
     879     1343496 :         xfs_agblock_t           eoag;
     880     1343496 :         xfs_agino_t             agino;
     881     1343496 :         xfs_agino_t             first_agino;
     882     1343496 :         xfs_agino_t             last_agino;
     883     1343496 :         xfs_agino_t             icount;
     884     1343496 :         int                     i;
     885     1343496 :         int                     level;
     886     1343496 :         int                     error = 0;
     887             : 
     888     1343496 :         error = xchk_ag_read_headers(sc, agno, &sc->sa);
     889     1343140 :         if (!xchk_process_error(sc, agno, XFS_AGI_BLOCK(sc->mp), &error))
     890       23542 :                 goto out;
     891     1319058 :         xchk_buffer_recheck(sc, sc->sa.agi_bp);
     892             : 
     893     1320030 :         agi = sc->sa.agi_bp->b_addr;
     894     1320030 :         pag = sc->sa.pag;
     895             : 
     896             :         /* Check the AG length */
     897     1320030 :         eoag = be32_to_cpu(agi->agi_length);
     898     1320030 :         if (eoag != pag->block_count)
     899           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     900             : 
     901             :         /* Check btree roots and levels */
     902     1320030 :         agbno = be32_to_cpu(agi->agi_root);
     903     1320030 :         if (!xfs_verify_agbno(pag, agbno))
     904           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     905             : 
     906     1320007 :         level = be32_to_cpu(agi->agi_level);
     907     1320007 :         if (level <= 0 || level > igeo->inobt_maxlevels)
     908           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     909             : 
     910     1319762 :         if (xfs_has_finobt(mp)) {
     911     1319740 :                 agbno = be32_to_cpu(agi->agi_free_root);
     912     1319740 :                 if (!xfs_verify_agbno(pag, agbno))
     913           0 :                         xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     914             : 
     915     1319655 :                 level = be32_to_cpu(agi->agi_free_level);
     916     1319655 :                 if (level <= 0 || level > igeo->inobt_maxlevels)
     917           0 :                         xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     918             :         }
     919             : 
     920             :         /* Check inode counters */
     921     1319677 :         xfs_agino_range(mp, agno, &first_agino, &last_agino);
     922     1317499 :         icount = be32_to_cpu(agi->agi_count);
     923     1317499 :         if (icount > last_agino - first_agino + 1 ||
     924     1317499 :             icount < be32_to_cpu(agi->agi_freecount))
     925           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     926             : 
     927             :         /* Check inode pointers */
     928     1318782 :         agino = be32_to_cpu(agi->agi_newino);
     929     1318782 :         if (!xfs_verify_agino_or_null(pag, agino))
     930           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     931             : 
     932     1318072 :         agino = be32_to_cpu(agi->agi_dirino);
     933     1318072 :         if (!xfs_verify_agino_or_null(pag, agino))
     934           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     935             : 
     936             :         /* Check unlinked inode buckets */
     937    85493311 :         for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
     938    84173796 :                 agino = be32_to_cpu(agi->agi_unlinked[i]);
     939    84175239 :                 if (!xfs_verify_agino_or_null(pag, agino))
     940           0 :                         xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     941             :         }
     942             : 
     943     1319515 :         if (agi->agi_pad32 != cpu_to_be32(0))
     944           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     945             : 
     946             :         /* Do the incore counters match? */
     947     1319515 :         if (pag->pagi_count != be32_to_cpu(agi->agi_count))
     948           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     949     1319515 :         if (pag->pagi_freecount != be32_to_cpu(agi->agi_freecount))
     950           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     951             : 
     952     1319515 :         xchk_agi_xref(sc);
     953     1343866 : out:
     954     1343866 :         return error;
     955             : }

Generated by: LCOV version 1.14