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-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 240 285 84.2 %
Date: 2023-07-31 20:08:12 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      164309 : xchk_setup_ag_rmapbt(
      34             :         struct xfs_scrub        *sc)
      35             : {
      36      164309 :         if (xchk_need_intent_drain(sc))
      37        2923 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      38             : 
      39      328618 :         if (xchk_could_repair(sc)) {
      40       15937 :                 int             error;
      41             : 
      42       15937 :                 error = xrep_setup_ag_rmapbt(sc);
      43       15937 :                 if (error)
      44             :                         return error;
      45             :         }
      46             : 
      47      164309 :         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   635627966 : xchk_rmapbt_xref_refc(
      80             :         struct xfs_scrub        *sc,
      81             :         struct xfs_rmap_irec    *irec)
      82             : {
      83   635627966 :         xfs_agblock_t           fbno;
      84   635627966 :         xfs_extlen_t            flen;
      85   635627966 :         bool                    non_inode;
      86   635627966 :         bool                    is_bmbt;
      87   635627966 :         bool                    is_attr;
      88   635627966 :         bool                    is_unwritten;
      89   635627966 :         int                     error;
      90             : 
      91   635627966 :         if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
      92       34347 :                 return;
      93             : 
      94   635593619 :         non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
      95   635593619 :         is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
      96   635593619 :         is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
      97   635593619 :         is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
      98             : 
      99             :         /* If this is shared, must be a data fork extent. */
     100   635593619 :         error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock,
     101             :                         irec->rm_blockcount, &fbno, &flen, false);
     102   635451108 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
     103             :                 return;
     104   635427133 :         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   640621924 : xchk_rmapbt_xref(
     111             :         struct xfs_scrub        *sc,
     112             :         struct xfs_rmap_irec    *irec)
     113             : {
     114   640621924 :         xfs_agblock_t           agbno = irec->rm_startblock;
     115   640621924 :         xfs_extlen_t            len = irec->rm_blockcount;
     116             : 
     117   640621924 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     118             :                 return;
     119             : 
     120   640639674 :         xchk_xref_is_used_space(sc, agbno, len);
     121   641250859 :         if (irec->rm_owner == XFS_RMAP_OWN_INODES)
     122     4053077 :                 xchk_xref_is_inode_chunk(sc, agbno, len);
     123             :         else
     124   637197782 :                 xchk_xref_is_not_inode_chunk(sc, agbno, len);
     125   641444899 :         if (irec->rm_owner == XFS_RMAP_OWN_COW)
     126     5861614 :                 xchk_xref_is_cow_staging(sc, irec->rm_startblock,
     127             :                                 irec->rm_blockcount);
     128             :         else
     129   635583285 :                 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   640822880 : xchk_rmapbt_check_unwritten_in_keyflags(
     146             :         struct xchk_btree       *bs)
     147             : {
     148   640822880 :         struct xfs_scrub        *sc = bs->sc;
     149   640822880 :         struct xfs_btree_cur    *cur = bs->cur;
     150   640822880 :         struct xfs_btree_block  *keyblock;
     151   640822880 :         union xfs_btree_key     *lkey, *hkey;
     152   640822880 :         __be64                  badflag = cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
     153   640822880 :         unsigned int            level;
     154             : 
     155   640822880 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN)
     156             :                 return;
     157             : 
     158  1874167717 :         for (level = 1; level < cur->bc_nlevels; level++) {
     159  1233313672 :                 struct xfs_buf  *bp;
     160  1233313672 :                 unsigned int    ptr;
     161             : 
     162             :                 /* Only check the first time we've seen this node block. */
     163  1233313672 :                 if (cur->bc_levels[level].ptr > 1)
     164  1086254202 :                         continue;
     165             : 
     166   147059470 :                 keyblock = xfs_btree_get_block(cur, level, &bp);
     167  1468744798 :                 for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) {
     168  1174594693 :                         lkey = xfs_btree_key_addr(cur, ptr, keyblock);
     169             : 
     170  1174654027 :                         if (lkey->rmap.rm_offset & badflag) {
     171           0 :                                 xchk_btree_set_preen(sc, cur, level);
     172           0 :                                 break;
     173             :                         }
     174             : 
     175  1174654027 :                         hkey = xfs_btree_high_key_addr(cur, ptr, keyblock);
     176  1174636829 :                         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   220823293 : xchk_rmapbt_is_shareable(
     186             :         struct xfs_scrub                *sc,
     187             :         const struct xfs_rmap_irec      *irec)
     188             : {
     189   220823293 :         if (!xfs_has_reflink(sc->mp))
     190             :                 return false;
     191   220823293 :         if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
     192             :                 return false;
     193   220823293 :         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   641003782 : xchk_rmapbt_check_overlapping(
     202             :         struct xchk_btree               *bs,
     203             :         struct xchk_rmap                *cr,
     204             :         const struct xfs_rmap_irec      *irec)
     205             : {
     206   641003782 :         xfs_agblock_t                   pnext, inext;
     207             : 
     208   641003782 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     209             :                 return;
     210             : 
     211             :         /* No previous record? */
     212   641003782 :         if (cr->overlap_rec.rm_blockcount == 0)
     213      161304 :                 goto set_prev;
     214             : 
     215             :         /* Do overlap_rec and irec overlap? */
     216   640842478 :         pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
     217   640842478 :         if (pnext <= irec->rm_startblock)
     218   530428568 :                 goto set_prev;
     219             : 
     220             :         /* Overlap is only allowed if both records are data fork mappings. */
     221   110413910 :         if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
     222   110413910 :             !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   110415392 :         inext = irec->rm_startblock + irec->rm_blockcount;
     227   110415392 :         if (pnext > inext)
     228             :                 return;
     229             : 
     230    85401301 : set_prev:
     231  1231982346 :         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   641282120 : xchk_rmap_mergeable(
     237             :         struct xchk_rmap                *cr,
     238             :         const struct xfs_rmap_irec      *r2)
     239             : {
     240   641282120 :         const struct xfs_rmap_irec      *r1 = &cr->prev_rec;
     241             : 
     242             :         /* Ignore if prev_rec is not yet initialized. */
     243   641282120 :         if (cr->prev_rec.rm_blockcount == 0)
     244             :                 return false;
     245             : 
     246   641120567 :         if (r1->rm_owner != r2->rm_owner)
     247             :                 return false;
     248   170638773 :         if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
     249             :                 return false;
     250    95331484 :         if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
     251             :             XFS_RMAP_LEN_MAX)
     252             :                 return false;
     253    95331484 :         if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
     254             :                 return true;
     255             :         /* must be an inode owner below here */
     256    95331484 :         if (r1->rm_flags != r2->rm_flags)
     257             :                 return false;
     258    35727190 :         if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
     259             :                 return true;
     260    35727190 :         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   640875901 : xchk_rmapbt_check_mergeable(
     266             :         struct xchk_btree               *bs,
     267             :         struct xchk_rmap                *cr,
     268             :         const struct xfs_rmap_irec      *irec)
     269             : {
     270   640875901 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     271             :                 return;
     272             : 
     273   640875901 :         if (xchk_rmap_mergeable(cr, irec))
     274           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     275             : 
     276  1281751802 :         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   641475165 : xchk_rmapbt_mark_bitmap(
     282             :         struct xchk_btree               *bs,
     283             :         struct xchk_rmap                *cr,
     284             :         const struct xfs_rmap_irec      *irec)
     285             : {
     286   641475165 :         struct xfs_scrub                *sc = bs->sc;
     287   641475165 :         struct xagb_bitmap              *bmp = NULL;
     288   641475165 :         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   641475165 :         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   641475165 :         if (!cr->bitmaps_complete)
     303             :                 return 0;
     304             : 
     305   641475165 :         switch (irec->rm_owner) {
     306      161607 :         case XFS_RMAP_OWN_FS:
     307      161607 :                 bmp = &cr->fs_owned;
     308      161607 :                 break;
     309       21323 :         case XFS_RMAP_OWN_LOG:
     310       21323 :                 bmp = &cr->log_owned;
     311       21323 :                 break;
     312     4461461 :         case XFS_RMAP_OWN_AG:
     313     4461461 :                 bmp = &cr->ag_owned;
     314     4461461 :                 break;
     315      220754 :         case XFS_RMAP_OWN_INOBT:
     316      220754 :                 bmp = &cr->inobt_owned;
     317      220754 :                 break;
     318      236411 :         case XFS_RMAP_OWN_REFC:
     319      236411 :                 bmp = &cr->refcbt_owned;
     320      236411 :                 break;
     321             :         }
     322             : 
     323     5101556 :         if (!bmp)
     324             :                 return 0;
     325             : 
     326     5101556 :         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     5100722 :                 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     5100722 :         return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount);
     348             : }
     349             : 
     350             : /* Scrub an rmapbt record. */
     351             : STATIC int
     352   641332835 : xchk_rmapbt_rec(
     353             :         struct xchk_btree       *bs,
     354             :         const union xfs_btree_rec *rec)
     355             : {
     356   641332835 :         struct xchk_rmap        *cr = bs->private;
     357   641332835 :         struct xfs_rmap_irec    irec;
     358             : 
     359  1282155375 :         if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
     360   641230230 :             xfs_rmap_check_irec(bs->cur, &irec) != NULL) {
     361           1 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     362           1 :                 return 0;
     363             :         }
     364             : 
     365   640834339 :         xchk_rmapbt_check_unwritten_in_keyflags(bs);
     366   641065709 :         xchk_rmapbt_check_mergeable(bs, cr, &irec);
     367   640881005 :         xchk_rmapbt_check_overlapping(bs, cr, &irec);
     368   640566485 :         xchk_rmapbt_xref(bs->sc, &irec);
     369             : 
     370   641412043 :         return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
     371             : }
     372             : 
     373             : /* Add an AGFL block to the rmap list. */
     374             : STATIC int
     375     1004797 : xchk_rmapbt_walk_agfl(
     376             :         struct xfs_mount        *mp,
     377             :         xfs_agblock_t           agbno,
     378             :         void                    *priv)
     379             : {
     380     1004797 :         struct xagb_bitmap      *bitmap = priv;
     381             : 
     382     1004797 :         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      161942 : xchk_rmapbt_walk_ag_metadata(
     396             :         struct xfs_scrub        *sc,
     397             :         struct xchk_rmap        *cr)
     398             : {
     399      161942 :         struct xfs_mount        *mp = sc->mp;
     400      161942 :         struct xfs_buf          *agfl_bp;
     401      161942 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     402      161942 :         struct xfs_btree_cur    *cur;
     403      161942 :         int                     error;
     404             : 
     405             :         /* OWN_FS: AG headers */
     406           0 :         error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp),
     407      161942 :                         XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1);
     408      161316 :         if (error)
     409           0 :                 goto out;
     410             : 
     411             :         /* OWN_LOG: Internal log */
     412      161316 :         if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) {
     413       21323 :                 error = xagb_bitmap_set(&cr->log_owned,
     414       21323 :                                 XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
     415             :                                 mp->m_sb.sb_logblocks);
     416       21323 :                 if (error)
     417           0 :                         goto out;
     418             :         }
     419             : 
     420             :         /* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
     421      161307 :         cur = sc->sa.bno_cur;
     422      161307 :         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      161307 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
     426      161981 :         if (cur != sc->sa.bno_cur)
     427           0 :                 xfs_btree_del_cursor(cur, error);
     428      161893 :         if (error)
     429           0 :                 goto out;
     430             : 
     431      161893 :         cur = sc->sa.cnt_cur;
     432      161893 :         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      161893 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
     436      161887 :         if (cur != sc->sa.cnt_cur)
     437           0 :                 xfs_btree_del_cursor(cur, error);
     438      161853 :         if (error)
     439           0 :                 goto out;
     440             : 
     441      161853 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
     442      161850 :         if (error)
     443           0 :                 goto out;
     444             : 
     445      161850 :         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
     446      162137 :         if (error)
     447           0 :                 goto out;
     448             : 
     449      162137 :         error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
     450             :                         &cr->ag_owned);
     451      161987 :         xfs_trans_brelse(sc->tp, agfl_bp);
     452      162147 :         if (error)
     453           0 :                 goto out;
     454             : 
     455             :         /* OWN_INOBT: inobt, finobt */
     456      162147 :         cur = sc->sa.ino_cur;
     457      162147 :         if (!cur)
     458           0 :                 cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp,
     459             :                                 XFS_BTNUM_INO);
     460      162147 :         error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
     461      162042 :         if (cur != sc->sa.ino_cur)
     462           0 :                 xfs_btree_del_cursor(cur, error);
     463      161783 :         if (error)
     464           0 :                 goto out;
     465             : 
     466      161783 :         if (xfs_has_finobt(sc->mp)) {
     467      161966 :                 cur = sc->sa.fino_cur;
     468      161966 :                 if (!cur)
     469           0 :                         cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp,
     470             :                                         sc->sa.agi_bp, XFS_BTNUM_FINO);
     471      161966 :                 error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
     472      162002 :                 if (cur != sc->sa.fino_cur)
     473           0 :                         xfs_btree_del_cursor(cur, error);
     474      162002 :                 if (error)
     475           0 :                         goto out;
     476             :         }
     477             : 
     478             :         /* OWN_REFC: refcountbt */
     479      161819 :         if (xfs_has_reflink(sc->mp)) {
     480      161707 :                 cur = sc->sa.refc_cur;
     481      161707 :                 if (!cur)
     482           0 :                         cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp,
     483             :                                         sc->sa.agf_bp, sc->sa.pag);
     484      161707 :                 error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur);
     485      162017 :                 if (cur != sc->sa.refc_cur)
     486           0 :                         xfs_btree_del_cursor(cur, error);
     487      162012 :                 if (error)
     488             :                         goto out;
     489             :         }
     490             : 
     491      162124 : 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      162124 :         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      162124 :                 cr->bitmaps_complete = true;
     501      162124 :         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      161982 : xchk_rmapbt_check_bitmaps(
     510             :         struct xfs_scrub        *sc,
     511             :         struct xchk_rmap        *cr)
     512             : {
     513      161982 :         struct xfs_btree_cur    *cur = sc->sa.rmap_cur;
     514      161982 :         unsigned int            level;
     515             : 
     516      161982 :         if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
     517             :                                 XFS_SCRUB_OFLAG_XFAIL))
     518             :                 return;
     519      161982 :         if (!cur)
     520             :                 return;
     521      161982 :         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      161982 :         if (xagb_bitmap_hweight(&cr->fs_owned) != 0)
     528           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     529             : 
     530      161524 :         if (xagb_bitmap_hweight(&cr->log_owned) != 0)
     531           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     532             : 
     533      161536 :         if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
     534           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     535             : 
     536      161595 :         if (xagb_bitmap_hweight(&cr->inobt_owned) != 0)
     537           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     538             : 
     539      161659 :         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      161976 : xchk_rmapbt(
     546             :         struct xfs_scrub        *sc)
     547             : {
     548      161976 :         struct xchk_rmap        *cr;
     549      161976 :         int                     error;
     550             : 
     551      161976 :         cr = kzalloc(sizeof(struct xchk_rmap), XCHK_GFP_FLAGS);
     552      161915 :         if (!cr)
     553             :                 return -ENOMEM;
     554             : 
     555      161915 :         xagb_bitmap_init(&cr->fs_owned);
     556      161818 :         xagb_bitmap_init(&cr->log_owned);
     557      161967 :         xagb_bitmap_init(&cr->ag_owned);
     558      161909 :         xagb_bitmap_init(&cr->inobt_owned);
     559      161899 :         xagb_bitmap_init(&cr->refcbt_owned);
     560             : 
     561      161912 :         error = xchk_rmapbt_walk_ag_metadata(sc, cr);
     562      161911 :         if (error)
     563           0 :                 goto out;
     564             : 
     565      161911 :         error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
     566             :                         &XFS_RMAP_OINFO_AG, cr);
     567      161998 :         if (error)
     568           2 :                 goto out;
     569             : 
     570      161996 :         xchk_rmapbt_check_bitmaps(sc, cr);
     571             : 
     572      161858 : out:
     573      161858 :         xagb_bitmap_destroy(&cr->refcbt_owned);
     574      161588 :         xagb_bitmap_destroy(&cr->inobt_owned);
     575      161682 :         xagb_bitmap_destroy(&cr->ag_owned);
     576      161633 :         xagb_bitmap_destroy(&cr->log_owned);
     577      161695 :         xagb_bitmap_destroy(&cr->fs_owned);
     578      161690 :         kfree(cr);
     579      161690 :         return error;
     580             : }
     581             : 
     582             : /* xref check that the extent is owned only by a given owner */
     583             : void
     584   669931633 : 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   669931633 :         struct xfs_rmap_matches         res;
     591   669931633 :         int                             error;
     592             : 
     593   669931633 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     594   267639443 :                 return;
     595             : 
     596   402292190 :         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
     597   402534164 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     598             :                 return;
     599   402454449 :         if (res.matches != 1)
     600           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     601   402454449 :         if (res.bad_non_owner_matches)
     602           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     603   402454449 :         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    25577765 : 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    25577765 :         struct xfs_rmap_matches         res;
     616    25577765 :         int                             error;
     617             : 
     618    25577765 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     619    12234362 :                 return;
     620             : 
     621    13343403 :         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
     622    13343440 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     623             :                 return;
     624    13343407 :         if (res.matches != 0)
     625           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     626    13343407 :         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   444947940 : xchk_xref_has_no_owner(
     633             :         struct xfs_scrub        *sc,
     634             :         xfs_agblock_t           bno,
     635             :         xfs_extlen_t            len)
     636             : {
     637   444947940 :         enum xbtree_recpacking  outcome;
     638   444947940 :         int                     error;
     639             : 
     640   444947940 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     641     3731202 :                 return;
     642             : 
     643   441216738 :         error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome);
     644   441209747 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     645             :                 return;
     646   441205455 :         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