LCOV - code coverage report
Current view: top level - fs/xfs/scrub - agheader_repair.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 384 425 90.4 %
Date: 2023-07-31 20:08:17 Functions: 22 22 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 2018-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_log_format.h"
      14             : #include "xfs_trans.h"
      15             : #include "xfs_sb.h"
      16             : #include "xfs_alloc.h"
      17             : #include "xfs_alloc_btree.h"
      18             : #include "xfs_ialloc.h"
      19             : #include "xfs_ialloc_btree.h"
      20             : #include "xfs_rmap.h"
      21             : #include "xfs_rmap_btree.h"
      22             : #include "xfs_refcount_btree.h"
      23             : #include "xfs_ag.h"
      24             : #include "scrub/scrub.h"
      25             : #include "scrub/common.h"
      26             : #include "scrub/trace.h"
      27             : #include "scrub/repair.h"
      28             : #include "scrub/bitmap.h"
      29             : 
      30             : /* Superblock */
      31             : 
      32             : /* Repair the superblock. */
      33             : int
      34      388564 : xrep_superblock(
      35             :         struct xfs_scrub        *sc)
      36             : {
      37      388564 :         struct xfs_mount        *mp = sc->mp;
      38      388564 :         struct xfs_buf          *bp;
      39      388564 :         xfs_agnumber_t          agno;
      40      388564 :         int                     error;
      41             : 
      42             :         /* Don't try to repair AG 0's sb; let xfs_repair deal with it. */
      43      388564 :         agno = sc->sm->sm_agno;
      44      388564 :         if (agno == 0)
      45             :                 return -EOPNOTSUPP;
      46             : 
      47      289380 :         error = xfs_sb_get_secondary(mp, sc->tp, agno, &bp);
      48      289358 :         if (error)
      49             :                 return error;
      50             : 
      51             :         /* Copy AG 0's superblock to this one. */
      52      289359 :         xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
      53      289370 :         xfs_sb_to_disk(bp->b_addr, &mp->m_sb);
      54             : 
      55             :         /*
      56             :          * Don't write out a secondary super with NEEDSREPAIR or log incompat
      57             :          * features set, since both are ignored when set on a secondary.
      58             :          */
      59      289372 :         if (xfs_has_crc(mp)) {
      60      289375 :                 struct xfs_dsb          *sb = bp->b_addr;
      61             : 
      62      289375 :                 sb->sb_features_incompat &=
      63             :                                 ~cpu_to_be32(XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR);
      64      289375 :                 sb->sb_features_log_incompat = 0;
      65             :         }
      66             : 
      67             :         /* Write this to disk. */
      68      289372 :         xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_SB_BUF);
      69      289374 :         xfs_trans_log_buf(sc->tp, bp, 0, BBTOB(bp->b_length) - 1);
      70      289374 :         return error;
      71             : }
      72             : 
      73             : /* AGF */
      74             : 
      75             : struct xrep_agf_allocbt {
      76             :         struct xfs_scrub        *sc;
      77             :         xfs_agblock_t           freeblks;
      78             :         xfs_agblock_t           longest;
      79             : };
      80             : 
      81             : /* Record free space shape information. */
      82             : STATIC int
      83   202629573 : xrep_agf_walk_allocbt(
      84             :         struct xfs_btree_cur            *cur,
      85             :         const struct xfs_alloc_rec_incore *rec,
      86             :         void                            *priv)
      87             : {
      88   202629573 :         struct xrep_agf_allocbt         *raa = priv;
      89   202629573 :         int                             error = 0;
      90             : 
      91   202629573 :         if (xchk_should_terminate(raa->sc, &error))
      92           0 :                 return error;
      93             : 
      94   202629597 :         raa->freeblks += rec->ar_blockcount;
      95   202629597 :         if (rec->ar_blockcount > raa->longest)
      96      597495 :                 raa->longest = rec->ar_blockcount;
      97   202629597 :         return error;
      98             : }
      99             : 
     100             : /* Does this AGFL block look sane? */
     101             : STATIC int
     102     1262387 : xrep_agf_check_agfl_block(
     103             :         struct xfs_mount        *mp,
     104             :         xfs_agblock_t           agbno,
     105             :         void                    *priv)
     106             : {
     107     1262387 :         struct xfs_scrub        *sc = priv;
     108             : 
     109     1262387 :         if (!xfs_verify_agbno(sc->sa.pag, agbno))
     110           0 :                 return -EFSCORRUPTED;
     111             :         return 0;
     112             : }
     113             : 
     114             : /*
     115             :  * Offset within the xrep_find_ag_btree array for each btree type.  Avoid the
     116             :  * XFS_BTNUM_ names here to avoid creating a sparse array.
     117             :  */
     118             : enum {
     119             :         XREP_AGF_BNOBT = 0,
     120             :         XREP_AGF_CNTBT,
     121             :         XREP_AGF_RMAPBT,
     122             :         XREP_AGF_REFCOUNTBT,
     123             :         XREP_AGF_END,
     124             :         XREP_AGF_MAX
     125             : };
     126             : 
     127             : /* Check a btree root candidate. */
     128             : static inline bool
     129             : xrep_check_btree_root(
     130             :         struct xfs_scrub                *sc,
     131             :         struct xrep_find_ag_btree       *fab)
     132             : {
     133      730705 :         return xfs_verify_agbno(sc->sa.pag, fab->root) &&
     134     1099845 :                fab->height <= fab->maxlevels;
     135             : }
     136             : 
     137             : /*
     138             :  * Given the btree roots described by *fab, find the roots, check them for
     139             :  * sanity, and pass the root data back out via *fab.
     140             :  *
     141             :  * This is /also/ a chicken and egg problem because we have to use the rmapbt
     142             :  * (rooted in the AGF) to find the btrees rooted in the AGF.  We also have no
     143             :  * idea if the btrees make any sense.  If we hit obvious corruptions in those
     144             :  * btrees we'll bail out.
     145             :  */
     146             : STATIC int
     147      180781 : xrep_agf_find_btrees(
     148             :         struct xfs_scrub                *sc,
     149             :         struct xfs_buf                  *agf_bp,
     150             :         struct xrep_find_ag_btree       *fab,
     151             :         struct xfs_buf                  *agfl_bp)
     152             : {
     153      180781 :         struct xfs_agf                  *old_agf = agf_bp->b_addr;
     154      180781 :         int                             error;
     155             : 
     156             :         /* Go find the root data. */
     157      180781 :         error = xrep_find_ag_btree_roots(sc, agf_bp, fab, agfl_bp);
     158      180782 :         if (error)
     159             :                 return error;
     160             : 
     161             :         /* We must find the bnobt, cntbt, and rmapbt roots. */
     162      542346 :         if (!xrep_check_btree_root(sc, &fab[XREP_AGF_BNOBT]) ||
     163      180782 :             !xrep_check_btree_root(sc, &fab[XREP_AGF_CNTBT]) ||
     164             :             !xrep_check_btree_root(sc, &fab[XREP_AGF_RMAPBT]))
     165             :                 return -EFSCORRUPTED;
     166             : 
     167             :         /*
     168             :          * We relied on the rmapbt to reconstruct the AGF.  If we get a
     169             :          * different root then something's seriously wrong.
     170             :          */
     171      180782 :         if (fab[XREP_AGF_RMAPBT].root !=
     172      180782 :             be32_to_cpu(old_agf->agf_roots[XFS_BTNUM_RMAPi]))
     173             :                 return -EFSCORRUPTED;
     174             : 
     175             :         /* We must find the refcountbt root if that feature is enabled. */
     176      361564 :         if (xfs_has_reflink(sc->mp) &&
     177             :             !xrep_check_btree_root(sc, &fab[XREP_AGF_REFCOUNTBT]))
     178           0 :                 return -EFSCORRUPTED;
     179             : 
     180             :         return 0;
     181             : }
     182             : 
     183             : /*
     184             :  * Reinitialize the AGF header, making an in-core copy of the old contents so
     185             :  * that we know which in-core state needs to be reinitialized.
     186             :  */
     187             : STATIC void
     188      180780 : xrep_agf_init_header(
     189             :         struct xfs_scrub        *sc,
     190             :         struct xfs_buf          *agf_bp,
     191             :         struct xfs_agf          *old_agf)
     192             : {
     193      180780 :         struct xfs_mount        *mp = sc->mp;
     194      180780 :         struct xfs_perag        *pag = sc->sa.pag;
     195      180780 :         struct xfs_agf          *agf = agf_bp->b_addr;
     196             : 
     197      361560 :         memcpy(old_agf, agf, sizeof(*old_agf));
     198      180780 :         memset(agf, 0, BBTOB(agf_bp->b_length));
     199      180780 :         agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
     200      180780 :         agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
     201      180780 :         agf->agf_seqno = cpu_to_be32(pag->pag_agno);
     202      180780 :         agf->agf_length = cpu_to_be32(pag->block_count);
     203      180780 :         agf->agf_flfirst = old_agf->agf_flfirst;
     204      180780 :         agf->agf_fllast = old_agf->agf_fllast;
     205      180780 :         agf->agf_flcount = old_agf->agf_flcount;
     206      180780 :         if (xfs_has_crc(mp))
     207      180783 :                 uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid);
     208             : 
     209             :         /* Mark the incore AGF data stale until we're done fixing things. */
     210      361558 :         ASSERT(xfs_perag_initialised_agf(pag));
     211      180779 :         clear_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
     212      180782 : }
     213             : 
     214             : /* Set btree root information in an AGF. */
     215             : STATIC void
     216      180782 : xrep_agf_set_roots(
     217             :         struct xfs_scrub                *sc,
     218             :         struct xfs_agf                  *agf,
     219             :         struct xrep_find_ag_btree       *fab)
     220             : {
     221      361564 :         agf->agf_roots[XFS_BTNUM_BNOi] =
     222      180782 :                         cpu_to_be32(fab[XREP_AGF_BNOBT].root);
     223      361564 :         agf->agf_levels[XFS_BTNUM_BNOi] =
     224      180782 :                         cpu_to_be32(fab[XREP_AGF_BNOBT].height);
     225             : 
     226      361564 :         agf->agf_roots[XFS_BTNUM_CNTi] =
     227      180782 :                         cpu_to_be32(fab[XREP_AGF_CNTBT].root);
     228      361564 :         agf->agf_levels[XFS_BTNUM_CNTi] =
     229      180782 :                         cpu_to_be32(fab[XREP_AGF_CNTBT].height);
     230             : 
     231      361564 :         agf->agf_roots[XFS_BTNUM_RMAPi] =
     232      180782 :                         cpu_to_be32(fab[XREP_AGF_RMAPBT].root);
     233      361564 :         agf->agf_levels[XFS_BTNUM_RMAPi] =
     234      180782 :                         cpu_to_be32(fab[XREP_AGF_RMAPBT].height);
     235             : 
     236      180782 :         if (xfs_has_reflink(sc->mp)) {
     237      361564 :                 agf->agf_refcount_root =
     238      180782 :                                 cpu_to_be32(fab[XREP_AGF_REFCOUNTBT].root);
     239      180782 :                 agf->agf_refcount_level =
     240      180782 :                                 cpu_to_be32(fab[XREP_AGF_REFCOUNTBT].height);
     241             :         }
     242      180782 : }
     243             : 
     244             : /* Update all AGF fields which derive from btree contents. */
     245             : STATIC int
     246      180782 : xrep_agf_calc_from_btrees(
     247             :         struct xfs_scrub        *sc,
     248             :         struct xfs_buf          *agf_bp)
     249             : {
     250      180782 :         struct xrep_agf_allocbt raa = { .sc = sc };
     251      180782 :         struct xfs_btree_cur    *cur = NULL;
     252      180782 :         struct xfs_agf          *agf = agf_bp->b_addr;
     253      180782 :         struct xfs_mount        *mp = sc->mp;
     254      180782 :         xfs_agblock_t           btreeblks;
     255      180782 :         xfs_agblock_t           blocks;
     256      180782 :         int                     error;
     257             : 
     258             :         /* Update the AGF counters from the bnobt. */
     259      180782 :         cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
     260             :                         sc->sa.pag, XFS_BTNUM_BNO);
     261      180782 :         error = xfs_alloc_query_all(cur, xrep_agf_walk_allocbt, &raa);
     262      180782 :         if (error)
     263           0 :                 goto err;
     264      180782 :         error = xfs_btree_count_blocks(cur, &blocks);
     265      180782 :         if (error)
     266           0 :                 goto err;
     267      180782 :         xfs_btree_del_cursor(cur, error);
     268      180783 :         btreeblks = blocks - 1;
     269      180783 :         agf->agf_freeblks = cpu_to_be32(raa.freeblks);
     270      180783 :         agf->agf_longest = cpu_to_be32(raa.longest);
     271             : 
     272             :         /* Update the AGF counters from the cntbt. */
     273      180783 :         cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
     274             :                         sc->sa.pag, XFS_BTNUM_CNT);
     275      180781 :         error = xfs_btree_count_blocks(cur, &blocks);
     276      180783 :         if (error)
     277           0 :                 goto err;
     278      180783 :         xfs_btree_del_cursor(cur, error);
     279      180783 :         btreeblks += blocks - 1;
     280             : 
     281             :         /* Update the AGF counters from the rmapbt. */
     282      180783 :         cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
     283      180783 :         error = xfs_btree_count_blocks(cur, &blocks);
     284      180783 :         if (error)
     285           0 :                 goto err;
     286      180783 :         xfs_btree_del_cursor(cur, error);
     287      180781 :         agf->agf_rmap_blocks = cpu_to_be32(blocks);
     288      180781 :         btreeblks += blocks - 1;
     289             : 
     290      180781 :         agf->agf_btreeblks = cpu_to_be32(btreeblks);
     291             : 
     292             :         /* Update the AGF counters from the refcountbt. */
     293      180781 :         if (xfs_has_reflink(mp)) {
     294      180783 :                 cur = xfs_refcountbt_init_cursor(mp, sc->tp, agf_bp,
     295             :                                 sc->sa.pag);
     296      180783 :                 error = xfs_btree_count_blocks(cur, &blocks);
     297      180783 :                 if (error)
     298           0 :                         goto err;
     299      180783 :                 xfs_btree_del_cursor(cur, error);
     300      361566 :                 agf->agf_refcount_blocks = cpu_to_be32(blocks);
     301             :         }
     302             : 
     303             :         return 0;
     304           0 : err:
     305           0 :         xfs_btree_del_cursor(cur, error);
     306           0 :         return error;
     307             : }
     308             : 
     309             : /* Commit the new AGF and reinitialize the incore state. */
     310             : STATIC int
     311      180780 : xrep_agf_commit_new(
     312             :         struct xfs_scrub        *sc,
     313             :         struct xfs_buf          *agf_bp)
     314             : {
     315      180780 :         struct xfs_perag        *pag;
     316      180780 :         struct xfs_agf          *agf = agf_bp->b_addr;
     317             : 
     318             :         /* Trigger fdblocks recalculation */
     319      180780 :         xfs_force_summary_recalc(sc->mp);
     320             : 
     321             :         /* Write this to disk. */
     322      180783 :         xfs_trans_buf_set_type(sc->tp, agf_bp, XFS_BLFT_AGF_BUF);
     323      180782 :         xfs_trans_log_buf(sc->tp, agf_bp, 0, BBTOB(agf_bp->b_length) - 1);
     324             : 
     325             :         /* Now reinitialize the in-core counters we changed. */
     326      180781 :         pag = sc->sa.pag;
     327      180781 :         pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
     328      180781 :         pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
     329      180781 :         pag->pagf_longest = be32_to_cpu(agf->agf_longest);
     330      180781 :         pag->pagf_levels[XFS_BTNUM_BNOi] =
     331      180781 :                         be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
     332      180781 :         pag->pagf_levels[XFS_BTNUM_CNTi] =
     333      180781 :                         be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
     334      180781 :         pag->pagf_levels[XFS_BTNUM_RMAPi] =
     335      180781 :                         be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]);
     336      180781 :         pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
     337      180781 :         set_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
     338             : 
     339      180782 :         return 0;
     340             : }
     341             : 
     342             : /* Repair the AGF. v5 filesystems only. */
     343             : int
     344      256729 : xrep_agf(
     345             :         struct xfs_scrub                *sc)
     346             : {
     347      256729 :         struct xrep_find_ag_btree       fab[XREP_AGF_MAX] = {
     348             :                 [XREP_AGF_BNOBT] = {
     349             :                         .rmap_owner = XFS_RMAP_OWN_AG,
     350             :                         .buf_ops = &xfs_bnobt_buf_ops,
     351      256729 :                         .maxlevels = sc->mp->m_alloc_maxlevels,
     352             :                 },
     353             :                 [XREP_AGF_CNTBT] = {
     354             :                         .rmap_owner = XFS_RMAP_OWN_AG,
     355             :                         .buf_ops = &xfs_cntbt_buf_ops,
     356             :                         .maxlevels = sc->mp->m_alloc_maxlevels,
     357             :                 },
     358             :                 [XREP_AGF_RMAPBT] = {
     359             :                         .rmap_owner = XFS_RMAP_OWN_AG,
     360             :                         .buf_ops = &xfs_rmapbt_buf_ops,
     361      256729 :                         .maxlevels = sc->mp->m_rmap_maxlevels,
     362             :                 },
     363             :                 [XREP_AGF_REFCOUNTBT] = {
     364             :                         .rmap_owner = XFS_RMAP_OWN_REFC,
     365             :                         .buf_ops = &xfs_refcountbt_buf_ops,
     366      256729 :                         .maxlevels = sc->mp->m_refc_maxlevels,
     367             :                 },
     368             :                 [XREP_AGF_END] = {
     369             :                         .buf_ops = NULL,
     370             :                 },
     371             :         };
     372      256729 :         struct xfs_agf                  old_agf;
     373      256729 :         struct xfs_mount                *mp = sc->mp;
     374      256729 :         struct xfs_buf                  *agf_bp;
     375      256729 :         struct xfs_buf                  *agfl_bp;
     376      256729 :         struct xfs_agf                  *agf;
     377      256729 :         int                             error;
     378             : 
     379             :         /* We require the rmapbt to rebuild anything. */
     380      256729 :         if (!xfs_has_rmapbt(mp))
     381             :                 return -EOPNOTSUPP;
     382             : 
     383             :         /*
     384             :          * Make sure we have the AGF buffer, as scrub might have decided it
     385             :          * was corrupt after xfs_alloc_read_agf failed with -EFSCORRUPTED.
     386             :          */
     387      542337 :         error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
     388      180779 :                         XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
     389             :                                                 XFS_AGF_DADDR(mp)),
     390      180779 :                         XFS_FSS_TO_BB(mp, 1), 0, &agf_bp, NULL);
     391      180780 :         if (error)
     392             :                 return error;
     393      180782 :         agf_bp->b_ops = &xfs_agf_buf_ops;
     394      180782 :         agf = agf_bp->b_addr;
     395             : 
     396             :         /*
     397             :          * Load the AGFL so that we can screen out OWN_AG blocks that are on
     398             :          * the AGFL now; these blocks might have once been part of the
     399             :          * bno/cnt/rmap btrees but are not now.  This is a chicken and egg
     400             :          * problem: the AGF is corrupt, so we have to trust the AGFL contents
     401             :          * because we can't do any serious cross-referencing with any of the
     402             :          * btrees rooted in the AGF.  If the AGFL contents are obviously bad
     403             :          * then we'll bail out.
     404             :          */
     405      180782 :         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
     406      180783 :         if (error)
     407             :                 return error;
     408             : 
     409             :         /*
     410             :          * Spot-check the AGFL blocks; if they're obviously corrupt then
     411             :          * there's nothing we can do but bail out.
     412             :          */
     413      180783 :         error = xfs_agfl_walk(sc->mp, agf_bp->b_addr, agfl_bp,
     414             :                         xrep_agf_check_agfl_block, sc);
     415      180783 :         if (error)
     416             :                 return error;
     417             : 
     418             :         /*
     419             :          * Find the AGF btree roots.  This is also a chicken-and-egg situation;
     420             :          * see the function for more details.
     421             :          */
     422      180783 :         error = xrep_agf_find_btrees(sc, agf_bp, fab, agfl_bp);
     423      180782 :         if (error)
     424             :                 return error;
     425             : 
     426             :         /* Start rewriting the header and implant the btrees we found. */
     427      180783 :         xrep_agf_init_header(sc, agf_bp, &old_agf);
     428      180779 :         xrep_agf_set_roots(sc, agf, fab);
     429      180782 :         error = xrep_agf_calc_from_btrees(sc, agf_bp);
     430      180783 :         if (error)
     431           0 :                 goto out_revert;
     432             : 
     433             :         /* Commit the changes and reinitialize incore state. */
     434      180783 :         return xrep_agf_commit_new(sc, agf_bp);
     435             : 
     436             : out_revert:
     437             :         /* Mark the incore AGF state stale and revert the AGF. */
     438           0 :         clear_bit(XFS_AGSTATE_AGF_INIT, &sc->sa.pag->pag_opstate);
     439           0 :         memcpy(agf, &old_agf, sizeof(old_agf));
     440           0 :         return error;
     441             : }
     442             : 
     443             : /* AGFL */
     444             : 
     445             : struct xrep_agfl {
     446             :         /* Bitmap of alleged AGFL blocks that we're not going to add. */
     447             :         struct xbitmap          crossed;
     448             : 
     449             :         /* Bitmap of other OWN_AG metadata blocks. */
     450             :         struct xbitmap          agmetablocks;
     451             : 
     452             :         /* Bitmap of free space. */
     453             :         struct xbitmap          *freesp;
     454             : 
     455             :         /* rmapbt cursor for finding crosslinked blocks */
     456             :         struct xfs_btree_cur    *rmap_cur;
     457             : 
     458             :         struct xfs_scrub        *sc;
     459             : };
     460             : 
     461             : /* Record all OWN_AG (free space btree) information from the rmap data. */
     462             : STATIC int
     463  2189030818 : xrep_agfl_walk_rmap(
     464             :         struct xfs_btree_cur    *cur,
     465             :         const struct xfs_rmap_irec *rec,
     466             :         void                    *priv)
     467             : {
     468  2189030818 :         struct xrep_agfl        *ra = priv;
     469  2189030818 :         xfs_fsblock_t           fsb;
     470  2189030818 :         int                     error = 0;
     471             : 
     472  2189030818 :         if (xchk_should_terminate(ra->sc, &error))
     473           0 :                 return error;
     474             : 
     475             :         /* Record all the OWN_AG blocks. */
     476  2189045787 :         if (rec->rm_owner == XFS_RMAP_OWN_AG) {
     477    16757068 :                 fsb = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno,
     478             :                                 rec->rm_startblock);
     479    16757068 :                 error = xbitmap_set(ra->freesp, fsb, rec->rm_blockcount);
     480    16757062 :                 if (error)
     481             :                         return error;
     482             :         }
     483             : 
     484  2189045781 :         return xbitmap_set_btcur_path(&ra->agmetablocks, cur);
     485             : }
     486             : 
     487             : /* Strike out the blocks that are cross-linked according to the rmapbt. */
     488             : STATIC int
     489      641430 : xrep_agfl_check_extent(
     490             :         uint64_t                start,
     491             :         uint64_t                len,
     492             :         void                    *priv)
     493             : {
     494      641430 :         struct xrep_agfl        *ra = priv;
     495      641430 :         xfs_agblock_t           agbno = XFS_FSB_TO_AGBNO(ra->sc->mp, start);
     496      641432 :         xfs_agblock_t           last_agbno = agbno + len - 1;
     497      641432 :         int                     error;
     498             : 
     499      641432 :         ASSERT(XFS_FSB_TO_AGNO(ra->sc->mp, start) == ra->sc->sa.pag->pag_agno);
     500             : 
     501     1944763 :         while (agbno <= last_agbno) {
     502     1303329 :                 bool            other_owners;
     503             : 
     504     1303329 :                 error = xfs_rmap_has_other_keys(ra->rmap_cur, agbno, 1,
     505             :                                 &XFS_RMAP_OINFO_AG, &other_owners);
     506     1303341 :                 if (error)
     507           0 :                         return error;
     508             : 
     509     1303341 :                 if (other_owners) {
     510           0 :                         error = xbitmap_set(&ra->crossed, agbno, 1);
     511           0 :                         if (error)
     512           0 :                                 return error;
     513             :                 }
     514             : 
     515     1303341 :                 if (xchk_should_terminate(ra->sc, &error))
     516           0 :                         return error;
     517     1303331 :                 agbno++;
     518             :         }
     519             : 
     520             :         return 0;
     521             : }
     522             : 
     523             : /*
     524             :  * Map out all the non-AGFL OWN_AG space in this AG so that we can deduce
     525             :  * which blocks belong to the AGFL.
     526             :  *
     527             :  * Compute the set of old AGFL blocks by subtracting from the list of OWN_AG
     528             :  * blocks the list of blocks owned by all other OWN_AG metadata (bnobt, cntbt,
     529             :  * rmapbt).  These are the old AGFL blocks, so return that list and the number
     530             :  * of blocks we're actually going to put back on the AGFL.
     531             :  */
     532             : STATIC int
     533      184899 : xrep_agfl_collect_blocks(
     534             :         struct xfs_scrub        *sc,
     535             :         struct xfs_buf          *agf_bp,
     536             :         struct xbitmap          *agfl_extents,
     537             :         xfs_agblock_t           *flcount)
     538             : {
     539      184899 :         struct xrep_agfl        ra;
     540      184899 :         struct xfs_mount        *mp = sc->mp;
     541      184899 :         struct xfs_btree_cur    *cur;
     542      184899 :         int                     error;
     543             : 
     544      184899 :         ra.sc = sc;
     545      184899 :         ra.freesp = agfl_extents;
     546      184899 :         xbitmap_init(&ra.agmetablocks);
     547      184903 :         xbitmap_init(&ra.crossed);
     548             : 
     549             :         /* Find all space used by the free space btrees & rmapbt. */
     550      184903 :         cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
     551      184902 :         error = xfs_rmap_query_all(cur, xrep_agfl_walk_rmap, &ra);
     552      184902 :         xfs_btree_del_cursor(cur, error);
     553      184903 :         if (error)
     554           0 :                 goto out_bmp;
     555             : 
     556             :         /* Find all blocks currently being used by the bnobt. */
     557      184903 :         cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
     558             :                         sc->sa.pag, XFS_BTNUM_BNO);
     559      184902 :         error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
     560      184902 :         xfs_btree_del_cursor(cur, error);
     561      184903 :         if (error)
     562           0 :                 goto out_bmp;
     563             : 
     564             :         /* Find all blocks currently being used by the cntbt. */
     565      184903 :         cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
     566             :                         sc->sa.pag, XFS_BTNUM_CNT);
     567      184902 :         error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
     568      184893 :         xfs_btree_del_cursor(cur, error);
     569      184903 :         if (error)
     570           0 :                 goto out_bmp;
     571             : 
     572             :         /*
     573             :          * Drop the freesp meta blocks that are in use by btrees.
     574             :          * The remaining blocks /should/ be AGFL blocks.
     575             :          */
     576      184903 :         error = xbitmap_disunion(agfl_extents, &ra.agmetablocks);
     577      184901 :         if (error)
     578           0 :                 goto out_bmp;
     579             : 
     580             :         /* Strike out the blocks that are cross-linked. */
     581      184901 :         ra.rmap_cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
     582      184899 :         error = xbitmap_walk(agfl_extents, xrep_agfl_check_extent, &ra);
     583      184895 :         xfs_btree_del_cursor(ra.rmap_cur, error);
     584      184903 :         if (error)
     585           0 :                 goto out_bmp;
     586      184903 :         error = xbitmap_disunion(agfl_extents, &ra.crossed);
     587      184903 :         if (error)
     588           0 :                 goto out_bmp;
     589             : 
     590             :         /*
     591             :          * Calculate the new AGFL size.  If we found more blocks than fit in
     592             :          * the AGFL we'll free them later.
     593             :          */
     594      184903 :         *flcount = min_t(uint64_t, xbitmap_hweight(agfl_extents),
     595             :                          xfs_agfl_size(mp));
     596             : 
     597      184901 : out_bmp:
     598      184901 :         xbitmap_destroy(&ra.crossed);
     599      184902 :         xbitmap_destroy(&ra.agmetablocks);
     600      184901 :         return error;
     601             : }
     602             : 
     603             : /* Update the AGF and reset the in-core state. */
     604             : STATIC void
     605      184903 : xrep_agfl_update_agf(
     606             :         struct xfs_scrub        *sc,
     607             :         struct xfs_buf          *agf_bp,
     608             :         xfs_agblock_t           flcount)
     609             : {
     610      184903 :         struct xfs_agf          *agf = agf_bp->b_addr;
     611             : 
     612      184903 :         ASSERT(flcount <= xfs_agfl_size(sc->mp));
     613             : 
     614             :         /* Trigger fdblocks recalculation */
     615      184902 :         xfs_force_summary_recalc(sc->mp);
     616             : 
     617             :         /* Update the AGF counters. */
     618      369806 :         if (xfs_perag_initialised_agf(sc->sa.pag))
     619      184903 :                 sc->sa.pag->pagf_flcount = flcount;
     620      184903 :         agf->agf_flfirst = cpu_to_be32(0);
     621      184903 :         agf->agf_flcount = cpu_to_be32(flcount);
     622      184903 :         agf->agf_fllast = cpu_to_be32(flcount - 1);
     623             : 
     624      184903 :         xfs_alloc_log_agf(sc->tp, agf_bp,
     625             :                         XFS_AGF_FLFIRST | XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
     626      184901 : }
     627             : 
     628             : struct xrep_agfl_fill {
     629             :         struct xbitmap          used_extents;
     630             :         struct xfs_scrub        *sc;
     631             :         __be32                  *agfl_bno;
     632             :         xfs_agblock_t           flcount;
     633             :         unsigned int            fl_off;
     634             : };
     635             : 
     636             : /* Fill the AGFL with whatever blocks are in this extent. */
     637             : static int
     638      641415 : xrep_agfl_fill(
     639             :         uint64_t                start,
     640             :         uint64_t                len,
     641             :         void                    *priv)
     642             : {
     643      641415 :         struct xrep_agfl_fill   *af = priv;
     644      641415 :         struct xfs_scrub        *sc = af->sc;
     645      641415 :         xfs_fsblock_t           fsbno = start;
     646      641415 :         int                     error;
     647             : 
     648     1944714 :         while (fsbno < start + len && af->fl_off < af->flcount)
     649     2606587 :                 af->agfl_bno[af->fl_off++] =
     650     1303288 :                                 cpu_to_be32(XFS_FSB_TO_AGBNO(sc->mp, fsbno++));
     651             : 
     652      641418 :         trace_xrep_agfl_insert(sc->mp, sc->sa.pag->pag_agno,
     653      641426 :                         XFS_FSB_TO_AGBNO(sc->mp, start), len);
     654             : 
     655      641407 :         error = xbitmap_set(&af->used_extents, start, fsbno - 1);
     656      641416 :         if (error)
     657             :                 return error;
     658             : 
     659      641416 :         if (af->fl_off == af->flcount)
     660      184871 :                 return -ECANCELED;
     661             : 
     662             :         return 0;
     663             : }
     664             : 
     665             : /* Write out a totally new AGFL. */
     666             : STATIC int
     667      184897 : xrep_agfl_init_header(
     668             :         struct xfs_scrub        *sc,
     669             :         struct xfs_buf          *agfl_bp,
     670             :         struct xbitmap          *agfl_extents,
     671             :         xfs_agblock_t           flcount)
     672             : {
     673      184897 :         struct xrep_agfl_fill   af = {
     674             :                 .sc             = sc,
     675             :                 .flcount        = flcount,
     676             :         };
     677      184897 :         struct xfs_mount        *mp = sc->mp;
     678      184897 :         struct xfs_agfl         *agfl;
     679      184897 :         int                     error;
     680             : 
     681      184897 :         ASSERT(flcount <= xfs_agfl_size(mp));
     682             : 
     683             :         /*
     684             :          * Start rewriting the header by setting the bno[] array to
     685             :          * NULLAGBLOCK, then setting AGFL header fields.
     686             :          */
     687      184899 :         agfl = XFS_BUF_TO_AGFL(agfl_bp);
     688      184899 :         memset(agfl, 0xFF, BBTOB(agfl_bp->b_length));
     689      184899 :         agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
     690      184899 :         agfl->agfl_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
     691      184899 :         uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid);
     692             : 
     693             :         /*
     694             :          * Fill the AGFL with the remaining blocks.  If agfl_extents has more
     695             :          * blocks than fit in the AGFL, they will be freed in a subsequent
     696             :          * step.
     697             :          */
     698      184901 :         xbitmap_init(&af.used_extents);
     699      184891 :         af.agfl_bno = xfs_buf_to_agfl_bno(agfl_bp),
     700      184891 :         xbitmap_walk(agfl_extents, xrep_agfl_fill, &af);
     701      184890 :         error = xbitmap_disunion(agfl_extents, &af.used_extents);
     702      184876 :         if (error)
     703             :                 return error;
     704             : 
     705             :         /* Write new AGFL to disk. */
     706      184876 :         xfs_trans_buf_set_type(sc->tp, agfl_bp, XFS_BLFT_AGFL_BUF);
     707      184877 :         xfs_trans_log_buf(sc->tp, agfl_bp, 0, BBTOB(agfl_bp->b_length) - 1);
     708      184878 :         xbitmap_destroy(&af.used_extents);
     709      184878 :         return 0;
     710             : }
     711             : 
     712             : /* Repair the AGFL. */
     713             : int
     714      260853 : xrep_agfl(
     715             :         struct xfs_scrub        *sc)
     716             : {
     717      260853 :         struct xbitmap          agfl_extents;
     718      260853 :         struct xfs_mount        *mp = sc->mp;
     719      260853 :         struct xfs_buf          *agf_bp;
     720      260853 :         struct xfs_buf          *agfl_bp;
     721      260853 :         xfs_agblock_t           flcount;
     722      260853 :         int                     error;
     723             : 
     724             :         /* We require the rmapbt to rebuild anything. */
     725      260853 :         if (!xfs_has_rmapbt(mp))
     726             :                 return -EOPNOTSUPP;
     727             : 
     728      184900 :         xbitmap_init(&agfl_extents);
     729             : 
     730             :         /*
     731             :          * Read the AGF so that we can query the rmapbt.  We hope that there's
     732             :          * nothing wrong with the AGF, but all the AG header repair functions
     733             :          * have this chicken-and-egg problem.
     734             :          */
     735      184903 :         error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
     736      184902 :         if (error)
     737             :                 return error;
     738             : 
     739             :         /*
     740             :          * Make sure we have the AGFL buffer, as scrub might have decided it
     741             :          * was corrupt after xfs_alloc_read_agfl failed with -EFSCORRUPTED.
     742             :          */
     743      554706 :         error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
     744      184902 :                         XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
     745             :                                                 XFS_AGFL_DADDR(mp)),
     746      184902 :                         XFS_FSS_TO_BB(mp, 1), 0, &agfl_bp, NULL);
     747      184903 :         if (error)
     748             :                 return error;
     749      184903 :         agfl_bp->b_ops = &xfs_agfl_buf_ops;
     750             : 
     751             :         /* Gather all the extents we're going to put on the new AGFL. */
     752      184903 :         error = xrep_agfl_collect_blocks(sc, agf_bp, &agfl_extents, &flcount);
     753      184903 :         if (error)
     754           0 :                 goto err;
     755             : 
     756             :         /*
     757             :          * Update AGF and AGFL.  We reset the global free block counter when
     758             :          * we adjust the AGF flcount (which can fail) so avoid updating any
     759             :          * buffers until we know that part works.
     760             :          */
     761      184903 :         xrep_agfl_update_agf(sc, agf_bp, flcount);
     762      184901 :         error = xrep_agfl_init_header(sc, agfl_bp, &agfl_extents, flcount);
     763      184891 :         if (error)
     764           0 :                 goto err;
     765             : 
     766             :         /*
     767             :          * Ok, the AGFL should be ready to go now.  Roll the transaction to
     768             :          * make the new AGFL permanent before we start using it to return
     769             :          * freespace overflow to the freespace btrees.
     770             :          */
     771      184891 :         sc->sa.agf_bp = agf_bp;
     772      184891 :         error = xrep_roll_ag_trans(sc);
     773      184895 :         if (error)
     774           0 :                 goto err;
     775             : 
     776             :         /* Dump any AGFL overflow. */
     777      184895 :         error = xrep_reap_extents(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
     778             :                         XFS_AG_RESV_AGFL);
     779      184863 : err:
     780      184863 :         xbitmap_destroy(&agfl_extents);
     781      184863 :         return error;
     782             : }
     783             : 
     784             : /* AGI */
     785             : 
     786             : /*
     787             :  * Offset within the xrep_find_ag_btree array for each btree type.  Avoid the
     788             :  * XFS_BTNUM_ names here to avoid creating a sparse array.
     789             :  */
     790             : enum {
     791             :         XREP_AGI_INOBT = 0,
     792             :         XREP_AGI_FINOBT,
     793             :         XREP_AGI_END,
     794             :         XREP_AGI_MAX
     795             : };
     796             : 
     797             : /*
     798             :  * Given the inode btree roots described by *fab, find the roots, check them
     799             :  * for sanity, and pass the root data back out via *fab.
     800             :  */
     801             : STATIC int
     802      188358 : xrep_agi_find_btrees(
     803             :         struct xfs_scrub                *sc,
     804             :         struct xrep_find_ag_btree       *fab)
     805             : {
     806      188358 :         struct xfs_buf                  *agf_bp;
     807      188358 :         struct xfs_mount                *mp = sc->mp;
     808      188358 :         int                             error;
     809             : 
     810             :         /* Read the AGF. */
     811      188358 :         error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
     812      188359 :         if (error)
     813             :                 return error;
     814             : 
     815             :         /* Find the btree roots. */
     816      188359 :         error = xrep_find_ag_btree_roots(sc, agf_bp, fab, NULL);
     817      188358 :         if (error)
     818             :                 return error;
     819             : 
     820             :         /* We must find the inobt root. */
     821      376716 :         if (!xrep_check_btree_root(sc, &fab[XREP_AGI_INOBT]))
     822             :                 return -EFSCORRUPTED;
     823             : 
     824             :         /* We must find the finobt root if that feature is enabled. */
     825      376717 :         if (xfs_has_finobt(mp) &&
     826             :             !xrep_check_btree_root(sc, &fab[XREP_AGI_FINOBT]))
     827           0 :                 return -EFSCORRUPTED;
     828             : 
     829             :         return 0;
     830             : }
     831             : 
     832             : /*
     833             :  * Reinitialize the AGI header, making an in-core copy of the old contents so
     834             :  * that we know which in-core state needs to be reinitialized.
     835             :  */
     836             : STATIC void
     837      188358 : xrep_agi_init_header(
     838             :         struct xfs_scrub        *sc,
     839             :         struct xfs_buf          *agi_bp,
     840             :         struct xfs_agi          *old_agi)
     841             : {
     842      188358 :         struct xfs_agi          *agi = agi_bp->b_addr;
     843      188358 :         struct xfs_perag        *pag = sc->sa.pag;
     844      188358 :         struct xfs_mount        *mp = sc->mp;
     845             : 
     846      376716 :         memcpy(old_agi, agi, sizeof(*old_agi));
     847      188358 :         memset(agi, 0, BBTOB(agi_bp->b_length));
     848      188358 :         agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
     849      188358 :         agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
     850      188358 :         agi->agi_seqno = cpu_to_be32(pag->pag_agno);
     851      188358 :         agi->agi_length = cpu_to_be32(pag->block_count);
     852      188358 :         agi->agi_newino = cpu_to_be32(NULLAGINO);
     853      188358 :         agi->agi_dirino = cpu_to_be32(NULLAGINO);
     854      188358 :         if (xfs_has_crc(mp))
     855      188359 :                 uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid);
     856             : 
     857             :         /* We don't know how to fix the unlinked list yet. */
     858      376716 :         memcpy(&agi->agi_unlinked, &old_agi->agi_unlinked,
     859             :                         sizeof(agi->agi_unlinked));
     860             : 
     861             :         /* Mark the incore AGF data stale until we're done fixing things. */
     862      376716 :         ASSERT(xfs_perag_initialised_agi(pag));
     863      188358 :         clear_bit(XFS_AGSTATE_AGI_INIT, &pag->pag_opstate);
     864      188359 : }
     865             : 
     866             : /* Set btree root information in an AGI. */
     867             : STATIC void
     868      188357 : xrep_agi_set_roots(
     869             :         struct xfs_scrub                *sc,
     870             :         struct xfs_agi                  *agi,
     871             :         struct xrep_find_ag_btree       *fab)
     872             : {
     873      188357 :         agi->agi_root = cpu_to_be32(fab[XREP_AGI_INOBT].root);
     874      188357 :         agi->agi_level = cpu_to_be32(fab[XREP_AGI_INOBT].height);
     875             : 
     876      188357 :         if (xfs_has_finobt(sc->mp)) {
     877      188359 :                 agi->agi_free_root = cpu_to_be32(fab[XREP_AGI_FINOBT].root);
     878      376718 :                 agi->agi_free_level = cpu_to_be32(fab[XREP_AGI_FINOBT].height);
     879             :         }
     880      188357 : }
     881             : 
     882             : /* Update the AGI counters. */
     883             : STATIC int
     884      188359 : xrep_agi_calc_from_btrees(
     885             :         struct xfs_scrub        *sc,
     886             :         struct xfs_buf          *agi_bp)
     887             : {
     888      188359 :         struct xfs_btree_cur    *cur;
     889      188359 :         struct xfs_agi          *agi = agi_bp->b_addr;
     890      188359 :         struct xfs_mount        *mp = sc->mp;
     891      188359 :         xfs_agino_t             count;
     892      188359 :         xfs_agino_t             freecount;
     893      188359 :         int                     error;
     894             : 
     895      188359 :         cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, agi_bp, XFS_BTNUM_INO);
     896      188359 :         error = xfs_ialloc_count_inodes(cur, &count, &freecount);
     897      188359 :         if (error)
     898           0 :                 goto err;
     899      188359 :         if (xfs_has_inobtcounts(mp)) {
     900      188359 :                 xfs_agblock_t   blocks;
     901             : 
     902      188359 :                 error = xfs_btree_count_blocks(cur, &blocks);
     903      188359 :                 if (error)
     904           0 :                         goto err;
     905      376718 :                 agi->agi_iblocks = cpu_to_be32(blocks);
     906             :         }
     907      188359 :         xfs_btree_del_cursor(cur, error);
     908             : 
     909      188356 :         agi->agi_count = cpu_to_be32(count);
     910      188356 :         agi->agi_freecount = cpu_to_be32(freecount);
     911             : 
     912      188356 :         if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
     913      188359 :                 xfs_agblock_t   blocks;
     914             : 
     915      188359 :                 cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, agi_bp,
     916             :                                 XFS_BTNUM_FINO);
     917      188359 :                 error = xfs_btree_count_blocks(cur, &blocks);
     918      188359 :                 if (error)
     919           0 :                         goto err;
     920      188359 :                 xfs_btree_del_cursor(cur, error);
     921      376718 :                 agi->agi_fblocks = cpu_to_be32(blocks);
     922             :         }
     923             : 
     924             :         return 0;
     925           0 : err:
     926           0 :         xfs_btree_del_cursor(cur, error);
     927           0 :         return error;
     928             : }
     929             : 
     930             : /* Trigger reinitialization of the in-core data. */
     931             : STATIC int
     932      188359 : xrep_agi_commit_new(
     933             :         struct xfs_scrub        *sc,
     934             :         struct xfs_buf          *agi_bp)
     935             : {
     936      188359 :         struct xfs_perag        *pag;
     937      188359 :         struct xfs_agi          *agi = agi_bp->b_addr;
     938             : 
     939             :         /* Trigger inode count recalculation */
     940      188359 :         xfs_force_summary_recalc(sc->mp);
     941             : 
     942             :         /* Write this to disk. */
     943      188359 :         xfs_trans_buf_set_type(sc->tp, agi_bp, XFS_BLFT_AGI_BUF);
     944      188359 :         xfs_trans_log_buf(sc->tp, agi_bp, 0, BBTOB(agi_bp->b_length) - 1);
     945             : 
     946             :         /* Now reinitialize the in-core counters if necessary. */
     947      188359 :         pag = sc->sa.pag;
     948      188359 :         pag->pagi_count = be32_to_cpu(agi->agi_count);
     949      188359 :         pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
     950      188359 :         set_bit(XFS_AGSTATE_AGI_INIT, &pag->pag_opstate);
     951             : 
     952      188359 :         return 0;
     953             : }
     954             : 
     955             : /* Repair the AGI. */
     956             : int
     957      264305 : xrep_agi(
     958             :         struct xfs_scrub                *sc)
     959             : {
     960      264305 :         struct xrep_find_ag_btree       fab[XREP_AGI_MAX] = {
     961             :                 [XREP_AGI_INOBT] = {
     962             :                         .rmap_owner = XFS_RMAP_OWN_INOBT,
     963             :                         .buf_ops = &xfs_inobt_buf_ops,
     964      264305 :                         .maxlevels = M_IGEO(sc->mp)->inobt_maxlevels,
     965             :                 },
     966             :                 [XREP_AGI_FINOBT] = {
     967             :                         .rmap_owner = XFS_RMAP_OWN_INOBT,
     968             :                         .buf_ops = &xfs_finobt_buf_ops,
     969             :                         .maxlevels = M_IGEO(sc->mp)->inobt_maxlevels,
     970             :                 },
     971             :                 [XREP_AGI_END] = {
     972             :                         .buf_ops = NULL
     973             :                 },
     974             :         };
     975      264305 :         struct xfs_agi                  old_agi;
     976      264305 :         struct xfs_mount                *mp = sc->mp;
     977      264305 :         struct xfs_buf                  *agi_bp;
     978      264305 :         struct xfs_agi                  *agi;
     979      264305 :         int                             error;
     980             : 
     981             :         /* We require the rmapbt to rebuild anything. */
     982      264305 :         if (!xfs_has_rmapbt(mp))
     983             :                 return -EOPNOTSUPP;
     984             : 
     985             :         /*
     986             :          * Make sure we have the AGI buffer, as scrub might have decided it
     987             :          * was corrupt after xfs_ialloc_read_agi failed with -EFSCORRUPTED.
     988             :          */
     989      565065 :         error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
     990      188355 :                         XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
     991             :                                                 XFS_AGI_DADDR(mp)),
     992      188355 :                         XFS_FSS_TO_BB(mp, 1), 0, &agi_bp, NULL);
     993      188358 :         if (error)
     994             :                 return error;
     995      188358 :         agi_bp->b_ops = &xfs_agi_buf_ops;
     996      188358 :         agi = agi_bp->b_addr;
     997             : 
     998             :         /* Find the AGI btree roots. */
     999      188358 :         error = xrep_agi_find_btrees(sc, fab);
    1000      188359 :         if (error)
    1001             :                 return error;
    1002             : 
    1003             :         /* Start rewriting the header and implant the btrees we found. */
    1004      188359 :         xrep_agi_init_header(sc, agi_bp, &old_agi);
    1005      188359 :         xrep_agi_set_roots(sc, agi, fab);
    1006      188359 :         error = xrep_agi_calc_from_btrees(sc, agi_bp);
    1007      188358 :         if (error)
    1008           0 :                 goto out_revert;
    1009             : 
    1010             :         /* Reinitialize in-core state. */
    1011      188358 :         return xrep_agi_commit_new(sc, agi_bp);
    1012             : 
    1013             : out_revert:
    1014             :         /* Mark the incore AGI state stale and revert the AGI. */
    1015           0 :         clear_bit(XFS_AGSTATE_AGI_INIT, &sc->sa.pag->pag_opstate);
    1016           0 :         memcpy(agi, &old_agi, sizeof(old_agi));
    1017           0 :         return error;
    1018             : }

Generated by: LCOV version 1.14