1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2017 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <darrick.wong@oracle.com>
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_defer.h"
13 #include "xfs_btree.h"
14 #include "xfs_bit.h"
15 #include "xfs_log_format.h"
16 #include "xfs_trans.h"
17 #include "xfs_sb.h"
18 #include "xfs_inode.h"
19 #include "xfs_icache.h"
20 #include "xfs_inode_buf.h"
21 #include "xfs_inode_fork.h"
22 #include "xfs_ialloc.h"
23 #include "xfs_da_format.h"
24 #include "xfs_reflink.h"
25 #include "xfs_rmap.h"
26 #include "xfs_bmap.h"
27 #include "xfs_bmap_util.h"
28 #include "scrub/xfs_scrub.h"
29 #include "scrub/scrub.h"
30 #include "scrub/common.h"
31 #include "scrub/btree.h"
32 #include "scrub/trace.h"
33 
34 /*
35  * Grab total control of the inode metadata.  It doesn't matter here if
36  * the file data is still changing; exclusive access to the metadata is
37  * the goal.
38  */
39 int
xchk_setup_inode(struct xfs_scrub * sc,struct xfs_inode * ip)40 xchk_setup_inode(
41 	struct xfs_scrub	*sc,
42 	struct xfs_inode	*ip)
43 {
44 	int			error;
45 
46 	/*
47 	 * Try to get the inode.  If the verifiers fail, we try again
48 	 * in raw mode.
49 	 */
50 	error = xchk_get_inode(sc, ip);
51 	switch (error) {
52 	case 0:
53 		break;
54 	case -EFSCORRUPTED:
55 	case -EFSBADCRC:
56 		return xchk_trans_alloc(sc, 0);
57 	default:
58 		return error;
59 	}
60 
61 	/* Got the inode, lock it and we're ready to go. */
62 	sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
63 	xfs_ilock(sc->ip, sc->ilock_flags);
64 	error = xchk_trans_alloc(sc, 0);
65 	if (error)
66 		goto out;
67 	sc->ilock_flags |= XFS_ILOCK_EXCL;
68 	xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
69 
70 out:
71 	/* scrub teardown will unlock and release the inode for us */
72 	return error;
73 }
74 
75 /* Inode core */
76 
77 /* Validate di_extsize hint. */
78 STATIC void
xchk_inode_extsize(struct xfs_scrub * sc,struct xfs_dinode * dip,xfs_ino_t ino,uint16_t mode,uint16_t flags)79 xchk_inode_extsize(
80 	struct xfs_scrub	*sc,
81 	struct xfs_dinode	*dip,
82 	xfs_ino_t		ino,
83 	uint16_t		mode,
84 	uint16_t		flags)
85 {
86 	xfs_failaddr_t		fa;
87 
88 	fa = xfs_inode_validate_extsize(sc->mp, be32_to_cpu(dip->di_extsize),
89 			mode, flags);
90 	if (fa)
91 		xchk_ino_set_corrupt(sc, ino);
92 }
93 
94 /*
95  * Validate di_cowextsize hint.
96  *
97  * The rules are documented at xfs_ioctl_setattr_check_cowextsize().
98  * These functions must be kept in sync with each other.
99  */
100 STATIC void
xchk_inode_cowextsize(struct xfs_scrub * sc,struct xfs_dinode * dip,xfs_ino_t ino,uint16_t mode,uint16_t flags,uint64_t flags2)101 xchk_inode_cowextsize(
102 	struct xfs_scrub	*sc,
103 	struct xfs_dinode	*dip,
104 	xfs_ino_t		ino,
105 	uint16_t		mode,
106 	uint16_t		flags,
107 	uint64_t		flags2)
108 {
109 	xfs_failaddr_t		fa;
110 
111 	fa = xfs_inode_validate_cowextsize(sc->mp,
112 			be32_to_cpu(dip->di_cowextsize), mode, flags,
113 			flags2);
114 	if (fa)
115 		xchk_ino_set_corrupt(sc, ino);
116 }
117 
118 /* Make sure the di_flags make sense for the inode. */
119 STATIC void
xchk_inode_flags(struct xfs_scrub * sc,struct xfs_dinode * dip,xfs_ino_t ino,uint16_t mode,uint16_t flags)120 xchk_inode_flags(
121 	struct xfs_scrub	*sc,
122 	struct xfs_dinode	*dip,
123 	xfs_ino_t		ino,
124 	uint16_t		mode,
125 	uint16_t		flags)
126 {
127 	struct xfs_mount	*mp = sc->mp;
128 
129 	/* di_flags are all taken, last bit cannot be used */
130 	if (flags & ~XFS_DIFLAG_ANY)
131 		goto bad;
132 
133 	/* rt flags require rt device */
134 	if ((flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
135 		goto bad;
136 
137 	/* new rt bitmap flag only valid for rbmino */
138 	if ((flags & XFS_DIFLAG_NEWRTBM) && ino != mp->m_sb.sb_rbmino)
139 		goto bad;
140 
141 	/* directory-only flags */
142 	if ((flags & (XFS_DIFLAG_RTINHERIT |
143 		     XFS_DIFLAG_EXTSZINHERIT |
144 		     XFS_DIFLAG_PROJINHERIT |
145 		     XFS_DIFLAG_NOSYMLINKS)) &&
146 	    !S_ISDIR(mode))
147 		goto bad;
148 
149 	/* file-only flags */
150 	if ((flags & (XFS_DIFLAG_REALTIME | FS_XFLAG_EXTSIZE)) &&
151 	    !S_ISREG(mode))
152 		goto bad;
153 
154 	/* filestreams and rt make no sense */
155 	if ((flags & XFS_DIFLAG_FILESTREAM) && (flags & XFS_DIFLAG_REALTIME))
156 		goto bad;
157 
158 	return;
159 bad:
160 	xchk_ino_set_corrupt(sc, ino);
161 }
162 
163 /* Make sure the di_flags2 make sense for the inode. */
164 STATIC void
xchk_inode_flags2(struct xfs_scrub * sc,struct xfs_dinode * dip,xfs_ino_t ino,uint16_t mode,uint16_t flags,uint64_t flags2)165 xchk_inode_flags2(
166 	struct xfs_scrub	*sc,
167 	struct xfs_dinode	*dip,
168 	xfs_ino_t		ino,
169 	uint16_t		mode,
170 	uint16_t		flags,
171 	uint64_t		flags2)
172 {
173 	struct xfs_mount	*mp = sc->mp;
174 
175 	/* Unknown di_flags2 could be from a future kernel */
176 	if (flags2 & ~XFS_DIFLAG2_ANY)
177 		xchk_ino_set_warning(sc, ino);
178 
179 	/* reflink flag requires reflink feature */
180 	if ((flags2 & XFS_DIFLAG2_REFLINK) &&
181 	    !xfs_sb_version_hasreflink(&mp->m_sb))
182 		goto bad;
183 
184 	/* cowextsize flag is checked w.r.t. mode separately */
185 
186 	/* file/dir-only flags */
187 	if ((flags2 & XFS_DIFLAG2_DAX) && !(S_ISREG(mode) || S_ISDIR(mode)))
188 		goto bad;
189 
190 	/* file-only flags */
191 	if ((flags2 & XFS_DIFLAG2_REFLINK) && !S_ISREG(mode))
192 		goto bad;
193 
194 	/* realtime and reflink make no sense, currently */
195 	if ((flags & XFS_DIFLAG_REALTIME) && (flags2 & XFS_DIFLAG2_REFLINK))
196 		goto bad;
197 
198 	/* dax and reflink make no sense, currently */
199 	if ((flags2 & XFS_DIFLAG2_DAX) && (flags2 & XFS_DIFLAG2_REFLINK))
200 		goto bad;
201 
202 	return;
203 bad:
204 	xchk_ino_set_corrupt(sc, ino);
205 }
206 
207 /* Scrub all the ondisk inode fields. */
208 STATIC void
xchk_dinode(struct xfs_scrub * sc,struct xfs_dinode * dip,xfs_ino_t ino)209 xchk_dinode(
210 	struct xfs_scrub	*sc,
211 	struct xfs_dinode	*dip,
212 	xfs_ino_t		ino)
213 {
214 	struct xfs_mount	*mp = sc->mp;
215 	size_t			fork_recs;
216 	unsigned long long	isize;
217 	uint64_t		flags2;
218 	uint32_t		nextents;
219 	uint16_t		flags;
220 	uint16_t		mode;
221 
222 	flags = be16_to_cpu(dip->di_flags);
223 	if (dip->di_version >= 3)
224 		flags2 = be64_to_cpu(dip->di_flags2);
225 	else
226 		flags2 = 0;
227 
228 	/* di_mode */
229 	mode = be16_to_cpu(dip->di_mode);
230 	switch (mode & S_IFMT) {
231 	case S_IFLNK:
232 	case S_IFREG:
233 	case S_IFDIR:
234 	case S_IFCHR:
235 	case S_IFBLK:
236 	case S_IFIFO:
237 	case S_IFSOCK:
238 		/* mode is recognized */
239 		break;
240 	default:
241 		xchk_ino_set_corrupt(sc, ino);
242 		break;
243 	}
244 
245 	/* v1/v2 fields */
246 	switch (dip->di_version) {
247 	case 1:
248 		/*
249 		 * We autoconvert v1 inodes into v2 inodes on writeout,
250 		 * so just mark this inode for preening.
251 		 */
252 		xchk_ino_set_preen(sc, ino);
253 		break;
254 	case 2:
255 	case 3:
256 		if (dip->di_onlink != 0)
257 			xchk_ino_set_corrupt(sc, ino);
258 
259 		if (dip->di_mode == 0 && sc->ip)
260 			xchk_ino_set_corrupt(sc, ino);
261 
262 		if (dip->di_projid_hi != 0 &&
263 		    !xfs_sb_version_hasprojid32bit(&mp->m_sb))
264 			xchk_ino_set_corrupt(sc, ino);
265 		break;
266 	default:
267 		xchk_ino_set_corrupt(sc, ino);
268 		return;
269 	}
270 
271 	/*
272 	 * di_uid/di_gid -- -1 isn't invalid, but there's no way that
273 	 * userspace could have created that.
274 	 */
275 	if (dip->di_uid == cpu_to_be32(-1U) ||
276 	    dip->di_gid == cpu_to_be32(-1U))
277 		xchk_ino_set_warning(sc, ino);
278 
279 	/* di_format */
280 	switch (dip->di_format) {
281 	case XFS_DINODE_FMT_DEV:
282 		if (!S_ISCHR(mode) && !S_ISBLK(mode) &&
283 		    !S_ISFIFO(mode) && !S_ISSOCK(mode))
284 			xchk_ino_set_corrupt(sc, ino);
285 		break;
286 	case XFS_DINODE_FMT_LOCAL:
287 		if (!S_ISDIR(mode) && !S_ISLNK(mode))
288 			xchk_ino_set_corrupt(sc, ino);
289 		break;
290 	case XFS_DINODE_FMT_EXTENTS:
291 		if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode))
292 			xchk_ino_set_corrupt(sc, ino);
293 		break;
294 	case XFS_DINODE_FMT_BTREE:
295 		if (!S_ISREG(mode) && !S_ISDIR(mode))
296 			xchk_ino_set_corrupt(sc, ino);
297 		break;
298 	case XFS_DINODE_FMT_UUID:
299 	default:
300 		xchk_ino_set_corrupt(sc, ino);
301 		break;
302 	}
303 
304 	/* di_[amc]time.nsec */
305 	if (be32_to_cpu(dip->di_atime.t_nsec) >= NSEC_PER_SEC)
306 		xchk_ino_set_corrupt(sc, ino);
307 	if (be32_to_cpu(dip->di_mtime.t_nsec) >= NSEC_PER_SEC)
308 		xchk_ino_set_corrupt(sc, ino);
309 	if (be32_to_cpu(dip->di_ctime.t_nsec) >= NSEC_PER_SEC)
310 		xchk_ino_set_corrupt(sc, ino);
311 
312 	/*
313 	 * di_size.  xfs_dinode_verify checks for things that screw up
314 	 * the VFS such as the upper bit being set and zero-length
315 	 * symlinks/directories, but we can do more here.
316 	 */
317 	isize = be64_to_cpu(dip->di_size);
318 	if (isize & (1ULL << 63))
319 		xchk_ino_set_corrupt(sc, ino);
320 
321 	/* Devices, fifos, and sockets must have zero size */
322 	if (!S_ISDIR(mode) && !S_ISREG(mode) && !S_ISLNK(mode) && isize != 0)
323 		xchk_ino_set_corrupt(sc, ino);
324 
325 	/* Directories can't be larger than the data section size (32G) */
326 	if (S_ISDIR(mode) && (isize == 0 || isize >= XFS_DIR2_SPACE_SIZE))
327 		xchk_ino_set_corrupt(sc, ino);
328 
329 	/* Symlinks can't be larger than SYMLINK_MAXLEN */
330 	if (S_ISLNK(mode) && (isize == 0 || isize >= XFS_SYMLINK_MAXLEN))
331 		xchk_ino_set_corrupt(sc, ino);
332 
333 	/*
334 	 * Warn if the running kernel can't handle the kinds of offsets
335 	 * needed to deal with the file size.  In other words, if the
336 	 * pagecache can't cache all the blocks in this file due to
337 	 * overly large offsets, flag the inode for admin review.
338 	 */
339 	if (isize >= mp->m_super->s_maxbytes)
340 		xchk_ino_set_warning(sc, ino);
341 
342 	/* di_nblocks */
343 	if (flags2 & XFS_DIFLAG2_REFLINK) {
344 		; /* nblocks can exceed dblocks */
345 	} else if (flags & XFS_DIFLAG_REALTIME) {
346 		/*
347 		 * nblocks is the sum of data extents (in the rtdev),
348 		 * attr extents (in the datadev), and both forks' bmbt
349 		 * blocks (in the datadev).  This clumsy check is the
350 		 * best we can do without cross-referencing with the
351 		 * inode forks.
352 		 */
353 		if (be64_to_cpu(dip->di_nblocks) >=
354 		    mp->m_sb.sb_dblocks + mp->m_sb.sb_rblocks)
355 			xchk_ino_set_corrupt(sc, ino);
356 	} else {
357 		if (be64_to_cpu(dip->di_nblocks) >= mp->m_sb.sb_dblocks)
358 			xchk_ino_set_corrupt(sc, ino);
359 	}
360 
361 	xchk_inode_flags(sc, dip, ino, mode, flags);
362 
363 	xchk_inode_extsize(sc, dip, ino, mode, flags);
364 
365 	/* di_nextents */
366 	nextents = be32_to_cpu(dip->di_nextents);
367 	fork_recs =  XFS_DFORK_DSIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
368 	switch (dip->di_format) {
369 	case XFS_DINODE_FMT_EXTENTS:
370 		if (nextents > fork_recs)
371 			xchk_ino_set_corrupt(sc, ino);
372 		break;
373 	case XFS_DINODE_FMT_BTREE:
374 		if (nextents <= fork_recs)
375 			xchk_ino_set_corrupt(sc, ino);
376 		break;
377 	default:
378 		if (nextents != 0)
379 			xchk_ino_set_corrupt(sc, ino);
380 		break;
381 	}
382 
383 	/* di_forkoff */
384 	if (XFS_DFORK_APTR(dip) >= (char *)dip + mp->m_sb.sb_inodesize)
385 		xchk_ino_set_corrupt(sc, ino);
386 	if (dip->di_anextents != 0 && dip->di_forkoff == 0)
387 		xchk_ino_set_corrupt(sc, ino);
388 	if (dip->di_forkoff == 0 && dip->di_aformat != XFS_DINODE_FMT_EXTENTS)
389 		xchk_ino_set_corrupt(sc, ino);
390 
391 	/* di_aformat */
392 	if (dip->di_aformat != XFS_DINODE_FMT_LOCAL &&
393 	    dip->di_aformat != XFS_DINODE_FMT_EXTENTS &&
394 	    dip->di_aformat != XFS_DINODE_FMT_BTREE)
395 		xchk_ino_set_corrupt(sc, ino);
396 
397 	/* di_anextents */
398 	nextents = be16_to_cpu(dip->di_anextents);
399 	fork_recs =  XFS_DFORK_ASIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
400 	switch (dip->di_aformat) {
401 	case XFS_DINODE_FMT_EXTENTS:
402 		if (nextents > fork_recs)
403 			xchk_ino_set_corrupt(sc, ino);
404 		break;
405 	case XFS_DINODE_FMT_BTREE:
406 		if (nextents <= fork_recs)
407 			xchk_ino_set_corrupt(sc, ino);
408 		break;
409 	default:
410 		if (nextents != 0)
411 			xchk_ino_set_corrupt(sc, ino);
412 	}
413 
414 	if (dip->di_version >= 3) {
415 		if (be32_to_cpu(dip->di_crtime.t_nsec) >= NSEC_PER_SEC)
416 			xchk_ino_set_corrupt(sc, ino);
417 		xchk_inode_flags2(sc, dip, ino, mode, flags, flags2);
418 		xchk_inode_cowextsize(sc, dip, ino, mode, flags,
419 				flags2);
420 	}
421 }
422 
423 /*
424  * Make sure the finobt doesn't think this inode is free.
425  * We don't have to check the inobt ourselves because we got the inode via
426  * IGET_UNTRUSTED, which checks the inobt for us.
427  */
428 static void
xchk_inode_xref_finobt(struct xfs_scrub * sc,xfs_ino_t ino)429 xchk_inode_xref_finobt(
430 	struct xfs_scrub		*sc,
431 	xfs_ino_t			ino)
432 {
433 	struct xfs_inobt_rec_incore	rec;
434 	xfs_agino_t			agino;
435 	int				has_record;
436 	int				error;
437 
438 	if (!sc->sa.fino_cur || xchk_skip_xref(sc->sm))
439 		return;
440 
441 	agino = XFS_INO_TO_AGINO(sc->mp, ino);
442 
443 	/*
444 	 * Try to get the finobt record.  If we can't get it, then we're
445 	 * in good shape.
446 	 */
447 	error = xfs_inobt_lookup(sc->sa.fino_cur, agino, XFS_LOOKUP_LE,
448 			&has_record);
449 	if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
450 	    !has_record)
451 		return;
452 
453 	error = xfs_inobt_get_rec(sc->sa.fino_cur, &rec, &has_record);
454 	if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
455 	    !has_record)
456 		return;
457 
458 	/*
459 	 * Otherwise, make sure this record either doesn't cover this inode,
460 	 * or that it does but it's marked present.
461 	 */
462 	if (rec.ir_startino > agino ||
463 	    rec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
464 		return;
465 
466 	if (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino))
467 		xchk_btree_xref_set_corrupt(sc, sc->sa.fino_cur, 0);
468 }
469 
470 /* Cross reference the inode fields with the forks. */
471 STATIC void
xchk_inode_xref_bmap(struct xfs_scrub * sc,struct xfs_dinode * dip)472 xchk_inode_xref_bmap(
473 	struct xfs_scrub	*sc,
474 	struct xfs_dinode	*dip)
475 {
476 	xfs_extnum_t		nextents;
477 	xfs_filblks_t		count;
478 	xfs_filblks_t		acount;
479 	int			error;
480 
481 	if (xchk_skip_xref(sc->sm))
482 		return;
483 
484 	/* Walk all the extents to check nextents/naextents/nblocks. */
485 	error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_DATA_FORK,
486 			&nextents, &count);
487 	if (!xchk_should_check_xref(sc, &error, NULL))
488 		return;
489 	if (nextents < be32_to_cpu(dip->di_nextents))
490 		xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
491 
492 	error = xfs_bmap_count_blocks(sc->tp, sc->ip, XFS_ATTR_FORK,
493 			&nextents, &acount);
494 	if (!xchk_should_check_xref(sc, &error, NULL))
495 		return;
496 	if (nextents != be16_to_cpu(dip->di_anextents))
497 		xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
498 
499 	/* Check nblocks against the inode. */
500 	if (count + acount != be64_to_cpu(dip->di_nblocks))
501 		xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
502 }
503 
504 /* Cross-reference with the other btrees. */
505 STATIC void
xchk_inode_xref(struct xfs_scrub * sc,xfs_ino_t ino,struct xfs_dinode * dip)506 xchk_inode_xref(
507 	struct xfs_scrub	*sc,
508 	xfs_ino_t		ino,
509 	struct xfs_dinode	*dip)
510 {
511 	struct xfs_owner_info	oinfo;
512 	xfs_agnumber_t		agno;
513 	xfs_agblock_t		agbno;
514 	int			error;
515 
516 	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
517 		return;
518 
519 	agno = XFS_INO_TO_AGNO(sc->mp, ino);
520 	agbno = XFS_INO_TO_AGBNO(sc->mp, ino);
521 
522 	error = xchk_ag_init(sc, agno, &sc->sa);
523 	if (!xchk_xref_process_error(sc, agno, agbno, &error))
524 		return;
525 
526 	xchk_xref_is_used_space(sc, agbno, 1);
527 	xchk_inode_xref_finobt(sc, ino);
528 	xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
529 	xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
530 	xchk_xref_is_not_shared(sc, agbno, 1);
531 	xchk_inode_xref_bmap(sc, dip);
532 
533 	xchk_ag_free(sc, &sc->sa);
534 }
535 
536 /*
537  * If the reflink iflag disagrees with a scan for shared data fork extents,
538  * either flag an error (shared extents w/ no flag) or a preen (flag set w/o
539  * any shared extents).  We already checked for reflink iflag set on a non
540  * reflink filesystem.
541  */
542 static void
xchk_inode_check_reflink_iflag(struct xfs_scrub * sc,xfs_ino_t ino)543 xchk_inode_check_reflink_iflag(
544 	struct xfs_scrub	*sc,
545 	xfs_ino_t		ino)
546 {
547 	struct xfs_mount	*mp = sc->mp;
548 	bool			has_shared;
549 	int			error;
550 
551 	if (!xfs_sb_version_hasreflink(&mp->m_sb))
552 		return;
553 
554 	error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip,
555 			&has_shared);
556 	if (!xchk_xref_process_error(sc, XFS_INO_TO_AGNO(mp, ino),
557 			XFS_INO_TO_AGBNO(mp, ino), &error))
558 		return;
559 	if (xfs_is_reflink_inode(sc->ip) && !has_shared)
560 		xchk_ino_set_preen(sc, ino);
561 	else if (!xfs_is_reflink_inode(sc->ip) && has_shared)
562 		xchk_ino_set_corrupt(sc, ino);
563 }
564 
565 /* Scrub an inode. */
566 int
xchk_inode(struct xfs_scrub * sc)567 xchk_inode(
568 	struct xfs_scrub	*sc)
569 {
570 	struct xfs_dinode	di;
571 	int			error = 0;
572 
573 	/*
574 	 * If sc->ip is NULL, that means that the setup function called
575 	 * xfs_iget to look up the inode.  xfs_iget returned a EFSCORRUPTED
576 	 * and a NULL inode, so flag the corruption error and return.
577 	 */
578 	if (!sc->ip) {
579 		xchk_ino_set_corrupt(sc, sc->sm->sm_ino);
580 		return 0;
581 	}
582 
583 	/* Scrub the inode core. */
584 	xfs_inode_to_disk(sc->ip, &di, 0);
585 	xchk_dinode(sc, &di, sc->ip->i_ino);
586 	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
587 		goto out;
588 
589 	/*
590 	 * Look for discrepancies between file's data blocks and the reflink
591 	 * iflag.  We already checked the iflag against the file mode when
592 	 * we scrubbed the dinode.
593 	 */
594 	if (S_ISREG(VFS_I(sc->ip)->i_mode))
595 		xchk_inode_check_reflink_iflag(sc, sc->ip->i_ino);
596 
597 	xchk_inode_xref(sc, sc->ip->i_ino, &di);
598 out:
599 	return error;
600 }
601