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