LCOV - code coverage report
Current view: top level - fs/xfs/scrub - inode.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 241 340 70.9 %
Date: 2023-07-31 20:08:07 Functions: 15 15 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_log_format.h"
      14             : #include "xfs_trans.h"
      15             : #include "xfs_ag.h"
      16             : #include "xfs_inode.h"
      17             : #include "xfs_ialloc.h"
      18             : #include "xfs_icache.h"
      19             : #include "xfs_da_format.h"
      20             : #include "xfs_reflink.h"
      21             : #include "xfs_rmap.h"
      22             : #include "xfs_bmap_util.h"
      23             : #include "scrub/scrub.h"
      24             : #include "scrub/common.h"
      25             : #include "scrub/btree.h"
      26             : #include "scrub/trace.h"
      27             : #include "scrub/repair.h"
      28             : 
      29             : /* Prepare the attached inode for scrubbing. */
      30             : static inline int
      31   103144882 : xchk_prepare_iscrub(
      32             :         struct xfs_scrub        *sc)
      33             : {
      34   103144882 :         int                     error;
      35             : 
      36   103144882 :         xchk_ilock(sc, XFS_IOLOCK_EXCL);
      37             : 
      38   103145787 :         error = xchk_trans_alloc(sc, 0);
      39   103143184 :         if (error)
      40             :                 return error;
      41             : 
      42   103143161 :         error = xchk_ino_dqattach(sc);
      43   103144273 :         if (error)
      44             :                 return error;
      45             : 
      46   103144171 :         xchk_ilock(sc, XFS_ILOCK_EXCL);
      47   103144171 :         return 0;
      48             : }
      49             : 
      50             : /* Install this scrub-by-handle inode and prepare it for scrubbing. */
      51             : static inline int
      52    77736473 : xchk_install_handle_iscrub(
      53             :         struct xfs_scrub        *sc,
      54             :         struct xfs_inode        *ip)
      55             : {
      56    77736473 :         int                     error;
      57             : 
      58    77736473 :         error = xchk_install_handle_inode(sc, ip);
      59    77733123 :         if (error)
      60             :                 return error;
      61             : 
      62    77638165 :         return xchk_prepare_iscrub(sc);
      63             : }
      64             : 
      65             : /*
      66             :  * Grab total control of the inode metadata.  In the best case, we grab the
      67             :  * incore inode and take all locks on it.  If the incore inode cannot be
      68             :  * constructed due to corruption problems, lock the AGI so that we can single
      69             :  * step the loading process to fix everything that can go wrong.
      70             :  */
      71             : int
      72   103762604 : xchk_setup_inode(
      73             :         struct xfs_scrub        *sc)
      74             : {
      75   103762604 :         struct xfs_imap         imap;
      76   103762604 :         struct xfs_inode        *ip;
      77   103762604 :         struct xfs_mount        *mp = sc->mp;
      78   103762604 :         struct xfs_inode        *ip_in = XFS_I(file_inode(sc->file));
      79   103762604 :         struct xfs_buf          *agi_bp;
      80   103762604 :         struct xfs_perag        *pag;
      81   103762604 :         xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, sc->sm->sm_ino);
      82   103762604 :         int                     error;
      83             : 
      84   103762604 :         if (xchk_need_intent_drain(sc))
      85           0 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      86             : 
      87             :         /* We want to scan the opened inode, so lock it and exit. */
      88   103762604 :         if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) {
      89    25498886 :                 error = xchk_install_live_inode(sc, ip_in);
      90    25505008 :                 if (error)
      91             :                         return error;
      92             : 
      93    25504828 :                 return xchk_prepare_iscrub(sc);
      94             :         }
      95             : 
      96             :         /* Reject internal metadata files and obviously bad inode numbers. */
      97    78263718 :         if (xfs_internal_inum(mp, sc->sm->sm_ino))
      98             :                 return -ENOENT;
      99    78223065 :         if (!xfs_verify_ino(sc->mp, sc->sm->sm_ino))
     100             :                 return -ENOENT;
     101             : 
     102             :         /* Try a regular untrusted iget. */
     103    78217251 :         error = xchk_iget(sc, sc->sm->sm_ino, &ip);
     104    78217482 :         if (!error)
     105    77735746 :                 return xchk_install_handle_iscrub(sc, ip);
     106      481736 :         if (error == -ENOENT)
     107             :                 return error;
     108        3775 :         if (error != -EFSCORRUPTED && error != -EFSBADCRC && error != -EINVAL)
     109           0 :                 goto out_error;
     110             : 
     111             :         /*
     112             :          * EINVAL with IGET_UNTRUSTED probably means one of several things:
     113             :          * userspace gave us an inode number that doesn't correspond to fs
     114             :          * space; the inode btree lacks a record for this inode; or there is
     115             :          * a record, and it says this inode is free.
     116             :          *
     117             :          * EFSCORRUPTED/EFSBADCRC could mean that the inode was mappable, but
     118             :          * some other metadata corruption (e.g. inode forks) prevented
     119             :          * instantiation of the incore inode.  Or it could mean the inobt is
     120             :          * corrupt.
     121             :          *
     122             :          * We want to look up this inode in the inobt directly to distinguish
     123             :          * three different scenarios: (1) the inobt says the inode is free,
     124             :          * in which case there's nothing to do; (2) the inobt is corrupt so we
     125             :          * should flag the corruption and exit to userspace to let it fix the
     126             :          * inobt; and (3) the inobt says the inode is allocated, but loading it
     127             :          * failed due to corruption.
     128             :          *
     129             :          * Allocate a transaction and grab the AGI to prevent inobt activity in
     130             :          * this AG.  Retry the iget in case someone allocated a new inode after
     131             :          * the first iget failed.
     132             :          */
     133        3775 :         error = xchk_trans_alloc(sc, 0);
     134        3775 :         if (error)
     135           0 :                 goto out_error;
     136             : 
     137        3775 :         error = xchk_iget_agi(sc, sc->sm->sm_ino, &agi_bp, &ip);
     138        3775 :         if (error == 0) {
     139             :                 /* Actually got the incore inode, so install it and proceed. */
     140           0 :                 xchk_trans_cancel(sc);
     141           0 :                 return xchk_install_handle_iscrub(sc, ip);
     142             :         }
     143        3775 :         if (error == -ENOENT)
     144           0 :                 goto out_gone;
     145        3775 :         if (error != -EFSCORRUPTED && error != -EFSBADCRC && error != -EINVAL)
     146           0 :                 goto out_cancel;
     147             : 
     148             :         /* Ensure that we have protected against inode allocation/freeing. */
     149        3775 :         if (agi_bp == NULL) {
     150           0 :                 ASSERT(agi_bp != NULL);
     151           0 :                 error = -ECANCELED;
     152           0 :                 goto out_cancel;
     153             :         }
     154             : 
     155             :         /*
     156             :          * Untrusted iget failed a second time.  Let's try an inobt lookup.
     157             :          * If the inobt doesn't think this is an allocated inode then we'll
     158             :          * return ENOENT to signal that the check can be skipped.
     159             :          *
     160             :          * If the lookup signals corruption, we'll mark this inode corrupt and
     161             :          * exit to userspace.  There's little chance of fixing anything until
     162             :          * the inobt is straightened out, but there's nothing we can do here.
     163             :          *
     164             :          * If the lookup encounters a runtime error, exit to userspace.
     165             :          */
     166        3775 :         pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, sc->sm->sm_ino));
     167        3775 :         if (!pag) {
     168           0 :                 error = -EFSCORRUPTED;
     169           0 :                 goto out_cancel;
     170             :         }
     171             : 
     172        3775 :         error = xfs_imap(pag, sc->tp, sc->sm->sm_ino, &imap,
     173             :                         XFS_IGET_UNTRUSTED);
     174        3775 :         xfs_perag_put(pag);
     175        3775 :         if (error == -EINVAL || error == -ENOENT)
     176        3775 :                 goto out_gone;
     177           0 :         if (error)
     178           0 :                 goto out_cancel;
     179             : 
     180             :         /*
     181             :          * The lookup succeeded.  Chances are the ondisk inode is corrupt and
     182             :          * preventing iget from reading it.  Retain the scrub transaction and
     183             :          * the AGI buffer to prevent anyone from allocating or freeing inodes.
     184             :          * This ensures that we preserve the inconsistency between the inobt
     185             :          * saying the inode is allocated and the icache being unable to load
     186             :          * the inode until we can flag the corruption in xchk_inode.  The
     187             :          * scrub function has to note the corruption, since we're not really
     188             :          * supposed to do that from the setup function.  Save the mapping to
     189             :          * make repairs to the ondisk inode buffer.
     190             :          */
     191           0 :         if (xchk_could_repair(sc))
     192           0 :                 xrep_setup_inode(sc, &imap);
     193             :         return 0;
     194             : 
     195           0 : out_cancel:
     196           0 :         xchk_trans_cancel(sc);
     197           0 : out_error:
     198           0 :         xchk_whine(mp, "type %s agno 0x%x agbno 0x%x error %d ret_ip %pS",
     199           0 :                         xchk_type_string(sc->sm->sm_type), agno,
     200           0 :                         XFS_INO_TO_AGBNO(mp, sc->sm->sm_ino), error,
     201             :                         __return_address);
     202           0 :         trace_xchk_op_error(sc, agno, XFS_INO_TO_AGBNO(mp, sc->sm->sm_ino),
     203             :                         error, __return_address);
     204           0 :         return error;
     205        3775 : out_gone:
     206             :         /* The file is gone, so there's nothing to check. */
     207        3775 :         xchk_trans_cancel(sc);
     208        3775 :         return -ENOENT;
     209             : }
     210             : 
     211             : /* Inode core */
     212             : 
     213             : /* Validate di_extsize hint. */
     214             : STATIC void
     215   103230757 : xchk_inode_extsize(
     216             :         struct xfs_scrub        *sc,
     217             :         struct xfs_dinode       *dip,
     218             :         xfs_ino_t               ino,
     219             :         uint16_t                mode,
     220             :         uint16_t                flags)
     221             : {
     222   103230757 :         xfs_failaddr_t          fa;
     223   103230757 :         uint32_t                value = be32_to_cpu(dip->di_extsize);
     224             : 
     225   103230757 :         fa = xfs_inode_validate_extsize(sc->mp, value, mode, flags);
     226   103239214 :         if (fa)
     227           0 :                 xchk_ino_set_corrupt(sc, ino);
     228             : 
     229             :         /*
     230             :          * XFS allows a sysadmin to change the rt extent size when adding a rt
     231             :          * section to a filesystem after formatting.  If there are any
     232             :          * directories with extszinherit and rtinherit set, the hint could
     233             :          * become misaligned with the new rextsize.  The verifier doesn't check
     234             :          * this, because we allow rtinherit directories even without an rt
     235             :          * device.  Flag this as an administrative warning since we will clean
     236             :          * this up eventually.
     237             :          */
     238   103239214 :         if ((flags & XFS_DIFLAG_RTINHERIT) &&
     239           0 :             (flags & XFS_DIFLAG_EXTSZINHERIT) &&
     240           0 :             value % sc->mp->m_sb.sb_rextsize > 0)
     241           0 :                 xchk_ino_set_warning(sc, ino);
     242   103239214 : }
     243             : 
     244             : /*
     245             :  * Validate di_cowextsize hint.
     246             :  *
     247             :  * The rules are documented at xfs_ioctl_setattr_check_cowextsize().
     248             :  * These functions must be kept in sync with each other.
     249             :  */
     250             : STATIC void
     251   103232290 : xchk_inode_cowextsize(
     252             :         struct xfs_scrub        *sc,
     253             :         struct xfs_dinode       *dip,
     254             :         xfs_ino_t               ino,
     255             :         uint16_t                mode,
     256             :         uint16_t                flags,
     257             :         uint64_t                flags2)
     258             : {
     259   103232290 :         xfs_failaddr_t          fa;
     260             : 
     261   103232290 :         fa = xfs_inode_validate_cowextsize(sc->mp,
     262   103232290 :                         be32_to_cpu(dip->di_cowextsize), mode, flags,
     263             :                         flags2);
     264   103235934 :         if (fa)
     265           0 :                 xchk_ino_set_corrupt(sc, ino);
     266   103235934 : }
     267             : 
     268             : /* Make sure the di_flags make sense for the inode. */
     269             : STATIC void
     270   103234717 : xchk_inode_flags(
     271             :         struct xfs_scrub        *sc,
     272             :         struct xfs_dinode       *dip,
     273             :         xfs_ino_t               ino,
     274             :         uint16_t                mode,
     275             :         uint16_t                flags)
     276             : {
     277   103234717 :         struct xfs_mount        *mp = sc->mp;
     278             : 
     279             :         /* di_flags are all taken, last bit cannot be used */
     280   103234717 :         if (flags & ~XFS_DIFLAG_ANY)
     281           0 :                 goto bad;
     282             : 
     283             :         /* rt flags require rt device */
     284   103234717 :         if ((flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
     285           0 :                 goto bad;
     286             : 
     287             :         /* new rt bitmap flag only valid for rbmino */
     288   103234717 :         if ((flags & XFS_DIFLAG_NEWRTBM) && ino != mp->m_sb.sb_rbmino)
     289           0 :                 goto bad;
     290             : 
     291             :         /* directory-only flags */
     292   103234717 :         if ((flags & (XFS_DIFLAG_RTINHERIT |
     293             :                      XFS_DIFLAG_EXTSZINHERIT |
     294             :                      XFS_DIFLAG_PROJINHERIT |
     295     7627471 :                      XFS_DIFLAG_NOSYMLINKS)) &&
     296             :             !S_ISDIR(mode))
     297           0 :                 goto bad;
     298             : 
     299             :         /* file-only flags */
     300   103234717 :         if ((flags & (XFS_DIFLAG_REALTIME | FS_XFLAG_EXTSIZE)) &&
     301             :             !S_ISREG(mode))
     302           0 :                 goto bad;
     303             : 
     304             :         /* filestreams and rt make no sense */
     305   103234717 :         if ((flags & XFS_DIFLAG_FILESTREAM) && (flags & XFS_DIFLAG_REALTIME))
     306           0 :                 goto bad;
     307             : 
     308             :         return;
     309           0 : bad:
     310           0 :         xchk_ino_set_corrupt(sc, ino);
     311             : }
     312             : 
     313             : /* Make sure the di_flags2 make sense for the inode. */
     314             : STATIC void
     315   103245631 : xchk_inode_flags2(
     316             :         struct xfs_scrub        *sc,
     317             :         struct xfs_dinode       *dip,
     318             :         xfs_ino_t               ino,
     319             :         uint16_t                mode,
     320             :         uint16_t                flags,
     321             :         uint64_t                flags2)
     322             : {
     323   103245631 :         struct xfs_mount        *mp = sc->mp;
     324             : 
     325             :         /* Unknown di_flags2 could be from a future kernel */
     326   103245631 :         if (flags2 & ~XFS_DIFLAG2_ANY)
     327           0 :                 xchk_ino_set_warning(sc, ino);
     328             : 
     329             :         /* reflink flag requires reflink feature */
     330   103245631 :         if ((flags2 & XFS_DIFLAG2_REFLINK) &&
     331             :             !xfs_has_reflink(mp))
     332           0 :                 goto bad;
     333             : 
     334             :         /* cowextsize flag is checked w.r.t. mode separately */
     335             : 
     336             :         /* file/dir-only flags */
     337   103245631 :         if ((flags2 & XFS_DIFLAG2_DAX) && !(S_ISREG(mode) || S_ISDIR(mode)))
     338           0 :                 goto bad;
     339             : 
     340             :         /* file-only flags */
     341   103245631 :         if ((flags2 & XFS_DIFLAG2_REFLINK) && !S_ISREG(mode))
     342           0 :                 goto bad;
     343             : 
     344             :         /* realtime and reflink make no sense, currently */
     345   103245631 :         if ((flags & XFS_DIFLAG_REALTIME) && (flags2 & XFS_DIFLAG2_REFLINK))
     346           0 :                 goto bad;
     347             : 
     348             :         /* no bigtime iflag without the bigtime feature */
     349   206491262 :         if (xfs_dinode_has_bigtime(dip) && !xfs_has_bigtime(mp))
     350           0 :                 goto bad;
     351             : 
     352             :         /* no large extent counts without the filesystem feature */
     353   103245631 :         if ((flags2 & XFS_DIFLAG2_NREXT64) && !xfs_has_large_extent_counts(mp))
     354           0 :                 goto bad;
     355             : 
     356             :         return;
     357           0 : bad:
     358           0 :         xchk_ino_set_corrupt(sc, ino);
     359             : }
     360             : 
     361             : static inline void
     362   412927078 : xchk_dinode_nsec(
     363             :         struct xfs_scrub        *sc,
     364             :         xfs_ino_t               ino,
     365             :         struct xfs_dinode       *dip,
     366             :         const xfs_timestamp_t   ts)
     367             : {
     368   412927078 :         struct timespec64       tv;
     369             : 
     370   412927078 :         tv = xfs_inode_from_disk_ts(dip, ts);
     371   412932133 :         if (tv.tv_nsec < 0 || tv.tv_nsec >= NSEC_PER_SEC)
     372           0 :                 xchk_ino_set_corrupt(sc, ino);
     373   412932133 : }
     374             : 
     375             : /* Scrub all the ondisk inode fields. */
     376             : STATIC void
     377   103255970 : xchk_dinode(
     378             :         struct xfs_scrub        *sc,
     379             :         struct xfs_dinode       *dip,
     380             :         xfs_ino_t               ino)
     381             : {
     382   103255970 :         struct xfs_mount        *mp = sc->mp;
     383   103255970 :         size_t                  fork_recs;
     384   103255970 :         unsigned long long      isize;
     385   103255970 :         uint64_t                flags2;
     386   103255970 :         xfs_extnum_t            nextents;
     387   103255970 :         xfs_extnum_t            naextents;
     388   103255970 :         prid_t                  prid;
     389   103255970 :         uint16_t                flags;
     390   103255970 :         uint16_t                mode;
     391             : 
     392   103255970 :         flags = be16_to_cpu(dip->di_flags);
     393   103255970 :         if (dip->di_version >= 3)
     394   103238159 :                 flags2 = be64_to_cpu(dip->di_flags2);
     395             :         else
     396             :                 flags2 = 0;
     397             : 
     398             :         /* di_mode */
     399   103255970 :         mode = be16_to_cpu(dip->di_mode);
     400   103255970 :         switch (mode & S_IFMT) {
     401             :         case S_IFLNK:
     402             :         case S_IFREG:
     403             :         case S_IFDIR:
     404             :         case S_IFCHR:
     405             :         case S_IFBLK:
     406             :         case S_IFIFO:
     407             :         case S_IFSOCK:
     408             :                 /* mode is recognized */
     409             :                 break;
     410           0 :         default:
     411           0 :                 xchk_ino_set_corrupt(sc, ino);
     412           0 :                 break;
     413             :         }
     414             : 
     415             :         /* v1/v2 fields */
     416   103255970 :         switch (dip->di_version) {
     417           0 :         case 1:
     418             :                 /*
     419             :                  * We autoconvert v1 inodes into v2 inodes on writeout,
     420             :                  * so just mark this inode for preening.
     421             :                  */
     422           0 :                 xchk_ino_set_preen(sc, ino);
     423           0 :                 prid = 0;
     424           0 :                 break;
     425   103255970 :         case 2:
     426             :         case 3:
     427   103255970 :                 if (dip->di_onlink != 0)
     428           0 :                         xchk_ino_set_corrupt(sc, ino);
     429             : 
     430   103255970 :                 if (dip->di_mode == 0 && sc->ip)
     431           0 :                         xchk_ino_set_corrupt(sc, ino);
     432             : 
     433   103255970 :                 if (dip->di_projid_hi != 0 &&
     434             :                     !xfs_has_projid32(mp))
     435           0 :                         xchk_ino_set_corrupt(sc, ino);
     436             : 
     437   103255970 :                 prid = be16_to_cpu(dip->di_projid_lo);
     438             :                 break;
     439           0 :         default:
     440           0 :                 xchk_ino_set_corrupt(sc, ino);
     441           0 :                 return;
     442             :         }
     443             : 
     444   103255970 :         if (xfs_has_projid32(mp))
     445   103255456 :                 prid |= (prid_t)be16_to_cpu(dip->di_projid_hi) << 16;
     446             : 
     447             :         /*
     448             :          * di_uid/di_gid -- -1 isn't invalid, but there's no way that
     449             :          * userspace could have created that.
     450             :          */
     451   103255970 :         if (dip->di_uid == cpu_to_be32(-1U) ||
     452   103255970 :             dip->di_gid == cpu_to_be32(-1U))
     453           0 :                 xchk_ino_set_warning(sc, ino);
     454             : 
     455             :         /*
     456             :          * project id of -1 isn't supposed to be valid, but the kernel didn't
     457             :          * always validate that.
     458             :          */
     459   103257359 :         if (prid == -1U)
     460           0 :                 xchk_ino_set_warning(sc, ino);
     461             : 
     462             :         /* di_format */
     463   103257359 :         switch (dip->di_format) {
     464    45287756 :         case XFS_DINODE_FMT_DEV:
     465    45287756 :                 if (!S_ISCHR(mode) && !S_ISBLK(mode) &&
     466           0 :                     !S_ISFIFO(mode) && !S_ISSOCK(mode))
     467           0 :                         xchk_ino_set_corrupt(sc, ino);
     468             :                 break;
     469    17479577 :         case XFS_DINODE_FMT_LOCAL:
     470    17479577 :                 if (!S_ISDIR(mode) && !S_ISLNK(mode))
     471           0 :                         xchk_ino_set_corrupt(sc, ino);
     472             :                 break;
     473    38939235 :         case XFS_DINODE_FMT_EXTENTS:
     474    38939235 :                 if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode))
     475           0 :                         xchk_ino_set_corrupt(sc, ino);
     476             :                 break;
     477     1550791 :         case XFS_DINODE_FMT_BTREE:
     478     1550791 :                 if (!S_ISREG(mode) && !S_ISDIR(mode))
     479           0 :                         xchk_ino_set_corrupt(sc, ino);
     480             :                 break;
     481           0 :         case XFS_DINODE_FMT_UUID:
     482             :         default:
     483           0 :                 xchk_ino_set_corrupt(sc, ino);
     484           0 :                 break;
     485             :         }
     486             : 
     487             :         /* di_[amc]time.nsec */
     488   103257359 :         xchk_dinode_nsec(sc, ino, dip, dip->di_atime);
     489   103249247 :         xchk_dinode_nsec(sc, ino, dip, dip->di_mtime);
     490   103246551 :         xchk_dinode_nsec(sc, ino, dip, dip->di_ctime);
     491             : 
     492             :         /*
     493             :          * di_size.  xfs_dinode_verify checks for things that screw up
     494             :          * the VFS such as the upper bit being set and zero-length
     495             :          * symlinks/directories, but we can do more here.
     496             :          */
     497   103240853 :         isize = be64_to_cpu(dip->di_size);
     498   103240853 :         if (isize & (1ULL << 63))
     499           0 :                 xchk_ino_set_corrupt(sc, ino);
     500             : 
     501             :         /* Devices, fifos, and sockets must have zero size */
     502   103240853 :         if (!S_ISDIR(mode) && !S_ISREG(mode) && !S_ISLNK(mode) && isize != 0)
     503           0 :                 xchk_ino_set_corrupt(sc, ino);
     504             : 
     505             :         /* Directories can't be larger than the data section size (32G) */
     506   103240853 :         if (S_ISDIR(mode) && (isize == 0 || isize >= XFS_DIR2_SPACE_SIZE))
     507           0 :                 xchk_ino_set_corrupt(sc, ino);
     508             : 
     509             :         /* Symlinks can't be larger than SYMLINK_MAXLEN */
     510   103240853 :         if (S_ISLNK(mode) && (isize == 0 || isize >= XFS_SYMLINK_MAXLEN))
     511           0 :                 xchk_ino_set_corrupt(sc, ino);
     512             : 
     513             :         /*
     514             :          * Warn if the running kernel can't handle the kinds of offsets
     515             :          * needed to deal with the file size.  In other words, if the
     516             :          * pagecache can't cache all the blocks in this file due to
     517             :          * overly large offsets, flag the inode for admin review.
     518             :          */
     519   103240853 :         if (isize > mp->m_super->s_maxbytes)
     520           0 :                 xchk_ino_set_warning(sc, ino);
     521             : 
     522             :         /* di_nblocks */
     523   103240853 :         if (flags2 & XFS_DIFLAG2_REFLINK) {
     524             :                 ; /* nblocks can exceed dblocks */
     525   100076359 :         } else if (flags & XFS_DIFLAG_REALTIME) {
     526             :                 /*
     527             :                  * nblocks is the sum of data extents (in the rtdev),
     528             :                  * attr extents (in the datadev), and both forks' bmbt
     529             :                  * blocks (in the datadev).  This clumsy check is the
     530             :                  * best we can do without cross-referencing with the
     531             :                  * inode forks.
     532             :                  */
     533    11089024 :                 if (be64_to_cpu(dip->di_nblocks) >=
     534    11089024 :                     mp->m_sb.sb_dblocks + mp->m_sb.sb_rblocks)
     535           0 :                         xchk_ino_set_corrupt(sc, ino);
     536             :         } else {
     537    88987335 :                 if (be64_to_cpu(dip->di_nblocks) >= mp->m_sb.sb_dblocks)
     538           0 :                         xchk_ino_set_corrupt(sc, ino);
     539             :         }
     540             : 
     541   103240853 :         xchk_inode_flags(sc, dip, ino, mode, flags);
     542             : 
     543   103232661 :         xchk_inode_extsize(sc, dip, ino, mode, flags);
     544             : 
     545   103244370 :         nextents = xfs_dfork_data_extents(dip);
     546   103244370 :         naextents = xfs_dfork_attr_extents(dip);
     547             : 
     548             :         /* di_nextents */
     549   103244384 :         fork_recs =  XFS_DFORK_DSIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
     550   103244370 :         switch (dip->di_format) {
     551    38927205 :         case XFS_DINODE_FMT_EXTENTS:
     552    38927205 :                 if (nextents > fork_recs)
     553           0 :                         xchk_ino_set_corrupt(sc, ino);
     554             :                 break;
     555     1550808 :         case XFS_DINODE_FMT_BTREE:
     556     1550808 :                 if (nextents <= fork_recs)
     557           0 :                         xchk_ino_set_corrupt(sc, ino);
     558             :                 break;
     559    62766357 :         default:
     560    62766357 :                 if (nextents != 0)
     561           0 :                         xchk_ino_set_corrupt(sc, ino);
     562             :                 break;
     563             :         }
     564             : 
     565             :         /* di_forkoff */
     566   206489784 :         if (XFS_DFORK_APTR(dip) >= (char *)dip + mp->m_sb.sb_inodesize)
     567           0 :                 xchk_ino_set_corrupt(sc, ino);
     568   103244370 :         if (naextents != 0 && dip->di_forkoff == 0)
     569           0 :                 xchk_ino_set_corrupt(sc, ino);
     570   103244370 :         if (dip->di_forkoff == 0 && dip->di_aformat != XFS_DINODE_FMT_EXTENTS)
     571           0 :                 xchk_ino_set_corrupt(sc, ino);
     572             : 
     573             :         /* di_aformat */
     574   103244370 :         if (dip->di_aformat != XFS_DINODE_FMT_LOCAL &&
     575   103244370 :             dip->di_aformat != XFS_DINODE_FMT_EXTENTS &&
     576             :             dip->di_aformat != XFS_DINODE_FMT_BTREE)
     577           0 :                 xchk_ino_set_corrupt(sc, ino);
     578             : 
     579             :         /* di_anextents */
     580   103251385 :         fork_recs =  XFS_DFORK_ASIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
     581   103251383 :         switch (dip->di_aformat) {
     582     1283452 :         case XFS_DINODE_FMT_EXTENTS:
     583     1283452 :                 if (naextents > fork_recs)
     584           0 :                         xchk_ino_set_corrupt(sc, ino);
     585             :                 break;
     586          38 :         case XFS_DINODE_FMT_BTREE:
     587          38 :                 if (naextents <= fork_recs)
     588           0 :                         xchk_ino_set_corrupt(sc, ino);
     589             :                 break;
     590   101967893 :         default:
     591   101967893 :                 if (naextents != 0)
     592           0 :                         xchk_ino_set_corrupt(sc, ino);
     593             :         }
     594             : 
     595   103251383 :         if (dip->di_version >= 3) {
     596   103239986 :                 xchk_dinode_nsec(sc, ino, dip, dip->di_crtime);
     597   103239562 :                 xchk_inode_flags2(sc, dip, ino, mode, flags, flags2);
     598   103232967 :                 xchk_inode_cowextsize(sc, dip, ino, mode, flags,
     599             :                                 flags2);
     600             :         }
     601             : }
     602             : 
     603             : /*
     604             :  * Make sure the finobt doesn't think this inode is free.
     605             :  * We don't have to check the inobt ourselves because we got the inode via
     606             :  * IGET_UNTRUSTED, which checks the inobt for us.
     607             :  */
     608             : static void
     609   103265780 : xchk_inode_xref_finobt(
     610             :         struct xfs_scrub                *sc,
     611             :         xfs_ino_t                       ino)
     612             : {
     613   103265780 :         struct xfs_inobt_rec_incore     rec;
     614   103265780 :         xfs_agino_t                     agino;
     615   103265780 :         int                             has_record;
     616   103265780 :         int                             error;
     617             : 
     618   103265780 :         if (!sc->sa.fino_cur || xchk_skip_xref(sc->sm))
     619    98062971 :                 return;
     620             : 
     621   103265774 :         agino = XFS_INO_TO_AGINO(sc->mp, ino);
     622             : 
     623             :         /*
     624             :          * Try to get the finobt record.  If we can't get it, then we're
     625             :          * in good shape.
     626             :          */
     627   103265774 :         error = xfs_inobt_lookup(sc->sa.fino_cur, agino, XFS_LOOKUP_LE,
     628             :                         &has_record);
     629   103265969 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
     630   103266028 :             !has_record)
     631             :                 return;
     632             : 
     633    21626164 :         error = xfs_inobt_get_rec(sc->sa.fino_cur, &rec, &has_record);
     634    21626154 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
     635    21626161 :             !has_record)
     636             :                 return;
     637             : 
     638             :         /*
     639             :          * Otherwise, make sure this record either doesn't cover this inode,
     640             :          * or that it does but it's marked present.
     641             :          */
     642    21626161 :         if (rec.ir_startino > agino ||
     643    21626161 :             rec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
     644             :                 return;
     645             : 
     646     5203060 :         if (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino))
     647           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.fino_cur, 0);
     648             : }
     649             : 
     650             : /* Cross reference the inode fields with the forks. */
     651             : STATIC void
     652   103265671 : xchk_inode_xref_bmap(
     653             :         struct xfs_scrub        *sc,
     654             :         struct xfs_dinode       *dip)
     655             : {
     656   103265671 :         xfs_extnum_t            nextents;
     657   103265671 :         xfs_filblks_t           count;
     658   103265671 :         xfs_filblks_t           acount;
     659   103265671 :         int                     error;
     660             : 
     661   103265671 :         if (xchk_skip_xref(sc->sm))
     662           0 :                 return;
     663             : 
     664             :         /* Walk all the extents to check nextents/naextents/nblocks. */
     665   103265671 :         error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_DATA_FORK,
     666             :                         &nextents, &count);
     667   103265495 :         if (!xchk_should_check_xref(sc, &error, NULL))
     668             :                 return;
     669   103265334 :         if (nextents < xfs_dfork_data_extents(dip))
     670           0 :                 xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
     671             : 
     672   103265334 :         error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_ATTR_FORK,
     673             :                         &nextents, &acount);
     674   103265630 :         if (!xchk_should_check_xref(sc, &error, NULL))
     675             :                 return;
     676   103265553 :         if (nextents != xfs_dfork_attr_extents(dip))
     677           0 :                 xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
     678             : 
     679             :         /* Check nblocks against the inode. */
     680   103265553 :         if (count + acount != be64_to_cpu(dip->di_nblocks))
     681           0 :                 xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
     682             : }
     683             : 
     684             : /* Cross-reference with the other btrees. */
     685             : STATIC void
     686   103251679 : xchk_inode_xref(
     687             :         struct xfs_scrub        *sc,
     688             :         xfs_ino_t               ino,
     689             :         struct xfs_dinode       *dip)
     690             : {
     691   103251679 :         xfs_agnumber_t          agno;
     692   103251679 :         xfs_agblock_t           agbno;
     693   103251679 :         int                     error;
     694             : 
     695   103251679 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     696           0 :                 return;
     697             : 
     698   103251679 :         agno = XFS_INO_TO_AGNO(sc->mp, ino);
     699   103251679 :         agbno = XFS_INO_TO_AGBNO(sc->mp, ino);
     700             : 
     701   103251679 :         error = xchk_ag_init_existing(sc, agno, &sc->sa);
     702   103265520 :         if (!xchk_xref_process_error(sc, agno, agbno, &error))
     703           1 :                 goto out_free;
     704             : 
     705   103265729 :         xchk_xref_is_used_space(sc, agbno, 1);
     706   103265740 :         xchk_inode_xref_finobt(sc, ino);
     707   103265591 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_INODES);
     708   103265551 :         xchk_xref_is_not_shared(sc, agbno, 1);
     709   103265744 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     710   103265788 :         xchk_inode_xref_bmap(sc, dip);
     711             : 
     712   103265461 : out_free:
     713   103265461 :         xchk_ag_free(sc, &sc->sa);
     714             : }
     715             : 
     716             : /*
     717             :  * If the reflink iflag disagrees with a scan for shared data fork extents,
     718             :  * either flag an error (shared extents w/ no flag) or a preen (flag set w/o
     719             :  * any shared extents).  We already checked for reflink iflag set on a non
     720             :  * reflink filesystem.
     721             :  */
     722             : static void
     723    26370352 : xchk_inode_check_reflink_iflag(
     724             :         struct xfs_scrub        *sc,
     725             :         xfs_ino_t               ino)
     726             : {
     727    26370352 :         struct xfs_mount        *mp = sc->mp;
     728    26370352 :         bool                    has_shared;
     729    26370352 :         int                     error;
     730             : 
     731    26370352 :         if (!xfs_has_reflink(mp))
     732    11140501 :                 return;
     733             : 
     734    15229851 :         error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip,
     735             :                         &has_shared);
     736    15229945 :         if (!xchk_xref_process_error(sc, XFS_INO_TO_AGNO(mp, ino),
     737    15229781 :                         XFS_INO_TO_AGBNO(mp, ino), &error))
     738             :                 return;
     739    15229945 :         if (xfs_is_reflink_inode(sc->ip) && !has_shared)
     740     2601531 :                 xchk_ino_set_preen(sc, ino);
     741    12628414 :         else if (!xfs_is_reflink_inode(sc->ip) && has_shared)
     742           0 :                 xchk_ino_set_corrupt(sc, ino);
     743             : }
     744             : 
     745             : /*
     746             :  * If this inode has zero link count, it must be on the unlinked list.  If
     747             :  * it has nonzero link count, it must not be on the unlinked list.
     748             :  */
     749             : STATIC void
     750   103234087 : xchk_inode_check_unlinked(
     751             :         struct xfs_scrub        *sc)
     752             : {
     753   103234087 :         if (VFS_I(sc->ip)->i_nlink == 0) {
     754        1387 :                 if (!xfs_inode_on_unlinked_list(sc->ip))
     755           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     756             :         } else {
     757   103232700 :                 if (xfs_inode_on_unlinked_list(sc->ip))
     758           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     759             :         }
     760   103234087 : }
     761             : 
     762             : /* Scrub an inode. */
     763             : int
     764   103253487 : xchk_inode(
     765             :         struct xfs_scrub        *sc)
     766             : {
     767   103253487 :         struct xfs_dinode       di;
     768   103253487 :         int                     error = 0;
     769             : 
     770             :         /*
     771             :          * If sc->ip is NULL, that means that the setup function called
     772             :          * xfs_iget to look up the inode.  xfs_iget returned a EFSCORRUPTED
     773             :          * and a NULL inode, so flag the corruption error and return.
     774             :          */
     775   103253487 :         if (!sc->ip) {
     776           0 :                 xchk_ino_set_corrupt(sc, sc->sm->sm_ino);
     777           0 :                 return 0;
     778             :         }
     779             : 
     780             :         /* Scrub the inode core. */
     781   103253487 :         xfs_inode_to_disk(sc->ip, &di, 0);
     782   103243602 :         xchk_dinode(sc, &di, sc->ip->i_ino);
     783   103234325 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     784           0 :                 goto out;
     785             : 
     786             :         /*
     787             :          * Look for discrepancies between file's data blocks and the reflink
     788             :          * iflag.  We already checked the iflag against the file mode when
     789             :          * we scrubbed the dinode.
     790             :          */
     791   103234325 :         if (S_ISREG(VFS_I(sc->ip)->i_mode))
     792    26370196 :                 xchk_inode_check_reflink_iflag(sc, sc->ip->i_ino);
     793             : 
     794   103234343 :         xchk_inode_check_unlinked(sc);
     795             : 
     796   103234230 :         xchk_inode_xref(sc, sc->ip->i_ino, &di);
     797             : out:
     798             :         return error;
     799             : }

Generated by: LCOV version 1.14