LCOV - code coverage report
Current view: top level - fs/xfs/scrub - rmap.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 238 284 83.8 %
Date: 2023-07-31 20:08:07 Functions: 17 17 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 2017-2023 Oracle.  All Rights Reserved.
       4             :  * Author: Darrick J. Wong <djwong@kernel.org>
       5             :  */
       6             : #include "xfs.h"
       7             : #include "xfs_fs.h"
       8             : #include "xfs_shared.h"
       9             : #include "xfs_format.h"
      10             : #include "xfs_log_format.h"
      11             : #include "xfs_trans_resv.h"
      12             : #include "xfs_mount.h"
      13             : #include "xfs_trans.h"
      14             : #include "xfs_btree.h"
      15             : #include "xfs_rmap.h"
      16             : #include "xfs_refcount.h"
      17             : #include "xfs_ag.h"
      18             : #include "xfs_bit.h"
      19             : #include "xfs_alloc.h"
      20             : #include "xfs_alloc_btree.h"
      21             : #include "xfs_ialloc_btree.h"
      22             : #include "xfs_refcount_btree.h"
      23             : #include "scrub/scrub.h"
      24             : #include "scrub/common.h"
      25             : #include "scrub/btree.h"
      26             : #include "scrub/bitmap.h"
      27             : #include "scrub/repair.h"
      28             : 
      29             : /*
      30             :  * Set us up to scrub reverse mapping btrees.
      31             :  */
      32             : int
      33       62812 : xchk_setup_ag_rmapbt(
      34             :         struct xfs_scrub        *sc)
      35             : {
      36       62812 :         if (xchk_need_intent_drain(sc))
      37         739 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      38             : 
      39      125624 :         if (xchk_could_repair(sc)) {
      40        4496 :                 int             error;
      41             : 
      42        4496 :                 error = xrep_setup_ag_rmapbt(sc);
      43        4497 :                 if (error)
      44             :                         return error;
      45             :         }
      46             : 
      47       62813 :         return xchk_setup_ag_btree(sc, false);
      48             : }
      49             : 
      50             : /* Reverse-mapping scrubber. */
      51             : 
      52             : struct xchk_rmap {
      53             :         /*
      54             :          * The furthest-reaching of the rmapbt records that we've already
      55             :          * processed.  This enables us to detect overlapping records for space
      56             :          * allocations that cannot be shared.
      57             :          */
      58             :         struct xfs_rmap_irec    overlap_rec;
      59             : 
      60             :         /*
      61             :          * The previous rmapbt record, so that we can check for two records
      62             :          * that could be one.
      63             :          */
      64             :         struct xfs_rmap_irec    prev_rec;
      65             : 
      66             :         /* Bitmaps containing all blocks for each type of AG metadata. */
      67             :         struct xagb_bitmap      fs_owned;
      68             :         struct xagb_bitmap      log_owned;
      69             :         struct xagb_bitmap      ag_owned;
      70             :         struct xagb_bitmap      inobt_owned;
      71             :         struct xagb_bitmap      refcbt_owned;
      72             : 
      73             :         /* Did we complete the AG space metadata bitmaps? */
      74             :         bool                    bitmaps_complete;
      75             : };
      76             : 
      77             : /* Cross-reference a rmap against the refcount btree. */
      78             : STATIC void
      79   678061115 : xchk_rmapbt_xref_refc(
      80             :         struct xfs_scrub        *sc,
      81             :         struct xfs_rmap_irec    *irec)
      82             : {
      83   678061115 :         xfs_agblock_t           fbno;
      84   678061115 :         xfs_extlen_t            flen;
      85   678061115 :         bool                    non_inode;
      86   678061115 :         bool                    is_bmbt;
      87   678061115 :         bool                    is_attr;
      88   678061115 :         bool                    is_unwritten;
      89   678061115 :         int                     error;
      90             : 
      91   678061115 :         if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
      92        3073 :                 return;
      93             : 
      94   678058042 :         non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
      95   678058042 :         is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
      96   678058042 :         is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
      97   678058042 :         is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
      98             : 
      99             :         /* If this is shared, must be a data fork extent. */
     100   678058042 :         error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock,
     101             :                         irec->rm_blockcount, &fbno, &flen, false);
     102   678130024 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
     103             :                 return;
     104   678127631 :         if (flen != 0 && (non_inode || is_attr || is_bmbt || is_unwritten))
     105           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0);
     106             : }
     107             : 
     108             : /* Cross-reference with the other btrees. */
     109             : STATIC void
     110   678306742 : xchk_rmapbt_xref(
     111             :         struct xfs_scrub        *sc,
     112             :         struct xfs_rmap_irec    *irec)
     113             : {
     114   678306742 :         xfs_agblock_t           agbno = irec->rm_startblock;
     115   678306742 :         xfs_extlen_t            len = irec->rm_blockcount;
     116             : 
     117   678306742 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     118             :                 return;
     119             : 
     120   678310927 :         xchk_xref_is_used_space(sc, agbno, len);
     121   678327258 :         if (irec->rm_owner == XFS_RMAP_OWN_INODES)
     122     5503828 :                 xchk_xref_is_inode_chunk(sc, agbno, len);
     123             :         else
     124   672823430 :                 xchk_xref_is_not_inode_chunk(sc, agbno, len);
     125   678253671 :         if (irec->rm_owner == XFS_RMAP_OWN_COW)
     126      194162 :                 xchk_xref_is_cow_staging(sc, irec->rm_startblock,
     127             :                                 irec->rm_blockcount);
     128             :         else
     129   678059509 :                 xchk_rmapbt_xref_refc(sc, irec);
     130             : }
     131             : 
     132             : /*
     133             :  * Check for bogus UNWRITTEN flags in the rmapbt node block keys.
     134             :  *
     135             :  * In reverse mapping records, the file mapping extent state
     136             :  * (XFS_RMAP_OFF_UNWRITTEN) is a record attribute, not a key field.  It is not
     137             :  * involved in lookups in any way.  In older kernels, the functions that
     138             :  * convert rmapbt records to keys forgot to filter out the extent state bit,
     139             :  * even though the key comparison functions have filtered the flag correctly.
     140             :  * If we spot an rmap key with the unwritten bit set in rm_offset, we should
     141             :  * mark the btree as needing optimization to rebuild the btree without those
     142             :  * flags.
     143             :  */
     144             : STATIC void
     145   678327925 : xchk_rmapbt_check_unwritten_in_keyflags(
     146             :         struct xchk_btree       *bs)
     147             : {
     148   678327925 :         struct xfs_scrub        *sc = bs->sc;
     149   678327925 :         struct xfs_btree_cur    *cur = bs->cur;
     150   678327925 :         struct xfs_btree_block  *keyblock;
     151   678327925 :         union xfs_btree_key     *lkey, *hkey;
     152   678327925 :         __be64                  badflag = cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
     153   678327925 :         unsigned int            level;
     154             : 
     155   678327925 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN)
     156             :                 return;
     157             : 
     158  1984773704 :         for (level = 1; level < cur->bc_nlevels; level++) {
     159  1306445816 :                 struct xfs_buf  *bp;
     160  1306445816 :                 unsigned int    ptr;
     161             : 
     162             :                 /* Only check the first time we've seen this node block. */
     163  1306445816 :                 if (cur->bc_levels[level].ptr > 1)
     164  1167405308 :                         continue;
     165             : 
     166   139040508 :                 keyblock = xfs_btree_get_block(cur, level, &bp);
     167  1515138882 :                 for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) {
     168  1237057903 :                         lkey = xfs_btree_key_addr(cur, ptr, keyblock);
     169             : 
     170  1237068986 :                         if (lkey->rmap.rm_offset & badflag) {
     171           0 :                                 xchk_btree_set_preen(sc, cur, level);
     172           0 :                                 break;
     173             :                         }
     174             : 
     175  1237068986 :                         hkey = xfs_btree_high_key_addr(cur, ptr, keyblock);
     176  1237057802 :                         if (hkey->rmap.rm_offset & badflag) {
     177           0 :                                 xchk_btree_set_preen(sc, cur, level);
     178           0 :                                 break;
     179             :                         }
     180             :                 }
     181             :         }
     182             : }
     183             : 
     184             : static inline bool
     185    51208912 : xchk_rmapbt_is_shareable(
     186             :         struct xfs_scrub                *sc,
     187             :         const struct xfs_rmap_irec      *irec)
     188             : {
     189    51208912 :         if (!xfs_has_reflink(sc->mp))
     190             :                 return false;
     191    51208912 :         if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
     192             :                 return false;
     193    51208912 :         if (irec->rm_flags & (XFS_RMAP_BMBT_BLOCK | XFS_RMAP_ATTR_FORK |
     194             :                               XFS_RMAP_UNWRITTEN))
     195           0 :                 return false;
     196             :         return true;
     197             : }
     198             : 
     199             : /* Flag failures for records that overlap but cannot. */
     200             : STATIC void
     201   678317658 : xchk_rmapbt_check_overlapping(
     202             :         struct xchk_btree               *bs,
     203             :         struct xchk_rmap                *cr,
     204             :         const struct xfs_rmap_irec      *irec)
     205             : {
     206   678317658 :         xfs_agblock_t                   pnext, inext;
     207             : 
     208   678317658 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     209             :                 return;
     210             : 
     211             :         /* No previous record? */
     212   678317658 :         if (cr->overlap_rec.rm_blockcount == 0)
     213       62140 :                 goto set_prev;
     214             : 
     215             :         /* Do overlap_rec and irec overlap? */
     216   678255518 :         pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
     217   678255518 :         if (pnext <= irec->rm_startblock)
     218   652651061 :                 goto set_prev;
     219             : 
     220             :         /* Overlap is only allowed if both records are data fork mappings. */
     221    25604457 :         if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
     222    25604457 :             !xchk_rmapbt_is_shareable(bs->sc, irec))
     223           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     224             : 
     225             :         /* Save whichever rmap record extends furthest. */
     226    25604462 :         inext = irec->rm_startblock + irec->rm_blockcount;
     227    25604462 :         if (pnext > inext)
     228             :                 return;
     229             : 
     230    20169768 : set_prev:
     231  1345765938 :         memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec));
     232             : }
     233             : 
     234             : /* Decide if two reverse-mapping records can be merged. */
     235             : static inline bool
     236   678304956 : xchk_rmap_mergeable(
     237             :         struct xchk_rmap                *cr,
     238             :         const struct xfs_rmap_irec      *r2)
     239             : {
     240   678304956 :         const struct xfs_rmap_irec      *r1 = &cr->prev_rec;
     241             : 
     242             :         /* Ignore if prev_rec is not yet initialized. */
     243   678304956 :         if (cr->prev_rec.rm_blockcount == 0)
     244             :                 return false;
     245             : 
     246   678242815 :         if (r1->rm_owner != r2->rm_owner)
     247             :                 return false;
     248   115412119 :         if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
     249             :                 return false;
     250    92620752 :         if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
     251             :             XFS_RMAP_LEN_MAX)
     252             :                 return false;
     253    92620752 :         if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
     254             :                 return true;
     255             :         /* must be an inode owner below here */
     256    92620752 :         if (r1->rm_flags != r2->rm_flags)
     257             :                 return false;
     258    32809421 :         if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
     259             :                 return true;
     260    32809421 :         return r1->rm_offset + r1->rm_blockcount == r2->rm_offset;
     261             : }
     262             : 
     263             : /* Flag failures for records that could be merged. */
     264             : STATIC void
     265   678314070 : xchk_rmapbt_check_mergeable(
     266             :         struct xchk_btree               *bs,
     267             :         struct xchk_rmap                *cr,
     268             :         const struct xfs_rmap_irec      *irec)
     269             : {
     270   678314070 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     271             :                 return;
     272             : 
     273   678314070 :         if (xchk_rmap_mergeable(cr, irec))
     274           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     275             : 
     276  1356628140 :         memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec));
     277             : }
     278             : 
     279             : /* Compare an rmap for AG metadata against the metadata walk. */
     280             : STATIC int
     281   678330855 : xchk_rmapbt_mark_bitmap(
     282             :         struct xchk_btree               *bs,
     283             :         struct xchk_rmap                *cr,
     284             :         const struct xfs_rmap_irec      *irec)
     285             : {
     286   678330855 :         struct xfs_scrub                *sc = bs->sc;
     287   678330855 :         struct xagb_bitmap              *bmp = NULL;
     288   678330855 :         xfs_extlen_t                    fsbcount = irec->rm_blockcount;
     289             : 
     290             :         /*
     291             :          * Skip corrupt records.  It is essential that we detect records in the
     292             :          * btree that cannot overlap but do, flag those as CORRUPT, and skip
     293             :          * the bitmap comparison to avoid generating false XCORRUPT reports.
     294             :          */
     295   678330855 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     296             :                 return 0;
     297             : 
     298             :         /*
     299             :          * If the AG metadata walk didn't complete, there's no point in
     300             :          * comparing against partial results.
     301             :          */
     302   678330855 :         if (!cr->bitmaps_complete)
     303             :                 return 0;
     304             : 
     305   678330855 :         switch (irec->rm_owner) {
     306       62140 :         case XFS_RMAP_OWN_FS:
     307       62140 :                 bmp = &cr->fs_owned;
     308       62140 :                 break;
     309       13525 :         case XFS_RMAP_OWN_LOG:
     310       13525 :                 bmp = &cr->log_owned;
     311       13525 :                 break;
     312     4995999 :         case XFS_RMAP_OWN_AG:
     313     4995999 :                 bmp = &cr->ag_owned;
     314     4995999 :                 break;
     315       92004 :         case XFS_RMAP_OWN_INOBT:
     316       92004 :                 bmp = &cr->inobt_owned;
     317       92004 :                 break;
     318       67598 :         case XFS_RMAP_OWN_REFC:
     319       67598 :                 bmp = &cr->refcbt_owned;
     320       67598 :                 break;
     321             :         }
     322             : 
     323     5231266 :         if (!bmp)
     324             :                 return 0;
     325             : 
     326     5231266 :         if (xagb_bitmap_test(bmp, irec->rm_startblock, &fsbcount)) {
     327             :                 /*
     328             :                  * The start of this reverse mapping corresponds to a set
     329             :                  * region in the bitmap.  If the mapping covers more area than
     330             :                  * the set region, then it covers space that wasn't found by
     331             :                  * the AG metadata walk.
     332             :                  */
     333     5231261 :                 if (fsbcount < irec->rm_blockcount)
     334           0 :                         xchk_btree_xref_set_corrupt(bs->sc,
     335             :                                         bs->sc->sa.rmap_cur, 0);
     336             :         } else {
     337             :                 /*
     338             :                  * The start of this reverse mapping does not correspond to a
     339             :                  * completely set region in the bitmap.  The region wasn't
     340             :                  * fully set by walking the AG metadata, so this is a
     341             :                  * cross-referencing corruption.
     342             :                  */
     343           0 :                 xchk_btree_xref_set_corrupt(bs->sc, bs->sc->sa.rmap_cur, 0);
     344             :         }
     345             : 
     346             :         /* Unset the region so that we can detect missing rmap records. */
     347     5231261 :         return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount);
     348             : }
     349             : 
     350             : /* Scrub an rmapbt record. */
     351             : STATIC int
     352   678323584 : xchk_rmapbt_rec(
     353             :         struct xchk_btree       *bs,
     354             :         const union xfs_btree_rec *rec)
     355             : {
     356   678323584 :         struct xchk_rmap        *cr = bs->private;
     357   678323584 :         struct xfs_rmap_irec    irec;
     358             : 
     359  1356662517 :         if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
     360   678338845 :             xfs_rmap_check_irec(bs->cur, &irec) != NULL) {
     361           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     362           0 :                 return 0;
     363             :         }
     364             : 
     365   678339128 :         xchk_rmapbt_check_unwritten_in_keyflags(bs);
     366   678317730 :         xchk_rmapbt_check_mergeable(bs, cr, &irec);
     367   678311928 :         xchk_rmapbt_check_overlapping(bs, cr, &irec);
     368   678311321 :         xchk_rmapbt_xref(bs->sc, &irec);
     369             : 
     370   678326238 :         return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
     371             : }
     372             : 
     373             : /* Add an AGFL block to the rmap list. */
     374             : STATIC int
     375      429183 : xchk_rmapbt_walk_agfl(
     376             :         struct xfs_mount        *mp,
     377             :         xfs_agblock_t           agbno,
     378             :         void                    *priv)
     379             : {
     380      429183 :         struct xagb_bitmap      *bitmap = priv;
     381             : 
     382      429183 :         return xagb_bitmap_set(bitmap, agbno, 1);
     383             : }
     384             : 
     385             : /*
     386             :  * Set up bitmaps mapping all the AG metadata to compare with the rmapbt
     387             :  * records.
     388             :  *
     389             :  * Grab our own btree cursors here if the scrub setup function didn't give us a
     390             :  * btree cursor due to reports of poor health.  We need to find out if the
     391             :  * rmapbt disagrees with primary metadata btrees to tag the rmapbt as being
     392             :  * XCORRUPT.
     393             :  */
     394             : STATIC int
     395       62140 : xchk_rmapbt_walk_ag_metadata(
     396             :         struct xfs_scrub        *sc,
     397             :         struct xchk_rmap        *cr)
     398             : {
     399       62140 :         struct xfs_mount        *mp = sc->mp;
     400       62140 :         struct xfs_buf          *agfl_bp;
     401       62140 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     402       62140 :         struct xfs_btree_cur    *cur;
     403       62140 :         int                     error;
     404             : 
     405             :         /* OWN_FS: AG headers */
     406      124281 :         error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp),
     407       62140 :                         XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1);
     408       62141 :         if (error)
     409           0 :                 goto out;
     410             : 
     411             :         /* OWN_LOG: Internal log */
     412      124282 :         if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) {
     413       27050 :                 error = xagb_bitmap_set(&cr->log_owned,
     414       13525 :                                 XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
     415             :                                 mp->m_sb.sb_logblocks);
     416       13525 :                 if (error)
     417           0 :                         goto out;
     418             :         }
     419             : 
     420             :         /* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
     421       62141 :         cur = sc->sa.bno_cur;
     422       62141 :         if (!cur)
     423           0 :                 cur = xfs_allocbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
     424             :                                 sc->sa.pag, XFS_BTNUM_BNO);
     425       62141 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
     426       62141 :         if (cur != sc->sa.bno_cur)
     427           0 :                 xfs_btree_del_cursor(cur, error);
     428       62141 :         if (error)
     429           0 :                 goto out;
     430             : 
     431       62141 :         cur = sc->sa.cnt_cur;
     432       62141 :         if (!cur)
     433           0 :                 cur = xfs_allocbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
     434             :                                 sc->sa.pag, XFS_BTNUM_CNT);
     435       62141 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
     436       62139 :         if (cur != sc->sa.cnt_cur)
     437           0 :                 xfs_btree_del_cursor(cur, error);
     438       62139 :         if (error)
     439           0 :                 goto out;
     440             : 
     441       62139 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
     442       62141 :         if (error)
     443           0 :                 goto out;
     444             : 
     445       62141 :         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
     446       62141 :         if (error)
     447           0 :                 goto out;
     448             : 
     449       62141 :         error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
     450             :                         &cr->ag_owned);
     451       62141 :         xfs_trans_brelse(sc->tp, agfl_bp);
     452       62141 :         if (error)
     453           0 :                 goto out;
     454             : 
     455             :         /* OWN_INOBT: inobt, finobt */
     456       62141 :         cur = sc->sa.ino_cur;
     457       62141 :         if (!cur)
     458           0 :                 cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp,
     459             :                                 XFS_BTNUM_INO);
     460       62141 :         error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
     461       62141 :         if (cur != sc->sa.ino_cur)
     462           0 :                 xfs_btree_del_cursor(cur, error);
     463       62141 :         if (error)
     464           0 :                 goto out;
     465             : 
     466       62141 :         if (xfs_has_finobt(sc->mp)) {
     467       62141 :                 cur = sc->sa.fino_cur;
     468       62141 :                 if (!cur)
     469           0 :                         cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp,
     470             :                                         sc->sa.agi_bp, XFS_BTNUM_FINO);
     471       62141 :                 error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
     472       62141 :                 if (cur != sc->sa.fino_cur)
     473           0 :                         xfs_btree_del_cursor(cur, error);
     474       62141 :                 if (error)
     475           0 :                         goto out;
     476             :         }
     477             : 
     478             :         /* OWN_REFC: refcountbt */
     479       62141 :         if (xfs_has_reflink(sc->mp)) {
     480       62133 :                 cur = sc->sa.refc_cur;
     481       62133 :                 if (!cur)
     482           0 :                         cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp,
     483             :                                         sc->sa.agf_bp, sc->sa.pag);
     484       62133 :                 error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur);
     485       62133 :                 if (cur != sc->sa.refc_cur)
     486           0 :                         xfs_btree_del_cursor(cur, error);
     487       62133 :                 if (error)
     488             :                         goto out;
     489             :         }
     490             : 
     491       62141 : out:
     492             :         /*
     493             :          * If there's an error, set XFAIL and disable the bitmap
     494             :          * cross-referencing checks, but proceed with the scrub anyway.
     495             :          */
     496       62141 :         if (error)
     497           0 :                 xchk_btree_xref_process_error(sc, sc->sa.rmap_cur,
     498           0 :                                 sc->sa.rmap_cur->bc_nlevels - 1, &error);
     499             :         else
     500       62141 :                 cr->bitmaps_complete = true;
     501       62141 :         return 0;
     502             : }
     503             : 
     504             : /*
     505             :  * Check for set regions in the bitmaps; if there are any, the rmap records do
     506             :  * not describe all the AG metadata.
     507             :  */
     508             : STATIC void
     509       62141 : xchk_rmapbt_check_bitmaps(
     510             :         struct xfs_scrub        *sc,
     511             :         struct xchk_rmap        *cr)
     512             : {
     513       62141 :         struct xfs_btree_cur    *cur = sc->sa.rmap_cur;
     514       62141 :         unsigned int            level;
     515             : 
     516       62141 :         if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
     517             :                                 XFS_SCRUB_OFLAG_XFAIL))
     518             :                 return;
     519       62141 :         if (!cur)
     520             :                 return;
     521       62141 :         level = cur->bc_nlevels - 1;
     522             : 
     523             :         /*
     524             :          * Any bitmap with bits still set indicates that the reverse mapping
     525             :          * doesn't cover the entire primary structure.
     526             :          */
     527       62141 :         if (xagb_bitmap_hweight(&cr->fs_owned) != 0)
     528           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     529             : 
     530       62141 :         if (xagb_bitmap_hweight(&cr->log_owned) != 0)
     531           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     532             : 
     533       62141 :         if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
     534           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     535             : 
     536       62141 :         if (xagb_bitmap_hweight(&cr->inobt_owned) != 0)
     537           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     538             : 
     539       62141 :         if (xagb_bitmap_hweight(&cr->refcbt_owned) != 0)
     540           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     541             : }
     542             : 
     543             : /* Scrub the rmap btree for some AG. */
     544             : int
     545       62141 : xchk_rmapbt(
     546             :         struct xfs_scrub        *sc)
     547             : {
     548       62141 :         struct xchk_rmap        *cr;
     549       62141 :         int                     error;
     550             : 
     551       62141 :         cr = kzalloc(sizeof(struct xchk_rmap), XCHK_GFP_FLAGS);
     552       62141 :         if (!cr)
     553             :                 return -ENOMEM;
     554             : 
     555       62141 :         xagb_bitmap_init(&cr->fs_owned);
     556       62141 :         xagb_bitmap_init(&cr->log_owned);
     557       62141 :         xagb_bitmap_init(&cr->ag_owned);
     558       62141 :         xagb_bitmap_init(&cr->inobt_owned);
     559       62141 :         xagb_bitmap_init(&cr->refcbt_owned);
     560             : 
     561       62141 :         error = xchk_rmapbt_walk_ag_metadata(sc, cr);
     562       62141 :         if (error)
     563           0 :                 goto out;
     564             : 
     565       62141 :         error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
     566             :                         &XFS_RMAP_OINFO_AG, cr);
     567       62141 :         if (error)
     568           0 :                 goto out;
     569             : 
     570       62141 :         xchk_rmapbt_check_bitmaps(sc, cr);
     571             : 
     572       62141 : out:
     573       62141 :         xagb_bitmap_destroy(&cr->refcbt_owned);
     574       62141 :         xagb_bitmap_destroy(&cr->inobt_owned);
     575       62141 :         xagb_bitmap_destroy(&cr->ag_owned);
     576       62141 :         xagb_bitmap_destroy(&cr->log_owned);
     577       62141 :         xagb_bitmap_destroy(&cr->fs_owned);
     578       62141 :         kfree(cr);
     579       62141 :         return error;
     580             : }
     581             : 
     582             : /* xref check that the extent is owned only by a given owner */
     583             : void
     584   619401596 : xchk_xref_is_only_owned_by(
     585             :         struct xfs_scrub                *sc,
     586             :         xfs_agblock_t                   bno,
     587             :         xfs_extlen_t                    len,
     588             :         const struct xfs_owner_info     *oinfo)
     589             : {
     590   619401596 :         struct xfs_rmap_matches         res;
     591   619401596 :         int                             error;
     592             : 
     593   619401596 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     594   234873886 :                 return;
     595             : 
     596   384527710 :         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
     597   384528943 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     598             :                 return;
     599   384529072 :         if (res.matches != 1)
     600           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     601   384529072 :         if (res.bad_non_owner_matches)
     602           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     603   384529072 :         if (res.non_owner_matches)
     604           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     605             : }
     606             : 
     607             : /* xref check that the extent is not owned by a given owner */
     608             : void
     609    29099898 : xchk_xref_is_not_owned_by(
     610             :         struct xfs_scrub                *sc,
     611             :         xfs_agblock_t                   bno,
     612             :         xfs_extlen_t                    len,
     613             :         const struct xfs_owner_info     *oinfo)
     614             : {
     615    29099898 :         struct xfs_rmap_matches         res;
     616    29099898 :         int                             error;
     617             : 
     618    29099898 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     619    13214642 :                 return;
     620             : 
     621    15885256 :         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
     622    15885268 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     623             :                 return;
     624    15885268 :         if (res.matches != 0)
     625           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     626    15885268 :         if (res.bad_non_owner_matches)
     627           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     628             : }
     629             : 
     630             : /* xref check that the extent has no reverse mapping at all */
     631             : void
     632   383146441 : xchk_xref_has_no_owner(
     633             :         struct xfs_scrub        *sc,
     634             :         xfs_agblock_t           bno,
     635             :         xfs_extlen_t            len)
     636             : {
     637   383146441 :         enum xbtree_recpacking  outcome;
     638   383146441 :         int                     error;
     639             : 
     640   383146441 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     641      749472 :                 return;
     642             : 
     643   382396969 :         error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome);
     644   382398598 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     645             :                 return;
     646   382398608 :         if (outcome != XBTREE_RECPACKING_EMPTY)
     647           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     648             : }

Generated by: LCOV version 1.14