18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2017 Oracle. All Rights Reserved. 48c2ecf20Sopenharmony_ci * Author: Darrick J. Wong <darrick.wong@oracle.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include "xfs.h" 78c2ecf20Sopenharmony_ci#include "xfs_fs.h" 88c2ecf20Sopenharmony_ci#include "xfs_shared.h" 98c2ecf20Sopenharmony_ci#include "xfs_format.h" 108c2ecf20Sopenharmony_ci#include "xfs_trans_resv.h" 118c2ecf20Sopenharmony_ci#include "xfs_mount.h" 128c2ecf20Sopenharmony_ci#include "xfs_btree.h" 138c2ecf20Sopenharmony_ci#include "xfs_sb.h" 148c2ecf20Sopenharmony_ci#include "xfs_alloc.h" 158c2ecf20Sopenharmony_ci#include "xfs_ialloc.h" 168c2ecf20Sopenharmony_ci#include "xfs_rmap.h" 178c2ecf20Sopenharmony_ci#include "scrub/scrub.h" 188c2ecf20Sopenharmony_ci#include "scrub/common.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* Superblock */ 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* Cross-reference with the other btrees. */ 238c2ecf20Sopenharmony_ciSTATIC void 248c2ecf20Sopenharmony_cixchk_superblock_xref( 258c2ecf20Sopenharmony_ci struct xfs_scrub *sc, 268c2ecf20Sopenharmony_ci struct xfs_buf *bp) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci struct xfs_mount *mp = sc->mp; 298c2ecf20Sopenharmony_ci xfs_agnumber_t agno = sc->sm->sm_agno; 308c2ecf20Sopenharmony_ci xfs_agblock_t agbno; 318c2ecf20Sopenharmony_ci int error; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 348c2ecf20Sopenharmony_ci return; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci agbno = XFS_SB_BLOCK(mp); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci error = xchk_ag_init(sc, agno, &sc->sa); 398c2ecf20Sopenharmony_ci if (!xchk_xref_process_error(sc, agno, agbno, &error)) 408c2ecf20Sopenharmony_ci return; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci xchk_xref_is_used_space(sc, agbno, 1); 438c2ecf20Sopenharmony_ci xchk_xref_is_not_inode_chunk(sc, agbno, 1); 448c2ecf20Sopenharmony_ci xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); 458c2ecf20Sopenharmony_ci xchk_xref_is_not_shared(sc, agbno, 1); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci /* scrub teardown will take care of sc->sa for us */ 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * Scrub the filesystem superblock. 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * Note: We do /not/ attempt to check AG 0's superblock. Mount is 548c2ecf20Sopenharmony_ci * responsible for validating all the geometry information in sb 0, so 558c2ecf20Sopenharmony_ci * if the filesystem is capable of initiating online scrub, then clearly 568c2ecf20Sopenharmony_ci * sb 0 is ok and we can use its information to check everything else. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_ciint 598c2ecf20Sopenharmony_cixchk_superblock( 608c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct xfs_mount *mp = sc->mp; 638c2ecf20Sopenharmony_ci struct xfs_buf *bp; 648c2ecf20Sopenharmony_ci struct xfs_dsb *sb; 658c2ecf20Sopenharmony_ci xfs_agnumber_t agno; 668c2ecf20Sopenharmony_ci uint32_t v2_ok; 678c2ecf20Sopenharmony_ci __be32 features_mask; 688c2ecf20Sopenharmony_ci int error; 698c2ecf20Sopenharmony_ci __be16 vernum_mask; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci agno = sc->sm->sm_agno; 728c2ecf20Sopenharmony_ci if (agno == 0) 738c2ecf20Sopenharmony_ci return 0; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci error = xfs_sb_read_secondary(mp, sc->tp, agno, &bp); 768c2ecf20Sopenharmony_ci /* 778c2ecf20Sopenharmony_ci * The superblock verifier can return several different error codes 788c2ecf20Sopenharmony_ci * if it thinks the superblock doesn't look right. For a mount these 798c2ecf20Sopenharmony_ci * would all get bounced back to userspace, but if we're here then the 808c2ecf20Sopenharmony_ci * fs mounted successfully, which means that this secondary superblock 818c2ecf20Sopenharmony_ci * is simply incorrect. Treat all these codes the same way we treat 828c2ecf20Sopenharmony_ci * any corruption. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci switch (error) { 858c2ecf20Sopenharmony_ci case -EINVAL: /* also -EWRONGFS */ 868c2ecf20Sopenharmony_ci case -ENOSYS: 878c2ecf20Sopenharmony_ci case -EFBIG: 888c2ecf20Sopenharmony_ci error = -EFSCORRUPTED; 898c2ecf20Sopenharmony_ci default: 908c2ecf20Sopenharmony_ci break; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci if (!xchk_process_error(sc, agno, XFS_SB_BLOCK(mp), &error)) 938c2ecf20Sopenharmony_ci return error; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci sb = bp->b_addr; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* 988c2ecf20Sopenharmony_ci * Verify the geometries match. Fields that are permanently 998c2ecf20Sopenharmony_ci * set by mkfs are checked; fields that can be updated later 1008c2ecf20Sopenharmony_ci * (and are not propagated to backup superblocks) are preen 1018c2ecf20Sopenharmony_ci * checked. 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci if (sb->sb_blocksize != cpu_to_be32(mp->m_sb.sb_blocksize)) 1048c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (sb->sb_dblocks != cpu_to_be64(mp->m_sb.sb_dblocks)) 1078c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (sb->sb_rblocks != cpu_to_be64(mp->m_sb.sb_rblocks)) 1108c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (sb->sb_rextents != cpu_to_be64(mp->m_sb.sb_rextents)) 1138c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (!uuid_equal(&sb->sb_uuid, &mp->m_sb.sb_uuid)) 1168c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (sb->sb_logstart != cpu_to_be64(mp->m_sb.sb_logstart)) 1198c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (sb->sb_rootino != cpu_to_be64(mp->m_sb.sb_rootino)) 1228c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (sb->sb_rbmino != cpu_to_be64(mp->m_sb.sb_rbmino)) 1258c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (sb->sb_rsumino != cpu_to_be64(mp->m_sb.sb_rsumino)) 1288c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (sb->sb_rextsize != cpu_to_be32(mp->m_sb.sb_rextsize)) 1318c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (sb->sb_agblocks != cpu_to_be32(mp->m_sb.sb_agblocks)) 1348c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (sb->sb_agcount != cpu_to_be32(mp->m_sb.sb_agcount)) 1378c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (sb->sb_rbmblocks != cpu_to_be32(mp->m_sb.sb_rbmblocks)) 1408c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci if (sb->sb_logblocks != cpu_to_be32(mp->m_sb.sb_logblocks)) 1438c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* Check sb_versionnum bits that are set at mkfs time. */ 1468c2ecf20Sopenharmony_ci vernum_mask = cpu_to_be16(~XFS_SB_VERSION_OKBITS | 1478c2ecf20Sopenharmony_ci XFS_SB_VERSION_NUMBITS | 1488c2ecf20Sopenharmony_ci XFS_SB_VERSION_ALIGNBIT | 1498c2ecf20Sopenharmony_ci XFS_SB_VERSION_DALIGNBIT | 1508c2ecf20Sopenharmony_ci XFS_SB_VERSION_SHAREDBIT | 1518c2ecf20Sopenharmony_ci XFS_SB_VERSION_LOGV2BIT | 1528c2ecf20Sopenharmony_ci XFS_SB_VERSION_SECTORBIT | 1538c2ecf20Sopenharmony_ci XFS_SB_VERSION_EXTFLGBIT | 1548c2ecf20Sopenharmony_ci XFS_SB_VERSION_DIRV2BIT); 1558c2ecf20Sopenharmony_ci if ((sb->sb_versionnum & vernum_mask) != 1568c2ecf20Sopenharmony_ci (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask)) 1578c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* Check sb_versionnum bits that can be set after mkfs time. */ 1608c2ecf20Sopenharmony_ci vernum_mask = cpu_to_be16(XFS_SB_VERSION_ATTRBIT | 1618c2ecf20Sopenharmony_ci XFS_SB_VERSION_NLINKBIT | 1628c2ecf20Sopenharmony_ci XFS_SB_VERSION_QUOTABIT); 1638c2ecf20Sopenharmony_ci if ((sb->sb_versionnum & vernum_mask) != 1648c2ecf20Sopenharmony_ci (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask)) 1658c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci if (sb->sb_sectsize != cpu_to_be16(mp->m_sb.sb_sectsize)) 1688c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (sb->sb_inodesize != cpu_to_be16(mp->m_sb.sb_inodesize)) 1718c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (sb->sb_inopblock != cpu_to_be16(mp->m_sb.sb_inopblock)) 1748c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci if (memcmp(sb->sb_fname, mp->m_sb.sb_fname, sizeof(sb->sb_fname))) 1778c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (sb->sb_blocklog != mp->m_sb.sb_blocklog) 1808c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (sb->sb_sectlog != mp->m_sb.sb_sectlog) 1838c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (sb->sb_inodelog != mp->m_sb.sb_inodelog) 1868c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (sb->sb_inopblog != mp->m_sb.sb_inopblog) 1898c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (sb->sb_agblklog != mp->m_sb.sb_agblklog) 1928c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (sb->sb_rextslog != mp->m_sb.sb_rextslog) 1958c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (sb->sb_imax_pct != mp->m_sb.sb_imax_pct) 1988c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci /* 2018c2ecf20Sopenharmony_ci * Skip the summary counters since we track them in memory anyway. 2028c2ecf20Sopenharmony_ci * sb_icount, sb_ifree, sb_fdblocks, sb_frexents 2038c2ecf20Sopenharmony_ci */ 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci if (sb->sb_uquotino != cpu_to_be64(mp->m_sb.sb_uquotino)) 2068c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (sb->sb_gquotino != cpu_to_be64(mp->m_sb.sb_gquotino)) 2098c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* 2128c2ecf20Sopenharmony_ci * Skip the quota flags since repair will force quotacheck. 2138c2ecf20Sopenharmony_ci * sb_qflags 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if (sb->sb_flags != mp->m_sb.sb_flags) 2178c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (sb->sb_shared_vn != mp->m_sb.sb_shared_vn) 2208c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci if (sb->sb_inoalignmt != cpu_to_be32(mp->m_sb.sb_inoalignmt)) 2238c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (sb->sb_unit != cpu_to_be32(mp->m_sb.sb_unit)) 2268c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (sb->sb_width != cpu_to_be32(mp->m_sb.sb_width)) 2298c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (sb->sb_dirblklog != mp->m_sb.sb_dirblklog) 2328c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (sb->sb_logsectlog != mp->m_sb.sb_logsectlog) 2358c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci if (sb->sb_logsectsize != cpu_to_be16(mp->m_sb.sb_logsectsize)) 2388c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (sb->sb_logsunit != cpu_to_be32(mp->m_sb.sb_logsunit)) 2418c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Do we see any invalid bits in sb_features2? */ 2448c2ecf20Sopenharmony_ci if (!xfs_sb_version_hasmorebits(&mp->m_sb)) { 2458c2ecf20Sopenharmony_ci if (sb->sb_features2 != 0) 2468c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2478c2ecf20Sopenharmony_ci } else { 2488c2ecf20Sopenharmony_ci v2_ok = XFS_SB_VERSION2_OKBITS; 2498c2ecf20Sopenharmony_ci if (XFS_SB_VERSION_NUM(&mp->m_sb) >= XFS_SB_VERSION_5) 2508c2ecf20Sopenharmony_ci v2_ok |= XFS_SB_VERSION2_CRCBIT; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok))) 2538c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (sb->sb_features2 != sb->sb_bad_features2) 2568c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* Check sb_features2 flags that are set at mkfs time. */ 2608c2ecf20Sopenharmony_ci features_mask = cpu_to_be32(XFS_SB_VERSION2_LAZYSBCOUNTBIT | 2618c2ecf20Sopenharmony_ci XFS_SB_VERSION2_PROJID32BIT | 2628c2ecf20Sopenharmony_ci XFS_SB_VERSION2_CRCBIT | 2638c2ecf20Sopenharmony_ci XFS_SB_VERSION2_FTYPE); 2648c2ecf20Sopenharmony_ci if ((sb->sb_features2 & features_mask) != 2658c2ecf20Sopenharmony_ci (cpu_to_be32(mp->m_sb.sb_features2) & features_mask)) 2668c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* Check sb_features2 flags that can be set after mkfs time. */ 2698c2ecf20Sopenharmony_ci features_mask = cpu_to_be32(XFS_SB_VERSION2_ATTR2BIT); 2708c2ecf20Sopenharmony_ci if ((sb->sb_features2 & features_mask) != 2718c2ecf20Sopenharmony_ci (cpu_to_be32(mp->m_sb.sb_features2) & features_mask)) 2728c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci if (!xfs_sb_version_hascrc(&mp->m_sb)) { 2758c2ecf20Sopenharmony_ci /* all v5 fields must be zero */ 2768c2ecf20Sopenharmony_ci if (memchr_inv(&sb->sb_features_compat, 0, 2778c2ecf20Sopenharmony_ci sizeof(struct xfs_dsb) - 2788c2ecf20Sopenharmony_ci offsetof(struct xfs_dsb, sb_features_compat))) 2798c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2808c2ecf20Sopenharmony_ci } else { 2818c2ecf20Sopenharmony_ci /* Check compat flags; all are set at mkfs time. */ 2828c2ecf20Sopenharmony_ci features_mask = cpu_to_be32(XFS_SB_FEAT_COMPAT_UNKNOWN); 2838c2ecf20Sopenharmony_ci if ((sb->sb_features_compat & features_mask) != 2848c2ecf20Sopenharmony_ci (cpu_to_be32(mp->m_sb.sb_features_compat) & features_mask)) 2858c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* Check ro compat flags; all are set at mkfs time. */ 2888c2ecf20Sopenharmony_ci features_mask = cpu_to_be32(XFS_SB_FEAT_RO_COMPAT_UNKNOWN | 2898c2ecf20Sopenharmony_ci XFS_SB_FEAT_RO_COMPAT_FINOBT | 2908c2ecf20Sopenharmony_ci XFS_SB_FEAT_RO_COMPAT_RMAPBT | 2918c2ecf20Sopenharmony_ci XFS_SB_FEAT_RO_COMPAT_REFLINK); 2928c2ecf20Sopenharmony_ci if ((sb->sb_features_ro_compat & features_mask) != 2938c2ecf20Sopenharmony_ci (cpu_to_be32(mp->m_sb.sb_features_ro_compat) & 2948c2ecf20Sopenharmony_ci features_mask)) 2958c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* Check incompat flags; all are set at mkfs time. */ 2988c2ecf20Sopenharmony_ci features_mask = cpu_to_be32(XFS_SB_FEAT_INCOMPAT_UNKNOWN | 2998c2ecf20Sopenharmony_ci XFS_SB_FEAT_INCOMPAT_FTYPE | 3008c2ecf20Sopenharmony_ci XFS_SB_FEAT_INCOMPAT_SPINODES | 3018c2ecf20Sopenharmony_ci XFS_SB_FEAT_INCOMPAT_META_UUID); 3028c2ecf20Sopenharmony_ci if ((sb->sb_features_incompat & features_mask) != 3038c2ecf20Sopenharmony_ci (cpu_to_be32(mp->m_sb.sb_features_incompat) & 3048c2ecf20Sopenharmony_ci features_mask)) 3058c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* Check log incompat flags; all are set at mkfs time. */ 3088c2ecf20Sopenharmony_ci features_mask = cpu_to_be32(XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN); 3098c2ecf20Sopenharmony_ci if ((sb->sb_features_log_incompat & features_mask) != 3108c2ecf20Sopenharmony_ci (cpu_to_be32(mp->m_sb.sb_features_log_incompat) & 3118c2ecf20Sopenharmony_ci features_mask)) 3128c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci /* Don't care about sb_crc */ 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci if (sb->sb_spino_align != cpu_to_be32(mp->m_sb.sb_spino_align)) 3178c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (sb->sb_pquotino != cpu_to_be64(mp->m_sb.sb_pquotino)) 3208c2ecf20Sopenharmony_ci xchk_block_set_preen(sc, bp); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* Don't care about sb_lsn */ 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (xfs_sb_version_hasmetauuid(&mp->m_sb)) { 3268c2ecf20Sopenharmony_ci /* The metadata UUID must be the same for all supers */ 3278c2ecf20Sopenharmony_ci if (!uuid_equal(&sb->sb_meta_uuid, &mp->m_sb.sb_meta_uuid)) 3288c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* Everything else must be zero. */ 3328c2ecf20Sopenharmony_ci if (memchr_inv(sb + 1, 0, 3338c2ecf20Sopenharmony_ci BBTOB(bp->b_length) - sizeof(struct xfs_dsb))) 3348c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, bp); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci xchk_superblock_xref(sc, bp); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci return error; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci/* AGF */ 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci/* Tally freespace record lengths. */ 3448c2ecf20Sopenharmony_ciSTATIC int 3458c2ecf20Sopenharmony_cixchk_agf_record_bno_lengths( 3468c2ecf20Sopenharmony_ci struct xfs_btree_cur *cur, 3478c2ecf20Sopenharmony_ci struct xfs_alloc_rec_incore *rec, 3488c2ecf20Sopenharmony_ci void *priv) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci xfs_extlen_t *blocks = priv; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci (*blocks) += rec->ar_blockcount; 3538c2ecf20Sopenharmony_ci return 0; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci/* Check agf_freeblks */ 3578c2ecf20Sopenharmony_cistatic inline void 3588c2ecf20Sopenharmony_cixchk_agf_xref_freeblks( 3598c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci struct xfs_agf *agf = sc->sa.agf_bp->b_addr; 3628c2ecf20Sopenharmony_ci xfs_extlen_t blocks = 0; 3638c2ecf20Sopenharmony_ci int error; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci if (!sc->sa.bno_cur) 3668c2ecf20Sopenharmony_ci return; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci error = xfs_alloc_query_all(sc->sa.bno_cur, 3698c2ecf20Sopenharmony_ci xchk_agf_record_bno_lengths, &blocks); 3708c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur)) 3718c2ecf20Sopenharmony_ci return; 3728c2ecf20Sopenharmony_ci if (blocks != be32_to_cpu(agf->agf_freeblks)) 3738c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp); 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci/* Cross reference the AGF with the cntbt (freespace by length btree) */ 3778c2ecf20Sopenharmony_cistatic inline void 3788c2ecf20Sopenharmony_cixchk_agf_xref_cntbt( 3798c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 3808c2ecf20Sopenharmony_ci{ 3818c2ecf20Sopenharmony_ci struct xfs_agf *agf = sc->sa.agf_bp->b_addr; 3828c2ecf20Sopenharmony_ci xfs_agblock_t agbno; 3838c2ecf20Sopenharmony_ci xfs_extlen_t blocks; 3848c2ecf20Sopenharmony_ci int have; 3858c2ecf20Sopenharmony_ci int error; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if (!sc->sa.cnt_cur) 3888c2ecf20Sopenharmony_ci return; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci /* Any freespace at all? */ 3918c2ecf20Sopenharmony_ci error = xfs_alloc_lookup_le(sc->sa.cnt_cur, 0, -1U, &have); 3928c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur)) 3938c2ecf20Sopenharmony_ci return; 3948c2ecf20Sopenharmony_ci if (!have) { 3958c2ecf20Sopenharmony_ci if (agf->agf_freeblks != cpu_to_be32(0)) 3968c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp); 3978c2ecf20Sopenharmony_ci return; 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci /* Check agf_longest */ 4018c2ecf20Sopenharmony_ci error = xfs_alloc_get_rec(sc->sa.cnt_cur, &agbno, &blocks, &have); 4028c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur)) 4038c2ecf20Sopenharmony_ci return; 4048c2ecf20Sopenharmony_ci if (!have || blocks != be32_to_cpu(agf->agf_longest)) 4058c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp); 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci/* Check the btree block counts in the AGF against the btrees. */ 4098c2ecf20Sopenharmony_ciSTATIC void 4108c2ecf20Sopenharmony_cixchk_agf_xref_btreeblks( 4118c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci struct xfs_agf *agf = sc->sa.agf_bp->b_addr; 4148c2ecf20Sopenharmony_ci struct xfs_mount *mp = sc->mp; 4158c2ecf20Sopenharmony_ci xfs_agblock_t blocks; 4168c2ecf20Sopenharmony_ci xfs_agblock_t btreeblks; 4178c2ecf20Sopenharmony_ci int error; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci /* Check agf_rmap_blocks; set up for agf_btreeblks check */ 4208c2ecf20Sopenharmony_ci if (sc->sa.rmap_cur) { 4218c2ecf20Sopenharmony_ci error = xfs_btree_count_blocks(sc->sa.rmap_cur, &blocks); 4228c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) 4238c2ecf20Sopenharmony_ci return; 4248c2ecf20Sopenharmony_ci btreeblks = blocks - 1; 4258c2ecf20Sopenharmony_ci if (blocks != be32_to_cpu(agf->agf_rmap_blocks)) 4268c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp); 4278c2ecf20Sopenharmony_ci } else { 4288c2ecf20Sopenharmony_ci btreeblks = 0; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci /* 4328c2ecf20Sopenharmony_ci * No rmap cursor; we can't xref if we have the rmapbt feature. 4338c2ecf20Sopenharmony_ci * We also can't do it if we're missing the free space btree cursors. 4348c2ecf20Sopenharmony_ci */ 4358c2ecf20Sopenharmony_ci if ((xfs_sb_version_hasrmapbt(&mp->m_sb) && !sc->sa.rmap_cur) || 4368c2ecf20Sopenharmony_ci !sc->sa.bno_cur || !sc->sa.cnt_cur) 4378c2ecf20Sopenharmony_ci return; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* Check agf_btreeblks */ 4408c2ecf20Sopenharmony_ci error = xfs_btree_count_blocks(sc->sa.bno_cur, &blocks); 4418c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur)) 4428c2ecf20Sopenharmony_ci return; 4438c2ecf20Sopenharmony_ci btreeblks += blocks - 1; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci error = xfs_btree_count_blocks(sc->sa.cnt_cur, &blocks); 4468c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur)) 4478c2ecf20Sopenharmony_ci return; 4488c2ecf20Sopenharmony_ci btreeblks += blocks - 1; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci if (btreeblks != be32_to_cpu(agf->agf_btreeblks)) 4518c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp); 4528c2ecf20Sopenharmony_ci} 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci/* Check agf_refcount_blocks against tree size */ 4558c2ecf20Sopenharmony_cistatic inline void 4568c2ecf20Sopenharmony_cixchk_agf_xref_refcblks( 4578c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci struct xfs_agf *agf = sc->sa.agf_bp->b_addr; 4608c2ecf20Sopenharmony_ci xfs_agblock_t blocks; 4618c2ecf20Sopenharmony_ci int error; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (!sc->sa.refc_cur) 4648c2ecf20Sopenharmony_ci return; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci error = xfs_btree_count_blocks(sc->sa.refc_cur, &blocks); 4678c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur)) 4688c2ecf20Sopenharmony_ci return; 4698c2ecf20Sopenharmony_ci if (blocks != be32_to_cpu(agf->agf_refcount_blocks)) 4708c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci/* Cross-reference with the other btrees. */ 4748c2ecf20Sopenharmony_ciSTATIC void 4758c2ecf20Sopenharmony_cixchk_agf_xref( 4768c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci struct xfs_mount *mp = sc->mp; 4798c2ecf20Sopenharmony_ci xfs_agblock_t agbno; 4808c2ecf20Sopenharmony_ci int error; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 4838c2ecf20Sopenharmony_ci return; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci agbno = XFS_AGF_BLOCK(mp); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci error = xchk_ag_btcur_init(sc, &sc->sa); 4888c2ecf20Sopenharmony_ci if (error) 4898c2ecf20Sopenharmony_ci return; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci xchk_xref_is_used_space(sc, agbno, 1); 4928c2ecf20Sopenharmony_ci xchk_agf_xref_freeblks(sc); 4938c2ecf20Sopenharmony_ci xchk_agf_xref_cntbt(sc); 4948c2ecf20Sopenharmony_ci xchk_xref_is_not_inode_chunk(sc, agbno, 1); 4958c2ecf20Sopenharmony_ci xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); 4968c2ecf20Sopenharmony_ci xchk_agf_xref_btreeblks(sc); 4978c2ecf20Sopenharmony_ci xchk_xref_is_not_shared(sc, agbno, 1); 4988c2ecf20Sopenharmony_ci xchk_agf_xref_refcblks(sc); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci /* scrub teardown will take care of sc->sa for us */ 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci/* Scrub the AGF. */ 5048c2ecf20Sopenharmony_ciint 5058c2ecf20Sopenharmony_cixchk_agf( 5068c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci struct xfs_mount *mp = sc->mp; 5098c2ecf20Sopenharmony_ci struct xfs_agf *agf; 5108c2ecf20Sopenharmony_ci struct xfs_perag *pag; 5118c2ecf20Sopenharmony_ci xfs_agnumber_t agno; 5128c2ecf20Sopenharmony_ci xfs_agblock_t agbno; 5138c2ecf20Sopenharmony_ci xfs_agblock_t eoag; 5148c2ecf20Sopenharmony_ci xfs_agblock_t agfl_first; 5158c2ecf20Sopenharmony_ci xfs_agblock_t agfl_last; 5168c2ecf20Sopenharmony_ci xfs_agblock_t agfl_count; 5178c2ecf20Sopenharmony_ci xfs_agblock_t fl_count; 5188c2ecf20Sopenharmony_ci int level; 5198c2ecf20Sopenharmony_ci int error = 0; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci agno = sc->sa.agno = sc->sm->sm_agno; 5228c2ecf20Sopenharmony_ci error = xchk_ag_read_headers(sc, agno, &sc->sa.agi_bp, 5238c2ecf20Sopenharmony_ci &sc->sa.agf_bp, &sc->sa.agfl_bp); 5248c2ecf20Sopenharmony_ci if (!xchk_process_error(sc, agno, XFS_AGF_BLOCK(sc->mp), &error)) 5258c2ecf20Sopenharmony_ci goto out; 5268c2ecf20Sopenharmony_ci xchk_buffer_recheck(sc, sc->sa.agf_bp); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci agf = sc->sa.agf_bp->b_addr; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* Check the AG length */ 5318c2ecf20Sopenharmony_ci eoag = be32_to_cpu(agf->agf_length); 5328c2ecf20Sopenharmony_ci if (eoag != xfs_ag_block_count(mp, agno)) 5338c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* Check the AGF btree roots and levels */ 5368c2ecf20Sopenharmony_ci agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]); 5378c2ecf20Sopenharmony_ci if (!xfs_verify_agbno(mp, agno, agbno)) 5388c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]); 5418c2ecf20Sopenharmony_ci if (!xfs_verify_agbno(mp, agno, agbno)) 5428c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]); 5458c2ecf20Sopenharmony_ci if (level <= 0 || level > XFS_BTREE_MAXLEVELS) 5468c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); 5498c2ecf20Sopenharmony_ci if (level <= 0 || level > XFS_BTREE_MAXLEVELS) 5508c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { 5538c2ecf20Sopenharmony_ci agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); 5548c2ecf20Sopenharmony_ci if (!xfs_verify_agbno(mp, agno, agbno)) 5558c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); 5588c2ecf20Sopenharmony_ci if (level <= 0 || level > XFS_BTREE_MAXLEVELS) 5598c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci if (xfs_sb_version_hasreflink(&mp->m_sb)) { 5638c2ecf20Sopenharmony_ci agbno = be32_to_cpu(agf->agf_refcount_root); 5648c2ecf20Sopenharmony_ci if (!xfs_verify_agbno(mp, agno, agbno)) 5658c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci level = be32_to_cpu(agf->agf_refcount_level); 5688c2ecf20Sopenharmony_ci if (level <= 0 || level > XFS_BTREE_MAXLEVELS) 5698c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci /* Check the AGFL counters */ 5738c2ecf20Sopenharmony_ci agfl_first = be32_to_cpu(agf->agf_flfirst); 5748c2ecf20Sopenharmony_ci agfl_last = be32_to_cpu(agf->agf_fllast); 5758c2ecf20Sopenharmony_ci agfl_count = be32_to_cpu(agf->agf_flcount); 5768c2ecf20Sopenharmony_ci if (agfl_last > agfl_first) 5778c2ecf20Sopenharmony_ci fl_count = agfl_last - agfl_first + 1; 5788c2ecf20Sopenharmony_ci else 5798c2ecf20Sopenharmony_ci fl_count = xfs_agfl_size(mp) - agfl_first + agfl_last + 1; 5808c2ecf20Sopenharmony_ci if (agfl_count != 0 && fl_count != agfl_count) 5818c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /* Do the incore counters match? */ 5848c2ecf20Sopenharmony_ci pag = xfs_perag_get(mp, agno); 5858c2ecf20Sopenharmony_ci if (pag->pagf_freeblks != be32_to_cpu(agf->agf_freeblks)) 5868c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5878c2ecf20Sopenharmony_ci if (pag->pagf_flcount != be32_to_cpu(agf->agf_flcount)) 5888c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5898c2ecf20Sopenharmony_ci if (pag->pagf_btreeblks != be32_to_cpu(agf->agf_btreeblks)) 5908c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 5918c2ecf20Sopenharmony_ci xfs_perag_put(pag); 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci xchk_agf_xref(sc); 5948c2ecf20Sopenharmony_ciout: 5958c2ecf20Sopenharmony_ci return error; 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci/* AGFL */ 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_cistruct xchk_agfl_info { 6018c2ecf20Sopenharmony_ci unsigned int sz_entries; 6028c2ecf20Sopenharmony_ci unsigned int nr_entries; 6038c2ecf20Sopenharmony_ci xfs_agblock_t *entries; 6048c2ecf20Sopenharmony_ci struct xfs_scrub *sc; 6058c2ecf20Sopenharmony_ci}; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci/* Cross-reference with the other btrees. */ 6088c2ecf20Sopenharmony_ciSTATIC void 6098c2ecf20Sopenharmony_cixchk_agfl_block_xref( 6108c2ecf20Sopenharmony_ci struct xfs_scrub *sc, 6118c2ecf20Sopenharmony_ci xfs_agblock_t agbno) 6128c2ecf20Sopenharmony_ci{ 6138c2ecf20Sopenharmony_ci if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 6148c2ecf20Sopenharmony_ci return; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci xchk_xref_is_used_space(sc, agbno, 1); 6178c2ecf20Sopenharmony_ci xchk_xref_is_not_inode_chunk(sc, agbno, 1); 6188c2ecf20Sopenharmony_ci xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG); 6198c2ecf20Sopenharmony_ci xchk_xref_is_not_shared(sc, agbno, 1); 6208c2ecf20Sopenharmony_ci} 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci/* Scrub an AGFL block. */ 6238c2ecf20Sopenharmony_ciSTATIC int 6248c2ecf20Sopenharmony_cixchk_agfl_block( 6258c2ecf20Sopenharmony_ci struct xfs_mount *mp, 6268c2ecf20Sopenharmony_ci xfs_agblock_t agbno, 6278c2ecf20Sopenharmony_ci void *priv) 6288c2ecf20Sopenharmony_ci{ 6298c2ecf20Sopenharmony_ci struct xchk_agfl_info *sai = priv; 6308c2ecf20Sopenharmony_ci struct xfs_scrub *sc = sai->sc; 6318c2ecf20Sopenharmony_ci xfs_agnumber_t agno = sc->sa.agno; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci if (xfs_verify_agbno(mp, agno, agbno) && 6348c2ecf20Sopenharmony_ci sai->nr_entries < sai->sz_entries) 6358c2ecf20Sopenharmony_ci sai->entries[sai->nr_entries++] = agbno; 6368c2ecf20Sopenharmony_ci else 6378c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agfl_bp); 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci xchk_agfl_block_xref(sc, agbno); 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 6428c2ecf20Sopenharmony_ci return -ECANCELED; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci return 0; 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic int 6488c2ecf20Sopenharmony_cixchk_agblock_cmp( 6498c2ecf20Sopenharmony_ci const void *pa, 6508c2ecf20Sopenharmony_ci const void *pb) 6518c2ecf20Sopenharmony_ci{ 6528c2ecf20Sopenharmony_ci const xfs_agblock_t *a = pa; 6538c2ecf20Sopenharmony_ci const xfs_agblock_t *b = pb; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci return (int)*a - (int)*b; 6568c2ecf20Sopenharmony_ci} 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci/* Cross-reference with the other btrees. */ 6598c2ecf20Sopenharmony_ciSTATIC void 6608c2ecf20Sopenharmony_cixchk_agfl_xref( 6618c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 6628c2ecf20Sopenharmony_ci{ 6638c2ecf20Sopenharmony_ci struct xfs_mount *mp = sc->mp; 6648c2ecf20Sopenharmony_ci xfs_agblock_t agbno; 6658c2ecf20Sopenharmony_ci int error; 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 6688c2ecf20Sopenharmony_ci return; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci agbno = XFS_AGFL_BLOCK(mp); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci error = xchk_ag_btcur_init(sc, &sc->sa); 6738c2ecf20Sopenharmony_ci if (error) 6748c2ecf20Sopenharmony_ci return; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci xchk_xref_is_used_space(sc, agbno, 1); 6778c2ecf20Sopenharmony_ci xchk_xref_is_not_inode_chunk(sc, agbno, 1); 6788c2ecf20Sopenharmony_ci xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); 6798c2ecf20Sopenharmony_ci xchk_xref_is_not_shared(sc, agbno, 1); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci /* 6828c2ecf20Sopenharmony_ci * Scrub teardown will take care of sc->sa for us. Leave sc->sa 6838c2ecf20Sopenharmony_ci * active so that the agfl block xref can use it too. 6848c2ecf20Sopenharmony_ci */ 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci/* Scrub the AGFL. */ 6888c2ecf20Sopenharmony_ciint 6898c2ecf20Sopenharmony_cixchk_agfl( 6908c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 6918c2ecf20Sopenharmony_ci{ 6928c2ecf20Sopenharmony_ci struct xchk_agfl_info sai; 6938c2ecf20Sopenharmony_ci struct xfs_agf *agf; 6948c2ecf20Sopenharmony_ci xfs_agnumber_t agno; 6958c2ecf20Sopenharmony_ci unsigned int agflcount; 6968c2ecf20Sopenharmony_ci unsigned int i; 6978c2ecf20Sopenharmony_ci int error; 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci agno = sc->sa.agno = sc->sm->sm_agno; 7008c2ecf20Sopenharmony_ci error = xchk_ag_read_headers(sc, agno, &sc->sa.agi_bp, 7018c2ecf20Sopenharmony_ci &sc->sa.agf_bp, &sc->sa.agfl_bp); 7028c2ecf20Sopenharmony_ci if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error)) 7038c2ecf20Sopenharmony_ci goto out; 7048c2ecf20Sopenharmony_ci if (!sc->sa.agf_bp) 7058c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 7068c2ecf20Sopenharmony_ci xchk_buffer_recheck(sc, sc->sa.agfl_bp); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci xchk_agfl_xref(sc); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 7118c2ecf20Sopenharmony_ci goto out; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci /* Allocate buffer to ensure uniqueness of AGFL entries. */ 7148c2ecf20Sopenharmony_ci agf = sc->sa.agf_bp->b_addr; 7158c2ecf20Sopenharmony_ci agflcount = be32_to_cpu(agf->agf_flcount); 7168c2ecf20Sopenharmony_ci if (agflcount > xfs_agfl_size(sc->mp)) { 7178c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 7188c2ecf20Sopenharmony_ci goto out; 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci memset(&sai, 0, sizeof(sai)); 7218c2ecf20Sopenharmony_ci sai.sc = sc; 7228c2ecf20Sopenharmony_ci sai.sz_entries = agflcount; 7238c2ecf20Sopenharmony_ci sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount, 7248c2ecf20Sopenharmony_ci KM_MAYFAIL); 7258c2ecf20Sopenharmony_ci if (!sai.entries) { 7268c2ecf20Sopenharmony_ci error = -ENOMEM; 7278c2ecf20Sopenharmony_ci goto out; 7288c2ecf20Sopenharmony_ci } 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci /* Check the blocks in the AGFL. */ 7318c2ecf20Sopenharmony_ci error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr, 7328c2ecf20Sopenharmony_ci sc->sa.agfl_bp, xchk_agfl_block, &sai); 7338c2ecf20Sopenharmony_ci if (error == -ECANCELED) { 7348c2ecf20Sopenharmony_ci error = 0; 7358c2ecf20Sopenharmony_ci goto out_free; 7368c2ecf20Sopenharmony_ci } 7378c2ecf20Sopenharmony_ci if (error) 7388c2ecf20Sopenharmony_ci goto out_free; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci if (agflcount != sai.nr_entries) { 7418c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 7428c2ecf20Sopenharmony_ci goto out_free; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* Sort entries, check for duplicates. */ 7468c2ecf20Sopenharmony_ci sort(sai.entries, sai.nr_entries, sizeof(sai.entries[0]), 7478c2ecf20Sopenharmony_ci xchk_agblock_cmp, NULL); 7488c2ecf20Sopenharmony_ci for (i = 1; i < sai.nr_entries; i++) { 7498c2ecf20Sopenharmony_ci if (sai.entries[i] == sai.entries[i - 1]) { 7508c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agf_bp); 7518c2ecf20Sopenharmony_ci break; 7528c2ecf20Sopenharmony_ci } 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ciout_free: 7568c2ecf20Sopenharmony_ci kmem_free(sai.entries); 7578c2ecf20Sopenharmony_ciout: 7588c2ecf20Sopenharmony_ci return error; 7598c2ecf20Sopenharmony_ci} 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci/* AGI */ 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci/* Check agi_count/agi_freecount */ 7648c2ecf20Sopenharmony_cistatic inline void 7658c2ecf20Sopenharmony_cixchk_agi_xref_icounts( 7668c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 7678c2ecf20Sopenharmony_ci{ 7688c2ecf20Sopenharmony_ci struct xfs_agi *agi = sc->sa.agi_bp->b_addr; 7698c2ecf20Sopenharmony_ci xfs_agino_t icount; 7708c2ecf20Sopenharmony_ci xfs_agino_t freecount; 7718c2ecf20Sopenharmony_ci int error; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if (!sc->sa.ino_cur) 7748c2ecf20Sopenharmony_ci return; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci error = xfs_ialloc_count_inodes(sc->sa.ino_cur, &icount, &freecount); 7778c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur)) 7788c2ecf20Sopenharmony_ci return; 7798c2ecf20Sopenharmony_ci if (be32_to_cpu(agi->agi_count) != icount || 7808c2ecf20Sopenharmony_ci be32_to_cpu(agi->agi_freecount) != freecount) 7818c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp); 7828c2ecf20Sopenharmony_ci} 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci/* Check agi_[fi]blocks against tree size */ 7858c2ecf20Sopenharmony_cistatic inline void 7868c2ecf20Sopenharmony_cixchk_agi_xref_fiblocks( 7878c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci struct xfs_agi *agi = sc->sa.agi_bp->b_addr; 7908c2ecf20Sopenharmony_ci xfs_agblock_t blocks; 7918c2ecf20Sopenharmony_ci int error = 0; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci if (!xfs_sb_version_hasinobtcounts(&sc->mp->m_sb)) 7948c2ecf20Sopenharmony_ci return; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci if (sc->sa.ino_cur) { 7978c2ecf20Sopenharmony_ci error = xfs_btree_count_blocks(sc->sa.ino_cur, &blocks); 7988c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur)) 7998c2ecf20Sopenharmony_ci return; 8008c2ecf20Sopenharmony_ci if (blocks != be32_to_cpu(agi->agi_iblocks)) 8018c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp); 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci if (sc->sa.fino_cur) { 8058c2ecf20Sopenharmony_ci error = xfs_btree_count_blocks(sc->sa.fino_cur, &blocks); 8068c2ecf20Sopenharmony_ci if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur)) 8078c2ecf20Sopenharmony_ci return; 8088c2ecf20Sopenharmony_ci if (blocks != be32_to_cpu(agi->agi_fblocks)) 8098c2ecf20Sopenharmony_ci xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp); 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci} 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci/* Cross-reference with the other btrees. */ 8148c2ecf20Sopenharmony_ciSTATIC void 8158c2ecf20Sopenharmony_cixchk_agi_xref( 8168c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci struct xfs_mount *mp = sc->mp; 8198c2ecf20Sopenharmony_ci xfs_agblock_t agbno; 8208c2ecf20Sopenharmony_ci int error; 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 8238c2ecf20Sopenharmony_ci return; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci agbno = XFS_AGI_BLOCK(mp); 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci error = xchk_ag_btcur_init(sc, &sc->sa); 8288c2ecf20Sopenharmony_ci if (error) 8298c2ecf20Sopenharmony_ci return; 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci xchk_xref_is_used_space(sc, agbno, 1); 8328c2ecf20Sopenharmony_ci xchk_xref_is_not_inode_chunk(sc, agbno, 1); 8338c2ecf20Sopenharmony_ci xchk_agi_xref_icounts(sc); 8348c2ecf20Sopenharmony_ci xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); 8358c2ecf20Sopenharmony_ci xchk_xref_is_not_shared(sc, agbno, 1); 8368c2ecf20Sopenharmony_ci xchk_agi_xref_fiblocks(sc); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* scrub teardown will take care of sc->sa for us */ 8398c2ecf20Sopenharmony_ci} 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci/* Scrub the AGI. */ 8428c2ecf20Sopenharmony_ciint 8438c2ecf20Sopenharmony_cixchk_agi( 8448c2ecf20Sopenharmony_ci struct xfs_scrub *sc) 8458c2ecf20Sopenharmony_ci{ 8468c2ecf20Sopenharmony_ci struct xfs_mount *mp = sc->mp; 8478c2ecf20Sopenharmony_ci struct xfs_agi *agi; 8488c2ecf20Sopenharmony_ci struct xfs_perag *pag; 8498c2ecf20Sopenharmony_ci xfs_agnumber_t agno; 8508c2ecf20Sopenharmony_ci xfs_agblock_t agbno; 8518c2ecf20Sopenharmony_ci xfs_agblock_t eoag; 8528c2ecf20Sopenharmony_ci xfs_agino_t agino; 8538c2ecf20Sopenharmony_ci xfs_agino_t first_agino; 8548c2ecf20Sopenharmony_ci xfs_agino_t last_agino; 8558c2ecf20Sopenharmony_ci xfs_agino_t icount; 8568c2ecf20Sopenharmony_ci int i; 8578c2ecf20Sopenharmony_ci int level; 8588c2ecf20Sopenharmony_ci int error = 0; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci agno = sc->sa.agno = sc->sm->sm_agno; 8618c2ecf20Sopenharmony_ci error = xchk_ag_read_headers(sc, agno, &sc->sa.agi_bp, 8628c2ecf20Sopenharmony_ci &sc->sa.agf_bp, &sc->sa.agfl_bp); 8638c2ecf20Sopenharmony_ci if (!xchk_process_error(sc, agno, XFS_AGI_BLOCK(sc->mp), &error)) 8648c2ecf20Sopenharmony_ci goto out; 8658c2ecf20Sopenharmony_ci xchk_buffer_recheck(sc, sc->sa.agi_bp); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci agi = sc->sa.agi_bp->b_addr; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci /* Check the AG length */ 8708c2ecf20Sopenharmony_ci eoag = be32_to_cpu(agi->agi_length); 8718c2ecf20Sopenharmony_ci if (eoag != xfs_ag_block_count(mp, agno)) 8728c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci /* Check btree roots and levels */ 8758c2ecf20Sopenharmony_ci agbno = be32_to_cpu(agi->agi_root); 8768c2ecf20Sopenharmony_ci if (!xfs_verify_agbno(mp, agno, agbno)) 8778c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci level = be32_to_cpu(agi->agi_level); 8808c2ecf20Sopenharmony_ci if (level <= 0 || level > XFS_BTREE_MAXLEVELS) 8818c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (xfs_sb_version_hasfinobt(&mp->m_sb)) { 8848c2ecf20Sopenharmony_ci agbno = be32_to_cpu(agi->agi_free_root); 8858c2ecf20Sopenharmony_ci if (!xfs_verify_agbno(mp, agno, agbno)) 8868c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci level = be32_to_cpu(agi->agi_free_level); 8898c2ecf20Sopenharmony_ci if (level <= 0 || level > XFS_BTREE_MAXLEVELS) 8908c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci /* Check inode counters */ 8948c2ecf20Sopenharmony_ci xfs_agino_range(mp, agno, &first_agino, &last_agino); 8958c2ecf20Sopenharmony_ci icount = be32_to_cpu(agi->agi_count); 8968c2ecf20Sopenharmony_ci if (icount > last_agino - first_agino + 1 || 8978c2ecf20Sopenharmony_ci icount < be32_to_cpu(agi->agi_freecount)) 8988c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* Check inode pointers */ 9018c2ecf20Sopenharmony_ci agino = be32_to_cpu(agi->agi_newino); 9028c2ecf20Sopenharmony_ci if (!xfs_verify_agino_or_null(mp, agno, agino)) 9038c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci agino = be32_to_cpu(agi->agi_dirino); 9068c2ecf20Sopenharmony_ci if (!xfs_verify_agino_or_null(mp, agno, agino)) 9078c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci /* Check unlinked inode buckets */ 9108c2ecf20Sopenharmony_ci for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) { 9118c2ecf20Sopenharmony_ci agino = be32_to_cpu(agi->agi_unlinked[i]); 9128c2ecf20Sopenharmony_ci if (!xfs_verify_agino_or_null(mp, agno, agino)) 9138c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci if (agi->agi_pad32 != cpu_to_be32(0)) 9178c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci /* Do the incore counters match? */ 9208c2ecf20Sopenharmony_ci pag = xfs_perag_get(mp, agno); 9218c2ecf20Sopenharmony_ci if (pag->pagi_count != be32_to_cpu(agi->agi_count)) 9228c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 9238c2ecf20Sopenharmony_ci if (pag->pagi_freecount != be32_to_cpu(agi->agi_freecount)) 9248c2ecf20Sopenharmony_ci xchk_block_set_corrupt(sc, sc->sa.agi_bp); 9258c2ecf20Sopenharmony_ci xfs_perag_put(pag); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci xchk_agi_xref(sc); 9288c2ecf20Sopenharmony_ciout: 9298c2ecf20Sopenharmony_ci return error; 9308c2ecf20Sopenharmony_ci} 931