LCOV - code coverage report
Current view: top level - fs/xfs/scrub - bmap.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 373 474 78.7 %
Date: 2023-07-31 20:08:27 Functions: 22 22 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 "xfs_rtgroup.h"
      23             : #include "xfs_rtalloc.h"
      24             : #include "xfs_rtrmap_btree.h"
      25             : #include "scrub/scrub.h"
      26             : #include "scrub/common.h"
      27             : #include "scrub/btree.h"
      28             : #include "xfs_ag.h"
      29             : 
      30             : /* Set us up with an inode's bmap. */
      31             : int
      32   234296382 : xchk_setup_inode_bmap(
      33             :         struct xfs_scrub        *sc)
      34             : {
      35   234296382 :         int                     error;
      36             : 
      37   234296382 :         if (xchk_need_intent_drain(sc))
      38           0 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      39             : 
      40   234296382 :         error = xchk_iget_for_scrubbing(sc);
      41   234285926 :         if (error)
      42     1538991 :                 goto out;
      43             : 
      44   232746935 :         xchk_ilock(sc, XFS_IOLOCK_EXCL);
      45             : 
      46             :         /*
      47             :          * We don't want any ephemeral data/cow fork updates sitting around
      48             :          * while we inspect block mappings, so wait for directio to finish
      49             :          * and flush dirty data if we have delalloc reservations.
      50             :          */
      51   232761388 :         if (S_ISREG(VFS_I(sc->ip)->i_mode) &&
      52    66847247 :             sc->sm->sm_type != XFS_SCRUB_TYPE_BMBTA) {
      53    44518258 :                 struct address_space    *mapping = VFS_I(sc->ip)->i_mapping;
      54    44518258 :                 bool                    is_repair = xchk_could_repair(sc);
      55             : 
      56    44518258 :                 xchk_ilock(sc, XFS_MMAPLOCK_EXCL);
      57             : 
      58             :                 /* Break all our leases, we're going to mess with things. */
      59    44517468 :                 if (is_repair) {
      60       75256 :                         error = xfs_break_layouts(VFS_I(sc->ip),
      61             :                                         &sc->ilock_flags, BREAK_WRITE);
      62       75256 :                         if (error)
      63           0 :                                 goto out;
      64             :                 }
      65             : 
      66    44517468 :                 inode_dio_wait(VFS_I(sc->ip));
      67             : 
      68             :                 /*
      69             :                  * Try to flush all incore state to disk before we examine the
      70             :                  * space mappings for the data fork.  Leave accumulated errors
      71             :                  * in the mapping for the writer threads to consume.
      72             :                  *
      73             :                  * On ENOSPC or EIO writeback errors, we continue into the
      74             :                  * extent mapping checks because write failures do not
      75             :                  * necessarily imply anything about the correctness of the file
      76             :                  * metadata.  The metadata and the file data could be on
      77             :                  * completely separate devices; a media failure might only
      78             :                  * affect a subset of the disk, etc.  We can handle delalloc
      79             :                  * extents in the scrubber, so leaving them in memory is fine.
      80             :                  */
      81    44517862 :                 error = filemap_fdatawrite(mapping);
      82    44517892 :                 if (!error)
      83    44517883 :                         error = filemap_fdatawait_keep_errors(mapping);
      84    44517396 :                 if (error && (error != -ENOSPC && error != -EIO))
      85           0 :                         goto out;
      86             : 
      87             :                 /* Drop the page cache if we're repairing block mappings. */
      88    44517396 :                 if (is_repair) {
      89       75256 :                         error = invalidate_inode_pages2(
      90       75256 :                                         VFS_I(sc->ip)->i_mapping);
      91       75256 :                         if (error)
      92           0 :                                 goto out;
      93             :                 }
      94             : 
      95             :         }
      96             : 
      97             :         /* Got the inode, lock it and we're ready to go. */
      98   232760526 :         error = xchk_trans_alloc(sc, 0);
      99   232755455 :         if (error)
     100           0 :                 goto out;
     101             : 
     102   232755455 :         error = xchk_ino_dqattach(sc);
     103   232758186 :         if (error)
     104           0 :                 goto out;
     105             : 
     106   232758186 :         xchk_ilock(sc, XFS_ILOCK_EXCL);
     107   234298365 : out:
     108             :         /* scrub teardown will unlock and release the inode */
     109   234298365 :         return error;
     110             : }
     111             : 
     112             : /*
     113             :  * Inode fork block mapping (BMBT) scrubber.
     114             :  * More complex than the others because we have to scrub
     115             :  * all the extents regardless of whether or not the fork
     116             :  * is in btree format.
     117             :  */
     118             : 
     119             : struct xchk_bmap_info {
     120             :         struct xfs_scrub        *sc;
     121             : 
     122             :         /* Incore extent tree cursor */
     123             :         struct xfs_iext_cursor  icur;
     124             : 
     125             :         /* Previous fork mapping that we examined */
     126             :         struct xfs_bmbt_irec    prev_rec;
     127             : 
     128             :         /* Is this a realtime fork? */
     129             :         bool                    is_rt;
     130             : 
     131             :         /* May mappings point to shared space? */
     132             :         bool                    is_shared;
     133             : 
     134             :         /* Was the incore extent tree loaded? */
     135             :         bool                    was_loaded;
     136             : 
     137             :         /* Which inode fork are we checking? */
     138             :         int                     whichfork;
     139             : };
     140             : 
     141             : /* Look for a corresponding rmap for this irec. */
     142             : static inline bool
     143   526233592 : xchk_bmap_get_rmap(
     144             :         struct xchk_bmap_info   *info,
     145             :         struct xfs_bmbt_irec    *irec,
     146             :         xfs_agblock_t           bno,
     147             :         uint64_t                owner,
     148             :         struct xfs_rmap_irec    *rmap)
     149             : {
     150   526233592 :         struct xfs_btree_cur    **curp = &info->sc->sa.rmap_cur;
     151   526233592 :         xfs_fileoff_t           offset;
     152   526233592 :         unsigned int            rflags = 0;
     153   526233592 :         int                     has_rmap;
     154   526233592 :         int                     error;
     155             : 
     156   526233592 :         if (xfs_ifork_is_realtime(info->sc->ip, info->whichfork))
     157    28592969 :                 curp = &info->sc->sr.rmap_cur;
     158             : 
     159   526234857 :         if (*curp == NULL)
     160             :                 return false;
     161             : 
     162   526229140 :         if (info->whichfork == XFS_ATTR_FORK)
     163     2219834 :                 rflags |= XFS_RMAP_ATTR_FORK;
     164   526229140 :         if (irec->br_state == XFS_EXT_UNWRITTEN)
     165    13868579 :                 rflags |= XFS_RMAP_UNWRITTEN;
     166             : 
     167             :         /*
     168             :          * CoW staging extents are owned (on disk) by the refcountbt, so
     169             :          * their rmaps do not have offsets.
     170             :          */
     171   526229140 :         if (info->whichfork == XFS_COW_FORK)
     172             :                 offset = 0;
     173             :         else
     174   526174521 :                 offset = irec->br_startoff;
     175             : 
     176             :         /*
     177             :          * If the caller thinks this could be a shared bmbt extent (IOWs,
     178             :          * any data fork extent of a reflink inode) then we have to use the
     179             :          * range rmap lookup to make sure we get the correct owner/offset.
     180             :          */
     181   526229140 :         if (info->is_shared) {
     182    60152329 :                 error = xfs_rmap_lookup_le_range(*curp, bno, owner, offset,
     183             :                                 rflags, rmap, &has_rmap);
     184             :         } else {
     185   466076811 :                 error = xfs_rmap_lookup_le(*curp, bno, owner, offset,
     186             :                                 rflags, rmap, &has_rmap);
     187             :         }
     188   526228825 :         if (!xchk_should_check_xref(info->sc, &error, curp))
     189             :                 return false;
     190             : 
     191   526228614 :         if (!has_rmap)
     192           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     193             :                         irec->br_startoff);
     194   526228614 :         return has_rmap;
     195             : }
     196             : 
     197             : /* Make sure that we have rmapbt records for this data/attr fork extent. */
     198             : STATIC void
     199   526179597 : xchk_bmap_xref_rmap(
     200             :         struct xchk_bmap_info   *info,
     201             :         struct xfs_bmbt_irec    *irec,
     202             :         xfs_agblock_t           bno)
     203             : {
     204   526179597 :         struct xfs_rmap_irec    rmap;
     205   526179597 :         unsigned long long      rmap_end;
     206   526179597 :         uint64_t                owner = info->sc->ip->i_ino;
     207             : 
     208   526179597 :         if (xchk_skip_xref(info->sc->sm))
     209        5717 :                 return;
     210             : 
     211             :         /* Find the rmap record for this irec. */
     212   526179597 :         if (!xchk_bmap_get_rmap(info, irec, bno, owner, &rmap))
     213             :                 return;
     214             : 
     215             :         /*
     216             :          * The rmap must be an exact match for this incore file mapping record,
     217             :          * which may have arisen from multiple ondisk records.
     218             :          */
     219   526174372 :         if (rmap.rm_startblock != bno)
     220           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     221             :                                 irec->br_startoff);
     222             : 
     223   526174372 :         rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
     224   526174372 :         if (rmap_end != bno + irec->br_blockcount)
     225           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     226             :                                 irec->br_startoff);
     227             : 
     228             :         /* Check the logical offsets. */
     229   526174372 :         if (rmap.rm_offset != irec->br_startoff)
     230           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     231             :                                 irec->br_startoff);
     232             : 
     233   526174372 :         rmap_end = (unsigned long long)rmap.rm_offset + rmap.rm_blockcount;
     234   526174372 :         if (rmap_end != irec->br_startoff + irec->br_blockcount)
     235           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     236             :                                 irec->br_startoff);
     237             : 
     238             :         /* Check the owner */
     239   526174372 :         if (rmap.rm_owner != owner)
     240           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     241             :                                 irec->br_startoff);
     242             : 
     243             :         /*
     244             :          * Check for discrepancies between the unwritten flag in the irec and
     245             :          * the rmap.  Note that the (in-memory) CoW fork distinguishes between
     246             :          * unwritten and written extents, but we don't track that in the rmap
     247             :          * records because the blocks are owned (on-disk) by the refcountbt,
     248             :          * which doesn't track unwritten state.
     249             :          */
     250   526174372 :         if (!!(irec->br_state == XFS_EXT_UNWRITTEN) !=
     251   526174372 :             !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN))
     252           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     253             :                                 irec->br_startoff);
     254             : 
     255   526174372 :         if (!!(info->whichfork == XFS_ATTR_FORK) !=
     256   526174372 :             !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK))
     257           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     258             :                                 irec->br_startoff);
     259   526174372 :         if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
     260           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     261             :                                 irec->br_startoff);
     262             : }
     263             : 
     264             : /* Make sure that we have rmapbt records for this COW fork extent. */
     265             : STATIC void
     266      153690 : xchk_bmap_xref_rmap_cow(
     267             :         struct xchk_bmap_info   *info,
     268             :         struct xfs_bmbt_irec    *irec,
     269             :         xfs_agblock_t           bno)
     270             : {
     271      153690 :         struct xfs_rmap_irec    rmap;
     272      153690 :         unsigned long long      rmap_end;
     273      153690 :         uint64_t                owner = XFS_RMAP_OWN_COW;
     274             : 
     275      153690 :         if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
     276       99848 :                 return;
     277             : 
     278             :         /* Find the rmap record for this irec. */
     279       53842 :         if (!xchk_bmap_get_rmap(info, irec, bno, owner, &rmap))
     280             :                 return;
     281             : 
     282             :         /*
     283             :          * CoW staging extents are owned by the refcount btree, so the rmap
     284             :          * can start before and end after the physical space allocated to this
     285             :          * mapping.  There are no offsets to check.
     286             :          */
     287       53842 :         if (rmap.rm_startblock > bno)
     288           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     289             :                                 irec->br_startoff);
     290             : 
     291       53842 :         rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
     292       53842 :         if (rmap_end < bno + irec->br_blockcount)
     293           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     294             :                                 irec->br_startoff);
     295             : 
     296             :         /* Check the owner */
     297       53842 :         if (rmap.rm_owner != owner)
     298           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     299             :                                 irec->br_startoff);
     300             : 
     301             :         /*
     302             :          * No flags allowed.  Note that the (in-memory) CoW fork distinguishes
     303             :          * between unwritten and written extents, but we don't track that in
     304             :          * the rmap records because the blocks are owned (on-disk) by the
     305             :          * refcountbt, which doesn't track unwritten state.
     306             :          */
     307       53842 :         if (rmap.rm_flags & XFS_RMAP_ATTR_FORK)
     308           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     309             :                                 irec->br_startoff);
     310       53842 :         if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
     311           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     312             :                                 irec->br_startoff);
     313       53842 :         if (rmap.rm_flags & XFS_RMAP_UNWRITTEN)
     314           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     315             :                                 irec->br_startoff);
     316             : }
     317             : 
     318             : /* Cross-reference a single rtdev extent record. */
     319             : STATIC void
     320    28691679 : xchk_bmap_rt_iextent_xref(
     321             :         struct xfs_inode        *ip,
     322             :         struct xchk_bmap_info   *info,
     323             :         struct xfs_bmbt_irec    *irec)
     324             : {
     325    28691679 :         struct xfs_owner_info   oinfo;
     326    28691679 :         struct xfs_mount        *mp = ip->i_mount;
     327    28691679 :         xfs_rgnumber_t          rgno;
     328    28691679 :         xfs_rgblock_t           rgbno;
     329    28691679 :         int                     error;
     330             : 
     331    28691679 :         if (!xfs_has_rtrmapbt(mp)) {
     332           0 :                 xchk_rt_init(info->sc, &info->sc->sr,
     333             :                                 XCHK_RTLOCK_BITMAP_SHARED);
     334           0 :                 xchk_xref_is_used_rt_space(info->sc, irec->br_startblock,
     335           0 :                                 irec->br_blockcount);
     336           0 :                 xchk_rt_unlock(info->sc, &info->sc->sr);
     337           0 :                 return;
     338             :         }
     339             : 
     340    28691679 :         rgbno = xfs_rtb_to_rgbno(mp, irec->br_startblock, &rgno);
     341    28691556 :         error = xchk_rtgroup_init(info->sc, rgno, &info->sc->sr,
     342             :                         XCHK_RTGLOCK_ALL);
     343    28691771 :         if (!xchk_fblock_process_error(info->sc, info->whichfork,
     344             :                         irec->br_startoff, &error))
     345           0 :                 goto out_free;
     346             : 
     347    28692362 :         xchk_xref_is_used_rt_space(info->sc, irec->br_startblock,
     348    28692362 :                         irec->br_blockcount);
     349    28692951 :         switch (info->whichfork) {
     350    28593103 :         case XFS_DATA_FORK:
     351    28593103 :                 xchk_bmap_xref_rmap(info, irec, rgbno);
     352    28590629 :                 if (!xfs_is_reflink_inode(info->sc->ip)) {
     353     5554175 :                         xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
     354             :                                         info->whichfork, irec->br_startoff);
     355     5554175 :                         xchk_xref_is_only_rt_owned_by(info->sc, rgbno,
     356     5554175 :                                         irec->br_blockcount, &oinfo);
     357     5554244 :                         xchk_xref_is_not_rt_shared(info->sc, rgbno,
     358     5554244 :                                         irec->br_blockcount);
     359             :                 }
     360    28590556 :                 xchk_xref_is_not_rt_cow_staging(info->sc, rgbno,
     361    28590556 :                                 irec->br_blockcount);
     362    28590556 :                 break;
     363       99848 :         case XFS_COW_FORK:
     364       99848 :                 xchk_bmap_xref_rmap_cow(info, irec, rgbno);
     365       99848 :                 xchk_xref_is_only_rt_owned_by(info->sc, rgbno,
     366       99848 :                                 irec->br_blockcount, &XFS_RMAP_OINFO_COW);
     367       99848 :                 xchk_xref_is_rt_cow_staging(info->sc, rgbno,
     368       99848 :                                 irec->br_blockcount);
     369       99848 :                 xchk_xref_is_not_rt_shared(info->sc, rgbno,
     370       99848 :                                 irec->br_blockcount);
     371       99848 :                 break;
     372             :         }
     373             : 
     374    28688325 : out_free:
     375    28688325 :         xchk_rtgroup_btcur_free(&info->sc->sr);
     376    28693239 :         xchk_rtgroup_free(info->sc, &info->sc->sr);
     377             : }
     378             : 
     379             : /* Cross-reference a single datadev extent record. */
     380             : STATIC void
     381   497643293 : xchk_bmap_iextent_xref(
     382             :         struct xfs_inode        *ip,
     383             :         struct xchk_bmap_info   *info,
     384             :         struct xfs_bmbt_irec    *irec)
     385             : {
     386   497643293 :         struct xfs_owner_info   oinfo;
     387   497643293 :         struct xfs_mount        *mp = info->sc->mp;
     388   497643293 :         xfs_agnumber_t          agno;
     389   497643293 :         xfs_agblock_t           agbno;
     390   497643293 :         xfs_extlen_t            len;
     391   497643293 :         int                     error;
     392             : 
     393   497643293 :         agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
     394   497643293 :         agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
     395   497643293 :         len = irec->br_blockcount;
     396             : 
     397   497643293 :         error = xchk_ag_init_existing(info->sc, agno, &info->sc->sa);
     398   497643923 :         if (!xchk_fblock_process_error(info->sc, info->whichfork,
     399             :                         irec->br_startoff, &error))
     400           0 :                 goto out_free;
     401             : 
     402   497644157 :         xchk_xref_is_used_space(info->sc, agbno, len);
     403   497643204 :         xchk_xref_is_not_inode_chunk(info->sc, agbno, len);
     404   497641005 :         switch (info->whichfork) {
     405   495367319 :         case XFS_DATA_FORK:
     406   495367319 :                 xchk_bmap_xref_rmap(info, irec, agbno);
     407   495369673 :                 if (!xfs_is_reflink_inode(info->sc->ip)) {
     408   458255627 :                         xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
     409             :                                         info->whichfork, irec->br_startoff);
     410   458255627 :                         xchk_xref_is_only_owned_by(info->sc, agbno,
     411   458255627 :                                         irec->br_blockcount, &oinfo);
     412   458255365 :                         xchk_xref_is_not_shared(info->sc, agbno,
     413   458255365 :                                         irec->br_blockcount);
     414             :                 }
     415   495369337 :                 xchk_xref_is_not_cow_staging(info->sc, agbno,
     416   495369337 :                                 irec->br_blockcount);
     417   495369337 :                 break;
     418     2219844 :         case XFS_ATTR_FORK:
     419     2219844 :                 xchk_bmap_xref_rmap(info, irec, agbno);
     420     2219875 :                 xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
     421             :                                 info->whichfork, irec->br_startoff);
     422     2219875 :                 xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
     423             :                                 &oinfo);
     424     2219855 :                 xchk_xref_is_not_shared(info->sc, agbno,
     425     2219855 :                                 irec->br_blockcount);
     426     2219878 :                 xchk_xref_is_not_cow_staging(info->sc, agbno,
     427     2219878 :                                 irec->br_blockcount);
     428     2219878 :                 break;
     429       53842 :         case XFS_COW_FORK:
     430       53842 :                 xchk_bmap_xref_rmap_cow(info, irec, agbno);
     431       53842 :                 xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
     432             :                                 &XFS_RMAP_OINFO_COW);
     433       53842 :                 xchk_xref_is_cow_staging(info->sc, agbno,
     434       53842 :                                 irec->br_blockcount);
     435       53842 :                 xchk_xref_is_not_shared(info->sc, agbno,
     436       53842 :                                 irec->br_blockcount);
     437       53842 :                 break;
     438             :         }
     439             : 
     440   497643582 : out_free:
     441   497643582 :         xchk_ag_free(info->sc, &info->sc->sa);
     442   497643850 : }
     443             : 
     444             : /*
     445             :  * Directories and attr forks should never have blocks that can't be addressed
     446             :  * by a xfs_dablk_t.
     447             :  */
     448             : STATIC void
     449   526332873 : xchk_bmap_dirattr_extent(
     450             :         struct xfs_inode        *ip,
     451             :         struct xchk_bmap_info   *info,
     452             :         struct xfs_bmbt_irec    *irec)
     453             : {
     454   526332873 :         struct xfs_mount        *mp = ip->i_mount;
     455   526332873 :         xfs_fileoff_t           off;
     456             : 
     457   526332873 :         if (!S_ISDIR(VFS_I(ip)->i_mode) && info->whichfork != XFS_ATTR_FORK)
     458             :                 return;
     459             : 
     460     2777310 :         if (!xfs_verify_dablk(mp, irec->br_startoff))
     461           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     462             :                                 irec->br_startoff);
     463             : 
     464     2777308 :         off = irec->br_startoff + irec->br_blockcount - 1;
     465     2777308 :         if (!xfs_verify_dablk(mp, off))
     466           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork, off);
     467             : }
     468             : 
     469             : /* Scrub a single extent record. */
     470             : STATIC void
     471   526332512 : xchk_bmap_iextent(
     472             :         struct xfs_inode        *ip,
     473             :         struct xchk_bmap_info   *info,
     474             :         struct xfs_bmbt_irec    *irec)
     475             : {
     476   526332512 :         struct xfs_mount        *mp = info->sc->mp;
     477             : 
     478             :         /*
     479             :          * Check for out-of-order extents.  This record could have come
     480             :          * from the incore list, for which there is no ordering check.
     481             :          */
     482   526332512 :         if (irec->br_startoff < info->prev_rec.br_startoff +
     483   526332512 :                                 info->prev_rec.br_blockcount)
     484           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     485             :                                 irec->br_startoff);
     486             : 
     487   526332512 :         if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
     488           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     489             :                                 irec->br_startoff);
     490             : 
     491   526332799 :         xchk_bmap_dirattr_extent(ip, info, irec);
     492             : 
     493             :         /* Make sure the extent points to a valid place. */
     494   555025266 :         if (info->is_rt &&
     495    28690876 :             !xfs_verify_rtbext(mp, irec->br_startblock, irec->br_blockcount))
     496           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     497             :                                 irec->br_startoff);
     498  1023977968 :         if (!info->is_rt &&
     499   497642802 :             !xfs_verify_fsbext(mp, irec->br_startblock, irec->br_blockcount))
     500           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     501             :                                 irec->br_startoff);
     502             : 
     503             :         /* We don't allow unwritten extents on attr forks. */
     504   526335166 :         if (irec->br_state == XFS_EXT_UNWRITTEN &&
     505    13969673 :             info->whichfork == XFS_ATTR_FORK)
     506           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     507             :                                 irec->br_startoff);
     508             : 
     509   526335166 :         if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     510             :                 return;
     511             : 
     512   526335166 :         if (info->is_rt)
     513    28691700 :                 xchk_bmap_rt_iextent_xref(ip, info, irec);
     514             :         else
     515   497643466 :                 xchk_bmap_iextent_xref(ip, info, irec);
     516             : }
     517             : 
     518             : /* Scrub a bmbt record. */
     519             : STATIC int
     520   493642857 : xchk_bmapbt_rec(
     521             :         struct xchk_btree       *bs,
     522             :         const union xfs_btree_rec *rec)
     523             : {
     524   493642857 :         struct xfs_bmbt_irec    irec;
     525   493642857 :         struct xfs_bmbt_irec    iext_irec;
     526   493642857 :         struct xfs_iext_cursor  icur;
     527   493642857 :         struct xchk_bmap_info   *info = bs->private;
     528   493642857 :         struct xfs_inode        *ip = bs->cur->bc_ino.ip;
     529   493642857 :         struct xfs_buf          *bp = NULL;
     530   493642857 :         struct xfs_btree_block  *block;
     531   493642857 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, info->whichfork);
     532   493654821 :         uint64_t                owner;
     533   493654821 :         int                     i;
     534             : 
     535             :         /*
     536             :          * Check the owners of the btree blocks up to the level below
     537             :          * the root since the verifiers don't do that.
     538             :          */
     539   493654821 :         if (xfs_has_crc(bs->cur->bc_mp) &&
     540   493655288 :             bs->cur->bc_levels[0].ptr == 1) {
     541     9242467 :                 for (i = 0; i < bs->cur->bc_nlevels - 1; i++) {
     542     5662134 :                         block = xfs_btree_get_block(bs->cur, i, &bp);
     543     5662138 :                         owner = be64_to_cpu(block->bb_u.l.bb_owner);
     544     5662138 :                         if (owner != ip->i_ino)
     545           0 :                                 xchk_fblock_set_corrupt(bs->sc,
     546             :                                                 info->whichfork, 0);
     547             :                 }
     548             :         }
     549             : 
     550             :         /*
     551             :          * Check that the incore extent tree contains an extent that matches
     552             :          * this one exactly.  We validate those cached bmaps later, so we don't
     553             :          * need to check them here.  If the incore extent tree was just loaded
     554             :          * from disk by the scrubber, we assume that its contents match what's
     555             :          * on disk (we still hold the ILOCK) and skip the equivalence check.
     556             :          */
     557   493654825 :         if (!info->was_loaded)
     558             :                 return 0;
     559             : 
     560   493641074 :         xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
     561   493652801 :         if (xfs_bmap_validate_extent(ip, info->whichfork, &irec) != NULL) {
     562           0 :                 xchk_fblock_set_corrupt(bs->sc, info->whichfork,
     563             :                                 irec.br_startoff);
     564           0 :                 return 0;
     565             :         }
     566             : 
     567   493662860 :         if (!xfs_iext_lookup_extent(ip, ifp, irec.br_startoff, &icur,
     568   493585654 :                                 &iext_irec) ||
     569   493585654 :             irec.br_startoff != iext_irec.br_startoff ||
     570   493589867 :             irec.br_startblock != iext_irec.br_startblock ||
     571   493591943 :             irec.br_blockcount != iext_irec.br_blockcount ||
     572   493593946 :             irec.br_state != iext_irec.br_state)
     573           0 :                 xchk_fblock_set_corrupt(bs->sc, info->whichfork,
     574             :                                 irec.br_startoff);
     575             :         return 0;
     576             : }
     577             : 
     578             : /* Scan the btree records. */
     579             : STATIC int
     580     1421326 : xchk_bmap_btree(
     581             :         struct xfs_scrub        *sc,
     582             :         int                     whichfork,
     583             :         struct xchk_bmap_info   *info)
     584             : {
     585     1421326 :         struct xfs_owner_info   oinfo;
     586     1421326 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(sc->ip, whichfork);
     587     1421328 :         struct xfs_mount        *mp = sc->mp;
     588     1421328 :         struct xfs_inode        *ip = sc->ip;
     589     1421328 :         struct xfs_btree_cur    *cur;
     590     1421328 :         int                     error;
     591             : 
     592             :         /* Load the incore bmap cache if it's not loaded. */
     593     1421328 :         info->was_loaded = !xfs_need_iread_extents(ifp);
     594             : 
     595     1421328 :         error = xfs_iread_extents(sc->tp, ip, whichfork);
     596     1421331 :         if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
     597           0 :                 goto out;
     598             : 
     599             :         /* Check the btree structure. */
     600     1421323 :         cur = xfs_bmbt_init_cursor(mp, sc->tp, ip, whichfork);
     601     1421326 :         xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
     602     1421326 :         error = xchk_btree(sc, cur, xchk_bmapbt_rec, &oinfo, info);
     603     1421335 :         xfs_btree_del_cursor(cur, error);
     604     1421338 : out:
     605     1421338 :         return error;
     606             : }
     607             : 
     608             : struct xchk_bmap_check_rmap_info {
     609             :         struct xfs_scrub        *sc;
     610             :         int                     whichfork;
     611             :         struct xfs_iext_cursor  icur;
     612             : };
     613             : 
     614             : /* Can we find bmaps that fit this rmap? */
     615             : STATIC int
     616 64234507809 : xchk_bmap_check_rmap(
     617             :         struct xfs_btree_cur            *cur,
     618             :         const struct xfs_rmap_irec      *rec,
     619             :         void                            *priv)
     620             : {
     621 64234507809 :         struct xfs_bmbt_irec            irec;
     622 64234507809 :         struct xfs_rmap_irec            check_rec;
     623 64234507809 :         struct xchk_bmap_check_rmap_info        *sbcri = priv;
     624 64234507809 :         struct xfs_ifork                *ifp;
     625 64234507809 :         struct xfs_scrub                *sc = sbcri->sc;
     626 64234507809 :         bool                            have_map;
     627             : 
     628             :         /* Is this even the right fork? */
     629 64234507809 :         if (rec->rm_owner != sc->ip->i_ino)
     630             :                 return 0;
     631         175 :         if ((sbcri->whichfork == XFS_ATTR_FORK) ^
     632         175 :             !!(rec->rm_flags & XFS_RMAP_ATTR_FORK))
     633             :                 return 0;
     634           0 :         if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
     635             :                 return 0;
     636             : 
     637             :         /* Now look up the bmbt record. */
     638           0 :         ifp = xfs_ifork_ptr(sc->ip, sbcri->whichfork);
     639           0 :         if (!ifp) {
     640           0 :                 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     641           0 :                                 rec->rm_offset);
     642           0 :                 goto out;
     643             :         }
     644           0 :         have_map = xfs_iext_lookup_extent(sc->ip, ifp, rec->rm_offset,
     645             :                         &sbcri->icur, &irec);
     646           0 :         if (!have_map)
     647           0 :                 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     648           0 :                                 rec->rm_offset);
     649             :         /*
     650             :          * bmap extent record lengths are constrained to 2^21 blocks in length
     651             :          * because of space constraints in the on-disk metadata structure.
     652             :          * However, rmap extent record lengths are constrained only by AG
     653             :          * length, so we have to loop through the bmbt to make sure that the
     654             :          * entire rmap is covered by bmbt records.
     655             :          */
     656           0 :         check_rec = *rec;
     657           0 :         while (have_map) {
     658           0 :                 xfs_fsblock_t   startblock;
     659             : 
     660           0 :                 if (irec.br_startoff != check_rec.rm_offset)
     661           0 :                         xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     662             :                                         check_rec.rm_offset);
     663           0 :                 if (cur->bc_btnum == XFS_BTNUM_RMAP)
     664           0 :                         startblock = XFS_AGB_TO_FSB(sc->mp,
     665             :                                         cur->bc_ag.pag->pag_agno,
     666             :                                         check_rec.rm_startblock);
     667             :                 else
     668           0 :                         startblock = xfs_rgbno_to_rtb(sc->mp,
     669           0 :                                         cur->bc_ino.rtg->rtg_rgno,
     670             :                                         check_rec.rm_startblock);
     671           0 :                 if (irec.br_startblock != startblock)
     672           0 :                         xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     673             :                                         check_rec.rm_offset);
     674           0 :                 if (irec.br_blockcount > check_rec.rm_blockcount)
     675           0 :                         xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     676             :                                         check_rec.rm_offset);
     677           0 :                 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     678             :                         break;
     679           0 :                 check_rec.rm_startblock += irec.br_blockcount;
     680           0 :                 check_rec.rm_offset += irec.br_blockcount;
     681           0 :                 check_rec.rm_blockcount -= irec.br_blockcount;
     682           0 :                 if (check_rec.rm_blockcount == 0)
     683             :                         break;
     684           0 :                 have_map = xfs_iext_next_extent(ifp, &sbcri->icur, &irec);
     685           0 :                 if (!have_map)
     686           0 :                         xchk_fblock_set_corrupt(sc, sbcri->whichfork,
     687             :                                         check_rec.rm_offset);
     688             :         }
     689             : 
     690           0 : out:
     691           0 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     692           0 :                 return -ECANCELED;
     693             :         return 0;
     694             : }
     695             : 
     696             : /* Make sure each rmap has a corresponding bmbt entry. */
     697             : STATIC int
     698      642184 : xchk_bmap_check_ag_rmaps(
     699             :         struct xfs_scrub                *sc,
     700             :         int                             whichfork,
     701             :         struct xfs_perag                *pag)
     702             : {
     703      642184 :         struct xchk_bmap_check_rmap_info        sbcri;
     704      642184 :         struct xfs_btree_cur            *cur;
     705      642184 :         struct xfs_buf                  *agf;
     706      642184 :         int                             error;
     707             : 
     708      642184 :         error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf);
     709      642182 :         if (error)
     710             :                 return error;
     711             : 
     712      642181 :         cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf, pag);
     713             : 
     714      642183 :         sbcri.sc = sc;
     715      642183 :         sbcri.whichfork = whichfork;
     716      642183 :         error = xfs_rmap_query_all(cur, xchk_bmap_check_rmap, &sbcri);
     717      642184 :         if (error == -ECANCELED)
     718           0 :                 error = 0;
     719             : 
     720      642184 :         xfs_btree_del_cursor(cur, error);
     721      642184 :         xfs_trans_brelse(sc->tp, agf);
     722      642184 :         return error;
     723             : }
     724             : 
     725             : /* Make sure each rt rmap has a corresponding bmbt entry. */
     726             : STATIC int
     727      590044 : xchk_bmap_check_rt_rmaps(
     728             :         struct xfs_scrub                *sc,
     729             :         struct xfs_rtgroup              *rtg)
     730             : {
     731      590044 :         struct xchk_bmap_check_rmap_info sbcri;
     732      590044 :         struct xfs_btree_cur            *cur;
     733      590044 :         int                             error;
     734             : 
     735      590044 :         xfs_rtgroup_lock(NULL, rtg, XFS_RTGLOCK_RMAP);
     736      588668 :         cur = xfs_rtrmapbt_init_cursor(sc->mp, sc->tp, rtg, rtg->rtg_rmapip);
     737             : 
     738      577792 :         sbcri.sc = sc;
     739      577792 :         sbcri.whichfork = XFS_DATA_FORK;
     740      577792 :         error = xfs_rmap_query_all(cur, xchk_bmap_check_rmap, &sbcri);
     741      590044 :         if (error == -ECANCELED)
     742           0 :                 error = 0;
     743             : 
     744      590044 :         xfs_btree_del_cursor(cur, error);
     745      590045 :         xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP);
     746      590044 :         return error;
     747             : }
     748             : 
     749             : /*
     750             :  * Decide if we want to walk every rmap btree in the fs to make sure that each
     751             :  * rmap for this file fork has corresponding bmbt entries.
     752             :  */
     753             : static bool
     754    38793706 : xchk_bmap_want_check_rmaps(
     755             :         struct xchk_bmap_info   *info)
     756             : {
     757    38793706 :         struct xfs_scrub        *sc = info->sc;
     758    38793706 :         struct xfs_ifork        *ifp;
     759             : 
     760    38793706 :         if (!xfs_has_rmapbt(sc->mp))
     761             :                 return false;
     762    38792579 :         if (info->whichfork == XFS_COW_FORK)
     763             :                 return false;
     764    34050372 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     765             :                 return false;
     766             : 
     767             :         /*
     768             :          * The inode repair code zaps broken inode forks by resetting them back
     769             :          * to EXTENTS format and zero extent records.  If we encounter a fork
     770             :          * in this state along with evidence that the fork isn't supposed to be
     771             :          * empty, we need to scan the reverse mappings to decide if we're going
     772             :          * to rebuild the fork.  Data forks with nonzero file size are scanned.
     773             :          * xattr forks are never empty of content, so they are always scanned.
     774             :          */
     775    34050420 :         ifp = xfs_ifork_ptr(sc->ip, info->whichfork);
     776    34050189 :         if (ifp->if_format == XFS_DINODE_FMT_EXTENTS && ifp->if_nextents == 0) {
     777    15118031 :                 if (info->whichfork == XFS_DATA_FORK &&
     778    15112605 :                     i_size_read(VFS_I(sc->ip)) == 0)
     779             :                         return false;
     780             : 
     781      277628 :                 return true;
     782             :         }
     783             : 
     784             :         return false;
     785             : }
     786             : 
     787             : /* Make sure each rmap has a corresponding bmbt entry. */
     788             : STATIC int
     789      277628 : xchk_bmap_check_rmaps(
     790             :         struct xfs_scrub        *sc,
     791             :         int                     whichfork)
     792             : {
     793      277628 :         struct xfs_perag        *pag;
     794      277628 :         xfs_agnumber_t          agno;
     795      277628 :         int                     error;
     796             : 
     797      277628 :         if (xfs_ifork_is_realtime(sc->ip, whichfork)) {
     798      118009 :                 struct xfs_rtgroup      *rtg;
     799      118009 :                 xfs_rgnumber_t          rgno;
     800             : 
     801      708054 :                 for_each_rtgroup(sc->mp, rgno, rtg) {
     802      590044 :                         error = xchk_bmap_check_rt_rmaps(sc, rtg);
     803      590045 :                         if (error ||
     804      590045 :                             (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
     805           0 :                                 xfs_rtgroup_rele(rtg);
     806           0 :                                 return error;
     807             :                         }
     808             :                 }
     809             : 
     810             :                 return 0;
     811             :         }
     812             : 
     813      801803 :         for_each_perag(sc->mp, agno, pag) {
     814      642184 :                 error = xchk_bmap_check_ag_rmaps(sc, whichfork, pag);
     815      642184 :                 if (error ||
     816      642184 :                     (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
     817           0 :                         xfs_perag_rele(pag);
     818           0 :                         return error;
     819             :                 }
     820             :         }
     821             : 
     822             :         return 0;
     823             : }
     824             : 
     825             : /* Scrub a delalloc reservation from the incore extent map tree. */
     826             : STATIC void
     827         151 : xchk_bmap_iextent_delalloc(
     828             :         struct xfs_inode        *ip,
     829             :         struct xchk_bmap_info   *info,
     830             :         struct xfs_bmbt_irec    *irec)
     831             : {
     832         151 :         struct xfs_mount        *mp = info->sc->mp;
     833             : 
     834             :         /*
     835             :          * Check for out-of-order extents.  This record could have come
     836             :          * from the incore list, for which there is no ordering check.
     837             :          */
     838         151 :         if (irec->br_startoff < info->prev_rec.br_startoff +
     839         151 :                                 info->prev_rec.br_blockcount)
     840           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     841             :                                 irec->br_startoff);
     842             : 
     843         151 :         if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
     844           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     845             :                                 irec->br_startoff);
     846             : 
     847             :         /* Make sure the extent points to a valid place. */
     848         151 :         if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN)
     849           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     850             :                                 irec->br_startoff);
     851         151 : }
     852             : 
     853             : /* Decide if this individual fork mapping is ok. */
     854             : static bool
     855             : xchk_bmap_iext_mapping(
     856             :         struct xchk_bmap_info           *info,
     857             :         const struct xfs_bmbt_irec      *irec)
     858             : {
     859             :         /* There should never be a "hole" extent in either extent list. */
     860   526334952 :         if (irec->br_startblock == HOLESTARTBLOCK)
     861             :                 return false;
     862   526334952 :         if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN)
     863             :                 return false;
     864             :         return true;
     865             : }
     866             : 
     867             : /* Are these two mappings contiguous with each other? */
     868             : static inline bool
     869   507333448 : xchk_are_bmaps_contiguous(
     870             :         const struct xfs_bmbt_irec      *b1,
     871             :         const struct xfs_bmbt_irec      *b2)
     872             : {
     873             :         /* Don't try to combine unallocated mappings. */
     874  1014665812 :         if (!xfs_bmap_is_real_extent(b1))
     875             :                 return false;
     876  1014667520 :         if (!xfs_bmap_is_real_extent(b2))
     877             :                 return false;
     878             : 
     879             :         /* Does b2 come right after b1 in the logical and physical range? */
     880   507333298 :         if (b1->br_startoff + b1->br_blockcount != b2->br_startoff)
     881             :                 return false;
     882    99565325 :         if (b1->br_startblock + b1->br_blockcount != b2->br_startblock)
     883             :                 return false;
     884     3220406 :         if (b1->br_state != b2->br_state)
     885     3219623 :                 return false;
     886             :         return true;
     887             : }
     888             : 
     889             : /*
     890             :  * Walk the incore extent records, accumulating consecutive contiguous records
     891             :  * into a single incore mapping.  Returns true if @irec has been set to a
     892             :  * mapping or false if there are no more mappings.  Caller must ensure that
     893             :  * @info.icur is zeroed before the first call.
     894             :  */
     895             : static bool
     896   565118938 : xchk_bmap_iext_iter(
     897             :         struct xchk_bmap_info   *info,
     898             :         struct xfs_bmbt_irec    *irec)
     899             : {
     900   565118938 :         struct xfs_bmbt_irec    got;
     901   565118938 :         struct xfs_ifork        *ifp;
     902   565118938 :         unsigned int            nr = 0;
     903             : 
     904   565118938 :         ifp = xfs_ifork_ptr(info->sc->ip, info->whichfork);
     905             : 
     906             :         /* Advance to the next iextent record and check the mapping. */
     907   565120698 :         xfs_iext_next(ifp, &info->icur);
     908   565122037 :         if (!xfs_iext_get_extent(ifp, &info->icur, irec))
     909             :                 return false;
     910             : 
     911   526334169 :         if (!xchk_bmap_iext_mapping(info, irec)) {
     912           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     913             :                                 irec->br_startoff);
     914           0 :                 return false;
     915             :         }
     916             :         nr++;
     917             : 
     918             :         /*
     919             :          * Iterate subsequent iextent records and merge them with the one
     920             :          * that we just read, if possible.
     921             :          */
     922   526334952 :         while (xfs_iext_peek_next_extent(ifp, &info->icur, &got)) {
     923   507332319 :                 if (!xchk_are_bmaps_contiguous(irec, &got))
     924             :                         break;
     925             : 
     926         783 :                 if (!xchk_bmap_iext_mapping(info, &got)) {
     927           0 :                         xchk_fblock_set_corrupt(info->sc, info->whichfork,
     928             :                                         got.br_startoff);
     929           0 :                         return false;
     930             :                 }
     931         783 :                 nr++;
     932             : 
     933         783 :                 irec->br_blockcount += got.br_blockcount;
     934         783 :                 xfs_iext_next(ifp, &info->icur);
     935             :         }
     936             : 
     937             :         /*
     938             :          * If the merged mapping could be expressed with fewer bmbt records
     939             :          * than we actually found, notify the user that this fork could be
     940             :          * optimized.  CoW forks only exist in memory so we ignore them.
     941             :          */
     942   526332974 :         if (nr > 1 && info->whichfork != XFS_COW_FORK &&
     943          11 :             howmany_64(irec->br_blockcount, XFS_MAX_BMBT_EXTLEN) < nr)
     944           0 :                 xchk_ino_set_preen(info->sc, info->sc->ip->i_ino);
     945             : 
     946             :         return true;
     947             : }
     948             : 
     949             : /*
     950             :  * Scrub an inode fork's block mappings.
     951             :  *
     952             :  * First we scan every record in every btree block, if applicable.
     953             :  * Then we unconditionally scan the incore extent cache.
     954             :  */
     955             : STATIC int
     956   233421532 : xchk_bmap(
     957             :         struct xfs_scrub        *sc,
     958             :         int                     whichfork)
     959             : {
     960   233421532 :         struct xfs_bmbt_irec    irec;
     961   233421532 :         struct xchk_bmap_info   info = { NULL };
     962   233421532 :         struct xfs_mount        *mp = sc->mp;
     963   233421532 :         struct xfs_inode        *ip = sc->ip;
     964   233421532 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     965   233428057 :         xfs_fileoff_t           endoff;
     966   233428057 :         int                     error = 0;
     967             : 
     968             :         /* Non-existent forks can be ignored. */
     969   233428057 :         if (!ifp)
     970             :                 return -ENOENT;
     971             : 
     972   160721823 :         info.is_rt = xfs_ifork_is_realtime(ip, whichfork);
     973   160722340 :         info.whichfork = whichfork;
     974   160722340 :         info.is_shared = whichfork == XFS_DATA_FORK && xfs_is_reflink_inode(ip);
     975   160722340 :         info.sc = sc;
     976             : 
     977   160722340 :         switch (whichfork) {
     978             :         case XFS_COW_FORK:
     979             :                 /* No CoW forks on non-reflink filesystems. */
     980     4742224 :                 if (!xfs_has_reflink(mp)) {
     981           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     982           0 :                         return 0;
     983             :                 }
     984             :                 break;
     985             :         case XFS_ATTR_FORK:
     986    77828612 :                 if (!xfs_has_attr(mp) && !xfs_has_attr2(mp))
     987           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     988             :                 break;
     989    78151504 :         default:
     990    78151504 :                 ASSERT(whichfork == XFS_DATA_FORK);
     991             :                 break;
     992             :         }
     993             : 
     994             :         /* Check the fork values */
     995   160722340 :         switch (ifp->if_format) {
     996   121927146 :         case XFS_DINODE_FMT_UUID:
     997             :         case XFS_DINODE_FMT_DEV:
     998             :         case XFS_DINODE_FMT_LOCAL:
     999             :         case XFS_DINODE_FMT_RMAP:
    1000             :         case XFS_DINODE_FMT_REFCOUNT:
    1001             :                 /* No mappings to check. */
    1002   121927146 :                 if (whichfork == XFS_COW_FORK)
    1003           0 :                         xchk_fblock_set_corrupt(sc, whichfork, 0);
    1004             :                 return 0;
    1005             :         case XFS_DINODE_FMT_EXTENTS:
    1006             :                 break;
    1007     1421332 :         case XFS_DINODE_FMT_BTREE:
    1008     1421332 :                 if (whichfork == XFS_COW_FORK) {
    1009           0 :                         xchk_fblock_set_corrupt(sc, whichfork, 0);
    1010           0 :                         return 0;
    1011             :                 }
    1012             : 
    1013     1421332 :                 error = xchk_bmap_btree(sc, whichfork, &info);
    1014     1421337 :                 if (error)
    1015             :                         return error;
    1016             :                 break;
    1017           0 :         default:
    1018           0 :                 xchk_fblock_set_corrupt(sc, whichfork, 0);
    1019           0 :                 return 0;
    1020             :         }
    1021             : 
    1022    38795199 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
    1023             :                 return 0;
    1024             : 
    1025             :         /* Find the offset of the last extent in the mapping. */
    1026    38794659 :         error = xfs_bmap_last_offset(ip, &endoff, whichfork);
    1027    38794795 :         if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
    1028           0 :                 return error;
    1029             : 
    1030             :         /*
    1031             :          * Scrub extent records.  We use a special iterator function here that
    1032             :          * combines adjacent mappings if they are logically and physically
    1033             :          * contiguous.   For large allocations that require multiple bmbt
    1034             :          * records, this reduces the number of cross-referencing calls, which
    1035             :          * reduces runtime.  Cross referencing with the rmap is simpler because
    1036             :          * the rmap must match the combined mapping exactly.
    1037             :          */
    1038   565131204 :         while (xchk_bmap_iext_iter(&info, &irec)) {
    1039   526331464 :                 if (xchk_should_terminate(sc, &error) ||
    1040   526334231 :                     (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
    1041             :                         return 0;
    1042             : 
    1043   526334231 :                 if (irec.br_startoff >= endoff) {
    1044           0 :                         xchk_fblock_set_corrupt(sc, whichfork,
    1045             :                                         irec.br_startoff);
    1046           0 :                         return 0;
    1047             :                 }
    1048             : 
    1049   526334231 :                 if (isnullstartblock(irec.br_startblock))
    1050         151 :                         xchk_bmap_iextent_delalloc(ip, &info, &irec);
    1051             :                 else
    1052   526334080 :                         xchk_bmap_iextent(ip, &info, &irec);
    1053   526336267 :                 memcpy(&info.prev_rec, &irec, sizeof(struct xfs_bmbt_irec));
    1054             :         }
    1055             : 
    1056    38792578 :         if (xchk_bmap_want_check_rmaps(&info)) {
    1057      277628 :                 error = xchk_bmap_check_rmaps(sc, whichfork);
    1058      277628 :                 if (!xchk_fblock_xref_process_error(sc, whichfork, 0, &error))
    1059           0 :                         return error;
    1060             :         }
    1061             : 
    1062             :         return 0;
    1063             : }
    1064             : 
    1065             : /* Scrub an inode's data fork. */
    1066             : int
    1067    78151275 : xchk_bmap_data(
    1068             :         struct xfs_scrub        *sc)
    1069             : {
    1070    78151275 :         return xchk_bmap(sc, XFS_DATA_FORK);
    1071             : }
    1072             : 
    1073             : /* Scrub an inode's attr fork. */
    1074             : int
    1075    77850843 : xchk_bmap_attr(
    1076             :         struct xfs_scrub        *sc)
    1077             : {
    1078    77850843 :         return xchk_bmap(sc, XFS_ATTR_FORK);
    1079             : }
    1080             : 
    1081             : /* Scrub an inode's CoW fork. */
    1082             : int
    1083    77427340 : xchk_bmap_cow(
    1084             :         struct xfs_scrub        *sc)
    1085             : {
    1086    77427340 :         return xchk_bmap(sc, XFS_COW_FORK);
    1087             : }

Generated by: LCOV version 1.14