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-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 317 402 78.9 %
Date: 2023-07-31 20:08:17 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   899408206 : xchk_setup_inode_bmap(
      30             :         struct xfs_scrub        *sc)
      31             : {
      32   899408206 :         int                     error;
      33             : 
      34   899408206 :         if (xchk_need_intent_drain(sc))
      35           0 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      36             : 
      37   899408206 :         error = xchk_iget_for_scrubbing(sc);
      38   899377668 :         if (error)
      39     4422465 :                 goto out;
      40             : 
      41   894955203 :         sc->ilock_flags = XFS_IOLOCK_EXCL;
      42   894955203 :         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   895043365 :         if (S_ISREG(VFS_I(sc->ip)->i_mode) &&
      50   265208975 :             sc->sm->sm_type != XFS_SCRUB_TYPE_BMBTA) {
      51   170622846 :                 struct address_space    *mapping = VFS_I(sc->ip)->i_mapping;
      52             : 
      53   170622846 :                 sc->ilock_flags |= XFS_MMAPLOCK_EXCL;
      54   170622846 :                 xfs_ilock(sc->ip, XFS_MMAPLOCK_EXCL);
      55             : 
      56   170619242 :                 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   170618960 :                 error = filemap_fdatawrite(mapping);
      72   170616149 :                 if (!error)
      73   170615924 :                         error = filemap_fdatawait_keep_errors(mapping);
      74   170612602 :                 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   895033121 :         error = xchk_trans_alloc(sc, 0);
      80   894992608 :         if (error)
      81           0 :                 goto out;
      82   894992608 :         sc->ilock_flags |= XFS_ILOCK_EXCL;
      83   894992608 :         xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
      84             : 
      85   899445328 : out:
      86             :         /* scrub teardown will unlock and release the inode */
      87   899445328 :         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   175434129 : 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   175434129 :         xfs_fileoff_t           offset;
     129   175434129 :         unsigned int            rflags = 0;
     130   175434129 :         int                     has_rmap;
     131   175434129 :         int                     error;
     132             : 
     133   175434129 :         if (info->whichfork == XFS_ATTR_FORK)
     134      449380 :                 rflags |= XFS_RMAP_ATTR_FORK;
     135   175434129 :         if (irec->br_state == XFS_EXT_UNWRITTEN)
     136    11712309 :                 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   175434129 :         if (info->whichfork == XFS_COW_FORK)
     143             :                 offset = 0;
     144             :         else
     145   175317458 :                 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   175434129 :         if (info->is_shared) {
     153    53258221 :                 error = xfs_rmap_lookup_le_range(info->sc->sa.rmap_cur, agbno,
     154             :                                 owner, offset, rflags, rmap, &has_rmap);
     155             :         } else {
     156   122175908 :                 error = xfs_rmap_lookup_le(info->sc->sa.rmap_cur, agbno,
     157             :                                 owner, offset, rflags, rmap, &has_rmap);
     158             :         }
     159   175434901 :         if (!xchk_should_check_xref(info->sc, &error, &info->sc->sa.rmap_cur))
     160             :                 return false;
     161             : 
     162   175434749 :         if (!has_rmap)
     163           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     164             :                         irec->br_startoff);
     165   175434749 :         return has_rmap;
     166             : }
     167             : 
     168             : /* Make sure that we have rmapbt records for this data/attr fork extent. */
     169             : STATIC void
     170   190200188 : xchk_bmap_xref_rmap(
     171             :         struct xchk_bmap_info   *info,
     172             :         struct xfs_bmbt_irec    *irec,
     173             :         xfs_agblock_t           agbno)
     174             : {
     175   190200188 :         struct xfs_rmap_irec    rmap;
     176   190200188 :         unsigned long long      rmap_end;
     177   190200188 :         uint64_t                owner = info->sc->ip->i_ino;
     178             : 
     179   190200188 :         if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
     180    14883069 :                 return;
     181             : 
     182             :         /* Find the rmap record for this irec. */
     183   175317119 :         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   175318514 :         if (rmap.rm_startblock != agbno)
     191           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     192             :                                 irec->br_startoff);
     193             : 
     194   175318514 :         rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
     195   175318514 :         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   175318514 :         if (rmap.rm_offset != irec->br_startoff)
     201           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     202             :                                 irec->br_startoff);
     203             : 
     204   175318514 :         rmap_end = (unsigned long long)rmap.rm_offset + rmap.rm_blockcount;
     205   175318514 :         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   175318514 :         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   175318514 :         if (!!(irec->br_state == XFS_EXT_UNWRITTEN) !=
     222   175318514 :             !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN))
     223           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     224             :                                 irec->br_startoff);
     225             : 
     226   175318514 :         if (!!(info->whichfork == XFS_ATTR_FORK) !=
     227   175318514 :             !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK))
     228           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     229             :                                 irec->br_startoff);
     230   175318514 :         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      116399 : xchk_bmap_xref_rmap_cow(
     238             :         struct xchk_bmap_info   *info,
     239             :         struct xfs_bmbt_irec    *irec,
     240             :         xfs_agblock_t           agbno)
     241             : {
     242      116399 :         struct xfs_rmap_irec    rmap;
     243      116399 :         unsigned long long      rmap_end;
     244      116399 :         uint64_t                owner = XFS_RMAP_OWN_COW;
     245             : 
     246      116399 :         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      116399 :         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      116399 :         if (rmap.rm_startblock > agbno)
     259           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     260             :                                 irec->br_startoff);
     261             : 
     262      116399 :         rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
     263      116399 :         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      116399 :         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      116399 :         if (rmap.rm_flags & XFS_RMAP_ATTR_FORK)
     279           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     280             :                                 irec->br_startoff);
     281      116399 :         if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
     282           0 :                 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
     283             :                                 irec->br_startoff);
     284      116399 :         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   163557757 : xchk_bmap_rt_iextent_xref(
     292             :         struct xfs_inode        *ip,
     293             :         struct xchk_bmap_info   *info,
     294             :         struct xfs_bmbt_irec    *irec)
     295             : {
     296   163557757 :         xchk_xref_is_used_rt_space(info->sc, irec->br_startblock,
     297   163557757 :                         irec->br_blockcount);
     298   163567133 : }
     299             : 
     300             : /* Cross-reference a single datadev extent record. */
     301             : STATIC void
     302   190317640 : xchk_bmap_iextent_xref(
     303             :         struct xfs_inode        *ip,
     304             :         struct xchk_bmap_info   *info,
     305             :         struct xfs_bmbt_irec    *irec)
     306             : {
     307   190317640 :         struct xfs_owner_info   oinfo;
     308   190317640 :         struct xfs_mount        *mp = info->sc->mp;
     309   190317640 :         xfs_agnumber_t          agno;
     310   190317640 :         xfs_agblock_t           agbno;
     311   190317640 :         xfs_extlen_t            len;
     312   190317640 :         int                     error;
     313             : 
     314   190317640 :         agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
     315   190317640 :         agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
     316   190318115 :         len = irec->br_blockcount;
     317             : 
     318   190318115 :         error = xchk_ag_init_existing(info->sc, agno, &info->sc->sa);
     319   190318660 :         if (!xchk_fblock_process_error(info->sc, info->whichfork,
     320             :                         irec->br_startoff, &error))
     321           0 :                 goto out_free;
     322             : 
     323   190318602 :         xchk_xref_is_used_space(info->sc, agbno, len);
     324   190318019 :         xchk_xref_is_not_inode_chunk(info->sc, agbno, len);
     325   190316945 :         switch (info->whichfork) {
     326   189106309 :         case XFS_DATA_FORK:
     327   189106309 :                 xchk_bmap_xref_rmap(info, irec, agbno);
     328   189107441 :                 if (!xfs_is_reflink_inode(info->sc->ip)) {
     329   135848388 :                         xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
     330             :                                         info->whichfork, irec->br_startoff);
     331   135848388 :                         xchk_xref_is_only_owned_by(info->sc, agbno,
     332   135848388 :                                         irec->br_blockcount, &oinfo);
     333   135848387 :                         xchk_xref_is_not_shared(info->sc, agbno,
     334   135848387 :                                         irec->br_blockcount);
     335             :                 }
     336   189107446 :                 xchk_xref_is_not_cow_staging(info->sc, agbno,
     337   189107446 :                                 irec->br_blockcount);
     338   189107446 :                 break;
     339     1094237 :         case XFS_ATTR_FORK:
     340     1094237 :                 xchk_bmap_xref_rmap(info, irec, agbno);
     341     1094237 :                 xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
     342             :                                 info->whichfork, irec->br_startoff);
     343     1094237 :                 xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
     344             :                                 &oinfo);
     345     1094238 :                 xchk_xref_is_not_shared(info->sc, agbno,
     346     1094238 :                                 irec->br_blockcount);
     347     1094239 :                 xchk_xref_is_not_cow_staging(info->sc, agbno,
     348     1094239 :                                 irec->br_blockcount);
     349     1094239 :                 break;
     350      116399 :         case XFS_COW_FORK:
     351      116399 :                 xchk_bmap_xref_rmap_cow(info, irec, agbno);
     352      116399 :                 xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
     353             :                                 &XFS_RMAP_OINFO_COW);
     354      116399 :                 xchk_xref_is_cow_staging(info->sc, agbno,
     355      116399 :                                 irec->br_blockcount);
     356      116399 :                 xchk_xref_is_not_shared(info->sc, agbno,
     357      116399 :                                 irec->br_blockcount);
     358      116399 :                 break;
     359             :         }
     360             : 
     361   190318513 : out_free:
     362   190318513 :         xchk_ag_free(info->sc, &info->sc->sa);
     363   190318312 : }
     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   353865478 : xchk_bmap_dirattr_extent(
     371             :         struct xfs_inode        *ip,
     372             :         struct xchk_bmap_info   *info,
     373             :         struct xfs_bmbt_irec    *irec)
     374             : {
     375   353865478 :         struct xfs_mount        *mp = ip->i_mount;
     376   353865478 :         xfs_fileoff_t           off;
     377             : 
     378   353865478 :         if (!S_ISDIR(VFS_I(ip)->i_mode) && info->whichfork != XFS_ATTR_FORK)
     379             :                 return;
     380             : 
     381     2268613 :         if (!xfs_verify_dablk(mp, irec->br_startoff))
     382           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     383             :                                 irec->br_startoff);
     384             : 
     385     2268614 :         off = irec->br_startoff + irec->br_blockcount - 1;
     386     2268614 :         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   353860504 : xchk_bmap_iextent(
     393             :         struct xfs_inode        *ip,
     394             :         struct xchk_bmap_info   *info,
     395             :         struct xfs_bmbt_irec    *irec)
     396             : {
     397   353860504 :         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   353860504 :         if (irec->br_startoff < info->prev_rec.br_startoff +
     404   353860504 :                                 info->prev_rec.br_blockcount)
     405           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     406             :                                 irec->br_startoff);
     407             : 
     408   353860504 :         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   353868688 :         xchk_bmap_dirattr_extent(ip, info, irec);
     413             : 
     414             :         /* Make sure the extent points to a valid place. */
     415   517413450 :         if (info->is_rt &&
     416   163549531 :             !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   544181740 :         if (!info->is_rt &&
     420   190316999 :             !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   353864741 :         if (irec->br_state == XFS_EXT_UNWRITTEN &&
     426    50812110 :             info->whichfork == XFS_ATTR_FORK)
     427           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     428             :                                 irec->br_startoff);
     429             : 
     430   353864741 :         if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     431             :                 return;
     432             : 
     433   353864741 :         if (info->is_rt)
     434   163546702 :                 xchk_bmap_rt_iextent_xref(ip, info, irec);
     435             :         else
     436   190318039 :                 xchk_bmap_iextent_xref(ip, info, irec);
     437             : }
     438             : 
     439             : /* Scrub a bmbt record. */
     440             : STATIC int
     441   191252406 : xchk_bmapbt_rec(
     442             :         struct xchk_btree       *bs,
     443             :         const union xfs_btree_rec *rec)
     444             : {
     445   191252406 :         struct xfs_bmbt_irec    irec;
     446   191252406 :         struct xfs_bmbt_irec    iext_irec;
     447   191252406 :         struct xfs_iext_cursor  icur;
     448   191252406 :         struct xchk_bmap_info   *info = bs->private;
     449   191252406 :         struct xfs_inode        *ip = bs->cur->bc_ino.ip;
     450   191252406 :         struct xfs_buf          *bp = NULL;
     451   191252406 :         struct xfs_btree_block  *block;
     452   191252406 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, info->whichfork);
     453   191252035 :         uint64_t                owner;
     454   191252035 :         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   191252035 :         if (xfs_has_crc(bs->cur->bc_mp) &&
     461   191253530 :             bs->cur->bc_levels[0].ptr == 1) {
     462     6360863 :                 for (i = 0; i < bs->cur->bc_nlevels - 1; i++) {
     463     3412848 :                         block = xfs_btree_get_block(bs->cur, i, &bp);
     464     3412848 :                         owner = be64_to_cpu(block->bb_u.l.bb_owner);
     465     3412848 :                         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   191252035 :         if (!info->was_loaded)
     479             :                 return 0;
     480             : 
     481   191142564 :         xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
     482   191142931 :         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   191142625 :         if (!xfs_iext_lookup_extent(ip, ifp, irec.br_startoff, &icur,
     489   191141451 :                                 &iext_irec) ||
     490   191141451 :             irec.br_startoff != iext_irec.br_startoff ||
     491   191141852 :             irec.br_startblock != iext_irec.br_startblock ||
     492   191142217 :             irec.br_blockcount != iext_irec.br_blockcount ||
     493   191142464 :             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     2425780 : xchk_bmap_btree(
     502             :         struct xfs_scrub        *sc,
     503             :         int                     whichfork,
     504             :         struct xchk_bmap_info   *info)
     505             : {
     506     2425780 :         struct xfs_owner_info   oinfo;
     507     2425780 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(sc->ip, whichfork);
     508     2425775 :         struct xfs_mount        *mp = sc->mp;
     509     2425775 :         struct xfs_inode        *ip = sc->ip;
     510     2425775 :         struct xfs_btree_cur    *cur;
     511     2425775 :         int                     error;
     512             : 
     513             :         /* Load the incore bmap cache if it's not loaded. */
     514     2425775 :         info->was_loaded = !xfs_need_iread_extents(ifp);
     515             : 
     516     2425779 :         error = xfs_iread_extents(sc->tp, ip, whichfork);
     517     2425781 :         if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
     518           0 :                 goto out;
     519             : 
     520             :         /* Check the btree structure. */
     521     2425779 :         cur = xfs_bmbt_init_cursor(mp, sc->tp, ip, whichfork);
     522     2425782 :         xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
     523     2425782 :         error = xchk_btree(sc, cur, xchk_bmapbt_rec, &oinfo, info);
     524     2425782 :         xfs_btree_del_cursor(cur, error);
     525     2425782 : out:
     526     2425782 :         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 38817855898 : xchk_bmap_check_rmap(
     538             :         struct xfs_btree_cur            *cur,
     539             :         const struct xfs_rmap_irec      *rec,
     540             :         void                            *priv)
     541             : {
     542 38817855898 :         struct xfs_bmbt_irec            irec;
     543 38817855898 :         struct xfs_rmap_irec            check_rec;
     544 38817855898 :         struct xchk_bmap_check_rmap_info        *sbcri = priv;
     545 38817855898 :         struct xfs_ifork                *ifp;
     546 38817855898 :         struct xfs_scrub                *sc = sbcri->sc;
     547 38817855898 :         bool                            have_map;
     548             : 
     549             :         /* Is this even the right fork? */
     550 38817855898 :         if (rec->rm_owner != sc->ip->i_ino)
     551             :                 return 0;
     552      169446 :         if ((sbcri->whichfork == XFS_ATTR_FORK) ^
     553      169446 :             !!(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     1156355 : xchk_bmap_check_ag_rmaps(
     612             :         struct xfs_scrub                *sc,
     613             :         int                             whichfork,
     614             :         struct xfs_perag                *pag)
     615             : {
     616     1156355 :         struct xchk_bmap_check_rmap_info        sbcri;
     617     1156355 :         struct xfs_btree_cur            *cur;
     618     1156355 :         struct xfs_buf                  *agf;
     619     1156355 :         int                             error;
     620             : 
     621     1156355 :         error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf);
     622     1156351 :         if (error)
     623             :                 return error;
     624             : 
     625     1156347 :         cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf, pag);
     626             : 
     627     1156340 :         sbcri.sc = sc;
     628     1156340 :         sbcri.whichfork = whichfork;
     629     1156340 :         error = xfs_rmap_query_all(cur, xchk_bmap_check_rmap, &sbcri);
     630     1156355 :         if (error == -ECANCELED)
     631           0 :                 error = 0;
     632             : 
     633     1156355 :         xfs_btree_del_cursor(cur, error);
     634     1156356 :         xfs_trans_brelse(sc->tp, agf);
     635     1156356 :         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   128433651 : xchk_bmap_want_check_rmaps(
     644             :         struct xchk_bmap_info   *info)
     645             : {
     646   128433651 :         struct xfs_scrub        *sc = info->sc;
     647   128433651 :         struct xfs_ifork        *ifp;
     648             : 
     649   128433651 :         if (!xfs_has_rmapbt(sc->mp))
     650             :                 return false;
     651    60792448 :         if (info->whichfork == XFS_COW_FORK)
     652             :                 return false;
     653    55141719 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     654             :                 return false;
     655             : 
     656             :         /* Don't support realtime rmap checks yet. */
     657    55141719 :         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    55141558 :         ifp = xfs_ifork_ptr(sc->ip, info->whichfork);
     669    55141610 :         if (ifp->if_format == XFS_DINODE_FMT_EXTENTS && ifp->if_nextents == 0) {
     670    34811152 :                 if (info->whichfork == XFS_DATA_FORK &&
     671    34791757 :                     i_size_read(VFS_I(sc->ip)) == 0)
     672             :                         return false;
     673             : 
     674      288135 :                 return true;
     675             :         }
     676             : 
     677             :         return false;
     678             : }
     679             : 
     680             : /* Make sure each rmap has a corresponding bmbt entry. */
     681             : STATIC int
     682      288135 : xchk_bmap_check_rmaps(
     683             :         struct xfs_scrub        *sc,
     684             :         int                     whichfork)
     685             : {
     686      288135 :         struct xfs_perag        *pag;
     687      288135 :         xfs_agnumber_t          agno;
     688      288135 :         int                     error;
     689             : 
     690     1444487 :         for_each_perag(sc->mp, agno, pag) {
     691     1156355 :                 error = xchk_bmap_check_ag_rmaps(sc, whichfork, pag);
     692     1156352 :                 if (error ||
     693     1156352 :                     (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         175 : xchk_bmap_iextent_delalloc(
     705             :         struct xfs_inode        *ip,
     706             :         struct xchk_bmap_info   *info,
     707             :         struct xfs_bmbt_irec    *irec)
     708             : {
     709         175 :         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         175 :         if (irec->br_startoff < info->prev_rec.br_startoff +
     716         175 :                                 info->prev_rec.br_blockcount)
     717           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     718             :                                 irec->br_startoff);
     719             : 
     720         175 :         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         175 :         if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN)
     726           0 :                 xchk_fblock_set_corrupt(info->sc, info->whichfork,
     727             :                                 irec->br_startoff);
     728         175 : }
     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   353826367 :         if (irec->br_startblock == HOLESTARTBLOCK)
     738             :                 return false;
     739   353826367 :         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   296818548 : 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   593635662 :         if (!xfs_bmap_is_real_extent(b1))
     752             :                 return false;
     753   593638020 :         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   296818415 :         if (b1->br_startoff + b1->br_blockcount != b2->br_startoff)
     758             :                 return false;
     759   100229894 :         if (b1->br_startblock + b1->br_blockcount != b2->br_startblock)
     760             :                 return false;
     761    16305453 :         if (b1->br_state != b2->br_state)
     762    16305582 :                 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   482219741 : xchk_bmap_iext_iter(
     774             :         struct xchk_bmap_info   *info,
     775             :         struct xfs_bmbt_irec    *irec)
     776             : {
     777   482219741 :         struct xfs_bmbt_irec    got;
     778   482219741 :         struct xfs_ifork        *ifp;
     779   482219741 :         unsigned int            nr = 0;
     780             : 
     781   482219741 :         ifp = xfs_ifork_ptr(info->sc->ip, info->whichfork);
     782             : 
     783             :         /* Advance to the next iextent record and check the mapping. */
     784   482227569 :         xfs_iext_next(ifp, &info->icur);
     785   482262775 :         if (!xfs_iext_get_extent(ifp, &info->icur, irec))
     786             :                 return false;
     787             : 
     788   353826360 :         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   353826367 :         while (xfs_iext_peek_next_extent(ifp, &info->icur, &got)) {
     800   296820703 :                 if (!xchk_are_bmaps_contiguous(irec, &got))
     801             :                         break;
     802             : 
     803           7 :                 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           7 :                 nr++;
     809             : 
     810           7 :                 irec->br_blockcount += got.br_blockcount;
     811           7 :                 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   353859887 :         if (nr > 1 && info->whichfork != XFS_COW_FORK &&
     820           7 :             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   652708242 : xchk_bmap(
     834             :         struct xfs_scrub        *sc,
     835             :         int                     whichfork)
     836             : {
     837   652708242 :         struct xfs_bmbt_irec    irec;
     838   652708242 :         struct xchk_bmap_info   info = { NULL };
     839   652708242 :         struct xfs_mount        *mp = sc->mp;
     840   652708242 :         struct xfs_inode        *ip = sc->ip;
     841   652708242 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     842   652748982 :         xfs_fileoff_t           endoff;
     843   652748982 :         int                     error = 0;
     844             : 
     845             :         /* Non-existent forks can be ignored. */
     846   652748982 :         if (!ifp)
     847   309257774 :                 goto out;
     848             : 
     849   343491208 :         info.is_rt = whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip);
     850   343491208 :         info.whichfork = whichfork;
     851   343491208 :         info.is_shared = whichfork == XFS_DATA_FORK && xfs_is_reflink_inode(ip);
     852   343491208 :         info.sc = sc;
     853             : 
     854   343491208 :         switch (whichfork) {
     855             :         case XFS_COW_FORK:
     856             :                 /* No CoW forks on non-reflink inodes/filesystems. */
     857     5650747 :                 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    13481487 :                 if (!xfs_has_attr(mp) && !xfs_has_attr2(mp))
     864           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     865             :                 break;
     866   324358974 :         default:
     867   324358974 :                 ASSERT(whichfork == XFS_DATA_FORK);
     868             :                 break;
     869             :         }
     870             : 
     871             :         /* Check the fork values */
     872   343491208 :         switch (ifp->if_format) {
     873   215057151 :         case XFS_DINODE_FMT_UUID:
     874             :         case XFS_DINODE_FMT_DEV:
     875             :         case XFS_DINODE_FMT_LOCAL:
     876             :                 /* No mappings to check. */
     877   215057151 :                 if (whichfork == XFS_COW_FORK)
     878           0 :                         xchk_fblock_set_corrupt(sc, whichfork, 0);
     879   215057151 :                 goto out;
     880             :         case XFS_DINODE_FMT_EXTENTS:
     881             :                 break;
     882     2425779 :         case XFS_DINODE_FMT_BTREE:
     883     2425779 :                 if (whichfork == XFS_COW_FORK) {
     884           0 :                         xchk_fblock_set_corrupt(sc, whichfork, 0);
     885           0 :                         goto out;
     886             :                 }
     887             : 
     888     2425779 :                 error = xchk_bmap_btree(sc, whichfork, &info);
     889     2425773 :                 if (error)
     890           1 :                         goto out;
     891             :                 break;
     892           0 :         default:
     893           0 :                 xchk_fblock_set_corrupt(sc, whichfork, 0);
     894           0 :                 goto out;
     895             :         }
     896             : 
     897   128434050 :         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   128434050 :         error = xfs_bmap_last_offset(ip, &endoff, whichfork);
     902   128434537 :         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   482318755 :         while (xchk_bmap_iext_iter(&info, &irec)) {
     914   353850899 :                 if (xchk_should_terminate(sc, &error) ||
     915   353851888 :                     (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
     916           7 :                         goto out;
     917             : 
     918   353851888 :                 if (irec.br_startoff >= endoff) {
     919           0 :                         xchk_fblock_set_corrupt(sc, whichfork,
     920             :                                         irec.br_startoff);
     921           0 :                         goto out;
     922             :                 }
     923             : 
     924   353851888 :                 if (isnullstartblock(irec.br_startblock))
     925         175 :                         xchk_bmap_iextent_delalloc(ip, &info, &irec);
     926             :                 else
     927   353851713 :                         xchk_bmap_iextent(ip, &info, &irec);
     928   353886875 :                 memcpy(&info.prev_rec, &irec, sizeof(struct xfs_bmbt_irec));
     929             :         }
     930             : 
     931   128429694 :         if (xchk_bmap_want_check_rmaps(&info)) {
     932      288135 :                 error = xchk_bmap_check_rmaps(sc, whichfork);
     933      288135 :                 if (!xchk_fblock_xref_process_error(sc, whichfork, 0, &error))
     934             :                         goto out;
     935             :         }
     936   128431914 : out:
     937   652746847 :         return error;
     938             : }
     939             : 
     940             : /* Scrub an inode's data fork. */
     941             : int
     942   324352970 : xchk_bmap_data(
     943             :         struct xfs_scrub        *sc)
     944             : {
     945   324352970 :         return xchk_bmap(sc, XFS_DATA_FORK);
     946             : }
     947             : 
     948             : /* Scrub an inode's attr fork. */
     949             : int
     950   322734375 : xchk_bmap_attr(
     951             :         struct xfs_scrub        *sc)
     952             : {
     953   322734375 :         return xchk_bmap(sc, XFS_ATTR_FORK);
     954             : }
     955             : 
     956             : /* Scrub an inode's CoW fork. */
     957             : int
     958   248936738 : xchk_bmap_cow(
     959             :         struct xfs_scrub        *sc)
     960             : {
     961   248936738 :         if (!xfs_is_reflink_inode(sc->ip))
     962             :                 return -ENOENT;
     963             : 
     964     5650745 :         return xchk_bmap(sc, XFS_COW_FORK);
     965             : }

Generated by: LCOV version 1.14