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-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 403 497 81.1 %
Date: 2023-07-31 20:08:17 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     4889565 : xchk_setup_agheader(
      23             :         struct xfs_scrub        *sc)
      24             : {
      25     4889565 :         if (xchk_need_intent_drain(sc))
      26       30957 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      27     4889565 :         return xchk_setup_fs(sc);
      28             : }
      29             : 
      30             : /* Superblock */
      31             : 
      32             : /* Cross-reference with the other btrees. */
      33             : STATIC void
      34     1071427 : xchk_superblock_xref(
      35             :         struct xfs_scrub        *sc,
      36             :         struct xfs_buf          *bp)
      37             : {
      38     1071427 :         struct xfs_mount        *mp = sc->mp;
      39     1071427 :         xfs_agnumber_t          agno = sc->sm->sm_agno;
      40     1071427 :         xfs_agblock_t           agbno;
      41     1071427 :         int                     error;
      42             : 
      43     1071427 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
      44        2736 :                 return;
      45             : 
      46     1071433 :         agbno = XFS_SB_BLOCK(mp);
      47             : 
      48     1071433 :         error = xchk_ag_init_existing(sc, agno, &sc->sa);
      49     1071431 :         if (!xchk_xref_process_error(sc, agno, agbno, &error))
      50             :                 return;
      51             : 
      52     1068737 :         xchk_xref_is_used_space(sc, agbno, 1);
      53     1068700 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
      54     1068753 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
      55     1068717 :         xchk_xref_is_not_shared(sc, agbno, 1);
      56     1068754 :         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     1460322 : xchk_superblock(
      71             :         struct xfs_scrub        *sc)
      72             : {
      73     1460322 :         struct xfs_mount        *mp = sc->mp;
      74     1460322 :         struct xfs_buf          *bp;
      75     1460322 :         struct xfs_dsb          *sb;
      76     1460322 :         struct xfs_perag        *pag;
      77     1460322 :         xfs_agnumber_t          agno;
      78     1460322 :         uint32_t                v2_ok;
      79     1460322 :         __be32                  features_mask;
      80     1460322 :         int                     error;
      81     1460322 :         __be16                  vernum_mask;
      82             : 
      83     1460322 :         agno = sc->sm->sm_agno;
      84     1460322 :         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     1071486 :         pag = xfs_perag_get(mp, agno);
      93     1071481 :         if (!pag)
      94             :                 return -ENOENT;
      95             : 
      96     1071481 :         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     1071462 :         switch (error) {
     106           2 :         case -EINVAL:   /* also -EWRONGFS */
     107             :         case -ENOSYS:
     108             :         case -EFBIG:
     109           2 :                 error = -EFSCORRUPTED;
     110     1071462 :                 fallthrough;
     111             :         default:
     112     1071462 :                 break;
     113             :         }
     114     1071462 :         if (!xchk_process_error(sc, agno, XFS_SB_BLOCK(mp), &error))
     115           2 :                 goto out_pag;
     116             : 
     117     1071472 :         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     2142944 :         if (sb->sb_blocksize != cpu_to_be32(mp->m_sb.sb_blocksize))
     126           0 :                 xchk_block_set_corrupt(sc, bp);
     127             : 
     128     1071457 :         if (sb->sb_dblocks != cpu_to_be64(mp->m_sb.sb_dblocks))
     129           0 :                 xchk_block_set_corrupt(sc, bp);
     130             : 
     131     1071438 :         if (sb->sb_rblocks != cpu_to_be64(mp->m_sb.sb_rblocks))
     132           0 :                 xchk_block_set_corrupt(sc, bp);
     133             : 
     134     1071446 :         if (sb->sb_rextents != cpu_to_be64(mp->m_sb.sb_rextents))
     135           0 :                 xchk_block_set_corrupt(sc, bp);
     136             : 
     137     1071446 :         if (!uuid_equal(&sb->sb_uuid, &mp->m_sb.sb_uuid))
     138           0 :                 xchk_block_set_preen(sc, bp);
     139             : 
     140     1071454 :         if (sb->sb_logstart != cpu_to_be64(mp->m_sb.sb_logstart))
     141           0 :                 xchk_block_set_corrupt(sc, bp);
     142             : 
     143     1071460 :         if (sb->sb_rootino != cpu_to_be64(mp->m_sb.sb_rootino))
     144      115145 :                 xchk_block_set_preen(sc, bp);
     145             : 
     146     1071440 :         if (sb->sb_rbmino != cpu_to_be64(mp->m_sb.sb_rbmino))
     147      338993 :                 xchk_block_set_preen(sc, bp);
     148             : 
     149     1071449 :         if (sb->sb_rsumino != cpu_to_be64(mp->m_sb.sb_rsumino))
     150      338993 :                 xchk_block_set_preen(sc, bp);
     151             : 
     152     2142910 :         if (sb->sb_rextsize != cpu_to_be32(mp->m_sb.sb_rextsize))
     153           0 :                 xchk_block_set_corrupt(sc, bp);
     154             : 
     155     2142906 :         if (sb->sb_agblocks != cpu_to_be32(mp->m_sb.sb_agblocks))
     156           0 :                 xchk_block_set_corrupt(sc, bp);
     157             : 
     158     2142918 :         if (sb->sb_agcount != cpu_to_be32(mp->m_sb.sb_agcount))
     159           0 :                 xchk_block_set_corrupt(sc, bp);
     160             : 
     161     2142920 :         if (sb->sb_rbmblocks != cpu_to_be32(mp->m_sb.sb_rbmblocks))
     162           0 :                 xchk_block_set_corrupt(sc, bp);
     163             : 
     164     2142922 :         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     1071464 :         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     2142928 :         if ((sb->sb_versionnum & vernum_mask) !=
     178     1071464 :             (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     1071460 :         vernum_mask = cpu_to_be16(XFS_SB_VERSION_ATTRBIT |
     183             :                                   XFS_SB_VERSION_NLINKBIT |
     184             :                                   XFS_SB_VERSION_QUOTABIT);
     185     2142920 :         if ((sb->sb_versionnum & vernum_mask) !=
     186     1071460 :             (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask))
     187      262925 :                 xchk_block_set_preen(sc, bp);
     188             : 
     189     1071459 :         if (sb->sb_sectsize != cpu_to_be16(mp->m_sb.sb_sectsize))
     190           0 :                 xchk_block_set_corrupt(sc, bp);
     191             : 
     192     1071458 :         if (sb->sb_inodesize != cpu_to_be16(mp->m_sb.sb_inodesize))
     193           0 :                 xchk_block_set_corrupt(sc, bp);
     194             : 
     195     1071454 :         if (sb->sb_inopblock != cpu_to_be16(mp->m_sb.sb_inopblock))
     196           0 :                 xchk_block_set_corrupt(sc, bp);
     197             : 
     198     2142744 :         if (memcmp(sb->sb_fname, mp->m_sb.sb_fname, sizeof(sb->sb_fname)))
     199           0 :                 xchk_block_set_preen(sc, bp);
     200             : 
     201     1071372 :         if (sb->sb_blocklog != mp->m_sb.sb_blocklog)
     202           0 :                 xchk_block_set_corrupt(sc, bp);
     203             : 
     204     1071372 :         if (sb->sb_sectlog != mp->m_sb.sb_sectlog)
     205           0 :                 xchk_block_set_corrupt(sc, bp);
     206             : 
     207     1071372 :         if (sb->sb_inodelog != mp->m_sb.sb_inodelog)
     208           0 :                 xchk_block_set_corrupt(sc, bp);
     209             : 
     210     1071372 :         if (sb->sb_inopblog != mp->m_sb.sb_inopblog)
     211           0 :                 xchk_block_set_corrupt(sc, bp);
     212             : 
     213     1071372 :         if (sb->sb_agblklog != mp->m_sb.sb_agblklog)
     214           0 :                 xchk_block_set_corrupt(sc, bp);
     215             : 
     216     1071372 :         if (sb->sb_rextslog != mp->m_sb.sb_rextslog)
     217           0 :                 xchk_block_set_corrupt(sc, bp);
     218             : 
     219     1071372 :         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     1071372 :         if (sb->sb_uquotino != cpu_to_be64(mp->m_sb.sb_uquotino))
     228      338992 :                 xchk_block_set_preen(sc, bp);
     229             : 
     230     1071430 :         if (sb->sb_gquotino != cpu_to_be64(mp->m_sb.sb_gquotino))
     231      338993 :                 xchk_block_set_preen(sc, bp);
     232             : 
     233             :         /*
     234             :          * Skip the quota flags since repair will force quotacheck.
     235             :          * sb_qflags
     236             :          */
     237             : 
     238     1071428 :         if (sb->sb_flags != mp->m_sb.sb_flags)
     239           0 :                 xchk_block_set_corrupt(sc, bp);
     240             : 
     241     1071428 :         if (sb->sb_shared_vn != mp->m_sb.sb_shared_vn)
     242           0 :                 xchk_block_set_corrupt(sc, bp);
     243             : 
     244     2142880 :         if (sb->sb_inoalignmt != cpu_to_be32(mp->m_sb.sb_inoalignmt))
     245           0 :                 xchk_block_set_corrupt(sc, bp);
     246             : 
     247     2142884 :         if (sb->sb_unit != cpu_to_be32(mp->m_sb.sb_unit))
     248           0 :                 xchk_block_set_preen(sc, bp);
     249             : 
     250     2142878 :         if (sb->sb_width != cpu_to_be32(mp->m_sb.sb_width))
     251          60 :                 xchk_block_set_preen(sc, bp);
     252             : 
     253     1071439 :         if (sb->sb_dirblklog != mp->m_sb.sb_dirblklog)
     254           0 :                 xchk_block_set_corrupt(sc, bp);
     255             : 
     256     1071439 :         if (sb->sb_logsectlog != mp->m_sb.sb_logsectlog)
     257           0 :                 xchk_block_set_corrupt(sc, bp);
     258             : 
     259     1071427 :         if (sb->sb_logsectsize != cpu_to_be16(mp->m_sb.sb_logsectsize))
     260           0 :                 xchk_block_set_corrupt(sc, bp);
     261             : 
     262     2142872 :         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     1071444 :         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     1071442 :                 v2_ok = XFS_SB_VERSION2_OKBITS;
     271     1071442 :                 if (xfs_sb_is_v5(&mp->m_sb))
     272     1071459 :                         v2_ok |= XFS_SB_VERSION2_CRCBIT;
     273             : 
     274     2142884 :                 if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok)))
     275           0 :                         xchk_block_set_corrupt(sc, bp);
     276             : 
     277     1071442 :                 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     1071442 :         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     1071442 :         if ((sb->sb_features2 & features_mask) !=
     287     1071442 :             (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     1071456 :         features_mask = cpu_to_be32(XFS_SB_VERSION2_ATTR2BIT);
     292     1071456 :         if ((sb->sb_features2 & features_mask) !=
     293     1071456 :             (cpu_to_be32(mp->m_sb.sb_features2) & features_mask))
     294           0 :                 xchk_block_set_preen(sc, bp);
     295             : 
     296     1071463 :         if (!xfs_has_crc(mp)) {
     297             :                 /* all v5 fields must be zero */
     298           4 :                 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     1071461 :                 if (sb->sb_features_compat !=
     305     1071461 :                                 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     1071458 :                 if (sb->sb_features_ro_compat !=
     310     1071458 :                                 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     1071463 :                 features_mask = cpu_to_be32(XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR);
     318     1071463 :                 if ((cpu_to_be32(mp->m_sb.sb_features_incompat) ^
     319     1071463 :                                 sb->sb_features_incompat) & features_mask)
     320           0 :                         xchk_block_set_preen(sc, bp);
     321             : 
     322             :                 /* all other incompat features must match */
     323     1071448 :                 if ((cpu_to_be32(mp->m_sb.sb_features_incompat) ^
     324     1071448 :                                 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     1071448 :                 if (sb->sb_features_log_incompat)
     333           0 :                         xchk_block_set_preen(sc, bp);
     334             : 
     335             :                 /* Don't care about sb_crc */
     336             : 
     337     2142940 :                 if (sb->sb_spino_align != cpu_to_be32(mp->m_sb.sb_spino_align))
     338           0 :                         xchk_block_set_corrupt(sc, bp);
     339             : 
     340     1071440 :                 if (sb->sb_pquotino != cpu_to_be64(mp->m_sb.sb_pquotino))
     341      338988 :                         xchk_block_set_preen(sc, bp);
     342             : 
     343             :                 /* Don't care about sb_lsn */
     344             :         }
     345             : 
     346     1071443 :         if (xfs_has_metauuid(mp)) {
     347             :                 /* The metadata UUID must be the same for all supers */
     348           6 :                 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     1071480 :         if (memchr_inv(sb + 1, 0,
     354     1071443 :                         BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
     355           0 :                 xchk_block_set_corrupt(sc, bp);
     356             : 
     357     1071480 :         xchk_superblock_xref(sc, bp);
     358     1071494 : out_pag:
     359     1071494 :         xfs_perag_put(pag);
     360     1071492 :         return error;
     361             : }
     362             : 
     363             : /* AGF */
     364             : 
     365             : /* Tally freespace record lengths. */
     366             : STATIC int
     367   800351580 : xchk_agf_record_bno_lengths(
     368             :         struct xfs_btree_cur            *cur,
     369             :         const struct xfs_alloc_rec_incore *rec,
     370             :         void                            *priv)
     371             : {
     372   800351580 :         xfs_extlen_t                    *blocks = priv;
     373             : 
     374   800351580 :         (*blocks) += rec->ar_blockcount;
     375   800351580 :         return 0;
     376             : }
     377             : 
     378             : /* Check agf_freeblks */
     379             : static inline void
     380     1121675 : xchk_agf_xref_freeblks(
     381             :         struct xfs_scrub        *sc)
     382             : {
     383     1121675 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     384     1121675 :         xfs_extlen_t            blocks = 0;
     385     1121675 :         int                     error;
     386             : 
     387     1121675 :         if (!sc->sa.bno_cur)
     388           0 :                 return;
     389             : 
     390     1121675 :         error = xfs_alloc_query_all(sc->sa.bno_cur,
     391             :                         xchk_agf_record_bno_lengths, &blocks);
     392     1121675 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
     393             :                 return;
     394     2243356 :         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     1121646 : xchk_agf_xref_cntbt(
     401             :         struct xfs_scrub        *sc)
     402             : {
     403     1121646 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     404     1121646 :         xfs_agblock_t           agbno;
     405     1121646 :         xfs_extlen_t            blocks;
     406     1121646 :         int                     have;
     407     1121646 :         int                     error;
     408             : 
     409     1121646 :         if (!sc->sa.cnt_cur)
     410           0 :                 return;
     411             : 
     412             :         /* Any freespace at all? */
     413     1121646 :         error = xfs_alloc_lookup_le(sc->sa.cnt_cur, 0, -1U, &have);
     414     1121687 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
     415             :                 return;
     416     1121672 :         if (!have) {
     417           0 :                 if (agf->agf_freeblks != cpu_to_be32(0))
     418           0 :                         xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
     419           0 :                 return;
     420             :         }
     421             : 
     422             :         /* Check agf_longest */
     423     1121672 :         error = xfs_alloc_get_rec(sc->sa.cnt_cur, &agbno, &blocks, &have);
     424     1121677 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
     425             :                 return;
     426     2243368 :         if (!have || blocks != be32_to_cpu(agf->agf_longest))
     427           8 :                 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     1121719 : xchk_agf_xref_btreeblks(
     433             :         struct xfs_scrub        *sc)
     434             : {
     435     1121719 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     436     1121719 :         struct xfs_mount        *mp = sc->mp;
     437     1121719 :         xfs_agblock_t           blocks;
     438     1121719 :         xfs_agblock_t           btreeblks;
     439     1121719 :         int                     error;
     440             : 
     441             :         /* agf_btreeblks didn't exist before lazysbcount */
     442     1121719 :         if (!xfs_has_lazysbcount(sc->mp))
     443           0 :                 return;
     444             : 
     445             :         /* Check agf_rmap_blocks; set up for agf_btreeblks check */
     446     1121719 :         if (sc->sa.rmap_cur) {
     447      795923 :                 error = xfs_btree_count_blocks(sc->sa.rmap_cur, &blocks);
     448      795874 :                 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     449             :                         return;
     450      795878 :                 btreeblks = blocks - 1;
     451     1591756 :                 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     1121674 :         if ((xfs_has_rmapbt(mp) && !sc->sa.rmap_cur) ||
     462     1121674 :             !sc->sa.bno_cur || !sc->sa.cnt_cur)
     463             :                 return;
     464             : 
     465             :         /* Check agf_btreeblks */
     466     1121674 :         error = xfs_btree_count_blocks(sc->sa.bno_cur, &blocks);
     467     1121639 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
     468             :                 return;
     469     1121648 :         btreeblks += blocks - 1;
     470             : 
     471     1121648 :         error = xfs_btree_count_blocks(sc->sa.cnt_cur, &blocks);
     472     1121641 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
     473             :                 return;
     474     1121656 :         btreeblks += blocks - 1;
     475             : 
     476     2243312 :         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     1121690 : xchk_agf_xref_refcblks(
     483             :         struct xfs_scrub        *sc)
     484             : {
     485     1121690 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     486     1121690 :         xfs_agblock_t           blocks;
     487     1121690 :         int                     error;
     488             : 
     489     1121690 :         if (!sc->sa.refc_cur)
     490      325753 :                 return;
     491             : 
     492      795937 :         error = xfs_btree_count_blocks(sc->sa.refc_cur, &blocks);
     493      795931 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
     494             :                 return;
     495     1591878 :         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     1121666 : xchk_agf_xref(
     502             :         struct xfs_scrub        *sc)
     503             : {
     504     1121666 :         struct xfs_mount        *mp = sc->mp;
     505     1121666 :         xfs_agblock_t           agbno;
     506             : 
     507     1121666 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     508             :                 return;
     509             : 
     510     1121666 :         agbno = XFS_AGF_BLOCK(mp);
     511             : 
     512     1121666 :         xchk_ag_btcur_init(sc, &sc->sa);
     513             : 
     514     1121681 :         xchk_xref_is_used_space(sc, agbno, 1);
     515     1121691 :         xchk_agf_xref_freeblks(sc);
     516     1121666 :         xchk_agf_xref_cntbt(sc);
     517     1121649 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
     518     1121690 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
     519     1121686 :         xchk_agf_xref_btreeblks(sc);
     520     1121674 :         xchk_xref_is_not_shared(sc, agbno, 1);
     521     1121686 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     522     1121689 :         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     1132432 : xchk_agf(
     530             :         struct xfs_scrub        *sc)
     531             : {
     532     1132432 :         struct xfs_mount        *mp = sc->mp;
     533     1132432 :         struct xfs_agf          *agf;
     534     1132432 :         struct xfs_perag        *pag;
     535     1132432 :         xfs_agnumber_t          agno = sc->sm->sm_agno;
     536     1132432 :         xfs_agblock_t           agbno;
     537     1132432 :         xfs_agblock_t           eoag;
     538     1132432 :         xfs_agblock_t           agfl_first;
     539     1132432 :         xfs_agblock_t           agfl_last;
     540     1132432 :         xfs_agblock_t           agfl_count;
     541     1132432 :         xfs_agblock_t           fl_count;
     542     1132432 :         int                     level;
     543     1132432 :         int                     error = 0;
     544             : 
     545     1132432 :         error = xchk_ag_read_headers(sc, agno, &sc->sa);
     546     1132464 :         if (!xchk_process_error(sc, agno, XFS_AGF_BLOCK(sc->mp), &error))
     547       10764 :                 goto out;
     548     1121685 :         xchk_buffer_recheck(sc, sc->sa.agf_bp);
     549             : 
     550     1121670 :         agf = sc->sa.agf_bp->b_addr;
     551     1121670 :         pag = sc->sa.pag;
     552             : 
     553             :         /* Check the AG length */
     554     1121670 :         eoag = be32_to_cpu(agf->agf_length);
     555     1121670 :         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     1121672 :         agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]);
     560     1121672 :         if (!xfs_verify_agbno(pag, agbno))
     561           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     562             : 
     563     1121675 :         agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]);
     564     1121675 :         if (!xfs_verify_agbno(pag, agbno))
     565          10 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     566             : 
     567     1121675 :         level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]);
     568     1121675 :         if (level <= 0 || level > mp->m_alloc_maxlevels)
     569           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     570             : 
     571     1121672 :         level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
     572     1121672 :         if (level <= 0 || level > mp->m_alloc_maxlevels)
     573           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     574             : 
     575     1121672 :         if (xfs_has_rmapbt(mp)) {
     576      795916 :                 agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]);
     577      795916 :                 if (!xfs_verify_agbno(pag, agbno))
     578           0 :                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     579             : 
     580      795919 :                 level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
     581      795919 :                 if (level <= 0 || level > mp->m_rmap_maxlevels)
     582           0 :                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     583             :         }
     584             : 
     585     1121675 :         if (xfs_has_reflink(mp)) {
     586      795920 :                 agbno = be32_to_cpu(agf->agf_refcount_root);
     587      795920 :                 if (!xfs_verify_agbno(pag, agbno))
     588           0 :                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     589             : 
     590      795925 :                 level = be32_to_cpu(agf->agf_refcount_level);
     591      795925 :                 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     1121680 :         agfl_first = be32_to_cpu(agf->agf_flfirst);
     597     1121680 :         agfl_last = be32_to_cpu(agf->agf_fllast);
     598     1121680 :         agfl_count = be32_to_cpu(agf->agf_flcount);
     599     1121680 :         if (agfl_last > agfl_first)
     600     1116871 :                 fl_count = agfl_last - agfl_first + 1;
     601             :         else
     602        4809 :                 fl_count = xfs_agfl_size(mp) - agfl_first + agfl_last + 1;
     603     1121680 :         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     2243366 :         if (pag->pagf_freeblks != be32_to_cpu(agf->agf_freeblks))
     608           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     609     2243358 :         if (pag->pagf_flcount != be32_to_cpu(agf->agf_flcount))
     610           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     611     2243356 :         if (xfs_has_lazysbcount(sc->mp) &&
     612     1121677 :             pag->pagf_btreeblks != be32_to_cpu(agf->agf_btreeblks))
     613           0 :                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
     614             : 
     615     1121679 :         xchk_agf_xref(sc);
     616     1132451 : out:
     617     1132451 :         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     6851208 : xchk_agfl_block_xref(
     639             :         struct xfs_scrub        *sc,
     640             :         xfs_agblock_t           agbno)
     641             : {
     642     6851208 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     643             :                 return;
     644             : 
     645     6851188 :         xchk_xref_is_used_space(sc, agbno, 1);
     646     6851532 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
     647     6851212 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG);
     648     6851344 :         xchk_xref_is_not_shared(sc, agbno, 1);
     649     6851601 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     650             : }
     651             : 
     652             : /* Scrub an AGFL block. */
     653             : STATIC int
     654     6851203 : xchk_agfl_block(
     655             :         struct xfs_mount        *mp,
     656             :         xfs_agblock_t           agbno,
     657             :         void                    *priv)
     658             : {
     659     6851203 :         struct xchk_agfl_info   *sai = priv;
     660     6851203 :         struct xfs_scrub        *sc = sai->sc;
     661             : 
     662     6851203 :         if (xfs_verify_agbno(sc->sa.pag, agbno) &&
     663     6851203 :             sai->nr_entries < sai->agflcount)
     664     6851191 :                 sai->entries[sai->nr_entries++] = agbno;
     665             :         else
     666          25 :                 xchk_block_set_corrupt(sc, sai->agfl_bp);
     667             : 
     668     6851191 :         xchk_agfl_block_xref(sc, agbno);
     669             : 
     670     6851569 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     671           0 :                 return -ECANCELED;
     672             : 
     673             :         return 0;
     674             : }
     675             : 
     676             : static int
     677    16637694 : xchk_agblock_cmp(
     678             :         const void              *pa,
     679             :         const void              *pb)
     680             : {
     681    16637694 :         const xfs_agblock_t     *a = pa;
     682    16637694 :         const xfs_agblock_t     *b = pb;
     683             : 
     684    16637694 :         return (int)*a - (int)*b;
     685             : }
     686             : 
     687             : /* Cross-reference with the other btrees. */
     688             : STATIC void
     689     1132279 : xchk_agfl_xref(
     690             :         struct xfs_scrub        *sc)
     691             : {
     692     1132279 :         struct xfs_mount        *mp = sc->mp;
     693     1132279 :         xfs_agblock_t           agbno;
     694             : 
     695     1132279 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     696             :                 return;
     697             : 
     698     1132279 :         agbno = XFS_AGFL_BLOCK(mp);
     699             : 
     700     1132279 :         xchk_ag_btcur_init(sc, &sc->sa);
     701             : 
     702     1132276 :         xchk_xref_is_used_space(sc, agbno, 1);
     703     1132297 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
     704     1132288 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
     705     1132293 :         xchk_xref_is_not_shared(sc, agbno, 1);
     706     1132295 :         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     1141437 : xchk_agfl(
     717             :         struct xfs_scrub        *sc)
     718             : {
     719     1141437 :         struct xchk_agfl_info   sai = {
     720             :                 .sc             = sc,
     721             :         };
     722     1141437 :         struct xfs_agf          *agf;
     723     1141437 :         xfs_agnumber_t          agno = sc->sm->sm_agno;
     724     1141437 :         unsigned int            i;
     725     1141437 :         int                     error;
     726             : 
     727             :         /* Lock the AGF and AGI so that nobody can touch this AG. */
     728     1141437 :         error = xchk_ag_read_headers(sc, agno, &sc->sa);
     729     1141451 :         if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
     730        9160 :                 return error;
     731     1132295 :         if (!sc->sa.agf_bp)
     732             :                 return -EFSCORRUPTED;
     733             : 
     734             :         /* Try to read the AGFL, and verify its structure if we get it. */
     735     1132295 :         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &sai.agfl_bp);
     736     1132295 :         if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
     737           0 :                 return error;
     738     1132269 :         xchk_buffer_recheck(sc, sai.agfl_bp);
     739             : 
     740     1132281 :         xchk_agfl_xref(sc);
     741             : 
     742     1132290 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     743           0 :                 goto out;
     744             : 
     745             :         /* Allocate buffer to ensure uniqueness of AGFL entries. */
     746     1132290 :         agf = sc->sa.agf_bp->b_addr;
     747     1132290 :         sai.agflcount = be32_to_cpu(agf->agf_flcount);
     748     1132290 :         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     1132285 :         sai.entries = kvcalloc(sai.agflcount, sizeof(xfs_agblock_t),
     753             :                                XCHK_GFP_FLAGS);
     754     1132250 :         if (!sai.entries) {
     755           0 :                 error = -ENOMEM;
     756           0 :                 goto out;
     757             :         }
     758             : 
     759             :         /* Check the blocks in the AGFL. */
     760     1132250 :         error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr, sai.agfl_bp,
     761             :                         xchk_agfl_block, &sai);
     762     1132269 :         if (error == -ECANCELED) {
     763           0 :                 error = 0;
     764           0 :                 goto out_free;
     765             :         }
     766     1132269 :         if (error)
     767           0 :                 goto out_free;
     768             : 
     769     1132269 :         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     1132269 :         sort(sai.entries, sai.nr_entries, sizeof(sai.entries[0]),
     776             :                         xchk_agblock_cmp, NULL);
     777     7988328 :         for (i = 1; i < sai.nr_entries; i++) {
     778     5723839 :                 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     1132220 : out_free:
     785     1132220 :         kvfree(sai.entries);
     786     1132247 : out:
     787     1132247 :         return error;
     788             : }
     789             : 
     790             : /* AGI */
     791             : 
     792             : /* Check agi_count/agi_freecount */
     793             : static inline void
     794     1147001 : xchk_agi_xref_icounts(
     795             :         struct xfs_scrub        *sc)
     796             : {
     797     1147001 :         struct xfs_agi          *agi = sc->sa.agi_bp->b_addr;
     798     1147001 :         xfs_agino_t             icount;
     799     1147001 :         xfs_agino_t             freecount;
     800     1147001 :         int                     error;
     801             : 
     802     1147001 :         if (!sc->sa.ino_cur)
     803           0 :                 return;
     804             : 
     805     1147001 :         error = xfs_ialloc_count_inodes(sc->sa.ino_cur, &icount, &freecount);
     806     1146989 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur))
     807             :                 return;
     808     2293974 :         if (be32_to_cpu(agi->agi_count) != icount ||
     809     2293902 :             be32_to_cpu(agi->agi_freecount) != freecount)
     810          36 :                 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     1146984 : xchk_agi_xref_fiblocks(
     816             :         struct xfs_scrub        *sc)
     817             : {
     818     1146984 :         struct xfs_agi          *agi = sc->sa.agi_bp->b_addr;
     819     1146984 :         xfs_agblock_t           blocks;
     820     1146984 :         int                     error = 0;
     821             : 
     822     1146984 :         if (!xfs_has_inobtcounts(sc->mp))
     823           4 :                 return;
     824             : 
     825     1146980 :         if (sc->sa.ino_cur) {
     826     1146984 :                 error = xfs_btree_count_blocks(sc->sa.ino_cur, &blocks);
     827     1146989 :                 if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur))
     828             :                         return;
     829     2293988 :                 if (blocks != be32_to_cpu(agi->agi_iblocks))
     830           0 :                         xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp);
     831             :         }
     832             : 
     833     1146990 :         if (sc->sa.fino_cur) {
     834     1146995 :                 error = xfs_btree_count_blocks(sc->sa.fino_cur, &blocks);
     835     1146995 :                 if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur))
     836             :                         return;
     837     2293992 :                 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     1146990 : xchk_agi_xref(
     845             :         struct xfs_scrub        *sc)
     846             : {
     847     1146990 :         struct xfs_mount        *mp = sc->mp;
     848     1146990 :         xfs_agblock_t           agbno;
     849             : 
     850     1146990 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     851             :                 return;
     852             : 
     853     1146990 :         agbno = XFS_AGI_BLOCK(mp);
     854             : 
     855     1146990 :         xchk_ag_btcur_init(sc, &sc->sa);
     856             : 
     857     1146980 :         xchk_xref_is_used_space(sc, agbno, 1);
     858     1146999 :         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
     859     1146983 :         xchk_agi_xref_icounts(sc);
     860     1146931 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
     861     1147002 :         xchk_xref_is_not_shared(sc, agbno, 1);
     862     1146998 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     863     1146999 :         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     1155657 : xchk_agi(
     871             :         struct xfs_scrub        *sc)
     872             : {
     873     1155657 :         struct xfs_mount        *mp = sc->mp;
     874     1155657 :         struct xfs_agi          *agi;
     875     1155657 :         struct xfs_perag        *pag;
     876     1155657 :         struct xfs_ino_geometry *igeo = M_IGEO(sc->mp);
     877     1155657 :         xfs_agnumber_t          agno = sc->sm->sm_agno;
     878     1155657 :         xfs_agblock_t           agbno;
     879     1155657 :         xfs_agblock_t           eoag;
     880     1155657 :         xfs_agino_t             agino;
     881     1155657 :         xfs_agino_t             first_agino;
     882     1155657 :         xfs_agino_t             last_agino;
     883     1155657 :         xfs_agino_t             icount;
     884     1155657 :         int                     i;
     885     1155657 :         int                     level;
     886     1155657 :         int                     error = 0;
     887             : 
     888     1155657 :         error = xchk_ag_read_headers(sc, agno, &sc->sa);
     889     1155678 :         if (!xchk_process_error(sc, agno, XFS_AGI_BLOCK(sc->mp), &error))
     890        8676 :                 goto out;
     891     1146962 :         xchk_buffer_recheck(sc, sc->sa.agi_bp);
     892             : 
     893     1146960 :         agi = sc->sa.agi_bp->b_addr;
     894     1146960 :         pag = sc->sa.pag;
     895             : 
     896             :         /* Check the AG length */
     897     1146960 :         eoag = be32_to_cpu(agi->agi_length);
     898     1146960 :         if (eoag != pag->block_count)
     899           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     900             : 
     901             :         /* Check btree roots and levels */
     902     1146962 :         agbno = be32_to_cpu(agi->agi_root);
     903     1146962 :         if (!xfs_verify_agbno(pag, agbno))
     904           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     905             : 
     906     1146965 :         level = be32_to_cpu(agi->agi_level);
     907     1146965 :         if (level <= 0 || level > igeo->inobt_maxlevels)
     908           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     909             : 
     910     1146976 :         if (xfs_has_finobt(mp)) {
     911     1146972 :                 agbno = be32_to_cpu(agi->agi_free_root);
     912     1146972 :                 if (!xfs_verify_agbno(pag, agbno))
     913           1 :                         xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     914             : 
     915     1146956 :                 level = be32_to_cpu(agi->agi_free_level);
     916     1146956 :                 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     1146960 :         xfs_agino_range(mp, agno, &first_agino, &last_agino);
     922     1146940 :         icount = be32_to_cpu(agi->agi_count);
     923     2293834 :         if (icount > last_agino - first_agino + 1 ||
     924     1146894 :             icount < be32_to_cpu(agi->agi_freecount))
     925          47 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     926             : 
     927             :         /* Check inode pointers */
     928     1146850 :         agino = be32_to_cpu(agi->agi_newino);
     929     1146850 :         if (!xfs_verify_agino_or_null(pag, agino))
     930           1 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     931             : 
     932     1146939 :         agino = be32_to_cpu(agi->agi_dirino);
     933     1146939 :         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    74537754 :         for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
     938    73390830 :                 agino = be32_to_cpu(agi->agi_unlinked[i]);
     939    73388953 :                 if (!xfs_verify_agino_or_null(pag, agino))
     940           0 :                         xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     941             :         }
     942             : 
     943     1146924 :         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     2293848 :         if (pag->pagi_count != be32_to_cpu(agi->agi_count))
     948           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     949     2293886 :         if (pag->pagi_freecount != be32_to_cpu(agi->agi_freecount))
     950           0 :                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
     951             : 
     952     1146943 :         xchk_agi_xref(sc);
     953     1155660 : out:
     954     1155660 :         return error;
     955             : }

Generated by: LCOV version 1.14