LCOV - code coverage report
Current view: top level - fs/xfs/scrub - rmap.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 238 285 83.5 %
Date: 2023-07-31 20:08:34 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      309386 : xchk_setup_ag_rmapbt(
      34             :         struct xfs_scrub        *sc)
      35             : {
      36      309386 :         if (xchk_need_intent_drain(sc))
      37        3194 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      38             : 
      39      618772 :         if (xchk_could_repair(sc)) {
      40       32679 :                 int             error;
      41             : 
      42       32679 :                 error = xrep_setup_ag_rmapbt(sc);
      43       32792 :                 if (error)
      44             :                         return error;
      45             :         }
      46             : 
      47      309499 :         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   968520766 : xchk_rmapbt_xref_refc(
      80             :         struct xfs_scrub        *sc,
      81             :         struct xfs_rmap_irec    *irec)
      82             : {
      83   968520766 :         xfs_agblock_t           fbno;
      84   968520766 :         xfs_extlen_t            flen;
      85   968520766 :         bool                    non_inode;
      86   968520766 :         bool                    is_bmbt;
      87   968520766 :         bool                    is_attr;
      88   968520766 :         bool                    is_unwritten;
      89   968520766 :         int                     error;
      90             : 
      91   968520766 :         if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
      92       42046 :                 return;
      93             : 
      94   968478720 :         non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
      95   968478720 :         is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
      96   968478720 :         is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
      97   968478720 :         is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
      98             : 
      99             :         /* If this is shared, must be a data fork extent. */
     100   968478720 :         error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock,
     101             :                         irec->rm_blockcount, &fbno, &flen, false);
     102   967670982 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
     103             :                 return;
     104   967596729 :         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   973054377 : xchk_rmapbt_xref(
     111             :         struct xfs_scrub        *sc,
     112             :         struct xfs_rmap_irec    *irec)
     113             : {
     114   973054377 :         xfs_agblock_t           agbno = irec->rm_startblock;
     115   973054377 :         xfs_extlen_t            len = irec->rm_blockcount;
     116             : 
     117   973054377 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     118             :                 return;
     119             : 
     120   973057456 :         xchk_xref_is_used_space(sc, agbno, len);
     121   974339079 :         if (irec->rm_owner == XFS_RMAP_OWN_INODES)
     122    17441237 :                 xchk_xref_is_inode_chunk(sc, agbno, len);
     123             :         else
     124   956897842 :                 xchk_xref_is_not_inode_chunk(sc, agbno, len);
     125   974667067 :         if (irec->rm_owner == XFS_RMAP_OWN_COW)
     126     6115371 :                 xchk_xref_is_cow_staging(sc, irec->rm_startblock,
     127             :                                 irec->rm_blockcount);
     128             :         else
     129   968551696 :                 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   973215844 : xchk_rmapbt_check_unwritten_in_keyflags(
     146             :         struct xchk_btree       *bs)
     147             : {
     148   973215844 :         struct xfs_scrub        *sc = bs->sc;
     149   973215844 :         struct xfs_btree_cur    *cur = bs->cur;
     150   973215844 :         struct xfs_btree_block  *keyblock;
     151   973215844 :         union xfs_btree_key     *lkey, *hkey;
     152   973215844 :         __be64                  badflag = cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
     153   973215844 :         unsigned int            level;
     154             : 
     155   973215844 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN)
     156             :                 return;
     157             : 
     158  2691531217 :         for (level = 1; level < cur->bc_nlevels; level++) {
     159  1718213442 :                 struct xfs_buf  *bp;
     160  1718213442 :                 unsigned int    ptr;
     161             : 
     162             :                 /* Only check the first time we've seen this node block. */
     163  1718213442 :                 if (cur->bc_levels[level].ptr > 1)
     164  1496607289 :                         continue;
     165             : 
     166   221606153 :                 keyblock = xfs_btree_get_block(cur, level, &bp);
     167  2070420820 :                 for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) {
     168  1627106583 :                         lkey = xfs_btree_key_addr(cur, ptr, keyblock);
     169             : 
     170  1627228869 :                         if (lkey->rmap.rm_offset & badflag) {
     171           0 :                                 xchk_btree_set_preen(sc, cur, level);
     172           0 :                                 break;
     173             :                         }
     174             : 
     175  1627228869 :                         hkey = xfs_btree_high_key_addr(cur, ptr, keyblock);
     176  1627246608 :                         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   227697155 : xchk_rmapbt_is_shareable(
     186             :         struct xfs_scrub                *sc,
     187             :         const struct xfs_rmap_irec      *irec)
     188             : {
     189   227697155 :         if (!xfs_has_reflink(sc->mp))
     190             :                 return false;
     191   227697155 :         if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
     192             :                 return false;
     193   227697155 :         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   973848442 : xchk_rmapbt_check_overlapping(
     202             :         struct xchk_btree               *bs,
     203             :         struct xchk_rmap                *cr,
     204             :         const struct xfs_rmap_irec      *irec)
     205             : {
     206   973848442 :         xfs_agblock_t                   pnext, inext;
     207             : 
     208   973848442 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     209             :                 return;
     210             : 
     211             :         /* No previous record? */
     212   973848442 :         if (cr->overlap_rec.rm_blockcount == 0)
     213      306022 :                 goto set_prev;
     214             : 
     215             :         /* Do overlap_rec and irec overlap? */
     216   973542420 :         pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
     217   973542420 :         if (pnext <= irec->rm_startblock)
     218   859689599 :                 goto set_prev;
     219             : 
     220             :         /* Overlap is only allowed if both records are data fork mappings. */
     221   113852821 :         if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
     222   113852821 :             !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   113860024 :         inext = irec->rm_startblock + irec->rm_blockcount;
     227   113860024 :         if (pnext > inext)
     228             :                 return;
     229             : 
     230    87501024 : set_prev:
     231  1894993290 :         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   974379716 : xchk_rmap_mergeable(
     237             :         struct xchk_rmap                *cr,
     238             :         const struct xfs_rmap_irec      *r2)
     239             : {
     240   974379716 :         const struct xfs_rmap_irec      *r1 = &cr->prev_rec;
     241             : 
     242             :         /* Ignore if prev_rec is not yet initialized. */
     243   974379716 :         if (cr->prev_rec.rm_blockcount == 0)
     244             :                 return false;
     245             : 
     246   974073517 :         if (r1->rm_owner != r2->rm_owner)
     247             :                 return false;
     248   248855595 :         if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
     249             :                 return false;
     250   172758764 :         if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
     251             :             XFS_RMAP_LEN_MAX)
     252             :                 return false;
     253   172758764 :         if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
     254             :                 return true;
     255             :         /* must be an inode owner below here */
     256   172758764 :         if (r1->rm_flags != r2->rm_flags)
     257             :                 return false;
     258   113004630 :         if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
     259             :                 return true;
     260   113004630 :         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   973773524 : xchk_rmapbt_check_mergeable(
     266             :         struct xchk_btree               *bs,
     267             :         struct xchk_rmap                *cr,
     268             :         const struct xfs_rmap_irec      *irec)
     269             : {
     270   973773524 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     271             :                 return;
     272             : 
     273   973773524 :         if (xchk_rmap_mergeable(cr, irec))
     274           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     275             : 
     276  1947547048 :         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   974764262 : xchk_rmapbt_mark_bitmap(
     282             :         struct xchk_btree               *bs,
     283             :         struct xchk_rmap                *cr,
     284             :         const struct xfs_rmap_irec      *irec)
     285             : {
     286   974764262 :         struct xfs_scrub                *sc = bs->sc;
     287   974764262 :         struct xagb_bitmap              *bmp = NULL;
     288   974764262 :         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   974764262 :         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   974764262 :         if (!cr->bitmaps_complete)
     303             :                 return 0;
     304             : 
     305   974764262 :         switch (irec->rm_owner) {
     306      306386 :         case XFS_RMAP_OWN_FS:
     307      306386 :                 bmp = &cr->fs_owned;
     308      306386 :                 break;
     309       34722 :         case XFS_RMAP_OWN_LOG:
     310       34722 :                 bmp = &cr->log_owned;
     311       34722 :                 break;
     312     6620071 :         case XFS_RMAP_OWN_AG:
     313     6620071 :                 bmp = &cr->ag_owned;
     314     6620071 :                 break;
     315      438106 :         case XFS_RMAP_OWN_INOBT:
     316      438106 :                 bmp = &cr->inobt_owned;
     317      438106 :                 break;
     318      379341 :         case XFS_RMAP_OWN_REFC:
     319      379341 :                 bmp = &cr->refcbt_owned;
     320      379341 :                 break;
     321             :         }
     322             : 
     323     7778626 :         if (!bmp)
     324             :                 return 0;
     325             : 
     326     7778626 :         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     7777772 :                 if (fsbcount < irec->rm_blockcount)
     334           0 :                         xchk_btree_xref_set_corrupt(bs->sc,
     335           0 :                                         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     7777772 :         return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount);
     348             : }
     349             : 
     350             : /* Scrub an rmapbt record. */
     351             : STATIC int
     352   974241213 : xchk_rmapbt_rec(
     353             :         struct xchk_btree       *bs,
     354             :         const union xfs_btree_rec *rec)
     355             : {
     356   974241213 :         struct xchk_rmap        *cr = bs->private;
     357   974241213 :         struct xfs_rmap_irec    irec;
     358             : 
     359  1947591535 :         if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
     360   973518691 :             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   973353413 :         xchk_rmapbt_check_unwritten_in_keyflags(bs);
     366   973850759 :         xchk_rmapbt_check_mergeable(bs, cr, &irec);
     367   973590135 :         xchk_rmapbt_check_overlapping(bs, cr, &irec);
     368   972802596 :         xchk_rmapbt_xref(bs->sc, &irec);
     369             : 
     370   974369917 :         return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
     371             : }
     372             : 
     373             : /* Add an AGFL block to the rmap list. */
     374             : STATIC int
     375     1880437 : xchk_rmapbt_walk_agfl(
     376             :         struct xfs_mount        *mp,
     377             :         xfs_agblock_t           agbno,
     378             :         void                    *priv)
     379             : {
     380     1880437 :         struct xagb_bitmap      *bitmap = priv;
     381             : 
     382     1880437 :         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      306802 : xchk_rmapbt_walk_ag_metadata(
     396             :         struct xfs_scrub        *sc,
     397             :         struct xchk_rmap        *cr)
     398             : {
     399      306802 :         struct xfs_mount        *mp = sc->mp;
     400      306802 :         struct xfs_buf          *agfl_bp;
     401      306802 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     402      306802 :         struct xfs_btree_cur    *cur;
     403      306802 :         int                     error;
     404             : 
     405             :         /* OWN_FS: AG headers */
     406           0 :         error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp),
     407      306802 :                         XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1);
     408      305884 :         if (error)
     409           0 :                 goto out;
     410             : 
     411             :         /* OWN_LOG: Internal log */
     412      305884 :         if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) {
     413       34722 :                 error = xagb_bitmap_set(&cr->log_owned,
     414       34722 :                                 XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
     415             :                                 mp->m_sb.sb_logblocks);
     416       34722 :                 if (error)
     417           0 :                         goto out;
     418             :         }
     419             : 
     420             :         /* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
     421      305867 :         cur = sc->sa.bno_cur;
     422      305867 :         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      305867 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
     426      306798 :         if (cur != sc->sa.bno_cur)
     427           0 :                 xfs_btree_del_cursor(cur, error);
     428      306696 :         if (error)
     429           0 :                 goto out;
     430             : 
     431      306696 :         cur = sc->sa.cnt_cur;
     432      306696 :         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      306696 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
     436      306334 :         if (cur != sc->sa.cnt_cur)
     437           0 :                 xfs_btree_del_cursor(cur, error);
     438      306354 :         if (error)
     439           0 :                 goto out;
     440             : 
     441      306354 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
     442      306674 :         if (error)
     443           0 :                 goto out;
     444             : 
     445      306674 :         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
     446      307169 :         if (error)
     447           0 :                 goto out;
     448             : 
     449      307169 :         error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
     450             :                         &cr->ag_owned);
     451      307098 :         xfs_trans_brelse(sc->tp, agfl_bp);
     452      307225 :         if (error)
     453           0 :                 goto out;
     454             : 
     455             :         /* OWN_INOBT: inobt, finobt */
     456      307225 :         cur = sc->sa.ino_cur;
     457      307225 :         if (!cur)
     458           0 :                 cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp,
     459             :                                 XFS_BTNUM_INO);
     460      307225 :         error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
     461      307127 :         if (cur != sc->sa.ino_cur)
     462           0 :                 xfs_btree_del_cursor(cur, error);
     463      306702 :         if (error)
     464           0 :                 goto out;
     465             : 
     466      306702 :         if (xfs_has_finobt(sc->mp)) {
     467      307038 :                 cur = sc->sa.fino_cur;
     468      307038 :                 if (!cur)
     469           0 :                         cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp,
     470             :                                         sc->sa.agi_bp, XFS_BTNUM_FINO);
     471      307038 :                 error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
     472      307004 :                 if (cur != sc->sa.fino_cur)
     473           0 :                         xfs_btree_del_cursor(cur, error);
     474      307004 :                 if (error)
     475           0 :                         goto out;
     476             :         }
     477             : 
     478             :         /* OWN_REFC: refcountbt */
     479      306668 :         if (xfs_has_reflink(sc->mp)) {
     480      306475 :                 cur = sc->sa.refc_cur;
     481      306475 :                 if (!cur)
     482           0 :                         cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp,
     483             :                                         sc->sa.agf_bp, sc->sa.pag);
     484      306475 :                 error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur);
     485      306991 :                 if (cur != sc->sa.refc_cur)
     486           0 :                         xfs_btree_del_cursor(cur, error);
     487      306968 :                 if (error)
     488             :                         goto out;
     489             :         }
     490             : 
     491      307161 : 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      307161 :         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      307161 :                 cr->bitmaps_complete = true;
     501      307161 :         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      306922 : xchk_rmapbt_check_bitmaps(
     510             :         struct xfs_scrub        *sc,
     511             :         struct xchk_rmap        *cr)
     512             : {
     513      306922 :         struct xfs_btree_cur    *cur = sc->sa.rmap_cur;
     514      306922 :         unsigned int            level;
     515             : 
     516      306922 :         if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
     517             :                                 XFS_SCRUB_OFLAG_XFAIL))
     518             :                 return;
     519      306922 :         if (!cur)
     520             :                 return;
     521      306922 :         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      306922 :         if (xagb_bitmap_hweight(&cr->fs_owned) != 0)
     528           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     529             : 
     530      306255 :         if (xagb_bitmap_hweight(&cr->log_owned) != 0)
     531           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     532             : 
     533      306432 :         if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
     534           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     535             : 
     536      306497 :         if (xagb_bitmap_hweight(&cr->inobt_owned) != 0)
     537           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     538             : 
     539      306622 :         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      306915 : xchk_rmapbt(
     546             :         struct xfs_scrub        *sc)
     547             : {
     548      306915 :         struct xchk_rmap        *cr;
     549      306915 :         int                     error;
     550             : 
     551      306915 :         cr = kzalloc(sizeof(struct xchk_rmap), XCHK_GFP_FLAGS);
     552      306966 :         if (!cr)
     553             :                 return -ENOMEM;
     554             : 
     555      306966 :         xagb_bitmap_init(&cr->fs_owned);
     556      306745 :         xagb_bitmap_init(&cr->log_owned);
     557      306889 :         xagb_bitmap_init(&cr->ag_owned);
     558      306845 :         xagb_bitmap_init(&cr->inobt_owned);
     559      306833 :         xagb_bitmap_init(&cr->refcbt_owned);
     560             : 
     561      306808 :         error = xchk_rmapbt_walk_ag_metadata(sc, cr);
     562      306879 :         if (error)
     563           0 :                 goto out;
     564             : 
     565      306879 :         error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
     566             :                         &XFS_RMAP_OINFO_AG, cr);
     567      307026 :         if (error)
     568           5 :                 goto out;
     569             : 
     570      307021 :         xchk_rmapbt_check_bitmaps(sc, cr);
     571             : 
     572      306806 : out:
     573      306806 :         xagb_bitmap_destroy(&cr->refcbt_owned);
     574      306425 :         xagb_bitmap_destroy(&cr->inobt_owned);
     575      306552 :         xagb_bitmap_destroy(&cr->ag_owned);
     576      306589 :         xagb_bitmap_destroy(&cr->log_owned);
     577      306749 :         xagb_bitmap_destroy(&cr->fs_owned);
     578      306808 :         kfree(cr);
     579      306808 :         return error;
     580             : }
     581             : 
     582             : /* xref check that the extent is owned only by a given owner */
     583             : void
     584   968809328 : 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   968809328 :         struct xfs_rmap_matches         res;
     591   968809328 :         int                             error;
     592             : 
     593   968809328 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     594    12294844 :                 return;
     595             : 
     596   956514484 :         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
     597   956876998 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     598             :                 return;
     599   956715332 :         if (res.matches != 1)
     600           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     601   956715332 :         if (res.bad_non_owner_matches)
     602           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     603   956715332 :         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    26500048 : 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    26500048 :         struct xfs_rmap_matches         res;
     616    26500048 :         int                             error;
     617             : 
     618    26500048 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     619      271268 :                 return;
     620             : 
     621    26228780 :         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
     622    26228869 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     623             :                 return;
     624    26228817 :         if (res.matches != 0)
     625           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     626    26228817 :         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   432718515 : xchk_xref_has_no_owner(
     633             :         struct xfs_scrub        *sc,
     634             :         xfs_agblock_t           bno,
     635             :         xfs_extlen_t            len)
     636             : {
     637   432718515 :         enum xbtree_recpacking  outcome;
     638   432718515 :         int                     error;
     639             : 
     640   432718515 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     641      532459 :                 return;
     642             : 
     643   432186056 :         error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome);
     644   432178515 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     645             :                 return;
     646   432172965 :         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