Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2017 Oracle.  All Rights Reserved.
0004  * Author: Darrick J. Wong <darrick.wong@oracle.com>
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_trans_resv.h"
0011 #include "xfs_mount.h"
0012 #include "xfs_btree.h"
0013 #include "xfs_log_format.h"
0014 #include "xfs_inode.h"
0015 #include "xfs_ialloc.h"
0016 #include "xfs_da_format.h"
0017 #include "xfs_reflink.h"
0018 #include "xfs_rmap.h"
0019 #include "xfs_bmap_util.h"
0020 #include "scrub/scrub.h"
0021 #include "scrub/common.h"
0022 #include "scrub/btree.h"
0023 
0024 /*
0025  * Grab total control of the inode metadata.  It doesn't matter here if
0026  * the file data is still changing; exclusive access to the metadata is
0027  * the goal.
0028  */
0029 int
0030 xchk_setup_inode(
0031     struct xfs_scrub    *sc)
0032 {
0033     int         error;
0034 
0035     /*
0036      * Try to get the inode.  If the verifiers fail, we try again
0037      * in raw mode.
0038      */
0039     error = xchk_get_inode(sc);
0040     switch (error) {
0041     case 0:
0042         break;
0043     case -EFSCORRUPTED:
0044     case -EFSBADCRC:
0045         return xchk_trans_alloc(sc, 0);
0046     default:
0047         return error;
0048     }
0049 
0050     /* Got the inode, lock it and we're ready to go. */
0051     sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
0052     xfs_ilock(sc->ip, sc->ilock_flags);
0053     error = xchk_trans_alloc(sc, 0);
0054     if (error)
0055         goto out;
0056     sc->ilock_flags |= XFS_ILOCK_EXCL;
0057     xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
0058 
0059 out:
0060     /* scrub teardown will unlock and release the inode for us */
0061     return error;
0062 }
0063 
0064 /* Inode core */
0065 
0066 /* Validate di_extsize hint. */
0067 STATIC void
0068 xchk_inode_extsize(
0069     struct xfs_scrub    *sc,
0070     struct xfs_dinode   *dip,
0071     xfs_ino_t       ino,
0072     uint16_t        mode,
0073     uint16_t        flags)
0074 {
0075     xfs_failaddr_t      fa;
0076     uint32_t        value = be32_to_cpu(dip->di_extsize);
0077 
0078     fa = xfs_inode_validate_extsize(sc->mp, value, mode, flags);
0079     if (fa)
0080         xchk_ino_set_corrupt(sc, ino);
0081 
0082     /*
0083      * XFS allows a sysadmin to change the rt extent size when adding a rt
0084      * section to a filesystem after formatting.  If there are any
0085      * directories with extszinherit and rtinherit set, the hint could
0086      * become misaligned with the new rextsize.  The verifier doesn't check
0087      * this, because we allow rtinherit directories even without an rt
0088      * device.  Flag this as an administrative warning since we will clean
0089      * this up eventually.
0090      */
0091     if ((flags & XFS_DIFLAG_RTINHERIT) &&
0092         (flags & XFS_DIFLAG_EXTSZINHERIT) &&
0093         value % sc->mp->m_sb.sb_rextsize > 0)
0094         xchk_ino_set_warning(sc, ino);
0095 }
0096 
0097 /*
0098  * Validate di_cowextsize hint.
0099  *
0100  * The rules are documented at xfs_ioctl_setattr_check_cowextsize().
0101  * These functions must be kept in sync with each other.
0102  */
0103 STATIC void
0104 xchk_inode_cowextsize(
0105     struct xfs_scrub    *sc,
0106     struct xfs_dinode   *dip,
0107     xfs_ino_t       ino,
0108     uint16_t        mode,
0109     uint16_t        flags,
0110     uint64_t        flags2)
0111 {
0112     xfs_failaddr_t      fa;
0113 
0114     fa = xfs_inode_validate_cowextsize(sc->mp,
0115             be32_to_cpu(dip->di_cowextsize), mode, flags,
0116             flags2);
0117     if (fa)
0118         xchk_ino_set_corrupt(sc, ino);
0119 }
0120 
0121 /* Make sure the di_flags make sense for the inode. */
0122 STATIC void
0123 xchk_inode_flags(
0124     struct xfs_scrub    *sc,
0125     struct xfs_dinode   *dip,
0126     xfs_ino_t       ino,
0127     uint16_t        mode,
0128     uint16_t        flags)
0129 {
0130     struct xfs_mount    *mp = sc->mp;
0131 
0132     /* di_flags are all taken, last bit cannot be used */
0133     if (flags & ~XFS_DIFLAG_ANY)
0134         goto bad;
0135 
0136     /* rt flags require rt device */
0137     if ((flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
0138         goto bad;
0139 
0140     /* new rt bitmap flag only valid for rbmino */
0141     if ((flags & XFS_DIFLAG_NEWRTBM) && ino != mp->m_sb.sb_rbmino)
0142         goto bad;
0143 
0144     /* directory-only flags */
0145     if ((flags & (XFS_DIFLAG_RTINHERIT |
0146              XFS_DIFLAG_EXTSZINHERIT |
0147              XFS_DIFLAG_PROJINHERIT |
0148              XFS_DIFLAG_NOSYMLINKS)) &&
0149         !S_ISDIR(mode))
0150         goto bad;
0151 
0152     /* file-only flags */
0153     if ((flags & (XFS_DIFLAG_REALTIME | FS_XFLAG_EXTSIZE)) &&
0154         !S_ISREG(mode))
0155         goto bad;
0156 
0157     /* filestreams and rt make no sense */
0158     if ((flags & XFS_DIFLAG_FILESTREAM) && (flags & XFS_DIFLAG_REALTIME))
0159         goto bad;
0160 
0161     return;
0162 bad:
0163     xchk_ino_set_corrupt(sc, ino);
0164 }
0165 
0166 /* Make sure the di_flags2 make sense for the inode. */
0167 STATIC void
0168 xchk_inode_flags2(
0169     struct xfs_scrub    *sc,
0170     struct xfs_dinode   *dip,
0171     xfs_ino_t       ino,
0172     uint16_t        mode,
0173     uint16_t        flags,
0174     uint64_t        flags2)
0175 {
0176     struct xfs_mount    *mp = sc->mp;
0177 
0178     /* Unknown di_flags2 could be from a future kernel */
0179     if (flags2 & ~XFS_DIFLAG2_ANY)
0180         xchk_ino_set_warning(sc, ino);
0181 
0182     /* reflink flag requires reflink feature */
0183     if ((flags2 & XFS_DIFLAG2_REFLINK) &&
0184         !xfs_has_reflink(mp))
0185         goto bad;
0186 
0187     /* cowextsize flag is checked w.r.t. mode separately */
0188 
0189     /* file/dir-only flags */
0190     if ((flags2 & XFS_DIFLAG2_DAX) && !(S_ISREG(mode) || S_ISDIR(mode)))
0191         goto bad;
0192 
0193     /* file-only flags */
0194     if ((flags2 & XFS_DIFLAG2_REFLINK) && !S_ISREG(mode))
0195         goto bad;
0196 
0197     /* realtime and reflink make no sense, currently */
0198     if ((flags & XFS_DIFLAG_REALTIME) && (flags2 & XFS_DIFLAG2_REFLINK))
0199         goto bad;
0200 
0201     /* no bigtime iflag without the bigtime feature */
0202     if (xfs_dinode_has_bigtime(dip) && !xfs_has_bigtime(mp))
0203         goto bad;
0204 
0205     return;
0206 bad:
0207     xchk_ino_set_corrupt(sc, ino);
0208 }
0209 
0210 static inline void
0211 xchk_dinode_nsec(
0212     struct xfs_scrub    *sc,
0213     xfs_ino_t       ino,
0214     struct xfs_dinode   *dip,
0215     const xfs_timestamp_t   ts)
0216 {
0217     struct timespec64   tv;
0218 
0219     tv = xfs_inode_from_disk_ts(dip, ts);
0220     if (tv.tv_nsec < 0 || tv.tv_nsec >= NSEC_PER_SEC)
0221         xchk_ino_set_corrupt(sc, ino);
0222 }
0223 
0224 /* Scrub all the ondisk inode fields. */
0225 STATIC void
0226 xchk_dinode(
0227     struct xfs_scrub    *sc,
0228     struct xfs_dinode   *dip,
0229     xfs_ino_t       ino)
0230 {
0231     struct xfs_mount    *mp = sc->mp;
0232     size_t          fork_recs;
0233     unsigned long long  isize;
0234     uint64_t        flags2;
0235     xfs_extnum_t        nextents;
0236     xfs_extnum_t        naextents;
0237     prid_t          prid;
0238     uint16_t        flags;
0239     uint16_t        mode;
0240 
0241     flags = be16_to_cpu(dip->di_flags);
0242     if (dip->di_version >= 3)
0243         flags2 = be64_to_cpu(dip->di_flags2);
0244     else
0245         flags2 = 0;
0246 
0247     /* di_mode */
0248     mode = be16_to_cpu(dip->di_mode);
0249     switch (mode & S_IFMT) {
0250     case S_IFLNK:
0251     case S_IFREG:
0252     case S_IFDIR:
0253     case S_IFCHR:
0254     case S_IFBLK:
0255     case S_IFIFO:
0256     case S_IFSOCK:
0257         /* mode is recognized */
0258         break;
0259     default:
0260         xchk_ino_set_corrupt(sc, ino);
0261         break;
0262     }
0263 
0264     /* v1/v2 fields */
0265     switch (dip->di_version) {
0266     case 1:
0267         /*
0268          * We autoconvert v1 inodes into v2 inodes on writeout,
0269          * so just mark this inode for preening.
0270          */
0271         xchk_ino_set_preen(sc, ino);
0272         prid = 0;
0273         break;
0274     case 2:
0275     case 3:
0276         if (dip->di_onlink != 0)
0277             xchk_ino_set_corrupt(sc, ino);
0278 
0279         if (dip->di_mode == 0 && sc->ip)
0280             xchk_ino_set_corrupt(sc, ino);
0281 
0282         if (dip->di_projid_hi != 0 &&
0283             !xfs_has_projid32(mp))
0284             xchk_ino_set_corrupt(sc, ino);
0285 
0286         prid = be16_to_cpu(dip->di_projid_lo);
0287         break;
0288     default:
0289         xchk_ino_set_corrupt(sc, ino);
0290         return;
0291     }
0292 
0293     if (xfs_has_projid32(mp))
0294         prid |= (prid_t)be16_to_cpu(dip->di_projid_hi) << 16;
0295 
0296     /*
0297      * di_uid/di_gid -- -1 isn't invalid, but there's no way that
0298      * userspace could have created that.
0299      */
0300     if (dip->di_uid == cpu_to_be32(-1U) ||
0301         dip->di_gid == cpu_to_be32(-1U))
0302         xchk_ino_set_warning(sc, ino);
0303 
0304     /*
0305      * project id of -1 isn't supposed to be valid, but the kernel didn't
0306      * always validate that.
0307      */
0308     if (prid == -1U)
0309         xchk_ino_set_warning(sc, ino);
0310 
0311     /* di_format */
0312     switch (dip->di_format) {
0313     case XFS_DINODE_FMT_DEV:
0314         if (!S_ISCHR(mode) && !S_ISBLK(mode) &&
0315             !S_ISFIFO(mode) && !S_ISSOCK(mode))
0316             xchk_ino_set_corrupt(sc, ino);
0317         break;
0318     case XFS_DINODE_FMT_LOCAL:
0319         if (!S_ISDIR(mode) && !S_ISLNK(mode))
0320             xchk_ino_set_corrupt(sc, ino);
0321         break;
0322     case XFS_DINODE_FMT_EXTENTS:
0323         if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode))
0324             xchk_ino_set_corrupt(sc, ino);
0325         break;
0326     case XFS_DINODE_FMT_BTREE:
0327         if (!S_ISREG(mode) && !S_ISDIR(mode))
0328             xchk_ino_set_corrupt(sc, ino);
0329         break;
0330     case XFS_DINODE_FMT_UUID:
0331     default:
0332         xchk_ino_set_corrupt(sc, ino);
0333         break;
0334     }
0335 
0336     /* di_[amc]time.nsec */
0337     xchk_dinode_nsec(sc, ino, dip, dip->di_atime);
0338     xchk_dinode_nsec(sc, ino, dip, dip->di_mtime);
0339     xchk_dinode_nsec(sc, ino, dip, dip->di_ctime);
0340 
0341     /*
0342      * di_size.  xfs_dinode_verify checks for things that screw up
0343      * the VFS such as the upper bit being set and zero-length
0344      * symlinks/directories, but we can do more here.
0345      */
0346     isize = be64_to_cpu(dip->di_size);
0347     if (isize & (1ULL << 63))
0348         xchk_ino_set_corrupt(sc, ino);
0349 
0350     /* Devices, fifos, and sockets must have zero size */
0351     if (!S_ISDIR(mode) && !S_ISREG(mode) && !S_ISLNK(mode) && isize != 0)
0352         xchk_ino_set_corrupt(sc, ino);
0353 
0354     /* Directories can't be larger than the data section size (32G) */
0355     if (S_ISDIR(mode) && (isize == 0 || isize >= XFS_DIR2_SPACE_SIZE))
0356         xchk_ino_set_corrupt(sc, ino);
0357 
0358     /* Symlinks can't be larger than SYMLINK_MAXLEN */
0359     if (S_ISLNK(mode) && (isize == 0 || isize >= XFS_SYMLINK_MAXLEN))
0360         xchk_ino_set_corrupt(sc, ino);
0361 
0362     /*
0363      * Warn if the running kernel can't handle the kinds of offsets
0364      * needed to deal with the file size.  In other words, if the
0365      * pagecache can't cache all the blocks in this file due to
0366      * overly large offsets, flag the inode for admin review.
0367      */
0368     if (isize >= mp->m_super->s_maxbytes)
0369         xchk_ino_set_warning(sc, ino);
0370 
0371     /* di_nblocks */
0372     if (flags2 & XFS_DIFLAG2_REFLINK) {
0373         ; /* nblocks can exceed dblocks */
0374     } else if (flags & XFS_DIFLAG_REALTIME) {
0375         /*
0376          * nblocks is the sum of data extents (in the rtdev),
0377          * attr extents (in the datadev), and both forks' bmbt
0378          * blocks (in the datadev).  This clumsy check is the
0379          * best we can do without cross-referencing with the
0380          * inode forks.
0381          */
0382         if (be64_to_cpu(dip->di_nblocks) >=
0383             mp->m_sb.sb_dblocks + mp->m_sb.sb_rblocks)
0384             xchk_ino_set_corrupt(sc, ino);
0385     } else {
0386         if (be64_to_cpu(dip->di_nblocks) >= mp->m_sb.sb_dblocks)
0387             xchk_ino_set_corrupt(sc, ino);
0388     }
0389 
0390     xchk_inode_flags(sc, dip, ino, mode, flags);
0391 
0392     xchk_inode_extsize(sc, dip, ino, mode, flags);
0393 
0394     nextents = xfs_dfork_data_extents(dip);
0395     naextents = xfs_dfork_attr_extents(dip);
0396 
0397     /* di_nextents */
0398     fork_recs =  XFS_DFORK_DSIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
0399     switch (dip->di_format) {
0400     case XFS_DINODE_FMT_EXTENTS:
0401         if (nextents > fork_recs)
0402             xchk_ino_set_corrupt(sc, ino);
0403         break;
0404     case XFS_DINODE_FMT_BTREE:
0405         if (nextents <= fork_recs)
0406             xchk_ino_set_corrupt(sc, ino);
0407         break;
0408     default:
0409         if (nextents != 0)
0410             xchk_ino_set_corrupt(sc, ino);
0411         break;
0412     }
0413 
0414     /* di_forkoff */
0415     if (XFS_DFORK_APTR(dip) >= (char *)dip + mp->m_sb.sb_inodesize)
0416         xchk_ino_set_corrupt(sc, ino);
0417     if (naextents != 0 && dip->di_forkoff == 0)
0418         xchk_ino_set_corrupt(sc, ino);
0419     if (dip->di_forkoff == 0 && dip->di_aformat != XFS_DINODE_FMT_EXTENTS)
0420         xchk_ino_set_corrupt(sc, ino);
0421 
0422     /* di_aformat */
0423     if (dip->di_aformat != XFS_DINODE_FMT_LOCAL &&
0424         dip->di_aformat != XFS_DINODE_FMT_EXTENTS &&
0425         dip->di_aformat != XFS_DINODE_FMT_BTREE)
0426         xchk_ino_set_corrupt(sc, ino);
0427 
0428     /* di_anextents */
0429     fork_recs =  XFS_DFORK_ASIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
0430     switch (dip->di_aformat) {
0431     case XFS_DINODE_FMT_EXTENTS:
0432         if (naextents > fork_recs)
0433             xchk_ino_set_corrupt(sc, ino);
0434         break;
0435     case XFS_DINODE_FMT_BTREE:
0436         if (naextents <= fork_recs)
0437             xchk_ino_set_corrupt(sc, ino);
0438         break;
0439     default:
0440         if (naextents != 0)
0441             xchk_ino_set_corrupt(sc, ino);
0442     }
0443 
0444     if (dip->di_version >= 3) {
0445         xchk_dinode_nsec(sc, ino, dip, dip->di_crtime);
0446         xchk_inode_flags2(sc, dip, ino, mode, flags, flags2);
0447         xchk_inode_cowextsize(sc, dip, ino, mode, flags,
0448                 flags2);
0449     }
0450 }
0451 
0452 /*
0453  * Make sure the finobt doesn't think this inode is free.
0454  * We don't have to check the inobt ourselves because we got the inode via
0455  * IGET_UNTRUSTED, which checks the inobt for us.
0456  */
0457 static void
0458 xchk_inode_xref_finobt(
0459     struct xfs_scrub        *sc,
0460     xfs_ino_t           ino)
0461 {
0462     struct xfs_inobt_rec_incore rec;
0463     xfs_agino_t         agino;
0464     int             has_record;
0465     int             error;
0466 
0467     if (!sc->sa.fino_cur || xchk_skip_xref(sc->sm))
0468         return;
0469 
0470     agino = XFS_INO_TO_AGINO(sc->mp, ino);
0471 
0472     /*
0473      * Try to get the finobt record.  If we can't get it, then we're
0474      * in good shape.
0475      */
0476     error = xfs_inobt_lookup(sc->sa.fino_cur, agino, XFS_LOOKUP_LE,
0477             &has_record);
0478     if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
0479         !has_record)
0480         return;
0481 
0482     error = xfs_inobt_get_rec(sc->sa.fino_cur, &rec, &has_record);
0483     if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
0484         !has_record)
0485         return;
0486 
0487     /*
0488      * Otherwise, make sure this record either doesn't cover this inode,
0489      * or that it does but it's marked present.
0490      */
0491     if (rec.ir_startino > agino ||
0492         rec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
0493         return;
0494 
0495     if (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino))
0496         xchk_btree_xref_set_corrupt(sc, sc->sa.fino_cur, 0);
0497 }
0498 
0499 /* Cross reference the inode fields with the forks. */
0500 STATIC void
0501 xchk_inode_xref_bmap(
0502     struct xfs_scrub    *sc,
0503     struct xfs_dinode   *dip)
0504 {
0505     xfs_extnum_t        nextents;
0506     xfs_filblks_t       count;
0507     xfs_filblks_t       acount;
0508     int         error;
0509 
0510     if (xchk_skip_xref(sc->sm))
0511         return;
0512 
0513     /* Walk all the extents to check nextents/naextents/nblocks. */
0514     error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_DATA_FORK,
0515             &nextents, &count);
0516     if (!xchk_should_check_xref(sc, &error, NULL))
0517         return;
0518     if (nextents < xfs_dfork_data_extents(dip))
0519         xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
0520 
0521     error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_ATTR_FORK,
0522             &nextents, &acount);
0523     if (!xchk_should_check_xref(sc, &error, NULL))
0524         return;
0525     if (nextents != xfs_dfork_attr_extents(dip))
0526         xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
0527 
0528     /* Check nblocks against the inode. */
0529     if (count + acount != be64_to_cpu(dip->di_nblocks))
0530         xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
0531 }
0532 
0533 /* Cross-reference with the other btrees. */
0534 STATIC void
0535 xchk_inode_xref(
0536     struct xfs_scrub    *sc,
0537     xfs_ino_t       ino,
0538     struct xfs_dinode   *dip)
0539 {
0540     xfs_agnumber_t      agno;
0541     xfs_agblock_t       agbno;
0542     int         error;
0543 
0544     if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
0545         return;
0546 
0547     agno = XFS_INO_TO_AGNO(sc->mp, ino);
0548     agbno = XFS_INO_TO_AGBNO(sc->mp, ino);
0549 
0550     error = xchk_ag_init_existing(sc, agno, &sc->sa);
0551     if (!xchk_xref_process_error(sc, agno, agbno, &error))
0552         goto out_free;
0553 
0554     xchk_xref_is_used_space(sc, agbno, 1);
0555     xchk_inode_xref_finobt(sc, ino);
0556     xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_INODES);
0557     xchk_xref_is_not_shared(sc, agbno, 1);
0558     xchk_inode_xref_bmap(sc, dip);
0559 
0560 out_free:
0561     xchk_ag_free(sc, &sc->sa);
0562 }
0563 
0564 /*
0565  * If the reflink iflag disagrees with a scan for shared data fork extents,
0566  * either flag an error (shared extents w/ no flag) or a preen (flag set w/o
0567  * any shared extents).  We already checked for reflink iflag set on a non
0568  * reflink filesystem.
0569  */
0570 static void
0571 xchk_inode_check_reflink_iflag(
0572     struct xfs_scrub    *sc,
0573     xfs_ino_t       ino)
0574 {
0575     struct xfs_mount    *mp = sc->mp;
0576     bool            has_shared;
0577     int         error;
0578 
0579     if (!xfs_has_reflink(mp))
0580         return;
0581 
0582     error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip,
0583             &has_shared);
0584     if (!xchk_xref_process_error(sc, XFS_INO_TO_AGNO(mp, ino),
0585             XFS_INO_TO_AGBNO(mp, ino), &error))
0586         return;
0587     if (xfs_is_reflink_inode(sc->ip) && !has_shared)
0588         xchk_ino_set_preen(sc, ino);
0589     else if (!xfs_is_reflink_inode(sc->ip) && has_shared)
0590         xchk_ino_set_corrupt(sc, ino);
0591 }
0592 
0593 /* Scrub an inode. */
0594 int
0595 xchk_inode(
0596     struct xfs_scrub    *sc)
0597 {
0598     struct xfs_dinode   di;
0599     int         error = 0;
0600 
0601     /*
0602      * If sc->ip is NULL, that means that the setup function called
0603      * xfs_iget to look up the inode.  xfs_iget returned a EFSCORRUPTED
0604      * and a NULL inode, so flag the corruption error and return.
0605      */
0606     if (!sc->ip) {
0607         xchk_ino_set_corrupt(sc, sc->sm->sm_ino);
0608         return 0;
0609     }
0610 
0611     /* Scrub the inode core. */
0612     xfs_inode_to_disk(sc->ip, &di, 0);
0613     xchk_dinode(sc, &di, sc->ip->i_ino);
0614     if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
0615         goto out;
0616 
0617     /*
0618      * Look for discrepancies between file's data blocks and the reflink
0619      * iflag.  We already checked the iflag against the file mode when
0620      * we scrubbed the dinode.
0621      */
0622     if (S_ISREG(VFS_I(sc->ip)->i_mode))
0623         xchk_inode_check_reflink_iflag(sc, sc->ip->i_ino);
0624 
0625     xchk_inode_xref(sc, sc->ip->i_ino, &di);
0626 out:
0627     return error;
0628 }