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-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 384 425 90.4 %
Date: 2023-07-31 20:08:22 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      451703 : xrep_superblock(
      35             :         struct xfs_scrub        *sc)
      36             : {
      37      451703 :         struct xfs_mount        *mp = sc->mp;
      38      451703 :         struct xfs_buf          *bp;
      39      451703 :         xfs_agnumber_t          agno;
      40      451703 :         int                     error;
      41             : 
      42             :         /* Don't try to repair AG 0's sb; let xfs_repair deal with it. */
      43      451703 :         agno = sc->sm->sm_agno;
      44      451703 :         if (agno == 0)
      45             :                 return -EOPNOTSUPP;
      46             : 
      47      360305 :         error = xfs_sb_get_secondary(mp, sc->tp, agno, &bp);
      48      359698 :         if (error)
      49             :                 return error;
      50             : 
      51             :         /* Copy AG 0's superblock to this one. */
      52      359701 :         xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
      53      360057 :         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      359557 :         if (xfs_has_crc(mp)) {
      60      359565 :                 struct xfs_dsb          *sb = bp->b_addr;
      61             : 
      62      359565 :                 sb->sb_features_incompat &=
      63             :                                 ~cpu_to_be32(XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR);
      64      359565 :                 sb->sb_features_log_incompat = 0;
      65             :         }
      66             : 
      67             :         /* Write this to disk. */
      68      359557 :         xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_SB_BUF);
      69      359707 :         xfs_trans_log_buf(sc->tp, bp, 0, BBTOB(bp->b_length) - 1);
      70      359707 :         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   339891125 : xrep_agf_walk_allocbt(
      84             :         struct xfs_btree_cur            *cur,
      85             :         const struct xfs_alloc_rec_incore *rec,
      86             :         void                            *priv)
      87             : {
      88   339891125 :         struct xrep_agf_allocbt         *raa = priv;
      89   339891125 :         int                             error = 0;
      90             : 
      91   339891125 :         if (xchk_should_terminate(raa->sc, &error))
      92           0 :                 return error;
      93             : 
      94   339894056 :         raa->freeblks += rec->ar_blockcount;
      95   339894056 :         if (rec->ar_blockcount > raa->longest)
      96      881544 :                 raa->longest = rec->ar_blockcount;
      97   339894056 :         return error;
      98             : }
      99             : 
     100             : /* Does this AGFL block look sane? */
     101             : STATIC int
     102     1382931 : xrep_agf_check_agfl_block(
     103             :         struct xfs_mount        *mp,
     104             :         xfs_agblock_t           agbno,
     105             :         void                    *priv)
     106             : {
     107     1382931 :         struct xfs_scrub        *sc = priv;
     108             : 
     109     1382931 :         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      799194 :         return xfs_verify_agbno(sc->sa.pag, fab->root) &&
     134     1205699 :                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      196234 : 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      196234 :         struct xfs_agf                  *old_agf = agf_bp->b_addr;
     154      196234 :         int                             error;
     155             : 
     156             :         /* Go find the root data. */
     157      196234 :         error = xrep_find_ag_btree_roots(sc, agf_bp, fab, agfl_bp);
     158      196373 :         if (error)
     159             :                 return error;
     160             : 
     161             :         /* We must find the bnobt, cntbt, and rmapbt roots. */
     162      589119 :         if (!xrep_check_btree_root(sc, &fab[XREP_AGF_BNOBT]) ||
     163      196373 :             !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      196373 :         if (fab[XREP_AGF_RMAPBT].root !=
     172      196373 :             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      392745 :         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      196397 : xrep_agf_init_header(
     189             :         struct xfs_scrub        *sc,
     190             :         struct xfs_buf          *agf_bp,
     191             :         struct xfs_agf          *old_agf)
     192             : {
     193      196397 :         struct xfs_mount        *mp = sc->mp;
     194      196397 :         struct xfs_perag        *pag = sc->sa.pag;
     195      196397 :         struct xfs_agf          *agf = agf_bp->b_addr;
     196             : 
     197      392794 :         memcpy(old_agf, agf, sizeof(*old_agf));
     198      196397 :         memset(agf, 0, BBTOB(agf_bp->b_length));
     199      196397 :         agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
     200      196397 :         agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
     201      196397 :         agf->agf_seqno = cpu_to_be32(pag->pag_agno);
     202      196397 :         agf->agf_length = cpu_to_be32(pag->block_count);
     203      196397 :         agf->agf_flfirst = old_agf->agf_flfirst;
     204      196397 :         agf->agf_fllast = old_agf->agf_fllast;
     205      196397 :         agf->agf_flcount = old_agf->agf_flcount;
     206      196397 :         if (xfs_has_crc(mp))
     207      196393 :                 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      392718 :         ASSERT(xfs_perag_initialised_agf(pag));
     211      196359 :         clear_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
     212      196404 : }
     213             : 
     214             : /* Set btree root information in an AGF. */
     215             : STATIC void
     216      196405 : xrep_agf_set_roots(
     217             :         struct xfs_scrub                *sc,
     218             :         struct xfs_agf                  *agf,
     219             :         struct xrep_find_ag_btree       *fab)
     220             : {
     221      196405 :         agf->agf_roots[XFS_BTNUM_BNOi] =
     222      196405 :                         cpu_to_be32(fab[XREP_AGF_BNOBT].root);
     223      196405 :         agf->agf_levels[XFS_BTNUM_BNOi] =
     224      196405 :                         cpu_to_be32(fab[XREP_AGF_BNOBT].height);
     225             : 
     226      196405 :         agf->agf_roots[XFS_BTNUM_CNTi] =
     227      196405 :                         cpu_to_be32(fab[XREP_AGF_CNTBT].root);
     228      196405 :         agf->agf_levels[XFS_BTNUM_CNTi] =
     229      196405 :                         cpu_to_be32(fab[XREP_AGF_CNTBT].height);
     230             : 
     231      196405 :         agf->agf_roots[XFS_BTNUM_RMAPi] =
     232      196405 :                         cpu_to_be32(fab[XREP_AGF_RMAPBT].root);
     233      196405 :         agf->agf_levels[XFS_BTNUM_RMAPi] =
     234      196405 :                         cpu_to_be32(fab[XREP_AGF_RMAPBT].height);
     235             : 
     236      196405 :         if (xfs_has_reflink(sc->mp)) {
     237      196406 :                 agf->agf_refcount_root =
     238      196406 :                                 cpu_to_be32(fab[XREP_AGF_REFCOUNTBT].root);
     239      196406 :                 agf->agf_refcount_level =
     240      196406 :                                 cpu_to_be32(fab[XREP_AGF_REFCOUNTBT].height);
     241             :         }
     242      196405 : }
     243             : 
     244             : /* Update all AGF fields which derive from btree contents. */
     245             : STATIC int
     246      196403 : xrep_agf_calc_from_btrees(
     247             :         struct xfs_scrub        *sc,
     248             :         struct xfs_buf          *agf_bp)
     249             : {
     250      196403 :         struct xrep_agf_allocbt raa = { .sc = sc };
     251      196403 :         struct xfs_btree_cur    *cur = NULL;
     252      196403 :         struct xfs_agf          *agf = agf_bp->b_addr;
     253      196403 :         struct xfs_mount        *mp = sc->mp;
     254      196403 :         xfs_agblock_t           btreeblks;
     255      196403 :         xfs_agblock_t           blocks;
     256      196403 :         int                     error;
     257             : 
     258             :         /* Update the AGF counters from the bnobt. */
     259      196403 :         cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
     260             :                         sc->sa.pag, XFS_BTNUM_BNO);
     261      196401 :         error = xfs_alloc_query_all(cur, xrep_agf_walk_allocbt, &raa);
     262      196368 :         if (error)
     263           0 :                 goto err;
     264      196368 :         error = xfs_btree_count_blocks(cur, &blocks);
     265      196346 :         if (error)
     266           0 :                 goto err;
     267      196346 :         xfs_btree_del_cursor(cur, error);
     268      196407 :         btreeblks = blocks - 1;
     269      196407 :         agf->agf_freeblks = cpu_to_be32(raa.freeblks);
     270      196407 :         agf->agf_longest = cpu_to_be32(raa.longest);
     271             : 
     272             :         /* Update the AGF counters from the cntbt. */
     273      196407 :         cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
     274             :                         sc->sa.pag, XFS_BTNUM_CNT);
     275      196406 :         error = xfs_btree_count_blocks(cur, &blocks);
     276      196377 :         if (error)
     277           0 :                 goto err;
     278      196377 :         xfs_btree_del_cursor(cur, error);
     279      196406 :         btreeblks += blocks - 1;
     280             : 
     281             :         /* Update the AGF counters from the rmapbt. */
     282      196406 :         cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
     283      196408 :         error = xfs_btree_count_blocks(cur, &blocks);
     284      196385 :         if (error)
     285           0 :                 goto err;
     286      196385 :         xfs_btree_del_cursor(cur, error);
     287      196406 :         agf->agf_rmap_blocks = cpu_to_be32(blocks);
     288      196406 :         btreeblks += blocks - 1;
     289             : 
     290      196406 :         agf->agf_btreeblks = cpu_to_be32(btreeblks);
     291             : 
     292             :         /* Update the AGF counters from the refcountbt. */
     293      196406 :         if (xfs_has_reflink(mp)) {
     294      196405 :                 cur = xfs_refcountbt_init_cursor(mp, sc->tp, agf_bp,
     295             :                                 sc->sa.pag);
     296      196407 :                 error = xfs_btree_count_blocks(cur, &blocks);
     297      196384 :                 if (error)
     298           0 :                         goto err;
     299      196384 :                 xfs_btree_del_cursor(cur, error);
     300      196411 :                 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      196374 : xrep_agf_commit_new(
     312             :         struct xfs_scrub        *sc,
     313             :         struct xfs_buf          *agf_bp)
     314             : {
     315      196374 :         struct xfs_perag        *pag;
     316      196374 :         struct xfs_agf          *agf = agf_bp->b_addr;
     317             : 
     318             :         /* Trigger fdblocks recalculation */
     319      196374 :         xfs_force_summary_recalc(sc->mp);
     320             : 
     321             :         /* Write this to disk. */
     322      196394 :         xfs_trans_buf_set_type(sc->tp, agf_bp, XFS_BLFT_AGF_BUF);
     323      196364 :         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      196325 :         pag = sc->sa.pag;
     327      196325 :         pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
     328      196325 :         pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
     329      196325 :         pag->pagf_longest = be32_to_cpu(agf->agf_longest);
     330      196325 :         pag->pagf_levels[XFS_BTNUM_BNOi] =
     331      196325 :                         be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
     332      196325 :         pag->pagf_levels[XFS_BTNUM_CNTi] =
     333      196325 :                         be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
     334      196325 :         pag->pagf_levels[XFS_BTNUM_RMAPi] =
     335      196325 :                         be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]);
     336      196325 :         pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
     337      196325 :         set_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
     338             : 
     339      196386 :         return 0;
     340             : }
     341             : 
     342             : /* Repair the AGF. v5 filesystems only. */
     343             : int
     344      266064 : xrep_agf(
     345             :         struct xfs_scrub                *sc)
     346             : {
     347      266064 :         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      266064 :                         .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      266064 :                         .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      266064 :                         .maxlevels = sc->mp->m_refc_maxlevels,
     367             :                 },
     368             :                 [XREP_AGF_END] = {
     369             :                         .buf_ops = NULL,
     370             :                 },
     371             :         };
     372      266064 :         struct xfs_agf                  old_agf;
     373      266064 :         struct xfs_mount                *mp = sc->mp;
     374      266064 :         struct xfs_buf                  *agf_bp;
     375      266064 :         struct xfs_buf                  *agfl_bp;
     376      266064 :         struct xfs_agf                  *agf;
     377      266064 :         int                             error;
     378             : 
     379             :         /* We require the rmapbt to rebuild anything. */
     380      266064 :         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      785408 :         error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
     388      196352 :                         XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
     389             :                                                 XFS_AGF_DADDR(mp)),
     390      196352 :                         XFS_FSS_TO_BB(mp, 1), 0, &agf_bp, NULL);
     391      196077 :         if (error)
     392             :                 return error;
     393      196076 :         agf_bp->b_ops = &xfs_agf_buf_ops;
     394      196076 :         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      196076 :         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
     406      196267 :         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      196234 :         error = xfs_agfl_walk(sc->mp, agf_bp->b_addr, agfl_bp,
     414             :                         xrep_agf_check_agfl_block, sc);
     415      196251 :         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      196253 :         error = xrep_agf_find_btrees(sc, agf_bp, fab, agfl_bp);
     423      196374 :         if (error)
     424             :                 return error;
     425             : 
     426             :         /* Start rewriting the header and implant the btrees we found. */
     427      196374 :         xrep_agf_init_header(sc, agf_bp, &old_agf);
     428      196406 :         xrep_agf_set_roots(sc, agf, fab);
     429      196403 :         error = xrep_agf_calc_from_btrees(sc, agf_bp);
     430      196395 :         if (error)
     431           0 :                 goto out_revert;
     432             : 
     433             :         /* Commit the changes and reinitialize incore state. */
     434      196395 :         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  2551853437 : xrep_agfl_walk_rmap(
     464             :         struct xfs_btree_cur    *cur,
     465             :         const struct xfs_rmap_irec *rec,
     466             :         void                    *priv)
     467             : {
     468  2551853437 :         struct xrep_agfl        *ra = priv;
     469  2551853437 :         xfs_fsblock_t           fsb;
     470  2551853437 :         int                     error = 0;
     471             : 
     472  2551853437 :         if (xchk_should_terminate(ra->sc, &error))
     473           0 :                 return error;
     474             : 
     475             :         /* Record all the OWN_AG blocks. */
     476  2552216230 :         if (rec->rm_owner == XFS_RMAP_OWN_AG) {
     477    20295374 :                 fsb = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno,
     478             :                                 rec->rm_startblock);
     479    20295374 :                 error = xbitmap_set(ra->freesp, fsb, rec->rm_blockcount);
     480    20295032 :                 if (error)
     481             :                         return error;
     482             :         }
     483             : 
     484  2552215888 :         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      753475 : xrep_agfl_check_extent(
     490             :         uint64_t                start,
     491             :         uint64_t                len,
     492             :         void                    *priv)
     493             : {
     494      753475 :         struct xrep_agfl        *ra = priv;
     495      753475 :         xfs_agblock_t           agbno = XFS_FSB_TO_AGBNO(ra->sc->mp, start);
     496      753460 :         xfs_agblock_t           last_agbno = agbno + len - 1;
     497      753460 :         int                     error;
     498             : 
     499      753460 :         ASSERT(XFS_FSB_TO_AGNO(ra->sc->mp, start) == ra->sc->sa.pag->pag_agno);
     500             : 
     501     2226363 :         while (agbno <= last_agbno) {
     502     1472712 :                 bool            other_owners;
     503             : 
     504     1472712 :                 error = xfs_rmap_has_other_keys(ra->rmap_cur, agbno, 1,
     505             :                                 &XFS_RMAP_OINFO_AG, &other_owners);
     506     1472791 :                 if (error)
     507           0 :                         return error;
     508             : 
     509     1472791 :                 if (other_owners) {
     510           0 :                         error = xbitmap_set(&ra->crossed, agbno, 1);
     511           0 :                         if (error)
     512           0 :                                 return error;
     513             :                 }
     514             : 
     515     1472791 :                 if (xchk_should_terminate(ra->sc, &error))
     516           0 :                         return error;
     517     1472903 :                 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      205433 : 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      205433 :         struct xrep_agfl        ra;
     540      205433 :         struct xfs_mount        *mp = sc->mp;
     541      205433 :         struct xfs_btree_cur    *cur;
     542      205433 :         int                     error;
     543             : 
     544      205433 :         ra.sc = sc;
     545      205433 :         ra.freesp = agfl_extents;
     546      205433 :         xbitmap_init(&ra.agmetablocks);
     547      205397 :         xbitmap_init(&ra.crossed);
     548             : 
     549             :         /* Find all space used by the free space btrees & rmapbt. */
     550      205457 :         cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
     551      205561 :         error = xfs_rmap_query_all(cur, xrep_agfl_walk_rmap, &ra);
     552      205534 :         xfs_btree_del_cursor(cur, error);
     553      205562 :         if (error)
     554           0 :                 goto out_bmp;
     555             : 
     556             :         /* Find all blocks currently being used by the bnobt. */
     557      205562 :         cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
     558             :                         sc->sa.pag, XFS_BTNUM_BNO);
     559      205564 :         error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
     560      205435 :         xfs_btree_del_cursor(cur, error);
     561      205564 :         if (error)
     562           0 :                 goto out_bmp;
     563             : 
     564             :         /* Find all blocks currently being used by the cntbt. */
     565      205564 :         cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
     566             :                         sc->sa.pag, XFS_BTNUM_CNT);
     567      205552 :         error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
     568      205403 :         xfs_btree_del_cursor(cur, error);
     569      205564 :         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      205564 :         error = xbitmap_disunion(agfl_extents, &ra.agmetablocks);
     577      205299 :         if (error)
     578           0 :                 goto out_bmp;
     579             : 
     580             :         /* Strike out the blocks that are cross-linked. */
     581      205299 :         ra.rmap_cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
     582      205547 :         error = xbitmap_walk(agfl_extents, xrep_agfl_check_extent, &ra);
     583      205545 :         xfs_btree_del_cursor(ra.rmap_cur, error);
     584      205557 :         if (error)
     585           0 :                 goto out_bmp;
     586      205557 :         error = xbitmap_disunion(agfl_extents, &ra.crossed);
     587      205512 :         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      205512 :         *flcount = min_t(uint64_t, xbitmap_hweight(agfl_extents),
     595             :                          xfs_agfl_size(mp));
     596             : 
     597      205441 : out_bmp:
     598      205441 :         xbitmap_destroy(&ra.crossed);
     599      205408 :         xbitmap_destroy(&ra.agmetablocks);
     600      205383 :         return error;
     601             : }
     602             : 
     603             : /* Update the AGF and reset the in-core state. */
     604             : STATIC void
     605      205435 : xrep_agfl_update_agf(
     606             :         struct xfs_scrub        *sc,
     607             :         struct xfs_buf          *agf_bp,
     608             :         xfs_agblock_t           flcount)
     609             : {
     610      205435 :         struct xfs_agf          *agf = agf_bp->b_addr;
     611             : 
     612      205435 :         ASSERT(flcount <= xfs_agfl_size(sc->mp));
     613             : 
     614             :         /* Trigger fdblocks recalculation */
     615      205299 :         xfs_force_summary_recalc(sc->mp);
     616             : 
     617             :         /* Update the AGF counters. */
     618      411126 :         if (xfs_perag_initialised_agf(sc->sa.pag))
     619      205562 :                 sc->sa.pag->pagf_flcount = flcount;
     620      205563 :         agf->agf_flfirst = cpu_to_be32(0);
     621      205563 :         agf->agf_flcount = cpu_to_be32(flcount);
     622      205563 :         agf->agf_fllast = cpu_to_be32(flcount - 1);
     623             : 
     624      205563 :         xfs_alloc_log_agf(sc->tp, agf_bp,
     625             :                         XFS_AGF_FLFIRST | XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
     626      205312 : }
     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      753401 : xrep_agfl_fill(
     639             :         uint64_t                start,
     640             :         uint64_t                len,
     641             :         void                    *priv)
     642             : {
     643      753401 :         struct xrep_agfl_fill   *af = priv;
     644      753401 :         struct xfs_scrub        *sc = af->sc;
     645      753401 :         xfs_fsblock_t           fsbno = start;
     646      753401 :         int                     error;
     647             : 
     648     2224355 :         while (fsbno < start + len && af->fl_off < af->flcount)
     649     2941928 :                 af->agfl_bno[af->fl_off++] =
     650     1470974 :                                 cpu_to_be32(XFS_FSB_TO_AGBNO(sc->mp, fsbno++));
     651             : 
     652      753409 :         trace_xrep_agfl_insert(sc->mp, sc->sa.pag->pag_agno,
     653      753381 :                         XFS_FSB_TO_AGBNO(sc->mp, start), len);
     654             : 
     655      753312 :         error = xbitmap_set(&af->used_extents, start, fsbno - 1);
     656      753520 :         if (error)
     657             :                 return error;
     658             : 
     659      753520 :         if (af->fl_off == af->flcount)
     660      205451 :                 return -ECANCELED;
     661             : 
     662             :         return 0;
     663             : }
     664             : 
     665             : /* Write out a totally new AGFL. */
     666             : STATIC int
     667      205305 : 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      205305 :         struct xrep_agfl_fill   af = {
     674             :                 .sc             = sc,
     675             :                 .flcount        = flcount,
     676             :         };
     677      205305 :         struct xfs_mount        *mp = sc->mp;
     678      205305 :         struct xfs_agfl         *agfl;
     679      205305 :         int                     error;
     680             : 
     681      205305 :         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      205316 :         agfl = XFS_BUF_TO_AGFL(agfl_bp);
     688      205316 :         memset(agfl, 0xFF, BBTOB(agfl_bp->b_length));
     689      205316 :         agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
     690      205316 :         agfl->agfl_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
     691      205316 :         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      205241 :         xbitmap_init(&af.used_extents);
     699      205270 :         af.agfl_bno = xfs_buf_to_agfl_bno(agfl_bp),
     700      205270 :         xbitmap_walk(agfl_extents, xrep_agfl_fill, &af);
     701      205253 :         error = xbitmap_disunion(agfl_extents, &af.used_extents);
     702      205368 :         if (error)
     703             :                 return error;
     704             : 
     705             :         /* Write new AGFL to disk. */
     706      205386 :         xfs_trans_buf_set_type(sc->tp, agfl_bp, XFS_BLFT_AGFL_BUF);
     707      205354 :         xfs_trans_log_buf(sc->tp, agfl_bp, 0, BBTOB(agfl_bp->b_length) - 1);
     708      205344 :         xbitmap_destroy(&af.used_extents);
     709      205344 :         return 0;
     710             : }
     711             : 
     712             : /* Repair the AGFL. */
     713             : int
     714      275214 : xrep_agfl(
     715             :         struct xfs_scrub        *sc)
     716             : {
     717      275214 :         struct xbitmap          agfl_extents;
     718      275214 :         struct xfs_mount        *mp = sc->mp;
     719      275214 :         struct xfs_buf          *agf_bp;
     720      275214 :         struct xfs_buf          *agfl_bp;
     721      275214 :         xfs_agblock_t           flcount;
     722      275214 :         int                     error;
     723             : 
     724             :         /* We require the rmapbt to rebuild anything. */
     725      275214 :         if (!xfs_has_rmapbt(mp))
     726             :                 return -EOPNOTSUPP;
     727             : 
     728      205512 :         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      205528 :         error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
     736      205477 :         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      821908 :         error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
     744      205477 :                         XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
     745             :                                                 XFS_AGFL_DADDR(mp)),
     746      205477 :                         XFS_FSS_TO_BB(mp, 1), 0, &agfl_bp, NULL);
     747      205517 :         if (error)
     748             :                 return error;
     749      205517 :         agfl_bp->b_ops = &xfs_agfl_buf_ops;
     750             : 
     751             :         /* Gather all the extents we're going to put on the new AGFL. */
     752      205517 :         error = xrep_agfl_collect_blocks(sc, agf_bp, &agfl_extents, &flcount);
     753      205455 :         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      205455 :         xrep_agfl_update_agf(sc, agf_bp, flcount);
     762      205320 :         error = xrep_agfl_init_header(sc, agfl_bp, &agfl_extents, flcount);
     763      205424 :         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      205424 :         sc->sa.agf_bp = agf_bp;
     772      205424 :         error = xrep_roll_ag_trans(sc);
     773      205504 :         if (error)
     774           0 :                 goto err;
     775             : 
     776             :         /* Dump any AGFL overflow. */
     777      205504 :         error = xrep_reap_extents(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
     778             :                         XFS_AG_RESV_AGFL);
     779      204988 : err:
     780      204988 :         xbitmap_destroy(&agfl_extents);
     781      204988 :         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      209866 : xrep_agi_find_btrees(
     803             :         struct xfs_scrub                *sc,
     804             :         struct xrep_find_ag_btree       *fab)
     805             : {
     806      209866 :         struct xfs_buf                  *agf_bp;
     807      209866 :         struct xfs_mount                *mp = sc->mp;
     808      209866 :         int                             error;
     809             : 
     810             :         /* Read the AGF. */
     811      209866 :         error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
     812      209986 :         if (error)
     813             :                 return error;
     814             : 
     815             :         /* Find the btree roots. */
     816      209991 :         error = xrep_find_ag_btree_roots(sc, agf_bp, fab, NULL);
     817      210076 :         if (error)
     818             :                 return error;
     819             : 
     820             :         /* We must find the inobt root. */
     821      420152 :         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      420152 :         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      210042 : xrep_agi_init_header(
     838             :         struct xfs_scrub        *sc,
     839             :         struct xfs_buf          *agi_bp,
     840             :         struct xfs_agi          *old_agi)
     841             : {
     842      210042 :         struct xfs_agi          *agi = agi_bp->b_addr;
     843      210042 :         struct xfs_perag        *pag = sc->sa.pag;
     844      210042 :         struct xfs_mount        *mp = sc->mp;
     845             : 
     846      420084 :         memcpy(old_agi, agi, sizeof(*old_agi));
     847      210042 :         memset(agi, 0, BBTOB(agi_bp->b_length));
     848      210042 :         agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
     849      210042 :         agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
     850      210042 :         agi->agi_seqno = cpu_to_be32(pag->pag_agno);
     851      210042 :         agi->agi_length = cpu_to_be32(pag->block_count);
     852      210042 :         agi->agi_newino = cpu_to_be32(NULLAGINO);
     853      210042 :         agi->agi_dirino = cpu_to_be32(NULLAGINO);
     854      210042 :         if (xfs_has_crc(mp))
     855      210056 :                 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      420100 :         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      420100 :         ASSERT(xfs_perag_initialised_agi(pag));
     863      210050 :         clear_bit(XFS_AGSTATE_AGI_INIT, &pag->pag_opstate);
     864      210097 : }
     865             : 
     866             : /* Set btree root information in an AGI. */
     867             : STATIC void
     868      210072 : xrep_agi_set_roots(
     869             :         struct xfs_scrub                *sc,
     870             :         struct xfs_agi                  *agi,
     871             :         struct xrep_find_ag_btree       *fab)
     872             : {
     873      210072 :         agi->agi_root = cpu_to_be32(fab[XREP_AGI_INOBT].root);
     874      210072 :         agi->agi_level = cpu_to_be32(fab[XREP_AGI_INOBT].height);
     875             : 
     876      210072 :         if (xfs_has_finobt(sc->mp)) {
     877      210074 :                 agi->agi_free_root = cpu_to_be32(fab[XREP_AGI_FINOBT].root);
     878      210074 :                 agi->agi_free_level = cpu_to_be32(fab[XREP_AGI_FINOBT].height);
     879             :         }
     880      210072 : }
     881             : 
     882             : /* Update the AGI counters. */
     883             : STATIC int
     884      210031 : xrep_agi_calc_from_btrees(
     885             :         struct xfs_scrub        *sc,
     886             :         struct xfs_buf          *agi_bp)
     887             : {
     888      210031 :         struct xfs_btree_cur    *cur;
     889      210031 :         struct xfs_agi          *agi = agi_bp->b_addr;
     890      210031 :         struct xfs_mount        *mp = sc->mp;
     891      210031 :         xfs_agino_t             count;
     892      210031 :         xfs_agino_t             freecount;
     893      210031 :         int                     error;
     894             : 
     895      210031 :         cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, agi_bp, XFS_BTNUM_INO);
     896      210080 :         error = xfs_ialloc_count_inodes(cur, &count, &freecount);
     897      210058 :         if (error)
     898           0 :                 goto err;
     899      210058 :         if (xfs_has_inobtcounts(mp)) {
     900      210052 :                 xfs_agblock_t   blocks;
     901             : 
     902      210052 :                 error = xfs_btree_count_blocks(cur, &blocks);
     903      210040 :                 if (error)
     904           0 :                         goto err;
     905      210040 :                 agi->agi_iblocks = cpu_to_be32(blocks);
     906             :         }
     907      210046 :         xfs_btree_del_cursor(cur, error);
     908             : 
     909      210089 :         agi->agi_count = cpu_to_be32(count);
     910      210089 :         agi->agi_freecount = cpu_to_be32(freecount);
     911             : 
     912      210089 :         if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
     913      210088 :                 xfs_agblock_t   blocks;
     914             : 
     915      210088 :                 cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, agi_bp,
     916             :                                 XFS_BTNUM_FINO);
     917      210082 :                 error = xfs_btree_count_blocks(cur, &blocks);
     918      210050 :                 if (error)
     919           0 :                         goto err;
     920      210050 :                 xfs_btree_del_cursor(cur, error);
     921      210087 :                 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      210038 : xrep_agi_commit_new(
     933             :         struct xfs_scrub        *sc,
     934             :         struct xfs_buf          *agi_bp)
     935             : {
     936      210038 :         struct xfs_perag        *pag;
     937      210038 :         struct xfs_agi          *agi = agi_bp->b_addr;
     938             : 
     939             :         /* Trigger inode count recalculation */
     940      210038 :         xfs_force_summary_recalc(sc->mp);
     941             : 
     942             :         /* Write this to disk. */
     943      210091 :         xfs_trans_buf_set_type(sc->tp, agi_bp, XFS_BLFT_AGI_BUF);
     944      210076 :         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      210004 :         pag = sc->sa.pag;
     948      210004 :         pag->pagi_count = be32_to_cpu(agi->agi_count);
     949      210004 :         pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
     950      210004 :         set_bit(XFS_AGSTATE_AGI_INIT, &pag->pag_opstate);
     951             : 
     952      210088 :         return 0;
     953             : }
     954             : 
     955             : /* Repair the AGI. */
     956             : int
     957      279780 : xrep_agi(
     958             :         struct xfs_scrub                *sc)
     959             : {
     960      279780 :         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      279780 :                         .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      279780 :         struct xfs_agi                  old_agi;
     976      279780 :         struct xfs_mount                *mp = sc->mp;
     977      279780 :         struct xfs_buf                  *agi_bp;
     978      279780 :         struct xfs_agi                  *agi;
     979      279780 :         int                             error;
     980             : 
     981             :         /* We require the rmapbt to rebuild anything. */
     982      279780 :         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      840260 :         error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
     990      210065 :                         XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
     991             :                                                 XFS_AGI_DADDR(mp)),
     992      210065 :                         XFS_FSS_TO_BB(mp, 1), 0, &agi_bp, NULL);
     993      209920 :         if (error)
     994             :                 return error;
     995      209922 :         agi_bp->b_ops = &xfs_agi_buf_ops;
     996      209922 :         agi = agi_bp->b_addr;
     997             : 
     998             :         /* Find the AGI btree roots. */
     999      209922 :         error = xrep_agi_find_btrees(sc, fab);
    1000      210066 :         if (error)
    1001             :                 return error;
    1002             : 
    1003             :         /* Start rewriting the header and implant the btrees we found. */
    1004      210067 :         xrep_agi_init_header(sc, agi_bp, &old_agi);
    1005      210094 :         xrep_agi_set_roots(sc, agi, fab);
    1006      210069 :         error = xrep_agi_calc_from_btrees(sc, agi_bp);
    1007      210077 :         if (error)
    1008           0 :                 goto out_revert;
    1009             : 
    1010             :         /* Reinitialize in-core state. */
    1011      210077 :         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