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 : }
|