LCOV - code coverage report
Current view: top level - fs/xfs/scrub - bmap.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 317 402 78.9 %
Date: 2023-07-31 20:08:22 Functions: 21 21 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_trans_resv.h"
      11             : #include "xfs_mount.h"
      12             : #include "xfs_btree.h"
      13             : #include "xfs_bit.h"
      14             : #include "xfs_log_format.h"
      15             : #include "xfs_trans.h"
      16             : #include "xfs_inode.h"
      17             : #include "xfs_alloc.h"
      18             : #include "xfs_bmap.h"
      19             : #include "xfs_bmap_btree.h"
      20             : #include "xfs_rmap.h"
      21             : #include "xfs_rmap_btree.h"
      22             : #include "scrub/scrub.h"
      23             : #include "scrub/common.h"
      24             : #include "scrub/btree.h"
      25             : #include "xfs_ag.h"
      26             : 
      27             : /* Set us up with an inode's bmap. */
      28             : int
      29  1054534192 : xchk_setup_inode_bmap(
      30             :         struct xfs_scrub        *sc)
      31             : {
      32  1054534192 :         int                     error;
      33             : 
      34  1054534192 :         if (xchk_need_intent_drain(sc))
      35           0 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      36             : 
      37  1054534192 :         error = xchk_iget_for_scrubbing(sc);
      38  1055145201 :         if (error)
      39     5297974 :                 goto out;
      40             : 
      41  1049847227 :         sc->ilock_flags = XFS_IOLOCK_EXCL;
      42  1049847227 :         xfs_ilock(sc->ip, XFS_IOLOCK_EXCL);
      43             : 
      44             :         /*
      45             :          * We don't want any ephemeral data/cow fork updates sitting around
      46             :          * while we inspect block mappings, so wait for directio to finish
      47             :          * and flush dirty data if we have delalloc reservations.
      48             :          */
      49  1049137389 :         if (S_ISREG(VFS_I(sc->ip)->i_mode) &&
      50   409798334 :             sc->sm->sm_type != XFS_SCRUB_TYPE_BMBTA) {
      51   263972441 :                 struct address_space    *mapping = VFS_I(sc->ip)->i_mapping;
      52             : 
      53   263972441 :                 sc->ilock_flags |= XFS_MMAPLOCK_EXCL;
      54   263972441 :                 xfs_ilock(sc->ip, XFS_MMAPLOCK_EXCL);
      55             : 
      56   264072049 :                 inode_dio_wait(VFS_I(sc->ip));
      57             : 
      58             :                 /*
      59             :                  * Try to flush all incore state to disk before we examine the
      60             :                  * space mappings for the data fork.  Leave accumulated errors
      61             :                  * in the mapping for the writer threads to consume.
      62             :                  *
      63             :                  * On ENOSPC or EIO writeback errors, we continue into the
      64             :                  * extent mapping checks because write failures do not
      65             :                  * necessarily imply anything about the correctness of the file
      66             :                  * metadata.  The metadata and the file data could be on
      67             :                  * completely separate devices; a media failure might only
      68             :                  * affect a subset of the disk, etc.  We can handle delalloc
      69             :                  * extents in the scrubber, so leaving them in memory is fine.
      70             :                  */
      71   263798089 :                 error = filemap_fdatawrite(mapping);
      72   263767157 :                 if (!error)
      73   263773041 :                         error = filemap_fdatawait_keep_errors(mapping);
      74   263903943 :                 if (error && (error != -ENOSPC && error != -EIO))
      75           0 :                         goto out;
      76             :         }
      77             : 
      78             :         /* Got the inode, lock it and we're ready to go. */
      79  1049068891 :         error = xchk_trans_alloc(sc, 0);
      80  1047665894 :         if (error)
      81           0 :                 goto out;
      82  1047665894 :         sc->ilock_flags |= XFS_ILOCK_EXCL;
      83  1047665894 :         xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
      84             : 
      85  1054421878 : out:
      86             :         /* scrub teardown will unlock and release the inode */
      87  1054421878 :         return error;
      88             : }
      89             : 
      90             : /*
      91             :  * Inode fork block mapping (BMBT) scrubber.
      92             :  * More complex than the others because we have to scrub
      93             :  * all the extents regardless of whether or not the fork
      94             :  * is in btree format.
      95             :  */
      96             : 
      97             : struct xchk_bmap_info {
      98             :         struct xfs_scrub        *sc;
      99             : 
     100             :         /* Incore extent tree cursor */
     101             :         struct xfs_iext_cursor  icur;
     102             : 
     103             :         /* Previous fork mapping that we examined */
     104             :         struct xfs_bmbt_irec    prev_rec;
     105             : 
     106             :         /* Is this a realtime fork? */
     107             :         bool                    is_rt;
     108             : 
     109             :         /* May mappings point to shared space? */
     110             :         bool                    is_shared;
     111             : 
     112             :         /* Was the incore extent tree loaded? */
     113             :         bool                    was_loaded;
     114             : 
     115             :         /* Which inode fork are we checking? */
     116             :         int                     whichfork;
     117             : };
     118             : 
     119             : /* Look for a corresponding rmap for this irec. */
     120             : static inline bool
     121   258066803 : xchk_bmap_get_rmap(
     122             :         struct xchk_bmap_info   *info,
     123             :         struct xfs_bmbt_irec    *irec,
     124             :         xfs_agblock_t           agbno,
     125             :         uint64_t                owner,
     126             :         struct xfs_rmap_irec    *rmap)
     127             : {
     128   258066803 :         xfs_fileoff_t           offset;
     129   258066803 :         unsigned int            rflags = 0;
     130   258066803 :         int                     has_rmap;
     131   258066803 :         int                     error;
     132             : 
     133   258066803 :         if (info->whichfork == XFS_ATTR_FORK)
     134      557848 :                 rflags |= XFS_RMAP_ATTR_FORK;
     135   258066803 :         if (irec->br_state == XFS_EXT_UNWRITTEN)
     136    22429251 :                 rflags |= XFS_RMAP_UNWRITTEN;
     137             : 
     138             :         /*
     139             :          * CoW staging extents are owned (on disk) by the refcountbt, so
     140             :          * their rmaps do not have offsets.
     141             :          */
     142   258066803 :         if (info->whichfork == XFS_COW_FORK)
     143             :                 offset = 0;
     144             :         else
     145   255825007 :                 offset = irec->br_startoff;
     146             : 
     147             :         /*
     148             :          * If the caller thinks this could be a shared bmbt extent (IOWs,
     149             :          * any data fork extent of a reflink inode) then we have to use the
     150             :          * range rmap lookup to make sure we get the correct owner/offset.
     151             :          */
     152   258066803 :         if (info->is_shared) {
     153   117769344 :                 error = xfs_rmap_lookup_le_range(info->sc->sa.rmap_cur, agbno,
     154             :                                 owner, offset, rflags, rmap, &has_rmap);
     155             :         } else {
     156   140297459 :                 error = xfs_rmap_lookup_le(info->sc->sa.rmap_cur, agbno,
     157             :                                 owner, offset, rflags, rmap, &has_rmap);
     158             :         }
     159   258066005 :         if (!xchk_should_check_xref(info->sc, &error, &info->sc->sa.rmap_cur))
     160             :                 return false;
     161             : 
     162   258028298 :         if (!has_rmap)
     163           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     164             :                         irec->br_startoff);
     165   258028298 :         return has_rmap;
     166             : }
     167             : 
     168             : /* Make sure that we have rmapbt records for this data/attr fork extent. */
     169             : STATIC void
     170   277018561 : xchk_bmap_xref_rmap(
     171             :         struct xchk_bmap_info   *info,
     172             :         struct xfs_bmbt_irec    *irec,
     173             :         xfs_agblock_t           agbno)
     174             : {
     175   277018561 :         struct xfs_rmap_irec    rmap;
     176   277018561 :         unsigned long long      rmap_end;
     177   277018561 :         uint64_t                owner = info->sc->ip->i_ino;
     178             : 
     179   277018561 :         if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
     180    21188835 :                 return;
     181             : 
     182             :         /* Find the rmap record for this irec. */
     183   255829726 :         if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap))
     184             :                 return;
     185             : 
     186             :         /*
     187             :          * The rmap must be an exact match for this incore file mapping record,
     188             :          * which may have arisen from multiple ondisk records.
     189             :          */
     190   255804756 :         if (rmap.rm_startblock != agbno)
     191           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     192             :                                 irec->br_startoff);
     193             : 
     194   255804756 :         rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
     195   255804756 :         if (rmap_end != agbno + irec->br_blockcount)
     196           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     197             :                                 irec->br_startoff);
     198             : 
     199             :         /* Check the logical offsets. */
     200   255804756 :         if (rmap.rm_offset != irec->br_startoff)
     201           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     202             :                                 irec->br_startoff);
     203             : 
     204   255804756 :         rmap_end = (unsigned long long)rmap.rm_offset + rmap.rm_blockcount;
     205   255804756 :         if (rmap_end != irec->br_startoff + irec->br_blockcount)
     206           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     207             :                                 irec->br_startoff);
     208             : 
     209             :         /* Check the owner */
     210   255804756 :         if (rmap.rm_owner != owner)
     211           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     212             :                                 irec->br_startoff);
     213             : 
     214             :         /*
     215             :          * Check for discrepancies between the unwritten flag in the irec and
     216             :          * the rmap.  Note that the (in-memory) CoW fork distinguishes between
     217             :          * unwritten and written extents, but we don't track that in the rmap
     218             :          * records because the blocks are owned (on-disk) by the refcountbt,
     219             :          * which doesn't track unwritten state.
     220             :          */
     221   255804756 :         if (!!(irec->br_state == XFS_EXT_UNWRITTEN) !=
     222   255804756 :             !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN))
     223           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     224             :                                 irec->br_startoff);
     225             : 
     226   255804756 :         if (!!(info->whichfork == XFS_ATTR_FORK) !=
     227   255804756 :             !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK))
     228           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     229             :                                 irec->br_startoff);
     230   255804756 :         if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
     231           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     232             :                                 irec->br_startoff);
     233             : }
     234             : 
     235             : /* Make sure that we have rmapbt records for this COW fork extent. */
     236             : STATIC void
     237     2251711 : xchk_bmap_xref_rmap_cow(
     238             :         struct xchk_bmap_info   *info,
     239             :         struct xfs_bmbt_irec    *irec,
     240             :         xfs_agblock_t           agbno)
     241             : {
     242     2251711 :         struct xfs_rmap_irec    rmap;
     243     2251711 :         unsigned long long      rmap_end;
     244     2251711 :         uint64_t                owner = XFS_RMAP_OWN_COW;
     245             : 
     246     2251711 :         if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
     247           0 :                 return;
     248             : 
     249             :         /* Find the rmap record for this irec. */
     250     2251711 :         if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap))
     251             :                 return;
     252             : 
     253             :         /*
     254             :          * CoW staging extents are owned by the refcount btree, so the rmap
     255             :          * can start before and end after the physical space allocated to this
     256             :          * mapping.  There are no offsets to check.
     257             :          */
     258     2251562 :         if (rmap.rm_startblock > agbno)
     259           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     260             :                                 irec->br_startoff);
     261             : 
     262     2251562 :         rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
     263     2251562 :         if (rmap_end < agbno + irec->br_blockcount)
     264           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     265             :                                 irec->br_startoff);
     266             : 
     267             :         /* Check the owner */
     268     2251562 :         if (rmap.rm_owner != owner)
     269           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     270             :                                 irec->br_startoff);
     271             : 
     272             :         /*
     273             :          * No flags allowed.  Note that the (in-memory) CoW fork distinguishes
     274             :          * between unwritten and written extents, but we don't track that in
     275             :          * the rmap records because the blocks are owned (on-disk) by the
     276             :          * refcountbt, which doesn't track unwritten state.
     277             :          */
     278     2251562 :         if (rmap.rm_flags & XFS_RMAP_ATTR_FORK)
     279           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     280             :                                 irec->br_startoff);
     281     2251562 :         if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
     282           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     283             :                                 irec->br_startoff);
     284     2251562 :         if (rmap.rm_flags & XFS_RMAP_UNWRITTEN)
     285           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     286             :                                 irec->br_startoff);
     287             : }
     288             : 
     289             : /* Cross-reference a single rtdev extent record. */
     290             : STATIC void
     291   263353786 : xchk_bmap_rt_iextent_xref(
     292             :         struct xfs_inode        *ip,
     293             :         struct xchk_bmap_info   *info,
     294             :         struct xfs_bmbt_irec    *irec)
     295             : {
     296   263353786 :         xchk_xref_is_used_rt_space(info->sc, irec->br_startblock,
     297   263353786 :                         irec->br_blockcount);
     298   263444099 : }
     299             : 
     300             : /* Cross-reference a single datadev extent record. */
     301             : STATIC void
     302   279229524 : xchk_bmap_iextent_xref(
     303             :         struct xfs_inode        *ip,
     304             :         struct xchk_bmap_info   *info,
     305             :         struct xfs_bmbt_irec    *irec)
     306             : {
     307   279229524 :         struct xfs_owner_info   oinfo;
     308   279229524 :         struct xfs_mount        *mp = info->sc->mp;
     309   279229524 :         xfs_agnumber_t          agno;
     310   279229524 :         xfs_agblock_t           agbno;
     311   279229524 :         xfs_extlen_t            len;
     312   279229524 :         int                     error;
     313             : 
     314   279229524 :         agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
     315   279229524 :         agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
     316   279217267 :         len = irec->br_blockcount;
     317             : 
     318   279217267 :         error = xchk_ag_init_existing(info->sc, agno, &info->sc->sa);
     319   279297511 :         if (!xchk_fblock_process_error(info->sc, info->whichfork,
     320             :                         irec->br_startoff, &error))
     321           0 :                 goto out_free;
     322             : 
     323   279228704 :         xchk_xref_is_used_space(info->sc, agbno, len);
     324   279213013 :         xchk_xref_is_not_inode_chunk(info->sc, agbno, len);
     325   279300410 :         switch (info->whichfork) {
     326   275611838 :         case XFS_DATA_FORK:
     327   275611838 :                 xchk_bmap_xref_rmap(info, irec, agbno);
     328   275554755 :                 if (!xfs_is_reflink_inode(info->sc->ip)) {
     329   157780619 :                         xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
     330             :                                         info->whichfork, irec->br_startoff);
     331   157780619 :                         xchk_xref_is_only_owned_by(info->sc, agbno,
     332   157780619 :                                         irec->br_blockcount, &oinfo);
     333   157820100 :                         xchk_xref_is_not_shared(info->sc, agbno,
     334   157820100 :                                         irec->br_blockcount);
     335             :                 }
     336   275590695 :                 xchk_xref_is_not_cow_staging(info->sc, agbno,
     337   275590695 :                                 irec->br_blockcount);
     338   275590695 :                 break;
     339     1436666 :         case XFS_ATTR_FORK:
     340     1436666 :                 xchk_bmap_xref_rmap(info, irec, agbno);
     341     1434124 :                 xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
     342             :                                 info->whichfork, irec->br_startoff);
     343     1434124 :                 xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
     344             :                                 &oinfo);
     345     1434792 :                 xchk_xref_is_not_shared(info->sc, agbno,
     346     1434792 :                                 irec->br_blockcount);
     347     1434692 :                 xchk_xref_is_not_cow_staging(info->sc, agbno,
     348     1434692 :                                 irec->br_blockcount);
     349     1434692 :                 break;
     350     2251906 :         case XFS_COW_FORK:
     351     2251906 :                 xchk_bmap_xref_rmap_cow(info, irec, agbno);
     352     2251631 :                 xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
     353             :                                 &XFS_RMAP_OINFO_COW);
     354     2251879 :                 xchk_xref_is_cow_staging(info->sc, agbno,
     355     2251879 :                                 irec->br_blockcount);
     356     2251858 :                 xchk_xref_is_not_shared(info->sc, agbno,
     357     2251858 :                                 irec->br_blockcount);
     358     2251858 :                 break;
     359             :         }
     360             : 
     361   279264555 : out_free:
     362   279264555 :         xchk_ag_free(info->sc, &info->sc->sa);
     363   279322680 : }
     364             : 
     365             : /*
     366             :  * Directories and attr forks should never have blocks that can't be addressed
     367             :  * by a xfs_dablk_t.
     368             :  */
     369             : STATIC void
     370   542454345 : xchk_bmap_dirattr_extent(
     371             :         struct xfs_inode        *ip,
     372             :         struct xchk_bmap_info   *info,
     373             :         struct xfs_bmbt_irec    *irec)
     374             : {
     375   542454345 :         struct xfs_mount        *mp = ip->i_mount;
     376   542454345 :         xfs_fileoff_t           off;
     377             : 
     378   542454345 :         if (!S_ISDIR(VFS_I(ip)->i_mode) && info->whichfork != XFS_ATTR_FORK)
     379             :                 return;
     380             : 
     381     2660780 :         if (!xfs_verify_dablk(mp, irec->br_startoff))
     382           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     383             :                                 irec->br_startoff);
     384             : 
     385     2657620 :         off = irec->br_startoff + irec->br_blockcount - 1;
     386     2657620 :         if (!xfs_verify_dablk(mp, off))
     387           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork, off);
     388             : }
     389             : 
     390             : /* Scrub a single extent record. */
     391             : STATIC void
     392   542532201 : xchk_bmap_iextent(
     393             :         struct xfs_inode        *ip,
     394             :         struct xchk_bmap_info   *info,
     395             :         struct xfs_bmbt_irec    *irec)
     396             : {
     397   542532201 :         struct xfs_mount        *mp = info->sc->mp;
     398             : 
     399             :         /*
     400             :          * Check for out-of-order extents.  This record could have come
     401             :          * from the incore list, for which there is no ordering check.
     402             :          */
     403   542532201 :         if (irec->br_startoff < info->prev_rec.br_startoff +
     404   542532201 :                                 info->prev_rec.br_blockcount)
     405           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     406             :                                 irec->br_startoff);
     407             : 
     408   542532201 :         if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
     409           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     410             :                                 irec->br_startoff);
     411             : 
     412   542448538 :         xchk_bmap_dirattr_extent(ip, info, irec);
     413             : 
     414             :         /* Make sure the extent points to a valid place. */
     415   805880607 :         if (info->is_rt &&
     416   263297557 :             !xfs_verify_rtext(mp, irec->br_startblock, irec->br_blockcount))
     417           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     418             :                                 irec->br_startoff);
     419   821822568 :         if (!info->is_rt &&
     420   279212193 :             !xfs_verify_fsbext(mp, irec->br_startblock, irec->br_blockcount))
     421           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     422             :                                 irec->br_startoff);
     423             : 
     424             :         /* We don't allow unwritten extents on attr forks. */
     425   542610375 :         if (irec->br_state == XFS_EXT_UNWRITTEN &&
     426    93531568 :             info->whichfork == XFS_ATTR_FORK)
     427           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     428             :                                 irec->br_startoff);
     429             : 
     430   542610375 :         if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     431             :                 return;
     432             : 
     433   542610375 :         if (info->is_rt)
     434   263360055 :                 xchk_bmap_rt_iextent_xref(ip, info, irec);
     435             :         else
     436   279250320 :                 xchk_bmap_iextent_xref(ip, info, irec);
     437             : }
     438             : 
     439             : /* Scrub a bmbt record. */
     440             : STATIC int
     441   304068556 : xchk_bmapbt_rec(
     442             :         struct xchk_btree       *bs,
     443             :         const union xfs_btree_rec *rec)
     444             : {
     445   304068556 :         struct xfs_bmbt_irec    irec;
     446   304068556 :         struct xfs_bmbt_irec    iext_irec;
     447   304068556 :         struct xfs_iext_cursor  icur;
     448   304068556 :         struct xchk_bmap_info   *info = bs->private;
     449   304068556 :         struct xfs_inode        *ip = bs->cur->bc_ino.ip;
     450   304068556 :         struct xfs_buf          *bp = NULL;
     451   304068556 :         struct xfs_btree_block  *block;
     452   304068556 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, info->whichfork);
     453   304065494 :         uint64_t                owner;
     454   304065494 :         int                     i;
     455             : 
     456             :         /*
     457             :          * Check the owners of the btree blocks up to the level below
     458             :          * the root since the verifiers don't do that.
     459             :          */
     460   304065494 :         if (xfs_has_crc(bs->cur->bc_mp) &&
     461   304066528 :             bs->cur->bc_levels[0].ptr == 1) {
     462    10242981 :                 for (i = 0; i < bs->cur->bc_nlevels - 1; i++) {
     463     5470022 :                         block = xfs_btree_get_block(bs->cur, i, &bp);
     464     5470189 :                         owner = be64_to_cpu(block->bb_u.l.bb_owner);
     465     5470189 :                         if (owner != ip->i_ino)
     466           0 :                                 xchk_fblock_set_corrupt(bs->sc,
     467             :                                                 info->whichfork, 0);
     468             :                 }
     469             :         }
     470             : 
     471             :         /*
     472             :          * Check that the incore extent tree contains an extent that matches
     473             :          * this one exactly.  We validate those cached bmaps later, so we don't
     474             :          * need to check them here.  If the incore extent tree was just loaded
     475             :          * from disk by the scrubber, we assume that its contents match what's
     476             :          * on disk (we still hold the ILOCK) and skip the equivalence check.
     477             :          */
     478   304065661 :         if (!info->was_loaded)
     479             :                 return 0;
     480             : 
     481   301752061 :         xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
     482   301751710 :         if (xfs_bmap_validate_extent(ip, info->whichfork, &irec) != NULL) {
     483           0 :                 xchk_fblock_set_corrupt(bs->sc, info->whichfork,
     484             :                                 irec.br_startoff);
     485           0 :                 return 0;
     486             :         }
     487             : 
     488   301752585 :         if (!xfs_iext_lookup_extent(ip, ifp, irec.br_startoff, &icur,
     489   301773532 :                                 &iext_irec) ||
     490   301773532 :             irec.br_startoff != iext_irec.br_startoff ||
     491   301776880 :             irec.br_startblock != iext_irec.br_startblock ||
     492   301777842 :             irec.br_blockcount != iext_irec.br_blockcount ||
     493   301778169 :             irec.br_state != iext_irec.br_state)
     494           0 :                 xchk_fblock_set_corrupt(bs->sc, info->whichfork,
     495             :                                 irec.br_startoff);
     496             :         return 0;
     497             : }
     498             : 
     499             : /* Scan the btree records. */
     500             : STATIC int
     501     3984524 : xchk_bmap_btree(
     502             :         struct xfs_scrub        *sc,
     503             :         int                     whichfork,
     504             :         struct xchk_bmap_info   *info)
     505             : {
     506     3984524 :         struct xfs_owner_info   oinfo;
     507     3984524 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(sc->ip, whichfork);
     508     3984124 :         struct xfs_mount        *mp = sc->mp;
     509     3984124 :         struct xfs_inode        *ip = sc->ip;
     510     3984124 :         struct xfs_btree_cur    *cur;
     511     3984124 :         int                     error;
     512             : 
     513             :         /* Load the incore bmap cache if it's not loaded. */
     514     3984124 :         info->was_loaded = !xfs_need_iread_extents(ifp);
     515             : 
     516     3984136 :         error = xfs_iread_extents(sc->tp, ip, whichfork);
     517     3984461 :         if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
     518           0 :                 goto out;
     519             : 
     520             :         /* Check the btree structure. */
     521     3984395 :         cur = xfs_bmbt_init_cursor(mp, sc->tp, ip, whichfork);
     522     3985145 :         xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
     523     3985145 :         error = xchk_btree(sc, cur, xchk_bmapbt_rec, &oinfo, info);
     524     3985278 :         xfs_btree_del_cursor(cur, error);
     525     3985286 : out:
     526     3985286 :         return error;
     527             : }
     528             : 
     529             : struct xchk_bmap_check_rmap_info {
     530             :         struct xfs_scrub        *sc;
     531             :         int                     whichfork;
     532             :         struct xfs_iext_cursor  icur;
     533             : };
     534             : 
     535             : /* Can we find bmaps that fit this rmap? */
     536             : STATIC int
     537 35119627545 : xchk_bmap_check_rmap(
     538             :         struct xfs_btree_cur            *cur,
     539             :         const struct xfs_rmap_irec      *rec,
     540             :         void                            *priv)
     541             : {
     542 35119627545 :         struct xfs_bmbt_irec            irec;
     543 35119627545 :         struct xfs_rmap_irec            check_rec;
     544 35119627545 :         struct xchk_bmap_check_rmap_info        *sbcri = priv;
     545 35119627545 :         struct xfs_ifork                *ifp;
     546 35119627545 :         struct xfs_scrub                *sc = sbcri->sc;
     547 35119627545 :         bool                            have_map;
     548             : 
     549             :         /* Is this even the right fork? */
     550 35119627545 :         if (rec->rm_owner != sc->ip->i_ino)
     551             :                 return 0;
     552      334065 :         if ((sbcri->whichfork == XFS_ATTR_FORK) ^
     553      334065 :             !!(rec->rm_flags & XFS_RMAP_ATTR_FORK))
     554             :                 return 0;
     555           0 :         if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
     556             :                 return 0;
     557             : 
     558             :         /* Now look up the bmbt record. */
     559           0 :         ifp = xfs_ifork_ptr(sc->ip, sbcri->whichfork);
     560           0 :         if (!ifp) {
     561           0 :                 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     562           0 :                                 rec->rm_offset);
     563           0 :                 goto out;
     564             :         }
     565           0 :         have_map = xfs_iext_lookup_extent(sc->ip, ifp, rec->rm_offset,
     566             :                         &sbcri->icur, &irec);
     567           0 :         if (!have_map)
     568           0 :                 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     569           0 :                                 rec->rm_offset);
     570             :         /*
     571             :          * bmap extent record lengths are constrained to 2^21 blocks in length
     572             :          * because of space constraints in the on-disk metadata structure.
     573             :          * However, rmap extent record lengths are constrained only by AG
     574             :          * length, so we have to loop through the bmbt to make sure that the
     575             :          * entire rmap is covered by bmbt records.
     576             :          */
     577           0 :         check_rec = *rec;
     578           0 :         while (have_map) {
     579           0 :                 if (irec.br_startoff != check_rec.rm_offset)
     580           0 :                         xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     581             :                                         check_rec.rm_offset);
     582           0 :                 if (irec.br_startblock != XFS_AGB_TO_FSB(sc->mp,
     583             :                                 cur->bc_ag.pag->pag_agno,
     584             :                                 check_rec.rm_startblock))
     585           0 :                         xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     586             :                                         check_rec.rm_offset);
     587           0 :                 if (irec.br_blockcount > check_rec.rm_blockcount)
     588           0 :                         xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     589             :                                         check_rec.rm_offset);
     590           0 :                 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     591             :                         break;
     592           0 :                 check_rec.rm_startblock += irec.br_blockcount;
     593           0 :                 check_rec.rm_offset += irec.br_blockcount;
     594           0 :                 check_rec.rm_blockcount -= irec.br_blockcount;
     595           0 :                 if (check_rec.rm_blockcount == 0)
     596             :                         break;
     597           0 :                 have_map = xfs_iext_next_extent(ifp, &sbcri->icur, &irec);
     598           0 :                 if (!have_map)
     599           0 :                         xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     600             :                                         check_rec.rm_offset);
     601             :         }
     602             : 
     603           0 : out:
     604           0 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     605           0 :                 return -ECANCELED;
     606             :         return 0;
     607             : }
     608             : 
     609             : /* Make sure each rmap has a corresponding bmbt entry. */
     610             : STATIC int
     611     1775500 : xchk_bmap_check_ag_rmaps(
     612             :         struct xfs_scrub                *sc,
     613             :         int                             whichfork,
     614             :         struct xfs_perag                *pag)
     615             : {
     616     1775500 :         struct xchk_bmap_check_rmap_info        sbcri;
     617     1775500 :         struct xfs_btree_cur            *cur;
     618     1775500 :         struct xfs_buf                  *agf;
     619     1775500 :         int                             error;
     620             : 
     621     1775500 :         error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf);
     622     1775501 :         if (error)
     623             :                 return error;
     624             : 
     625     1775503 :         cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf, pag);
     626             : 
     627     1775520 :         sbcri.sc = sc;
     628     1775520 :         sbcri.whichfork = whichfork;
     629     1775520 :         error = xfs_rmap_query_all(cur, xchk_bmap_check_rmap, &sbcri);
     630     1775511 :         if (error == -ECANCELED)
     631           0 :                 error = 0;
     632             : 
     633     1775511 :         xfs_btree_del_cursor(cur, error);
     634     1775518 :         xfs_trans_brelse(sc->tp, agf);
     635     1775518 :         return error;
     636             : }
     637             : 
     638             : /*
     639             :  * Decide if we want to walk every rmap btree in the fs to make sure that each
     640             :  * rmap for this file fork has corresponding bmbt entries.
     641             :  */
     642             : static bool
     643   183666888 : xchk_bmap_want_check_rmaps(
     644             :         struct xchk_bmap_info   *info)
     645             : {
     646   183666888 :         struct xfs_scrub        *sc = info->sc;
     647   183666888 :         struct xfs_ifork        *ifp;
     648             : 
     649   183666888 :         if (!xfs_has_rmapbt(sc->mp))
     650             :                 return false;
     651    82916525 :         if (info->whichfork == XFS_COW_FORK)
     652             :                 return false;
     653    75871297 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     654             :                 return false;
     655             : 
     656             :         /* Don't support realtime rmap checks yet. */
     657    75871297 :         if (info->is_rt)
     658             :                 return false;
     659             : 
     660             :         /*
     661             :          * The inode repair code zaps broken inode forks by resetting them back
     662             :          * to EXTENTS format and zero extent records.  If we encounter a fork
     663             :          * in this state along with evidence that the fork isn't supposed to be
     664             :          * empty, we need to scan the reverse mappings to decide if we're going
     665             :          * to rebuild the fork.  Data forks with nonzero file size are scanned.
     666             :          * xattr forks are never empty of content, so they are always scanned.
     667             :          */
     668    75856199 :         ifp = xfs_ifork_ptr(sc->ip, info->whichfork);
     669    75849758 :         if (ifp->if_format == XFS_DINODE_FMT_EXTENTS && ifp->if_nextents == 0) {
     670    44391279 :                 if (info->whichfork == XFS_DATA_FORK &&
     671    44353177 :                     i_size_read(VFS_I(sc->ip)) == 0)
     672             :                         return false;
     673             : 
     674      365670 :                 return true;
     675             :         }
     676             : 
     677             :         return false;
     678             : }
     679             : 
     680             : /* Make sure each rmap has a corresponding bmbt entry. */
     681             : STATIC int
     682      365670 : xchk_bmap_check_rmaps(
     683             :         struct xfs_scrub        *sc,
     684             :         int                     whichfork)
     685             : {
     686      365670 :         struct xfs_perag        *pag;
     687      365670 :         xfs_agnumber_t          agno;
     688      365670 :         int                     error;
     689             : 
     690     2141189 :         for_each_perag(sc->mp, agno, pag) {
     691     1775506 :                 error = xchk_bmap_check_ag_rmaps(sc, whichfork, pag);
     692     1775519 :                 if (error ||
     693     1775519 :                     (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
     694           0 :                         xfs_perag_rele(pag);
     695           0 :                         return error;
     696             :                 }
     697             :         }
     698             : 
     699             :         return 0;
     700             : }
     701             : 
     702             : /* Scrub a delalloc reservation from the incore extent map tree. */
     703             : STATIC void
     704        1023 : xchk_bmap_iextent_delalloc(
     705             :         struct xfs_inode        *ip,
     706             :         struct xchk_bmap_info   *info,
     707             :         struct xfs_bmbt_irec    *irec)
     708             : {
     709        1023 :         struct xfs_mount        *mp = info->sc->mp;
     710             : 
     711             :         /*
     712             :          * Check for out-of-order extents.  This record could have come
     713             :          * from the incore list, for which there is no ordering check.
     714             :          */
     715        1023 :         if (irec->br_startoff < info->prev_rec.br_startoff +
     716        1023 :                                 info->prev_rec.br_blockcount)
     717           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     718             :                                 irec->br_startoff);
     719             : 
     720        1023 :         if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
     721           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     722             :                                 irec->br_startoff);
     723             : 
     724             :         /* Make sure the extent points to a valid place. */
     725        1023 :         if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN)
     726           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     727             :                                 irec->br_startoff);
     728        1023 : }
     729             : 
     730             : /* Decide if this individual fork mapping is ok. */
     731             : static bool
     732             : xchk_bmap_iext_mapping(
     733             :         struct xchk_bmap_info           *info,
     734             :         const struct xfs_bmbt_irec      *irec)
     735             : {
     736             :         /* There should never be a "hole" extent in either extent list. */
     737   542625296 :         if (irec->br_startblock == HOLESTARTBLOCK)
     738             :                 return false;
     739   542625296 :         if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN)
     740             :                 return false;
     741             :         return true;
     742             : }
     743             : 
     744             : /* Are these two mappings contiguous with each other? */
     745             : static inline bool
     746   456772375 : xchk_are_bmaps_contiguous(
     747             :         const struct xfs_bmbt_irec      *b1,
     748             :         const struct xfs_bmbt_irec      *b2)
     749             : {
     750             :         /* Don't try to combine unallocated mappings. */
     751   913547455 :         if (!xfs_bmap_is_real_extent(b1))
     752             :                 return false;
     753   913523716 :         if (!xfs_bmap_is_real_extent(b2))
     754             :                 return false;
     755             : 
     756             :         /* Does b2 come right after b1 in the logical and physical range? */
     757   456771504 :         if (b1->br_startoff + b1->br_blockcount != b2->br_startoff)
     758             :                 return false;
     759   187631177 :         if (b1->br_startblock + b1->br_blockcount != b2->br_startblock)
     760             :                 return false;
     761    41579649 :         if (b1->br_state != b2->br_state)
     762    41580369 :                 return false;
     763             :         return true;
     764             : }
     765             : 
     766             : /*
     767             :  * Walk the incore extent records, accumulating consecutive contiguous records
     768             :  * into a single incore mapping.  Returns true if @irec has been set to a
     769             :  * mapping or false if there are no more mappings.  Caller must ensure that
     770             :  * @info.icur is zeroed before the first call.
     771             :  */
     772             : static bool
     773   726184556 : xchk_bmap_iext_iter(
     774             :         struct xchk_bmap_info   *info,
     775             :         struct xfs_bmbt_irec    *irec)
     776             : {
     777   726184556 :         struct xfs_bmbt_irec    got;
     778   726184556 :         struct xfs_ifork        *ifp;
     779   726184556 :         unsigned int            nr = 0;
     780             : 
     781   726184556 :         ifp = xfs_ifork_ptr(info->sc->ip, info->whichfork);
     782             : 
     783             :         /* Advance to the next iextent record and check the mapping. */
     784   725790180 :         xfs_iext_next(ifp, &info->icur);
     785   725909853 :         if (!xfs_iext_get_extent(ifp, &info->icur, irec))
     786             :                 return false;
     787             : 
     788   542625162 :         if (!xchk_bmap_iext_mapping(info, irec)) {
     789           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     790             :                                 irec->br_startoff);
     791           0 :                 return false;
     792             :         }
     793             :         nr++;
     794             : 
     795             :         /*
     796             :          * Iterate subsequent iextent records and merge them with the one
     797             :          * that we just read, if possible.
     798             :          */
     799   542625296 :         while (xfs_iext_peek_next_extent(ifp, &info->icur, &got)) {
     800   456654832 :                 if (!xchk_are_bmaps_contiguous(irec, &got))
     801             :                         break;
     802             : 
     803         134 :                 if (!xchk_bmap_iext_mapping(info, &got)) {
     804           0 :                         xchk_fblock_set_corrupt(info->sc, info->whichfork,
     805             :                                         got.br_startoff);
     806           0 :                         return false;
     807             :                 }
     808         134 :                 nr++;
     809             : 
     810         134 :                 irec->br_blockcount += got.br_blockcount;
     811         134 :                 xfs_iext_next(ifp, &info->icur);
     812             :         }
     813             : 
     814             :         /*
     815             :          * If the merged mapping could be expressed with fewer bmbt records
     816             :          * than we actually found, notify the user that this fork could be
     817             :          * optimized.  CoW forks only exist in memory so we ignore them.
     818             :          */
     819   542425404 :         if (nr > 1 && info->whichfork != XFS_COW_FORK &&
     820          87 :             howmany_64(irec->br_blockcount, XFS_MAX_BMBT_EXTLEN) < nr)
     821           0 :                 xchk_ino_set_preen(info->sc, info->sc->ip->i_ino);
     822             : 
     823             :         return true;
     824             : }
     825             : 
     826             : /*
     827             :  * Scrub an inode fork's block mappings.
     828             :  *
     829             :  * First we scan every record in every btree block, if applicable.
     830             :  * Then we unconditionally scan the incore extent cache.
     831             :  */
     832             : STATIC int
     833   763325591 : xchk_bmap(
     834             :         struct xfs_scrub        *sc,
     835             :         int                     whichfork)
     836             : {
     837   763325591 :         struct xfs_bmbt_irec    irec;
     838   763325591 :         struct xchk_bmap_info   info = { NULL };
     839   763325591 :         struct xfs_mount        *mp = sc->mp;
     840   763325591 :         struct xfs_inode        *ip = sc->ip;
     841   763325591 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     842   764115636 :         xfs_fileoff_t           endoff;
     843   764115636 :         int                     error = 0;
     844             : 
     845             :         /* Non-existent forks can be ignored. */
     846   764115636 :         if (!ifp)
     847   358575095 :                 goto out;
     848             : 
     849   405540541 :         info.is_rt = whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip);
     850   405540541 :         info.whichfork = whichfork;
     851   405540541 :         info.is_shared = whichfork == XFS_DATA_FORK && xfs_is_reflink_inode(ip);
     852   405540541 :         info.sc = sc;
     853             : 
     854   405540541 :         switch (whichfork) {
     855             :         case XFS_COW_FORK:
     856             :                 /* No CoW forks on non-reflink inodes/filesystems. */
     857     7045852 :                 if (!xfs_is_reflink_inode(ip)) {
     858           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     859           0 :                         goto out;
     860             :                 }
     861             :                 break;
     862             :         case XFS_ATTR_FORK:
     863    18905600 :                 if (!xfs_has_attr(mp) && !xfs_has_attr2(mp))
     864           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     865             :                 break;
     866   379589089 :         default:
     867   379589089 :                 ASSERT(whichfork == XFS_DATA_FORK);
     868             :                 break;
     869             :         }
     870             : 
     871             :         /* Check the fork values */
     872   405540541 :         switch (ifp->if_format) {
     873   221920234 :         case XFS_DINODE_FMT_UUID:
     874             :         case XFS_DINODE_FMT_DEV:
     875             :         case XFS_DINODE_FMT_LOCAL:
     876             :                 /* No mappings to check. */
     877   221920234 :                 if (whichfork == XFS_COW_FORK)
     878           0 :                         xchk_fblock_set_corrupt(sc, whichfork, 0);
     879   221920234 :                 goto out;
     880             :         case XFS_DINODE_FMT_EXTENTS:
     881             :                 break;
     882     3984566 :         case XFS_DINODE_FMT_BTREE:
     883     3984566 :                 if (whichfork == XFS_COW_FORK) {
     884           0 :                         xchk_fblock_set_corrupt(sc, whichfork, 0);
     885           0 :                         goto out;
     886             :                 }
     887             : 
     888     3984566 :                 error = xchk_bmap_btree(sc, whichfork, &info);
     889     3985233 :                 if (error)
     890           4 :                         goto out;
     891             :                 break;
     892           0 :         default:
     893           0 :                 xchk_fblock_set_corrupt(sc, whichfork, 0);
     894           0 :                 goto out;
     895             :         }
     896             : 
     897   183620970 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     898           0 :                 goto out;
     899             : 
     900             :         /* Find the offset of the last extent in the mapping. */
     901   183620970 :         error = xfs_bmap_last_offset(ip, &endoff, whichfork);
     902   183613511 :         if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
     903           0 :                 goto out;
     904             : 
     905             :         /*
     906             :          * Scrub extent records.  We use a special iterator function here that
     907             :          * combines adjacent mappings if they are logically and physically
     908             :          * contiguous.   For large allocations that require multiple bmbt
     909             :          * records, this reduces the number of cross-referencing calls, which
     910             :          * reduces runtime.  Cross referencing with the rmap is simpler because
     911             :          * the rmap must match the combined mapping exactly.
     912             :          */
     913   726389346 :         while (xchk_bmap_iext_iter(&info, &irec)) {
     914   542408415 :                 if (xchk_should_terminate(sc, &error) ||
     915   542442510 :                     (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
     916          40 :                         goto out;
     917             : 
     918   542442510 :                 if (irec.br_startoff >= endoff) {
     919           0 :                         xchk_fblock_set_corrupt(sc, whichfork,
     920             :                                         irec.br_startoff);
     921           0 :                         goto out;
     922             :                 }
     923             : 
     924   542442510 :                 if (isnullstartblock(irec.br_startblock))
     925        1023 :                         xchk_bmap_iextent_delalloc(ip, &info, &irec);
     926             :                 else
     927   542441487 :                         xchk_bmap_iextent(ip, &info, &irec);
     928   542844960 :                 memcpy(&info.prev_rec, &irec, sizeof(struct xfs_bmbt_irec));
     929             :         }
     930             : 
     931   183747514 :         if (xchk_bmap_want_check_rmaps(&info)) {
     932      365670 :                 error = xchk_bmap_check_rmaps(sc, whichfork);
     933      365680 :                 if (!xchk_fblock_xref_process_error(sc, whichfork, 0, &error))
     934             :                         goto out;
     935             :         }
     936   183664115 : out:
     937   764159488 :         return error;
     938             : }
     939             : 
     940             : /* Scrub an inode's data fork. */
     941             : int
     942   379527146 : xchk_bmap_data(
     943             :         struct xfs_scrub        *sc)
     944             : {
     945   379527146 :         return xchk_bmap(sc, XFS_DATA_FORK);
     946             : }
     947             : 
     948             : /* Scrub an inode's attr fork. */
     949             : int
     950   377586958 : xchk_bmap_attr(
     951             :         struct xfs_scrub        *sc)
     952             : {
     953   377586958 :         return xchk_bmap(sc, XFS_ATTR_FORK);
     954             : }
     955             : 
     956             : /* Scrub an inode's CoW fork. */
     957             : int
     958   293620667 : xchk_bmap_cow(
     959             :         struct xfs_scrub        *sc)
     960             : {
     961   293620667 :         if (!xfs_is_reflink_inode(sc->ip))
     962             :                 return -ENOENT;
     963             : 
     964     7047182 :         return xchk_bmap(sc, XFS_COW_FORK);
     965             : }

Generated by: LCOV version 1.14