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-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 244 341 71.6 %
Date: 2023-07-31 20:08:12 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   179388918 : xchk_prepare_iscrub(
      32             :         struct xfs_scrub        *sc)
      33             : {
      34   179388918 :         int                     error;
      35             : 
      36   179388918 :         xchk_ilock(sc, XFS_IOLOCK_EXCL);
      37             : 
      38   178797061 :         error = xchk_trans_alloc(sc, 0);
      39   178527061 :         if (error)
      40             :                 return error;
      41             : 
      42   178653171 :         error = xchk_ino_dqattach(sc);
      43   178615114 :         if (error)
      44             :                 return error;
      45             : 
      46   178642748 :         xchk_ilock(sc, XFS_ILOCK_EXCL);
      47   178642748 :         return 0;
      48             : }
      49             : 
      50             : /* Install this scrub-by-handle inode and prepare it for scrubbing. */
      51             : static inline int
      52   112114400 : xchk_install_handle_iscrub(
      53             :         struct xfs_scrub        *sc,
      54             :         struct xfs_inode        *ip)
      55             : {
      56   112114400 :         int                     error;
      57             : 
      58   112114400 :         error = xchk_install_handle_inode(sc, ip);
      59   111991284 :         if (error)
      60             :                 return error;
      61             : 
      62   111793017 :         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   179759772 : xchk_setup_inode(
      73             :         struct xfs_scrub        *sc)
      74             : {
      75   179759772 :         struct xfs_imap         imap;
      76   179759772 :         struct xfs_inode        *ip;
      77   179759772 :         struct xfs_mount        *mp = sc->mp;
      78   179759772 :         struct xfs_inode        *ip_in = XFS_I(file_inode(sc->file));
      79   179759772 :         struct xfs_buf          *agi_bp;
      80   179759772 :         struct xfs_perag        *pag;
      81   179759772 :         xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, sc->sm->sm_ino);
      82   179759772 :         int                     error;
      83             : 
      84   179759772 :         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   179759772 :         if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) {
      89    67215658 :                 error = xchk_install_live_inode(sc, ip_in);
      90    67721699 :                 if (error)
      91             :                         return error;
      92             : 
      93    67719573 :                 return xchk_prepare_iscrub(sc);
      94             :         }
      95             : 
      96             :         /* Reject internal metadata files and obviously bad inode numbers. */
      97   112544114 :         if (xfs_internal_inum(mp, sc->sm->sm_ino))
      98             :                 return -ENOENT;
      99   112201227 :         if (!xfs_verify_ino(sc->mp, sc->sm->sm_ino))
     100             :                 return -ENOENT;
     101             : 
     102             :         /* Try a regular untrusted iget. */
     103   112332366 :         error = xchk_iget(sc, sc->sm->sm_ino, &ip);
     104   112781468 :         if (!error)
     105   112164507 :                 return xchk_install_handle_iscrub(sc, ip);
     106      616961 :         if (error == -ENOENT)
     107             :                 return error;
     108        1879 :         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        1879 :         error = xchk_trans_alloc(sc, 0);
     134        1879 :         if (error)
     135           0 :                 goto out_error;
     136             : 
     137        1879 :         error = xchk_iget_agi(sc, sc->sm->sm_ino, &agi_bp, &ip);
     138        1879 :         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        1879 :         if (error == -ENOENT)
     144           0 :                 goto out_gone;
     145        1879 :         if (error != -EFSCORRUPTED && error != -EFSBADCRC && error != -EINVAL)
     146           0 :                 goto out_cancel;
     147             : 
     148             :         /* Ensure that we have protected against inode allocation/freeing. */
     149        1879 :         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        1879 :         pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, sc->sm->sm_ino));
     167        1879 :         if (!pag) {
     168           0 :                 error = -EFSCORRUPTED;
     169           0 :                 goto out_cancel;
     170             :         }
     171             : 
     172        1879 :         error = xfs_imap(pag, sc->tp, sc->sm->sm_ino, &imap,
     173             :                         XFS_IGET_UNTRUSTED);
     174        1879 :         xfs_perag_put(pag);
     175        1879 :         if (error == -EINVAL || error == -ENOENT)
     176        1879 :                 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        1879 : out_gone:
     206             :         /* The file is gone, so there's nothing to check. */
     207        1879 :         xchk_trans_cancel(sc);
     208        1879 :         return -ENOENT;
     209             : }
     210             : 
     211             : /* Inode core */
     212             : 
     213             : /* Validate di_extsize hint. */
     214             : STATIC void
     215   177922313 : 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   177922313 :         xfs_failaddr_t          fa;
     223   177922313 :         uint32_t                value = be32_to_cpu(dip->di_extsize);
     224             : 
     225   177922313 :         fa = xfs_inode_validate_extsize(sc->mp, value, mode, flags);
     226   176385962 :         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   176385962 :         if ((flags & XFS_DIFLAG_RTINHERIT) &&
     239         104 :             (flags & XFS_DIFLAG_EXTSZINHERIT) &&
     240          52 :             value % sc->mp->m_sb.sb_rextsize > 0)
     241           0 :                 xchk_ino_set_warning(sc, ino);
     242   176385962 : }
     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   177014606 : 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   177014606 :         xfs_failaddr_t          fa;
     260             : 
     261   177014606 :         fa = xfs_inode_validate_cowextsize(sc->mp,
     262   177014606 :                         be32_to_cpu(dip->di_cowextsize), mode, flags,
     263             :                         flags2);
     264   177181007 :         if (fa)
     265           0 :                 xchk_ino_set_corrupt(sc, ino);
     266   177181007 : }
     267             : 
     268             : /* Make sure the di_flags make sense for the inode. */
     269             : STATIC void
     270   177977221 : 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   177977221 :         struct xfs_mount        *mp = sc->mp;
     278             : 
     279             :         /* di_flags are all taken, last bit cannot be used */
     280   177977221 :         if (flags & ~XFS_DIFLAG_ANY)
     281           0 :                 goto bad;
     282             : 
     283             :         /* rt flags require rt device */
     284   177977221 :         if ((flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
     285           0 :                 goto bad;
     286             : 
     287             :         /* new rt bitmap flag only valid for rbmino */
     288   177977221 :         if ((flags & XFS_DIFLAG_NEWRTBM) && ino != mp->m_sb.sb_rbmino)
     289           0 :                 goto bad;
     290             : 
     291             :         /* directory-only flags */
     292   177977221 :         if ((flags & (XFS_DIFLAG_RTINHERIT |
     293             :                      XFS_DIFLAG_EXTSZINHERIT |
     294             :                      XFS_DIFLAG_PROJINHERIT |
     295    12100305 :                      XFS_DIFLAG_NOSYMLINKS)) &&
     296             :             !S_ISDIR(mode))
     297           0 :                 goto bad;
     298             : 
     299             :         /* file-only flags */
     300   177977221 :         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   177977221 :         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   177291412 : 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   177291412 :         struct xfs_mount        *mp = sc->mp;
     324             : 
     325             :         /* Unknown di_flags2 could be from a future kernel */
     326   177291412 :         if (flags2 & ~XFS_DIFLAG2_ANY)
     327           0 :                 xchk_ino_set_warning(sc, ino);
     328             : 
     329             :         /* reflink flag requires reflink feature */
     330   177291412 :         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   177291412 :         if ((flags2 & XFS_DIFLAG2_DAX) && !(S_ISREG(mode) || S_ISDIR(mode)))
     338           0 :                 goto bad;
     339             : 
     340             :         /* file-only flags */
     341   177291412 :         if ((flags2 & XFS_DIFLAG2_REFLINK) && !S_ISREG(mode))
     342           0 :                 goto bad;
     343             : 
     344             :         /* realtime and reflink make no sense, currently */
     345   177291412 :         if ((flags & XFS_DIFLAG_REALTIME) && (flags2 & XFS_DIFLAG2_REFLINK))
     346           0 :                 goto bad;
     347             : 
     348             :         /* no bigtime iflag without the bigtime feature */
     349   354582824 :         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   177291412 :         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   708071478 : 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   708071478 :         struct timespec64       tv;
     369             : 
     370   708071478 :         tv = xfs_inode_from_disk_ts(dip, ts);
     371   708077848 :         if (tv.tv_nsec < 0 || tv.tv_nsec >= NSEC_PER_SEC)
     372           0 :                 xchk_ino_set_corrupt(sc, ino);
     373   708077848 : }
     374             : 
     375             : /* Scrub all the ondisk inode fields. */
     376             : STATIC void
     377   177667489 : xchk_dinode(
     378             :         struct xfs_scrub        *sc,
     379             :         struct xfs_dinode       *dip,
     380             :         xfs_ino_t               ino)
     381             : {
     382   177667489 :         struct xfs_mount        *mp = sc->mp;
     383   177667489 :         size_t                  fork_recs;
     384   177667489 :         unsigned long long      isize;
     385   177667489 :         uint64_t                flags2;
     386   177667489 :         xfs_extnum_t            nextents;
     387   177667489 :         xfs_extnum_t            naextents;
     388   177667489 :         prid_t                  prid;
     389   177667489 :         uint16_t                flags;
     390   177667489 :         uint16_t                mode;
     391             : 
     392   177667489 :         flags = be16_to_cpu(dip->di_flags);
     393   177667489 :         if (dip->di_version >= 3)
     394   178285682 :                 flags2 = be64_to_cpu(dip->di_flags2);
     395             :         else
     396             :                 flags2 = 0;
     397             : 
     398             :         /* di_mode */
     399   177667489 :         mode = be16_to_cpu(dip->di_mode);
     400   177667489 :         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   177667489 :         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   177667489 :         case 2:
     426             :         case 3:
     427   177667489 :                 if (dip->di_onlink != 0)
     428           0 :                         xchk_ino_set_corrupt(sc, ino);
     429             : 
     430   177667489 :                 if (dip->di_mode == 0 && sc->ip)
     431           0 :                         xchk_ino_set_corrupt(sc, ino);
     432             : 
     433   177667489 :                 if (dip->di_projid_hi != 0 &&
     434             :                     !xfs_has_projid32(mp))
     435           0 :                         xchk_ino_set_corrupt(sc, ino);
     436             : 
     437   177667489 :                 prid = be16_to_cpu(dip->di_projid_lo);
     438   177667489 :                 break;
     439           0 :         default:
     440           0 :                 xchk_ino_set_corrupt(sc, ino);
     441           0 :                 return;
     442             :         }
     443             : 
     444   177667489 :         if (xfs_has_projid32(mp))
     445   178194720 :                 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   177667489 :         if (dip->di_uid == cpu_to_be32(-1U) ||
     452   177667489 :             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   177805975 :         if (prid == -1U)
     460           0 :                 xchk_ino_set_warning(sc, ino);
     461             : 
     462             :         /* di_format */
     463   177805975 :         switch (dip->di_format) {
     464    53287301 :         case XFS_DINODE_FMT_DEV:
     465    53287301 :                 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    27530447 :         case XFS_DINODE_FMT_LOCAL:
     470    27530447 :                 if (!S_ISDIR(mode) && !S_ISLNK(mode))
     471           0 :                         xchk_ino_set_corrupt(sc, ino);
     472             :                 break;
     473    94614797 :         case XFS_DINODE_FMT_EXTENTS:
     474    94614797 :                 if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode))
     475           0 :                         xchk_ino_set_corrupt(sc, ino);
     476             :                 break;
     477     2373430 :         case XFS_DINODE_FMT_BTREE:
     478     2373430 :                 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   177805975 :         xchk_dinode_nsec(sc, ino, dip, dip->di_atime);
     489   177371232 :         xchk_dinode_nsec(sc, ino, dip, dip->di_mtime);
     490   177884345 :         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   178388582 :         isize = be64_to_cpu(dip->di_size);
     498   178388582 :         if (isize & (1ULL << 63))
     499           0 :                 xchk_ino_set_corrupt(sc, ino);
     500             : 
     501             :         /* Devices, fifos, and sockets must have zero size */
     502   178388582 :         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   178388582 :         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   178388582 :         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   178388582 :         if (isize > mp->m_super->s_maxbytes)
     520           0 :                 xchk_ino_set_warning(sc, ino);
     521             : 
     522             :         /* di_nblocks */
     523   178388582 :         if (flags2 & XFS_DIFLAG2_REFLINK) {
     524             :                 ; /* nblocks can exceed dblocks */
     525   174203804 :         } 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    39509040 :                 if (be64_to_cpu(dip->di_nblocks) >=
     534    39509040 :                     mp->m_sb.sb_dblocks + mp->m_sb.sb_rblocks)
     535           0 :                         xchk_ino_set_corrupt(sc, ino);
     536             :         } else {
     537   134694764 :                 if (be64_to_cpu(dip->di_nblocks) >= mp->m_sb.sb_dblocks)
     538           0 :                         xchk_ino_set_corrupt(sc, ino);
     539             :         }
     540             : 
     541   178388582 :         xchk_inode_flags(sc, dip, ino, mode, flags);
     542             : 
     543   177933895 :         xchk_inode_extsize(sc, dip, ino, mode, flags);
     544             : 
     545   176686114 :         nextents = xfs_dfork_data_extents(dip);
     546   176686114 :         naextents = xfs_dfork_attr_extents(dip);
     547             : 
     548             :         /* di_nextents */
     549   176686191 :         fork_recs =  XFS_DFORK_DSIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
     550   176686114 :         switch (dip->di_format) {
     551    93914304 :         case XFS_DINODE_FMT_EXTENTS:
     552    93914304 :                 if (nextents > fork_recs)
     553           0 :                         xchk_ino_set_corrupt(sc, ino);
     554             :                 break;
     555     2372845 :         case XFS_DINODE_FMT_BTREE:
     556     2372845 :                 if (nextents <= fork_recs)
     557           0 :                         xchk_ino_set_corrupt(sc, ino);
     558             :                 break;
     559    80398965 :         default:
     560    80398965 :                 if (nextents != 0)
     561           0 :                         xchk_ino_set_corrupt(sc, ino);
     562             :                 break;
     563             :         }
     564             : 
     565             :         /* di_forkoff */
     566   353704980 :         if (XFS_DFORK_APTR(dip) >= (char *)dip + mp->m_sb.sb_inodesize)
     567           0 :                 xchk_ino_set_corrupt(sc, ino);
     568   176686114 :         if (naextents != 0 && dip->di_forkoff == 0)
     569           0 :                 xchk_ino_set_corrupt(sc, ino);
     570   176686114 :         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   176686114 :         if (dip->di_aformat != XFS_DINODE_FMT_LOCAL &&
     575   176686114 :             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   177404596 :         fork_recs =  XFS_DFORK_ASIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
     581   177404585 :         switch (dip->di_aformat) {
     582     6714802 :         case XFS_DINODE_FMT_EXTENTS:
     583     6714802 :                 if (naextents > fork_recs)
     584           0 :                         xchk_ino_set_corrupt(sc, ino);
     585             :                 break;
     586         161 :         case XFS_DINODE_FMT_BTREE:
     587         161 :                 if (naextents <= fork_recs)
     588           0 :                         xchk_ino_set_corrupt(sc, ino);
     589             :                 break;
     590   170689622 :         default:
     591   170689622 :                 if (naextents != 0)
     592           0 :                         xchk_ino_set_corrupt(sc, ino);
     593             :         }
     594             : 
     595   177404585 :         if (dip->di_version >= 3) {
     596   177734209 :                 xchk_dinode_nsec(sc, ino, dip, dip->di_crtime);
     597   176804970 :                 xchk_inode_flags2(sc, dip, ino, mode, flags, flags2);
     598   177249854 :                 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   178841907 : xchk_inode_xref_finobt(
     610             :         struct xfs_scrub                *sc,
     611             :         xfs_ino_t                       ino)
     612             : {
     613   178841907 :         struct xfs_inobt_rec_incore     rec;
     614   178841907 :         xfs_agino_t                     agino;
     615   178841907 :         int                             has_record;
     616   178841907 :         int                             error;
     617             : 
     618   178841907 :         if (!sc->sa.fino_cur || xchk_skip_xref(sc->sm))
     619   170752496 :                 return;
     620             : 
     621   178841819 :         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   178841819 :         error = xfs_inobt_lookup(sc->sa.fino_cur, agino, XFS_LOOKUP_LE,
     628             :                         &has_record);
     629   180188374 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
     630   179940036 :             !has_record)
     631             :                 return;
     632             : 
     633    40222361 :         error = xfs_inobt_get_rec(sc->sa.fino_cur, &rec, &has_record);
     634    40224637 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
     635    40217311 :             !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    40217311 :         if (rec.ir_startino > agino ||
     643    40217311 :             rec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
     644             :                 return;
     645             : 
     646     9182578 :         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   179817026 : xchk_inode_xref_bmap(
     653             :         struct xfs_scrub        *sc,
     654             :         struct xfs_dinode       *dip)
     655             : {
     656   179817026 :         xfs_extnum_t            nextents;
     657   179817026 :         xfs_filblks_t           count;
     658   179817026 :         xfs_filblks_t           acount;
     659   179817026 :         int                     error;
     660             : 
     661   179817026 :         if (xchk_skip_xref(sc->sm))
     662           0 :                 return;
     663             : 
     664             :         /* Walk all the extents to check nextents/naextents/nblocks. */
     665   179817026 :         error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_DATA_FORK,
     666             :                         &nextents, &count);
     667   179849717 :         if (!xchk_should_check_xref(sc, &error, NULL))
     668             :                 return;
     669   179860868 :         if (nextents < xfs_dfork_data_extents(dip))
     670           0 :                 xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
     671             : 
     672   179860868 :         error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_ATTR_FORK,
     673             :                         &nextents, &acount);
     674   179885465 :         if (!xchk_should_check_xref(sc, &error, NULL))
     675             :                 return;
     676   179788346 :         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   179788346 :         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   178022922 : xchk_inode_xref(
     687             :         struct xfs_scrub        *sc,
     688             :         xfs_ino_t               ino,
     689             :         struct xfs_dinode       *dip)
     690             : {
     691   178022922 :         xfs_agnumber_t          agno;
     692   178022922 :         xfs_agblock_t           agbno;
     693   178022922 :         int                     error;
     694             : 
     695   178022922 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     696           0 :                 return;
     697             : 
     698   178022922 :         agno = XFS_INO_TO_AGNO(sc->mp, ino);
     699   178022922 :         agbno = XFS_INO_TO_AGBNO(sc->mp, ino);
     700             : 
     701   178022922 :         error = xchk_ag_init_existing(sc, agno, &sc->sa);
     702   180100538 :         if (!xchk_xref_process_error(sc, agno, agbno, &error))
     703           7 :                 goto out_free;
     704             : 
     705   179067754 :         xchk_xref_is_used_space(sc, agbno, 1);
     706   178968928 :         xchk_inode_xref_finobt(sc, ino);
     707   179993192 :         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_INODES);
     708   179817252 :         xchk_xref_is_not_shared(sc, agbno, 1);
     709   179675222 :         xchk_xref_is_not_cow_staging(sc, agbno, 1);
     710   179812812 :         xchk_inode_xref_bmap(sc, dip);
     711             : 
     712   179777792 : out_free:
     713   179777792 :         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    81474660 : xchk_inode_check_reflink_iflag(
     724             :         struct xfs_scrub        *sc,
     725             :         xfs_ino_t               ino)
     726             : {
     727    81474660 :         struct xfs_mount        *mp = sc->mp;
     728    81474660 :         bool                    has_shared;
     729    81474660 :         int                     error;
     730             : 
     731    81474660 :         if (!xfs_has_reflink(mp))
     732    40317411 :                 return;
     733             : 
     734    41157249 :         error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip,
     735             :                         &has_shared);
     736    41280049 :         if (!xchk_xref_process_error(sc, XFS_INO_TO_AGNO(mp, ino),
     737    41280049 :                         XFS_INO_TO_AGBNO(mp, ino), &error))
     738             :                 return;
     739    41092647 :         if (xfs_is_reflink_inode(sc->ip) && !has_shared)
     740     1970594 :                 xchk_ino_set_preen(sc, ino);
     741    39122053 :         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   177525749 : xchk_inode_check_unlinked(
     751             :         struct xfs_scrub        *sc)
     752             : {
     753   177525749 :         if (VFS_I(sc->ip)->i_nlink == 0) {
     754        3459 :                 if (!xfs_inode_on_unlinked_list(sc->ip))
     755           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     756             :         } else {
     757   177522290 :                 if (xfs_inode_on_unlinked_list(sc->ip))
     758           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
     759             :         }
     760   177525749 : }
     761             : 
     762             : /* Scrub an inode. */
     763             : int
     764   179066355 : xchk_inode(
     765             :         struct xfs_scrub        *sc)
     766             : {
     767   179066355 :         struct xfs_dinode       di;
     768   179066355 :         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   179066355 :         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   179066355 :         xfs_inode_to_disk(sc->ip, &di, 0);
     782   177689265 :         xchk_dinode(sc, &di, sc->ip->i_ino);
     783   177510167 :         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   177510167 :         if (S_ISREG(VFS_I(sc->ip)->i_mode))
     792    81375086 :                 xchk_inode_check_reflink_iflag(sc, sc->ip->i_ino);
     793             : 
     794   177016925 :         xchk_inode_check_unlinked(sc);
     795             : 
     796   177845131 :         xchk_inode_xref(sc, sc->ip->i_ino, &di);
     797             : out:
     798             :         return error;
     799             : }

Generated by: LCOV version 1.14