Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2018 Oracle.  All Rights Reserved.
0004  * Author: Darrick J. Wong <darrick.wong@oracle.com>
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_trans_resv.h"
0011 #include "xfs_mount.h"
0012 #include "xfs_btree.h"
0013 #include "xfs_log_format.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_sb.h"
0016 #include "xfs_alloc.h"
0017 #include "xfs_alloc_btree.h"
0018 #include "xfs_ialloc.h"
0019 #include "xfs_ialloc_btree.h"
0020 #include "xfs_rmap.h"
0021 #include "xfs_rmap_btree.h"
0022 #include "xfs_refcount_btree.h"
0023 #include "xfs_ag.h"
0024 #include "scrub/scrub.h"
0025 #include "scrub/common.h"
0026 #include "scrub/trace.h"
0027 #include "scrub/repair.h"
0028 #include "scrub/bitmap.h"
0029 
0030 /* Superblock */
0031 
0032 /* Repair the superblock. */
0033 int
0034 xrep_superblock(
0035     struct xfs_scrub    *sc)
0036 {
0037     struct xfs_mount    *mp = sc->mp;
0038     struct xfs_buf      *bp;
0039     xfs_agnumber_t      agno;
0040     int         error;
0041 
0042     /* Don't try to repair AG 0's sb; let xfs_repair deal with it. */
0043     agno = sc->sm->sm_agno;
0044     if (agno == 0)
0045         return -EOPNOTSUPP;
0046 
0047     error = xfs_sb_get_secondary(mp, sc->tp, agno, &bp);
0048     if (error)
0049         return error;
0050 
0051     /* Copy AG 0's superblock to this one. */
0052     xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
0053     xfs_sb_to_disk(bp->b_addr, &mp->m_sb);
0054 
0055     /*
0056      * Don't write out a secondary super with NEEDSREPAIR or log incompat
0057      * features set, since both are ignored when set on a secondary.
0058      */
0059     if (xfs_has_crc(mp)) {
0060         struct xfs_dsb      *sb = bp->b_addr;
0061 
0062         sb->sb_features_incompat &=
0063                 ~cpu_to_be32(XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR);
0064         sb->sb_features_log_incompat = 0;
0065     }
0066 
0067     /* Write this to disk. */
0068     xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_SB_BUF);
0069     xfs_trans_log_buf(sc->tp, bp, 0, BBTOB(bp->b_length) - 1);
0070     return error;
0071 }
0072 
0073 /* AGF */
0074 
0075 struct xrep_agf_allocbt {
0076     struct xfs_scrub    *sc;
0077     xfs_agblock_t       freeblks;
0078     xfs_agblock_t       longest;
0079 };
0080 
0081 /* Record free space shape information. */
0082 STATIC int
0083 xrep_agf_walk_allocbt(
0084     struct xfs_btree_cur        *cur,
0085     const struct xfs_alloc_rec_incore *rec,
0086     void                *priv)
0087 {
0088     struct xrep_agf_allocbt     *raa = priv;
0089     int             error = 0;
0090 
0091     if (xchk_should_terminate(raa->sc, &error))
0092         return error;
0093 
0094     raa->freeblks += rec->ar_blockcount;
0095     if (rec->ar_blockcount > raa->longest)
0096         raa->longest = rec->ar_blockcount;
0097     return error;
0098 }
0099 
0100 /* Does this AGFL block look sane? */
0101 STATIC int
0102 xrep_agf_check_agfl_block(
0103     struct xfs_mount    *mp,
0104     xfs_agblock_t       agbno,
0105     void            *priv)
0106 {
0107     struct xfs_scrub    *sc = priv;
0108 
0109     if (!xfs_verify_agbno(sc->sa.pag, agbno))
0110         return -EFSCORRUPTED;
0111     return 0;
0112 }
0113 
0114 /*
0115  * Offset within the xrep_find_ag_btree array for each btree type.  Avoid the
0116  * XFS_BTNUM_ names here to avoid creating a sparse array.
0117  */
0118 enum {
0119     XREP_AGF_BNOBT = 0,
0120     XREP_AGF_CNTBT,
0121     XREP_AGF_RMAPBT,
0122     XREP_AGF_REFCOUNTBT,
0123     XREP_AGF_END,
0124     XREP_AGF_MAX
0125 };
0126 
0127 /* Check a btree root candidate. */
0128 static inline bool
0129 xrep_check_btree_root(
0130     struct xfs_scrub        *sc,
0131     struct xrep_find_ag_btree   *fab)
0132 {
0133     return xfs_verify_agbno(sc->sa.pag, fab->root) &&
0134            fab->height <= fab->maxlevels;
0135 }
0136 
0137 /*
0138  * Given the btree roots described by *fab, find the roots, check them for
0139  * sanity, and pass the root data back out via *fab.
0140  *
0141  * This is /also/ a chicken and egg problem because we have to use the rmapbt
0142  * (rooted in the AGF) to find the btrees rooted in the AGF.  We also have no
0143  * idea if the btrees make any sense.  If we hit obvious corruptions in those
0144  * btrees we'll bail out.
0145  */
0146 STATIC int
0147 xrep_agf_find_btrees(
0148     struct xfs_scrub        *sc,
0149     struct xfs_buf          *agf_bp,
0150     struct xrep_find_ag_btree   *fab,
0151     struct xfs_buf          *agfl_bp)
0152 {
0153     struct xfs_agf          *old_agf = agf_bp->b_addr;
0154     int             error;
0155 
0156     /* Go find the root data. */
0157     error = xrep_find_ag_btree_roots(sc, agf_bp, fab, agfl_bp);
0158     if (error)
0159         return error;
0160 
0161     /* We must find the bnobt, cntbt, and rmapbt roots. */
0162     if (!xrep_check_btree_root(sc, &fab[XREP_AGF_BNOBT]) ||
0163         !xrep_check_btree_root(sc, &fab[XREP_AGF_CNTBT]) ||
0164         !xrep_check_btree_root(sc, &fab[XREP_AGF_RMAPBT]))
0165         return -EFSCORRUPTED;
0166 
0167     /*
0168      * We relied on the rmapbt to reconstruct the AGF.  If we get a
0169      * different root then something's seriously wrong.
0170      */
0171     if (fab[XREP_AGF_RMAPBT].root !=
0172         be32_to_cpu(old_agf->agf_roots[XFS_BTNUM_RMAPi]))
0173         return -EFSCORRUPTED;
0174 
0175     /* We must find the refcountbt root if that feature is enabled. */
0176     if (xfs_has_reflink(sc->mp) &&
0177         !xrep_check_btree_root(sc, &fab[XREP_AGF_REFCOUNTBT]))
0178         return -EFSCORRUPTED;
0179 
0180     return 0;
0181 }
0182 
0183 /*
0184  * Reinitialize the AGF header, making an in-core copy of the old contents so
0185  * that we know which in-core state needs to be reinitialized.
0186  */
0187 STATIC void
0188 xrep_agf_init_header(
0189     struct xfs_scrub    *sc,
0190     struct xfs_buf      *agf_bp,
0191     struct xfs_agf      *old_agf)
0192 {
0193     struct xfs_mount    *mp = sc->mp;
0194     struct xfs_agf      *agf = agf_bp->b_addr;
0195 
0196     memcpy(old_agf, agf, sizeof(*old_agf));
0197     memset(agf, 0, BBTOB(agf_bp->b_length));
0198     agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
0199     agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
0200     agf->agf_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
0201     agf->agf_length = cpu_to_be32(sc->sa.pag->block_count);
0202     agf->agf_flfirst = old_agf->agf_flfirst;
0203     agf->agf_fllast = old_agf->agf_fllast;
0204     agf->agf_flcount = old_agf->agf_flcount;
0205     if (xfs_has_crc(mp))
0206         uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid);
0207 
0208     /* Mark the incore AGF data stale until we're done fixing things. */
0209     ASSERT(sc->sa.pag->pagf_init);
0210     sc->sa.pag->pagf_init = 0;
0211 }
0212 
0213 /* Set btree root information in an AGF. */
0214 STATIC void
0215 xrep_agf_set_roots(
0216     struct xfs_scrub        *sc,
0217     struct xfs_agf          *agf,
0218     struct xrep_find_ag_btree   *fab)
0219 {
0220     agf->agf_roots[XFS_BTNUM_BNOi] =
0221             cpu_to_be32(fab[XREP_AGF_BNOBT].root);
0222     agf->agf_levels[XFS_BTNUM_BNOi] =
0223             cpu_to_be32(fab[XREP_AGF_BNOBT].height);
0224 
0225     agf->agf_roots[XFS_BTNUM_CNTi] =
0226             cpu_to_be32(fab[XREP_AGF_CNTBT].root);
0227     agf->agf_levels[XFS_BTNUM_CNTi] =
0228             cpu_to_be32(fab[XREP_AGF_CNTBT].height);
0229 
0230     agf->agf_roots[XFS_BTNUM_RMAPi] =
0231             cpu_to_be32(fab[XREP_AGF_RMAPBT].root);
0232     agf->agf_levels[XFS_BTNUM_RMAPi] =
0233             cpu_to_be32(fab[XREP_AGF_RMAPBT].height);
0234 
0235     if (xfs_has_reflink(sc->mp)) {
0236         agf->agf_refcount_root =
0237                 cpu_to_be32(fab[XREP_AGF_REFCOUNTBT].root);
0238         agf->agf_refcount_level =
0239                 cpu_to_be32(fab[XREP_AGF_REFCOUNTBT].height);
0240     }
0241 }
0242 
0243 /* Update all AGF fields which derive from btree contents. */
0244 STATIC int
0245 xrep_agf_calc_from_btrees(
0246     struct xfs_scrub    *sc,
0247     struct xfs_buf      *agf_bp)
0248 {
0249     struct xrep_agf_allocbt raa = { .sc = sc };
0250     struct xfs_btree_cur    *cur = NULL;
0251     struct xfs_agf      *agf = agf_bp->b_addr;
0252     struct xfs_mount    *mp = sc->mp;
0253     xfs_agblock_t       btreeblks;
0254     xfs_agblock_t       blocks;
0255     int         error;
0256 
0257     /* Update the AGF counters from the bnobt. */
0258     cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
0259             sc->sa.pag, XFS_BTNUM_BNO);
0260     error = xfs_alloc_query_all(cur, xrep_agf_walk_allocbt, &raa);
0261     if (error)
0262         goto err;
0263     error = xfs_btree_count_blocks(cur, &blocks);
0264     if (error)
0265         goto err;
0266     xfs_btree_del_cursor(cur, error);
0267     btreeblks = blocks - 1;
0268     agf->agf_freeblks = cpu_to_be32(raa.freeblks);
0269     agf->agf_longest = cpu_to_be32(raa.longest);
0270 
0271     /* Update the AGF counters from the cntbt. */
0272     cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
0273             sc->sa.pag, XFS_BTNUM_CNT);
0274     error = xfs_btree_count_blocks(cur, &blocks);
0275     if (error)
0276         goto err;
0277     xfs_btree_del_cursor(cur, error);
0278     btreeblks += blocks - 1;
0279 
0280     /* Update the AGF counters from the rmapbt. */
0281     cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
0282     error = xfs_btree_count_blocks(cur, &blocks);
0283     if (error)
0284         goto err;
0285     xfs_btree_del_cursor(cur, error);
0286     agf->agf_rmap_blocks = cpu_to_be32(blocks);
0287     btreeblks += blocks - 1;
0288 
0289     agf->agf_btreeblks = cpu_to_be32(btreeblks);
0290 
0291     /* Update the AGF counters from the refcountbt. */
0292     if (xfs_has_reflink(mp)) {
0293         cur = xfs_refcountbt_init_cursor(mp, sc->tp, agf_bp,
0294                 sc->sa.pag);
0295         error = xfs_btree_count_blocks(cur, &blocks);
0296         if (error)
0297             goto err;
0298         xfs_btree_del_cursor(cur, error);
0299         agf->agf_refcount_blocks = cpu_to_be32(blocks);
0300     }
0301 
0302     return 0;
0303 err:
0304     xfs_btree_del_cursor(cur, error);
0305     return error;
0306 }
0307 
0308 /* Commit the new AGF and reinitialize the incore state. */
0309 STATIC int
0310 xrep_agf_commit_new(
0311     struct xfs_scrub    *sc,
0312     struct xfs_buf      *agf_bp)
0313 {
0314     struct xfs_perag    *pag;
0315     struct xfs_agf      *agf = agf_bp->b_addr;
0316 
0317     /* Trigger fdblocks recalculation */
0318     xfs_force_summary_recalc(sc->mp);
0319 
0320     /* Write this to disk. */
0321     xfs_trans_buf_set_type(sc->tp, agf_bp, XFS_BLFT_AGF_BUF);
0322     xfs_trans_log_buf(sc->tp, agf_bp, 0, BBTOB(agf_bp->b_length) - 1);
0323 
0324     /* Now reinitialize the in-core counters we changed. */
0325     pag = sc->sa.pag;
0326     pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
0327     pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
0328     pag->pagf_longest = be32_to_cpu(agf->agf_longest);
0329     pag->pagf_levels[XFS_BTNUM_BNOi] =
0330             be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
0331     pag->pagf_levels[XFS_BTNUM_CNTi] =
0332             be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
0333     pag->pagf_levels[XFS_BTNUM_RMAPi] =
0334             be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]);
0335     pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
0336     pag->pagf_init = 1;
0337 
0338     return 0;
0339 }
0340 
0341 /* Repair the AGF. v5 filesystems only. */
0342 int
0343 xrep_agf(
0344     struct xfs_scrub        *sc)
0345 {
0346     struct xrep_find_ag_btree   fab[XREP_AGF_MAX] = {
0347         [XREP_AGF_BNOBT] = {
0348             .rmap_owner = XFS_RMAP_OWN_AG,
0349             .buf_ops = &xfs_bnobt_buf_ops,
0350             .maxlevels = sc->mp->m_alloc_maxlevels,
0351         },
0352         [XREP_AGF_CNTBT] = {
0353             .rmap_owner = XFS_RMAP_OWN_AG,
0354             .buf_ops = &xfs_cntbt_buf_ops,
0355             .maxlevels = sc->mp->m_alloc_maxlevels,
0356         },
0357         [XREP_AGF_RMAPBT] = {
0358             .rmap_owner = XFS_RMAP_OWN_AG,
0359             .buf_ops = &xfs_rmapbt_buf_ops,
0360             .maxlevels = sc->mp->m_rmap_maxlevels,
0361         },
0362         [XREP_AGF_REFCOUNTBT] = {
0363             .rmap_owner = XFS_RMAP_OWN_REFC,
0364             .buf_ops = &xfs_refcountbt_buf_ops,
0365             .maxlevels = sc->mp->m_refc_maxlevels,
0366         },
0367         [XREP_AGF_END] = {
0368             .buf_ops = NULL,
0369         },
0370     };
0371     struct xfs_agf          old_agf;
0372     struct xfs_mount        *mp = sc->mp;
0373     struct xfs_buf          *agf_bp;
0374     struct xfs_buf          *agfl_bp;
0375     struct xfs_agf          *agf;
0376     int             error;
0377 
0378     /* We require the rmapbt to rebuild anything. */
0379     if (!xfs_has_rmapbt(mp))
0380         return -EOPNOTSUPP;
0381 
0382     /*
0383      * Make sure we have the AGF buffer, as scrub might have decided it
0384      * was corrupt after xfs_alloc_read_agf failed with -EFSCORRUPTED.
0385      */
0386     error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
0387             XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
0388                         XFS_AGF_DADDR(mp)),
0389             XFS_FSS_TO_BB(mp, 1), 0, &agf_bp, NULL);
0390     if (error)
0391         return error;
0392     agf_bp->b_ops = &xfs_agf_buf_ops;
0393     agf = agf_bp->b_addr;
0394 
0395     /*
0396      * Load the AGFL so that we can screen out OWN_AG blocks that are on
0397      * the AGFL now; these blocks might have once been part of the
0398      * bno/cnt/rmap btrees but are not now.  This is a chicken and egg
0399      * problem: the AGF is corrupt, so we have to trust the AGFL contents
0400      * because we can't do any serious cross-referencing with any of the
0401      * btrees rooted in the AGF.  If the AGFL contents are obviously bad
0402      * then we'll bail out.
0403      */
0404     error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
0405     if (error)
0406         return error;
0407 
0408     /*
0409      * Spot-check the AGFL blocks; if they're obviously corrupt then
0410      * there's nothing we can do but bail out.
0411      */
0412     error = xfs_agfl_walk(sc->mp, agf_bp->b_addr, agfl_bp,
0413             xrep_agf_check_agfl_block, sc);
0414     if (error)
0415         return error;
0416 
0417     /*
0418      * Find the AGF btree roots.  This is also a chicken-and-egg situation;
0419      * see the function for more details.
0420      */
0421     error = xrep_agf_find_btrees(sc, agf_bp, fab, agfl_bp);
0422     if (error)
0423         return error;
0424 
0425     /* Start rewriting the header and implant the btrees we found. */
0426     xrep_agf_init_header(sc, agf_bp, &old_agf);
0427     xrep_agf_set_roots(sc, agf, fab);
0428     error = xrep_agf_calc_from_btrees(sc, agf_bp);
0429     if (error)
0430         goto out_revert;
0431 
0432     /* Commit the changes and reinitialize incore state. */
0433     return xrep_agf_commit_new(sc, agf_bp);
0434 
0435 out_revert:
0436     /* Mark the incore AGF state stale and revert the AGF. */
0437     sc->sa.pag->pagf_init = 0;
0438     memcpy(agf, &old_agf, sizeof(old_agf));
0439     return error;
0440 }
0441 
0442 /* AGFL */
0443 
0444 struct xrep_agfl {
0445     /* Bitmap of other OWN_AG metadata blocks. */
0446     struct xbitmap      agmetablocks;
0447 
0448     /* Bitmap of free space. */
0449     struct xbitmap      *freesp;
0450 
0451     struct xfs_scrub    *sc;
0452 };
0453 
0454 /* Record all OWN_AG (free space btree) information from the rmap data. */
0455 STATIC int
0456 xrep_agfl_walk_rmap(
0457     struct xfs_btree_cur    *cur,
0458     const struct xfs_rmap_irec *rec,
0459     void            *priv)
0460 {
0461     struct xrep_agfl    *ra = priv;
0462     xfs_fsblock_t       fsb;
0463     int         error = 0;
0464 
0465     if (xchk_should_terminate(ra->sc, &error))
0466         return error;
0467 
0468     /* Record all the OWN_AG blocks. */
0469     if (rec->rm_owner == XFS_RMAP_OWN_AG) {
0470         fsb = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno,
0471                 rec->rm_startblock);
0472         error = xbitmap_set(ra->freesp, fsb, rec->rm_blockcount);
0473         if (error)
0474             return error;
0475     }
0476 
0477     return xbitmap_set_btcur_path(&ra->agmetablocks, cur);
0478 }
0479 
0480 /*
0481  * Map out all the non-AGFL OWN_AG space in this AG so that we can deduce
0482  * which blocks belong to the AGFL.
0483  *
0484  * Compute the set of old AGFL blocks by subtracting from the list of OWN_AG
0485  * blocks the list of blocks owned by all other OWN_AG metadata (bnobt, cntbt,
0486  * rmapbt).  These are the old AGFL blocks, so return that list and the number
0487  * of blocks we're actually going to put back on the AGFL.
0488  */
0489 STATIC int
0490 xrep_agfl_collect_blocks(
0491     struct xfs_scrub    *sc,
0492     struct xfs_buf      *agf_bp,
0493     struct xbitmap      *agfl_extents,
0494     xfs_agblock_t       *flcount)
0495 {
0496     struct xrep_agfl    ra;
0497     struct xfs_mount    *mp = sc->mp;
0498     struct xfs_btree_cur    *cur;
0499     int         error;
0500 
0501     ra.sc = sc;
0502     ra.freesp = agfl_extents;
0503     xbitmap_init(&ra.agmetablocks);
0504 
0505     /* Find all space used by the free space btrees & rmapbt. */
0506     cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.pag);
0507     error = xfs_rmap_query_all(cur, xrep_agfl_walk_rmap, &ra);
0508     if (error)
0509         goto err;
0510     xfs_btree_del_cursor(cur, error);
0511 
0512     /* Find all blocks currently being used by the bnobt. */
0513     cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
0514             sc->sa.pag, XFS_BTNUM_BNO);
0515     error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
0516     if (error)
0517         goto err;
0518     xfs_btree_del_cursor(cur, error);
0519 
0520     /* Find all blocks currently being used by the cntbt. */
0521     cur = xfs_allocbt_init_cursor(mp, sc->tp, agf_bp,
0522             sc->sa.pag, XFS_BTNUM_CNT);
0523     error = xbitmap_set_btblocks(&ra.agmetablocks, cur);
0524     if (error)
0525         goto err;
0526 
0527     xfs_btree_del_cursor(cur, error);
0528 
0529     /*
0530      * Drop the freesp meta blocks that are in use by btrees.
0531      * The remaining blocks /should/ be AGFL blocks.
0532      */
0533     error = xbitmap_disunion(agfl_extents, &ra.agmetablocks);
0534     xbitmap_destroy(&ra.agmetablocks);
0535     if (error)
0536         return error;
0537 
0538     /*
0539      * Calculate the new AGFL size.  If we found more blocks than fit in
0540      * the AGFL we'll free them later.
0541      */
0542     *flcount = min_t(uint64_t, xbitmap_hweight(agfl_extents),
0543              xfs_agfl_size(mp));
0544     return 0;
0545 
0546 err:
0547     xbitmap_destroy(&ra.agmetablocks);
0548     xfs_btree_del_cursor(cur, error);
0549     return error;
0550 }
0551 
0552 /* Update the AGF and reset the in-core state. */
0553 STATIC void
0554 xrep_agfl_update_agf(
0555     struct xfs_scrub    *sc,
0556     struct xfs_buf      *agf_bp,
0557     xfs_agblock_t       flcount)
0558 {
0559     struct xfs_agf      *agf = agf_bp->b_addr;
0560 
0561     ASSERT(flcount <= xfs_agfl_size(sc->mp));
0562 
0563     /* Trigger fdblocks recalculation */
0564     xfs_force_summary_recalc(sc->mp);
0565 
0566     /* Update the AGF counters. */
0567     if (sc->sa.pag->pagf_init)
0568         sc->sa.pag->pagf_flcount = flcount;
0569     agf->agf_flfirst = cpu_to_be32(0);
0570     agf->agf_flcount = cpu_to_be32(flcount);
0571     agf->agf_fllast = cpu_to_be32(flcount - 1);
0572 
0573     xfs_alloc_log_agf(sc->tp, agf_bp,
0574             XFS_AGF_FLFIRST | XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
0575 }
0576 
0577 /* Write out a totally new AGFL. */
0578 STATIC void
0579 xrep_agfl_init_header(
0580     struct xfs_scrub    *sc,
0581     struct xfs_buf      *agfl_bp,
0582     struct xbitmap      *agfl_extents,
0583     xfs_agblock_t       flcount)
0584 {
0585     struct xfs_mount    *mp = sc->mp;
0586     __be32          *agfl_bno;
0587     struct xbitmap_range    *br;
0588     struct xbitmap_range    *n;
0589     struct xfs_agfl     *agfl;
0590     xfs_agblock_t       agbno;
0591     unsigned int        fl_off;
0592 
0593     ASSERT(flcount <= xfs_agfl_size(mp));
0594 
0595     /*
0596      * Start rewriting the header by setting the bno[] array to
0597      * NULLAGBLOCK, then setting AGFL header fields.
0598      */
0599     agfl = XFS_BUF_TO_AGFL(agfl_bp);
0600     memset(agfl, 0xFF, BBTOB(agfl_bp->b_length));
0601     agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
0602     agfl->agfl_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
0603     uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid);
0604 
0605     /*
0606      * Fill the AGFL with the remaining blocks.  If agfl_extents has more
0607      * blocks than fit in the AGFL, they will be freed in a subsequent
0608      * step.
0609      */
0610     fl_off = 0;
0611     agfl_bno = xfs_buf_to_agfl_bno(agfl_bp);
0612     for_each_xbitmap_extent(br, n, agfl_extents) {
0613         agbno = XFS_FSB_TO_AGBNO(mp, br->start);
0614 
0615         trace_xrep_agfl_insert(mp, sc->sa.pag->pag_agno, agbno,
0616                 br->len);
0617 
0618         while (br->len > 0 && fl_off < flcount) {
0619             agfl_bno[fl_off] = cpu_to_be32(agbno);
0620             fl_off++;
0621             agbno++;
0622 
0623             /*
0624              * We've now used br->start by putting it in the AGFL,
0625              * so bump br so that we don't reap the block later.
0626              */
0627             br->start++;
0628             br->len--;
0629         }
0630 
0631         if (br->len)
0632             break;
0633         list_del(&br->list);
0634         kmem_free(br);
0635     }
0636 
0637     /* Write new AGFL to disk. */
0638     xfs_trans_buf_set_type(sc->tp, agfl_bp, XFS_BLFT_AGFL_BUF);
0639     xfs_trans_log_buf(sc->tp, agfl_bp, 0, BBTOB(agfl_bp->b_length) - 1);
0640 }
0641 
0642 /* Repair the AGFL. */
0643 int
0644 xrep_agfl(
0645     struct xfs_scrub    *sc)
0646 {
0647     struct xbitmap      agfl_extents;
0648     struct xfs_mount    *mp = sc->mp;
0649     struct xfs_buf      *agf_bp;
0650     struct xfs_buf      *agfl_bp;
0651     xfs_agblock_t       flcount;
0652     int         error;
0653 
0654     /* We require the rmapbt to rebuild anything. */
0655     if (!xfs_has_rmapbt(mp))
0656         return -EOPNOTSUPP;
0657 
0658     xbitmap_init(&agfl_extents);
0659 
0660     /*
0661      * Read the AGF so that we can query the rmapbt.  We hope that there's
0662      * nothing wrong with the AGF, but all the AG header repair functions
0663      * have this chicken-and-egg problem.
0664      */
0665     error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
0666     if (error)
0667         return error;
0668 
0669     /*
0670      * Make sure we have the AGFL buffer, as scrub might have decided it
0671      * was corrupt after xfs_alloc_read_agfl failed with -EFSCORRUPTED.
0672      */
0673     error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
0674             XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
0675                         XFS_AGFL_DADDR(mp)),
0676             XFS_FSS_TO_BB(mp, 1), 0, &agfl_bp, NULL);
0677     if (error)
0678         return error;
0679     agfl_bp->b_ops = &xfs_agfl_buf_ops;
0680 
0681     /* Gather all the extents we're going to put on the new AGFL. */
0682     error = xrep_agfl_collect_blocks(sc, agf_bp, &agfl_extents, &flcount);
0683     if (error)
0684         goto err;
0685 
0686     /*
0687      * Update AGF and AGFL.  We reset the global free block counter when
0688      * we adjust the AGF flcount (which can fail) so avoid updating any
0689      * buffers until we know that part works.
0690      */
0691     xrep_agfl_update_agf(sc, agf_bp, flcount);
0692     xrep_agfl_init_header(sc, agfl_bp, &agfl_extents, flcount);
0693 
0694     /*
0695      * Ok, the AGFL should be ready to go now.  Roll the transaction to
0696      * make the new AGFL permanent before we start using it to return
0697      * freespace overflow to the freespace btrees.
0698      */
0699     sc->sa.agf_bp = agf_bp;
0700     sc->sa.agfl_bp = agfl_bp;
0701     error = xrep_roll_ag_trans(sc);
0702     if (error)
0703         goto err;
0704 
0705     /* Dump any AGFL overflow. */
0706     error = xrep_reap_extents(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
0707             XFS_AG_RESV_AGFL);
0708 err:
0709     xbitmap_destroy(&agfl_extents);
0710     return error;
0711 }
0712 
0713 /* AGI */
0714 
0715 /*
0716  * Offset within the xrep_find_ag_btree array for each btree type.  Avoid the
0717  * XFS_BTNUM_ names here to avoid creating a sparse array.
0718  */
0719 enum {
0720     XREP_AGI_INOBT = 0,
0721     XREP_AGI_FINOBT,
0722     XREP_AGI_END,
0723     XREP_AGI_MAX
0724 };
0725 
0726 /*
0727  * Given the inode btree roots described by *fab, find the roots, check them
0728  * for sanity, and pass the root data back out via *fab.
0729  */
0730 STATIC int
0731 xrep_agi_find_btrees(
0732     struct xfs_scrub        *sc,
0733     struct xrep_find_ag_btree   *fab)
0734 {
0735     struct xfs_buf          *agf_bp;
0736     struct xfs_mount        *mp = sc->mp;
0737     int             error;
0738 
0739     /* Read the AGF. */
0740     error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
0741     if (error)
0742         return error;
0743 
0744     /* Find the btree roots. */
0745     error = xrep_find_ag_btree_roots(sc, agf_bp, fab, NULL);
0746     if (error)
0747         return error;
0748 
0749     /* We must find the inobt root. */
0750     if (!xrep_check_btree_root(sc, &fab[XREP_AGI_INOBT]))
0751         return -EFSCORRUPTED;
0752 
0753     /* We must find the finobt root if that feature is enabled. */
0754     if (xfs_has_finobt(mp) &&
0755         !xrep_check_btree_root(sc, &fab[XREP_AGI_FINOBT]))
0756         return -EFSCORRUPTED;
0757 
0758     return 0;
0759 }
0760 
0761 /*
0762  * Reinitialize the AGI header, making an in-core copy of the old contents so
0763  * that we know which in-core state needs to be reinitialized.
0764  */
0765 STATIC void
0766 xrep_agi_init_header(
0767     struct xfs_scrub    *sc,
0768     struct xfs_buf      *agi_bp,
0769     struct xfs_agi      *old_agi)
0770 {
0771     struct xfs_agi      *agi = agi_bp->b_addr;
0772     struct xfs_mount    *mp = sc->mp;
0773 
0774     memcpy(old_agi, agi, sizeof(*old_agi));
0775     memset(agi, 0, BBTOB(agi_bp->b_length));
0776     agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
0777     agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
0778     agi->agi_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
0779     agi->agi_length = cpu_to_be32(sc->sa.pag->block_count);
0780     agi->agi_newino = cpu_to_be32(NULLAGINO);
0781     agi->agi_dirino = cpu_to_be32(NULLAGINO);
0782     if (xfs_has_crc(mp))
0783         uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid);
0784 
0785     /* We don't know how to fix the unlinked list yet. */
0786     memcpy(&agi->agi_unlinked, &old_agi->agi_unlinked,
0787             sizeof(agi->agi_unlinked));
0788 
0789     /* Mark the incore AGF data stale until we're done fixing things. */
0790     ASSERT(sc->sa.pag->pagi_init);
0791     sc->sa.pag->pagi_init = 0;
0792 }
0793 
0794 /* Set btree root information in an AGI. */
0795 STATIC void
0796 xrep_agi_set_roots(
0797     struct xfs_scrub        *sc,
0798     struct xfs_agi          *agi,
0799     struct xrep_find_ag_btree   *fab)
0800 {
0801     agi->agi_root = cpu_to_be32(fab[XREP_AGI_INOBT].root);
0802     agi->agi_level = cpu_to_be32(fab[XREP_AGI_INOBT].height);
0803 
0804     if (xfs_has_finobt(sc->mp)) {
0805         agi->agi_free_root = cpu_to_be32(fab[XREP_AGI_FINOBT].root);
0806         agi->agi_free_level = cpu_to_be32(fab[XREP_AGI_FINOBT].height);
0807     }
0808 }
0809 
0810 /* Update the AGI counters. */
0811 STATIC int
0812 xrep_agi_calc_from_btrees(
0813     struct xfs_scrub    *sc,
0814     struct xfs_buf      *agi_bp)
0815 {
0816     struct xfs_btree_cur    *cur;
0817     struct xfs_agi      *agi = agi_bp->b_addr;
0818     struct xfs_mount    *mp = sc->mp;
0819     xfs_agino_t     count;
0820     xfs_agino_t     freecount;
0821     int         error;
0822 
0823     cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp,
0824             sc->sa.pag, XFS_BTNUM_INO);
0825     error = xfs_ialloc_count_inodes(cur, &count, &freecount);
0826     if (error)
0827         goto err;
0828     if (xfs_has_inobtcounts(mp)) {
0829         xfs_agblock_t   blocks;
0830 
0831         error = xfs_btree_count_blocks(cur, &blocks);
0832         if (error)
0833             goto err;
0834         agi->agi_iblocks = cpu_to_be32(blocks);
0835     }
0836     xfs_btree_del_cursor(cur, error);
0837 
0838     agi->agi_count = cpu_to_be32(count);
0839     agi->agi_freecount = cpu_to_be32(freecount);
0840 
0841     if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
0842         xfs_agblock_t   blocks;
0843 
0844         cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp,
0845                 sc->sa.pag, XFS_BTNUM_FINO);
0846         error = xfs_btree_count_blocks(cur, &blocks);
0847         if (error)
0848             goto err;
0849         xfs_btree_del_cursor(cur, error);
0850         agi->agi_fblocks = cpu_to_be32(blocks);
0851     }
0852 
0853     return 0;
0854 err:
0855     xfs_btree_del_cursor(cur, error);
0856     return error;
0857 }
0858 
0859 /* Trigger reinitialization of the in-core data. */
0860 STATIC int
0861 xrep_agi_commit_new(
0862     struct xfs_scrub    *sc,
0863     struct xfs_buf      *agi_bp)
0864 {
0865     struct xfs_perag    *pag;
0866     struct xfs_agi      *agi = agi_bp->b_addr;
0867 
0868     /* Trigger inode count recalculation */
0869     xfs_force_summary_recalc(sc->mp);
0870 
0871     /* Write this to disk. */
0872     xfs_trans_buf_set_type(sc->tp, agi_bp, XFS_BLFT_AGI_BUF);
0873     xfs_trans_log_buf(sc->tp, agi_bp, 0, BBTOB(agi_bp->b_length) - 1);
0874 
0875     /* Now reinitialize the in-core counters if necessary. */
0876     pag = sc->sa.pag;
0877     pag->pagi_count = be32_to_cpu(agi->agi_count);
0878     pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
0879     pag->pagi_init = 1;
0880 
0881     return 0;
0882 }
0883 
0884 /* Repair the AGI. */
0885 int
0886 xrep_agi(
0887     struct xfs_scrub        *sc)
0888 {
0889     struct xrep_find_ag_btree   fab[XREP_AGI_MAX] = {
0890         [XREP_AGI_INOBT] = {
0891             .rmap_owner = XFS_RMAP_OWN_INOBT,
0892             .buf_ops = &xfs_inobt_buf_ops,
0893             .maxlevels = M_IGEO(sc->mp)->inobt_maxlevels,
0894         },
0895         [XREP_AGI_FINOBT] = {
0896             .rmap_owner = XFS_RMAP_OWN_INOBT,
0897             .buf_ops = &xfs_finobt_buf_ops,
0898             .maxlevels = M_IGEO(sc->mp)->inobt_maxlevels,
0899         },
0900         [XREP_AGI_END] = {
0901             .buf_ops = NULL
0902         },
0903     };
0904     struct xfs_agi          old_agi;
0905     struct xfs_mount        *mp = sc->mp;
0906     struct xfs_buf          *agi_bp;
0907     struct xfs_agi          *agi;
0908     int             error;
0909 
0910     /* We require the rmapbt to rebuild anything. */
0911     if (!xfs_has_rmapbt(mp))
0912         return -EOPNOTSUPP;
0913 
0914     /*
0915      * Make sure we have the AGI buffer, as scrub might have decided it
0916      * was corrupt after xfs_ialloc_read_agi failed with -EFSCORRUPTED.
0917      */
0918     error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
0919             XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
0920                         XFS_AGI_DADDR(mp)),
0921             XFS_FSS_TO_BB(mp, 1), 0, &agi_bp, NULL);
0922     if (error)
0923         return error;
0924     agi_bp->b_ops = &xfs_agi_buf_ops;
0925     agi = agi_bp->b_addr;
0926 
0927     /* Find the AGI btree roots. */
0928     error = xrep_agi_find_btrees(sc, fab);
0929     if (error)
0930         return error;
0931 
0932     /* Start rewriting the header and implant the btrees we found. */
0933     xrep_agi_init_header(sc, agi_bp, &old_agi);
0934     xrep_agi_set_roots(sc, agi, fab);
0935     error = xrep_agi_calc_from_btrees(sc, agi_bp);
0936     if (error)
0937         goto out_revert;
0938 
0939     /* Reinitialize in-core state. */
0940     return xrep_agi_commit_new(sc, agi_bp);
0941 
0942 out_revert:
0943     /* Mark the incore AGI state stale and revert the AGI. */
0944     sc->sa.pag->pagi_init = 0;
0945     memcpy(agi, &old_agi, sizeof(old_agi));
0946     return error;
0947 }