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-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 235 281 83.6 %
Date: 2023-07-31 20:08:22 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             : 
      28             : /*
      29             :  * Set us up to scrub reverse mapping btrees.
      30             :  */
      31             : int
      32      532033 : xchk_setup_ag_rmapbt(
      33             :         struct xfs_scrub        *sc)
      34             : {
      35      532033 :         if (xchk_need_intent_drain(sc))
      36        4229 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      37             : 
      38      532033 :         return xchk_setup_ag_btree(sc, false);
      39             : }
      40             : 
      41             : /* Reverse-mapping scrubber. */
      42             : 
      43             : struct xchk_rmap {
      44             :         /*
      45             :          * The furthest-reaching of the rmapbt records that we've already
      46             :          * processed.  This enables us to detect overlapping records for space
      47             :          * allocations that cannot be shared.
      48             :          */
      49             :         struct xfs_rmap_irec    overlap_rec;
      50             : 
      51             :         /*
      52             :          * The previous rmapbt record, so that we can check for two records
      53             :          * that could be one.
      54             :          */
      55             :         struct xfs_rmap_irec    prev_rec;
      56             : 
      57             :         /* Bitmaps containing all blocks for each type of AG metadata. */
      58             :         struct xagb_bitmap      fs_owned;
      59             :         struct xagb_bitmap      log_owned;
      60             :         struct xagb_bitmap      ag_owned;
      61             :         struct xagb_bitmap      inobt_owned;
      62             :         struct xagb_bitmap      refcbt_owned;
      63             : 
      64             :         /* Did we complete the AG space metadata bitmaps? */
      65             :         bool                    bitmaps_complete;
      66             : };
      67             : 
      68             : /* Cross-reference a rmap against the refcount btree. */
      69             : STATIC void
      70   568817267 : xchk_rmapbt_xref_refc(
      71             :         struct xfs_scrub        *sc,
      72             :         struct xfs_rmap_irec    *irec)
      73             : {
      74   568817267 :         xfs_agblock_t           fbno;
      75   568817267 :         xfs_extlen_t            flen;
      76   568817267 :         bool                    non_inode;
      77   568817267 :         bool                    is_bmbt;
      78   568817267 :         bool                    is_attr;
      79   568817267 :         bool                    is_unwritten;
      80   568817267 :         int                     error;
      81             : 
      82   568817267 :         if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
      83           0 :                 return;
      84             : 
      85   568817267 :         non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
      86   568817267 :         is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
      87   568817267 :         is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
      88   568817267 :         is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
      89             : 
      90             :         /* If this is shared, must be a data fork extent. */
      91   568817267 :         error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock,
      92             :                         irec->rm_blockcount, &fbno, &flen, false);
      93   568054230 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
      94             :                 return;
      95   567934074 :         if (flen != 0 && (non_inode || is_attr || is_bmbt || is_unwritten))
      96           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0);
      97             : }
      98             : 
      99             : /* Cross-reference with the other btrees. */
     100             : STATIC void
     101   572628392 : xchk_rmapbt_xref(
     102             :         struct xfs_scrub        *sc,
     103             :         struct xfs_rmap_irec    *irec)
     104             : {
     105   572628392 :         xfs_agblock_t           agbno = irec->rm_startblock;
     106   572628392 :         xfs_extlen_t            len = irec->rm_blockcount;
     107             : 
     108   572628392 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     109             :                 return;
     110             : 
     111   572642414 :         xchk_xref_is_used_space(sc, agbno, len);
     112   573536278 :         if (irec->rm_owner == XFS_RMAP_OWN_INODES)
     113     3695787 :                 xchk_xref_is_inode_chunk(sc, agbno, len);
     114             :         else
     115   569840491 :                 xchk_xref_is_not_inode_chunk(sc, agbno, len);
     116   574505883 :         if (irec->rm_owner == XFS_RMAP_OWN_COW)
     117     5704081 :                 xchk_xref_is_cow_staging(sc, irec->rm_startblock,
     118             :                                 irec->rm_blockcount);
     119             :         else
     120   568801802 :                 xchk_rmapbt_xref_refc(sc, irec);
     121             : }
     122             : 
     123             : /*
     124             :  * Check for bogus UNWRITTEN flags in the rmapbt node block keys.
     125             :  *
     126             :  * In reverse mapping records, the file mapping extent state
     127             :  * (XFS_RMAP_OFF_UNWRITTEN) is a record attribute, not a key field.  It is not
     128             :  * involved in lookups in any way.  In older kernels, the functions that
     129             :  * convert rmapbt records to keys forgot to filter out the extent state bit,
     130             :  * even though the key comparison functions have filtered the flag correctly.
     131             :  * If we spot an rmap key with the unwritten bit set in rm_offset, we should
     132             :  * mark the btree as needing optimization to rebuild the btree without those
     133             :  * flags.
     134             :  */
     135             : STATIC void
     136   572929180 : xchk_rmapbt_check_unwritten_in_keyflags(
     137             :         struct xchk_btree       *bs)
     138             : {
     139   572929180 :         struct xfs_scrub        *sc = bs->sc;
     140   572929180 :         struct xfs_btree_cur    *cur = bs->cur;
     141   572929180 :         struct xfs_btree_block  *keyblock;
     142   572929180 :         union xfs_btree_key     *lkey, *hkey;
     143   572929180 :         __be64                  badflag = cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
     144   572929180 :         unsigned int            level;
     145             : 
     146   572929180 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN)
     147             :                 return;
     148             : 
     149  1650931835 :         for (level = 1; level < cur->bc_nlevels; level++) {
     150  1077867731 :                 struct xfs_buf  *bp;
     151  1077867731 :                 unsigned int    ptr;
     152             : 
     153             :                 /* Only check the first time we've seen this node block. */
     154  1077867731 :                 if (cur->bc_levels[level].ptr > 1)
     155   940292129 :                         continue;
     156             : 
     157   137575602 :                 keyblock = xfs_btree_get_block(cur, level, &bp);
     158  1310567238 :                 for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) {
     159  1035281110 :                         lkey = xfs_btree_key_addr(cur, ptr, keyblock);
     160             : 
     161  1035427885 :                         if (lkey->rmap.rm_offset & badflag) {
     162           0 :                                 xchk_btree_set_preen(sc, cur, level);
     163           0 :                                 break;
     164             :                         }
     165             : 
     166  1035427885 :                         hkey = xfs_btree_high_key_addr(cur, ptr, keyblock);
     167  1035462525 :                         if (hkey->rmap.rm_offset & badflag) {
     168           0 :                                 xchk_btree_set_preen(sc, cur, level);
     169           0 :                                 break;
     170             :                         }
     171             :                 }
     172             :         }
     173             : }
     174             : 
     175             : static inline bool
     176   190411347 : xchk_rmapbt_is_shareable(
     177             :         struct xfs_scrub                *sc,
     178             :         const struct xfs_rmap_irec      *irec)
     179             : {
     180   190411347 :         if (!xfs_has_reflink(sc->mp))
     181             :                 return false;
     182   190411347 :         if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
     183             :                 return false;
     184   190411347 :         if (irec->rm_flags & (XFS_RMAP_BMBT_BLOCK | XFS_RMAP_ATTR_FORK |
     185             :                               XFS_RMAP_UNWRITTEN))
     186           0 :                 return false;
     187             :         return true;
     188             : }
     189             : 
     190             : /* Flag failures for records that overlap but cannot. */
     191             : STATIC void
     192   573530938 : xchk_rmapbt_check_overlapping(
     193             :         struct xchk_btree               *bs,
     194             :         struct xchk_rmap                *cr,
     195             :         const struct xfs_rmap_irec      *irec)
     196             : {
     197   573530938 :         xfs_agblock_t                   pnext, inext;
     198             : 
     199   573530938 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     200             :                 return;
     201             : 
     202             :         /* No previous record? */
     203   573530938 :         if (cr->overlap_rec.rm_blockcount == 0)
     204      525410 :                 goto set_prev;
     205             : 
     206             :         /* Do overlap_rec and irec overlap? */
     207   573005528 :         pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
     208   573005528 :         if (pnext <= irec->rm_startblock)
     209   477796156 :                 goto set_prev;
     210             : 
     211             :         /* Overlap is only allowed if both records are data fork mappings. */
     212    95209372 :         if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
     213    95209372 :             !xchk_rmapbt_is_shareable(bs->sc, irec))
     214           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     215             : 
     216             :         /* Save whichever rmap record extends furthest. */
     217    95216288 :         inext = irec->rm_startblock + irec->rm_blockcount;
     218    95216288 :         if (pnext > inext)
     219             :                 return;
     220             : 
     221    70776003 : set_prev:
     222  1098195138 :         memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec));
     223             : }
     224             : 
     225             : /* Decide if two reverse-mapping records can be merged. */
     226             : static inline bool
     227   574060061 : xchk_rmap_mergeable(
     228             :         struct xchk_rmap                *cr,
     229             :         const struct xfs_rmap_irec      *r2)
     230             : {
     231   574060061 :         const struct xfs_rmap_irec      *r1 = &cr->prev_rec;
     232             : 
     233             :         /* Ignore if prev_rec is not yet initialized. */
     234   574060061 :         if (cr->prev_rec.rm_blockcount == 0)
     235             :                 return false;
     236             : 
     237   573534026 :         if (r1->rm_owner != r2->rm_owner)
     238             :                 return false;
     239   153257921 :         if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
     240             :                 return false;
     241    88963075 :         if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
     242             :             XFS_RMAP_LEN_MAX)
     243             :                 return false;
     244    88963075 :         if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
     245             :                 return true;
     246             :         /* must be an inode owner below here */
     247    88963075 :         if (r1->rm_flags != r2->rm_flags)
     248             :                 return false;
     249    32979431 :         if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
     250             :                 return true;
     251    32979431 :         return r1->rm_offset + r1->rm_blockcount == r2->rm_offset;
     252             : }
     253             : 
     254             : /* Flag failures for records that could be merged. */
     255             : STATIC void
     256   573338978 : xchk_rmapbt_check_mergeable(
     257             :         struct xchk_btree               *bs,
     258             :         struct xchk_rmap                *cr,
     259             :         const struct xfs_rmap_irec      *irec)
     260             : {
     261   573338978 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     262             :                 return;
     263             : 
     264   573338978 :         if (xchk_rmap_mergeable(cr, irec))
     265           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     266             : 
     267  1146677956 :         memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec));
     268             : }
     269             : 
     270             : /* Compare an rmap for AG metadata against the metadata walk. */
     271             : STATIC int
     272   574602771 : xchk_rmapbt_mark_bitmap(
     273             :         struct xchk_btree               *bs,
     274             :         struct xchk_rmap                *cr,
     275             :         const struct xfs_rmap_irec      *irec)
     276             : {
     277   574602771 :         struct xfs_scrub                *sc = bs->sc;
     278   574602771 :         struct xagb_bitmap              *bmp = NULL;
     279   574602771 :         xfs_extlen_t                    fsbcount = irec->rm_blockcount;
     280             : 
     281             :         /*
     282             :          * Skip corrupt records.  It is essential that we detect records in the
     283             :          * btree that cannot overlap but do, flag those as CORRUPT, and skip
     284             :          * the bitmap comparison to avoid generating false XCORRUPT reports.
     285             :          */
     286   574602771 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     287             :                 return 0;
     288             : 
     289             :         /*
     290             :          * If the AG metadata walk didn't complete, there's no point in
     291             :          * comparing against partial results.
     292             :          */
     293   574602771 :         if (!cr->bitmaps_complete)
     294             :                 return 0;
     295             : 
     296   574602771 :         switch (irec->rm_owner) {
     297      526259 :         case XFS_RMAP_OWN_FS:
     298      526259 :                 bmp = &cr->fs_owned;
     299      526259 :                 break;
     300      107775 :         case XFS_RMAP_OWN_LOG:
     301      107775 :                 bmp = &cr->log_owned;
     302      107775 :                 break;
     303     5818594 :         case XFS_RMAP_OWN_AG:
     304     5818594 :                 bmp = &cr->ag_owned;
     305     5818594 :                 break;
     306      551079 :         case XFS_RMAP_OWN_INOBT:
     307      551079 :                 bmp = &cr->inobt_owned;
     308      551079 :                 break;
     309      595107 :         case XFS_RMAP_OWN_REFC:
     310      595107 :                 bmp = &cr->refcbt_owned;
     311      595107 :                 break;
     312             :         }
     313             : 
     314     7598814 :         if (!bmp)
     315             :                 return 0;
     316             : 
     317     7598814 :         if (xagb_bitmap_test(bmp, irec->rm_startblock, &fsbcount)) {
     318             :                 /*
     319             :                  * The start of this reverse mapping corresponds to a set
     320             :                  * region in the bitmap.  If the mapping covers more area than
     321             :                  * the set region, then it covers space that wasn't found by
     322             :                  * the AG metadata walk.
     323             :                  */
     324     7594893 :                 if (fsbcount < irec->rm_blockcount)
     325           0 :                         xchk_btree_xref_set_corrupt(bs->sc,
     326           0 :                                         bs->sc->sa.rmap_cur, 0);
     327             :         } else {
     328             :                 /*
     329             :                  * The start of this reverse mapping does not correspond to a
     330             :                  * completely set region in the bitmap.  The region wasn't
     331             :                  * fully set by walking the AG metadata, so this is a
     332             :                  * cross-referencing corruption.
     333             :                  */
     334           0 :                 xchk_btree_xref_set_corrupt(bs->sc, bs->sc->sa.rmap_cur, 0);
     335             :         }
     336             : 
     337             :         /* Unset the region so that we can detect missing rmap records. */
     338     7594893 :         return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount);
     339             : }
     340             : 
     341             : /* Scrub an rmapbt record. */
     342             : STATIC int
     343   574102917 : xchk_rmapbt_rec(
     344             :         struct xchk_btree       *bs,
     345             :         const union xfs_btree_rec *rec)
     346             : {
     347   574102917 :         struct xchk_rmap        *cr = bs->private;
     348   574102917 :         struct xfs_rmap_irec    irec;
     349             : 
     350  1147058469 :         if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
     351   573294313 :             xfs_rmap_check_irec(bs->cur, &irec) != NULL) {
     352           1 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     353           1 :                 return 0;
     354             :         }
     355             : 
     356   572969414 :         xchk_rmapbt_check_unwritten_in_keyflags(bs);
     357   573585176 :         xchk_rmapbt_check_mergeable(bs, cr, &irec);
     358   573231678 :         xchk_rmapbt_check_overlapping(bs, cr, &irec);
     359   572457257 :         xchk_rmapbt_xref(bs->sc, &irec);
     360             : 
     361   573847076 :         return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
     362             : }
     363             : 
     364             : /* Add an AGFL block to the rmap list. */
     365             : STATIC int
     366     3203268 : xchk_rmapbt_walk_agfl(
     367             :         struct xfs_mount        *mp,
     368             :         xfs_agblock_t           agbno,
     369             :         void                    *priv)
     370             : {
     371     3203268 :         struct xagb_bitmap      *bitmap = priv;
     372             : 
     373     3203268 :         return xagb_bitmap_set(bitmap, agbno, 1);
     374             : }
     375             : 
     376             : /*
     377             :  * Set up bitmaps mapping all the AG metadata to compare with the rmapbt
     378             :  * records.
     379             :  *
     380             :  * Grab our own btree cursors here if the scrub setup function didn't give us a
     381             :  * btree cursor due to reports of poor health.  We need to find out if the
     382             :  * rmapbt disagrees with primary metadata btrees to tag the rmapbt as being
     383             :  * XCORRUPT.
     384             :  */
     385             : STATIC int
     386      527375 : xchk_rmapbt_walk_ag_metadata(
     387             :         struct xfs_scrub        *sc,
     388             :         struct xchk_rmap        *cr)
     389             : {
     390      527375 :         struct xfs_mount        *mp = sc->mp;
     391      527375 :         struct xfs_buf          *agfl_bp;
     392      527375 :         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
     393      527375 :         struct xfs_btree_cur    *cur;
     394      527375 :         int                     error;
     395             : 
     396             :         /* OWN_FS: AG headers */
     397           0 :         error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp),
     398      527375 :                         XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1);
     399      526604 :         if (error)
     400           0 :                 goto out;
     401             : 
     402             :         /* OWN_LOG: Internal log */
     403      526604 :         if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) {
     404      107775 :                 error = xagb_bitmap_set(&cr->log_owned,
     405      107775 :                                 XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
     406             :                                 mp->m_sb.sb_logblocks);
     407      107775 :                 if (error)
     408           0 :                         goto out;
     409             :         }
     410             : 
     411             :         /* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
     412      526522 :         cur = sc->sa.bno_cur;
     413      526522 :         if (!cur)
     414           0 :                 cur = xfs_allocbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
     415             :                                 sc->sa.pag, XFS_BTNUM_BNO);
     416      526522 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
     417      527126 :         if (cur != sc->sa.bno_cur)
     418           0 :                 xfs_btree_del_cursor(cur, error);
     419      527068 :         if (error)
     420           0 :                 goto out;
     421             : 
     422      527068 :         cur = sc->sa.cnt_cur;
     423      527068 :         if (!cur)
     424           0 :                 cur = xfs_allocbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
     425             :                                 sc->sa.pag, XFS_BTNUM_CNT);
     426      527068 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
     427      526919 :         if (cur != sc->sa.cnt_cur)
     428           0 :                 xfs_btree_del_cursor(cur, error);
     429      526956 :         if (error)
     430           0 :                 goto out;
     431             : 
     432      526956 :         error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
     433      527183 :         if (error)
     434           0 :                 goto out;
     435             : 
     436      527183 :         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
     437      527769 :         if (error)
     438           0 :                 goto out;
     439             : 
     440      527769 :         error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
     441             :                         &cr->ag_owned);
     442      527876 :         xfs_trans_brelse(sc->tp, agfl_bp);
     443      527752 :         if (error)
     444           0 :                 goto out;
     445             : 
     446             :         /* OWN_INOBT: inobt, finobt */
     447      527752 :         cur = sc->sa.ino_cur;
     448      527752 :         if (!cur)
     449           0 :                 cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp,
     450             :                                 XFS_BTNUM_INO);
     451      527752 :         error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
     452      527288 :         if (cur != sc->sa.ino_cur)
     453           0 :                 xfs_btree_del_cursor(cur, error);
     454      526768 :         if (error)
     455           0 :                 goto out;
     456             : 
     457      526768 :         if (xfs_has_finobt(sc->mp)) {
     458      527120 :                 cur = sc->sa.fino_cur;
     459      527120 :                 if (!cur)
     460           0 :                         cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp,
     461             :                                         sc->sa.agi_bp, XFS_BTNUM_FINO);
     462      527120 :                 error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
     463      527280 :                 if (cur != sc->sa.fino_cur)
     464           0 :                         xfs_btree_del_cursor(cur, error);
     465      527280 :                 if (error)
     466           0 :                         goto out;
     467             :         }
     468             : 
     469             :         /* OWN_REFC: refcountbt */
     470      526928 :         if (xfs_has_reflink(sc->mp)) {
     471      526928 :                 cur = sc->sa.refc_cur;
     472      526928 :                 if (!cur)
     473           0 :                         cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp,
     474             :                                         sc->sa.agf_bp, sc->sa.pag);
     475      526928 :                 error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur);
     476      527489 :                 if (cur != sc->sa.refc_cur)
     477           0 :                         xfs_btree_del_cursor(cur, error);
     478      527442 :                 if (error)
     479             :                         goto out;
     480             :         }
     481             : 
     482      527442 : out:
     483             :         /*
     484             :          * If there's an error, set XFAIL and disable the bitmap
     485             :          * cross-referencing checks, but proceed with the scrub anyway.
     486             :          */
     487      527442 :         if (error)
     488           0 :                 xchk_btree_xref_process_error(sc, sc->sa.rmap_cur,
     489           0 :                                 sc->sa.rmap_cur->bc_nlevels - 1, &error);
     490             :         else
     491      527442 :                 cr->bitmaps_complete = true;
     492      527442 :         return 0;
     493             : }
     494             : 
     495             : /*
     496             :  * Check for set regions in the bitmaps; if there are any, the rmap records do
     497             :  * not describe all the AG metadata.
     498             :  */
     499             : STATIC void
     500      527249 : xchk_rmapbt_check_bitmaps(
     501             :         struct xfs_scrub        *sc,
     502             :         struct xchk_rmap        *cr)
     503             : {
     504      527249 :         struct xfs_btree_cur    *cur = sc->sa.rmap_cur;
     505      527249 :         unsigned int            level;
     506             : 
     507      527249 :         if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
     508             :                                 XFS_SCRUB_OFLAG_XFAIL))
     509             :                 return;
     510      527249 :         if (!cur)
     511             :                 return;
     512      527249 :         level = cur->bc_nlevels - 1;
     513             : 
     514             :         /*
     515             :          * Any bitmap with bits still set indicates that the reverse mapping
     516             :          * doesn't cover the entire primary structure.
     517             :          */
     518      527249 :         if (xagb_bitmap_hweight(&cr->fs_owned) != 0)
     519           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     520             : 
     521      526299 :         if (xagb_bitmap_hweight(&cr->log_owned) != 0)
     522           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     523             : 
     524      526498 :         if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
     525           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     526             : 
     527      526537 :         if (xagb_bitmap_hweight(&cr->inobt_owned) != 0)
     528           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     529             : 
     530      526703 :         if (xagb_bitmap_hweight(&cr->refcbt_owned) != 0)
     531           0 :                 xchk_btree_xref_set_corrupt(sc, cur, level);
     532             : }
     533             : 
     534             : /* Scrub the rmap btree for some AG. */
     535             : int
     536      527383 : xchk_rmapbt(
     537             :         struct xfs_scrub        *sc)
     538             : {
     539      527383 :         struct xchk_rmap        *cr;
     540      527383 :         int                     error;
     541             : 
     542      527383 :         cr = kzalloc(sizeof(struct xchk_rmap), XCHK_GFP_FLAGS);
     543      527590 :         if (!cr)
     544             :                 return -ENOMEM;
     545             : 
     546      527590 :         xagb_bitmap_init(&cr->fs_owned);
     547      527323 :         xagb_bitmap_init(&cr->log_owned);
     548      527644 :         xagb_bitmap_init(&cr->ag_owned);
     549      527458 :         xagb_bitmap_init(&cr->inobt_owned);
     550      527453 :         xagb_bitmap_init(&cr->refcbt_owned);
     551             : 
     552      527548 :         error = xchk_rmapbt_walk_ag_metadata(sc, cr);
     553      526732 :         if (error)
     554           0 :                 goto out;
     555             : 
     556      526732 :         error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
     557             :                         &XFS_RMAP_OINFO_AG, cr);
     558      527279 :         if (error)
     559           2 :                 goto out;
     560             : 
     561      527277 :         xchk_rmapbt_check_bitmaps(sc, cr);
     562             : 
     563      527092 : out:
     564      527092 :         xagb_bitmap_destroy(&cr->refcbt_owned);
     565      526644 :         xagb_bitmap_destroy(&cr->inobt_owned);
     566      526636 :         xagb_bitmap_destroy(&cr->ag_owned);
     567      526740 :         xagb_bitmap_destroy(&cr->log_owned);
     568      526773 :         xagb_bitmap_destroy(&cr->fs_owned);
     569      526857 :         kfree(cr);
     570      526857 :         return error;
     571             : }
     572             : 
     573             : /* xref check that the extent is owned only by a given owner */
     574             : void
     575   814090762 : xchk_xref_is_only_owned_by(
     576             :         struct xfs_scrub                *sc,
     577             :         xfs_agblock_t                   bno,
     578             :         xfs_extlen_t                    len,
     579             :         const struct xfs_owner_info     *oinfo)
     580             : {
     581   814090762 :         struct xfs_rmap_matches         res;
     582   814090762 :         int                             error;
     583             : 
     584   814090762 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     585   384357914 :                 return;
     586             : 
     587   429732848 :         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
     588   429865824 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     589             :                 return;
     590   429732328 :         if (res.matches != 1)
     591           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     592   429732328 :         if (res.bad_non_owner_matches)
     593           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     594   429732328 :         if (res.non_owner_matches)
     595           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     596             : }
     597             : 
     598             : /* xref check that the extent is not owned by a given owner */
     599             : void
     600    18656566 : xchk_xref_is_not_owned_by(
     601             :         struct xfs_scrub                *sc,
     602             :         xfs_agblock_t                   bno,
     603             :         xfs_extlen_t                    len,
     604             :         const struct xfs_owner_info     *oinfo)
     605             : {
     606    18656566 :         struct xfs_rmap_matches         res;
     607    18656566 :         int                             error;
     608             : 
     609    18656566 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     610    10204885 :                 return;
     611             : 
     612     8451681 :         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
     613     8451720 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     614             :                 return;
     615     8451690 :         if (res.matches != 0)
     616           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     617     8451690 :         if (res.bad_non_owner_matches)
     618           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     619             : }
     620             : 
     621             : /* xref check that the extent has no reverse mapping at all */
     622             : void
     623   327559374 : xchk_xref_has_no_owner(
     624             :         struct xfs_scrub        *sc,
     625             :         xfs_agblock_t           bno,
     626             :         xfs_extlen_t            len)
     627             : {
     628   327559374 :         enum xbtree_recpacking  outcome;
     629   327559374 :         int                     error;
     630             : 
     631   327559374 :         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
     632     5037487 :                 return;
     633             : 
     634   322521887 :         error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome);
     635   322522505 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
     636             :                 return;
     637   322511144 :         if (outcome != XBTREE_RECPACKING_EMPTY)
     638           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
     639             : }

Generated by: LCOV version 1.14