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 "xfs_rtbitmap.h"
24 : #include "scrub/scrub.h"
25 : #include "scrub/common.h"
26 : #include "scrub/btree.h"
27 : #include "scrub/trace.h"
28 : #include "scrub/repair.h"
29 :
30 : /* Prepare the attached inode for scrubbing. */
31 : static inline int
32 77619823 : xchk_prepare_iscrub(
33 : struct xfs_scrub *sc)
34 : {
35 77619823 : int error;
36 :
37 77619823 : xchk_ilock(sc, XFS_IOLOCK_EXCL);
38 :
39 77621881 : error = xchk_trans_alloc(sc, 0);
40 77623303 : if (error)
41 : return error;
42 :
43 77623460 : error = xchk_ino_dqattach(sc);
44 77623714 : if (error)
45 : return error;
46 :
47 77623712 : xchk_ilock(sc, XFS_ILOCK_EXCL);
48 77623712 : return 0;
49 : }
50 :
51 : /* Install this scrub-by-handle inode and prepare it for scrubbing. */
52 : static inline int
53 55535093 : xchk_install_handle_iscrub(
54 : struct xfs_scrub *sc,
55 : struct xfs_inode *ip)
56 : {
57 55535093 : int error;
58 :
59 55535093 : error = xchk_install_handle_inode(sc, ip);
60 55536114 : if (error)
61 : return error;
62 :
63 55452396 : return xchk_prepare_iscrub(sc);
64 : }
65 :
66 : /*
67 : * Grab total control of the inode metadata. In the best case, we grab the
68 : * incore inode and take all locks on it. If the incore inode cannot be
69 : * constructed due to corruption problems, lock the AGI so that we can single
70 : * step the loading process to fix everything that can go wrong.
71 : */
72 : int
73 78137650 : xchk_setup_inode(
74 : struct xfs_scrub *sc)
75 : {
76 78137650 : struct xfs_imap imap;
77 78137650 : struct xfs_inode *ip;
78 78137650 : struct xfs_mount *mp = sc->mp;
79 78137650 : struct xfs_inode *ip_in = XFS_I(file_inode(sc->file));
80 78137650 : struct xfs_buf *agi_bp;
81 78137650 : struct xfs_perag *pag;
82 78137650 : xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, sc->sm->sm_ino);
83 78137650 : int error;
84 :
85 78137650 : if (xchk_need_intent_drain(sc))
86 0 : xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
87 :
88 : /* We want to scan the opened inode, so lock it and exit. */
89 78137650 : if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) {
90 22171178 : error = xchk_install_live_inode(sc, ip_in);
91 22172670 : if (error)
92 : return error;
93 :
94 22172416 : return xchk_prepare_iscrub(sc);
95 : }
96 :
97 : /* Reject internal metadata files and obviously bad inode numbers. */
98 55966472 : if (xfs_internal_inum(mp, sc->sm->sm_ino))
99 : return -ENOENT;
100 55911454 : if (!xfs_verify_ino(sc->mp, sc->sm->sm_ino))
101 : return -ENOENT;
102 :
103 : /* Try a regular untrusted iget. */
104 55911470 : error = xchk_iget(sc, sc->sm->sm_ino, &ip);
105 55910251 : if (!error)
106 55534714 : return xchk_install_handle_iscrub(sc, ip);
107 375537 : if (error == -ENOENT)
108 : return error;
109 1458 : if (error != -EFSCORRUPTED && error != -EFSBADCRC && error != -EINVAL)
110 0 : goto out_error;
111 :
112 : /*
113 : * EINVAL with IGET_UNTRUSTED probably means one of several things:
114 : * userspace gave us an inode number that doesn't correspond to fs
115 : * space; the inode btree lacks a record for this inode; or there is
116 : * a record, and it says this inode is free.
117 : *
118 : * EFSCORRUPTED/EFSBADCRC could mean that the inode was mappable, but
119 : * some other metadata corruption (e.g. inode forks) prevented
120 : * instantiation of the incore inode. Or it could mean the inobt is
121 : * corrupt.
122 : *
123 : * We want to look up this inode in the inobt directly to distinguish
124 : * three different scenarios: (1) the inobt says the inode is free,
125 : * in which case there's nothing to do; (2) the inobt is corrupt so we
126 : * should flag the corruption and exit to userspace to let it fix the
127 : * inobt; and (3) the inobt says the inode is allocated, but loading it
128 : * failed due to corruption.
129 : *
130 : * Allocate a transaction and grab the AGI to prevent inobt activity in
131 : * this AG. Retry the iget in case someone allocated a new inode after
132 : * the first iget failed.
133 : */
134 1458 : error = xchk_trans_alloc(sc, 0);
135 1458 : if (error)
136 0 : goto out_error;
137 :
138 1458 : error = xchk_iget_agi(sc, sc->sm->sm_ino, &agi_bp, &ip);
139 1458 : if (error == 0) {
140 : /* Actually got the incore inode, so install it and proceed. */
141 0 : xchk_trans_cancel(sc);
142 0 : return xchk_install_handle_iscrub(sc, ip);
143 : }
144 1458 : if (error == -ENOENT)
145 0 : goto out_gone;
146 1458 : if (error != -EFSCORRUPTED && error != -EFSBADCRC && error != -EINVAL)
147 0 : goto out_cancel;
148 :
149 : /* Ensure that we have protected against inode allocation/freeing. */
150 1458 : if (agi_bp == NULL) {
151 0 : ASSERT(agi_bp != NULL);
152 0 : error = -ECANCELED;
153 0 : goto out_cancel;
154 : }
155 :
156 : /*
157 : * Untrusted iget failed a second time. Let's try an inobt lookup.
158 : * If the inobt doesn't think this is an allocated inode then we'll
159 : * return ENOENT to signal that the check can be skipped.
160 : *
161 : * If the lookup signals corruption, we'll mark this inode corrupt and
162 : * exit to userspace. There's little chance of fixing anything until
163 : * the inobt is straightened out, but there's nothing we can do here.
164 : *
165 : * If the lookup encounters a runtime error, exit to userspace.
166 : */
167 1458 : pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, sc->sm->sm_ino));
168 1458 : if (!pag) {
169 0 : error = -EFSCORRUPTED;
170 0 : goto out_cancel;
171 : }
172 :
173 1458 : error = xfs_imap(pag, sc->tp, sc->sm->sm_ino, &imap,
174 : XFS_IGET_UNTRUSTED);
175 1458 : xfs_perag_put(pag);
176 1458 : if (error == -EINVAL || error == -ENOENT)
177 1458 : goto out_gone;
178 0 : if (error)
179 0 : goto out_cancel;
180 :
181 : /*
182 : * The lookup succeeded. Chances are the ondisk inode is corrupt and
183 : * preventing iget from reading it. Retain the scrub transaction and
184 : * the AGI buffer to prevent anyone from allocating or freeing inodes.
185 : * This ensures that we preserve the inconsistency between the inobt
186 : * saying the inode is allocated and the icache being unable to load
187 : * the inode until we can flag the corruption in xchk_inode. The
188 : * scrub function has to note the corruption, since we're not really
189 : * supposed to do that from the setup function. Save the mapping to
190 : * make repairs to the ondisk inode buffer.
191 : */
192 0 : if (xchk_could_repair(sc))
193 0 : xrep_setup_inode(sc, &imap);
194 : return 0;
195 :
196 0 : out_cancel:
197 0 : xchk_trans_cancel(sc);
198 0 : out_error:
199 0 : xchk_whine(mp, "type %s agno 0x%x agbno 0x%x error %d ret_ip %pS",
200 0 : xchk_type_string(sc->sm->sm_type), agno,
201 0 : XFS_INO_TO_AGBNO(mp, sc->sm->sm_ino), error,
202 : __return_address);
203 0 : trace_xchk_op_error(sc, agno, XFS_INO_TO_AGBNO(mp, sc->sm->sm_ino),
204 : error, __return_address);
205 0 : return error;
206 1458 : out_gone:
207 : /* The file is gone, so there's nothing to check. */
208 1458 : xchk_trans_cancel(sc);
209 1458 : return -ENOENT;
210 : }
211 :
212 : /* Inode core */
213 :
214 : /* Validate di_extsize hint. */
215 : STATIC void
216 78135765 : xchk_inode_extsize(
217 : struct xfs_scrub *sc,
218 : struct xfs_dinode *dip,
219 : xfs_ino_t ino,
220 : uint16_t mode,
221 : uint16_t flags)
222 : {
223 78135765 : xfs_failaddr_t fa;
224 78135765 : uint32_t value = be32_to_cpu(dip->di_extsize);
225 :
226 78135765 : fa = xfs_inode_validate_extsize(sc->mp, value, mode, flags);
227 78136218 : if (fa)
228 0 : xchk_ino_set_corrupt(sc, ino);
229 :
230 : /*
231 : * XFS allows a sysadmin to change the rt extent size when adding a rt
232 : * section to a filesystem after formatting. If there are any
233 : * directories with extszinherit and rtinherit set, the hint could
234 : * become misaligned with the new rextsize. The verifier doesn't check
235 : * this, because we allow rtinherit directories even without an rt
236 : * device. Flag this as an administrative warning since we will clean
237 : * this up eventually.
238 : */
239 78136218 : if ((flags & XFS_DIFLAG_RTINHERIT) &&
240 0 : (flags & XFS_DIFLAG_EXTSZINHERIT) &&
241 0 : xfs_extlen_to_rtxmod(sc->mp, value) > 0)
242 0 : xchk_ino_set_warning(sc, ino);
243 78136218 : }
244 :
245 : /* Validate di_cowextsize hint. */
246 : STATIC void
247 78136347 : xchk_inode_cowextsize(
248 : struct xfs_scrub *sc,
249 : struct xfs_dinode *dip,
250 : xfs_ino_t ino,
251 : uint16_t mode,
252 : uint16_t flags,
253 : uint64_t flags2)
254 : {
255 78136347 : xfs_failaddr_t fa;
256 78136347 : uint32_t value = be32_to_cpu(dip->di_cowextsize);
257 :
258 78136347 : fa = xfs_inode_validate_cowextsize(sc->mp, value, mode, flags, flags2);
259 78136940 : if (fa)
260 0 : xchk_ino_set_corrupt(sc, ino);
261 :
262 : /*
263 : * XFS allows a sysadmin to change the rt extent size when adding a rt
264 : * section to a filesystem after formatting. If there are any
265 : * directories with cowextsize and rtinherit set, the hint could become
266 : * misaligned with the new rextsize. The verifier doesn't check this,
267 : * because we allow rtinherit directories even without an rt device.
268 : * Flag this as an administrative warning since we will clean this up
269 : * eventually.
270 : */
271 78137324 : if ((flags & XFS_DIFLAG_RTINHERIT) &&
272 4515373 : (flags2 & XFS_DIFLAG2_COWEXTSIZE) &&
273 0 : value % sc->mp->m_sb.sb_rextsize > 0)
274 0 : xchk_ino_set_warning(sc, ino);
275 78137324 : }
276 :
277 : /* Make sure the di_flags make sense for the inode. */
278 : STATIC void
279 78136945 : xchk_inode_flags(
280 : struct xfs_scrub *sc,
281 : struct xfs_dinode *dip,
282 : xfs_ino_t ino,
283 : uint16_t mode,
284 : uint16_t flags)
285 : {
286 78136945 : struct xfs_mount *mp = sc->mp;
287 :
288 : /* di_flags are all taken, last bit cannot be used */
289 78136945 : if (flags & ~XFS_DIFLAG_ANY)
290 0 : goto bad;
291 :
292 : /* rt flags require rt device */
293 78136945 : if ((flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
294 0 : goto bad;
295 :
296 : /* new rt bitmap flag only valid for rbmino */
297 78136945 : if ((flags & XFS_DIFLAG_NEWRTBM) && ino != mp->m_sb.sb_rbmino)
298 0 : goto bad;
299 :
300 : /* directory-only flags */
301 78136945 : if ((flags & (XFS_DIFLAG_RTINHERIT |
302 : XFS_DIFLAG_EXTSZINHERIT |
303 : XFS_DIFLAG_PROJINHERIT |
304 4529679 : XFS_DIFLAG_NOSYMLINKS)) &&
305 : !S_ISDIR(mode))
306 0 : goto bad;
307 :
308 : /* file-only flags */
309 78136945 : if ((flags & (XFS_DIFLAG_REALTIME | FS_XFLAG_EXTSIZE)) &&
310 : !S_ISREG(mode))
311 0 : goto bad;
312 :
313 : /* filestreams and rt make no sense */
314 78136945 : if ((flags & XFS_DIFLAG_FILESTREAM) && (flags & XFS_DIFLAG_REALTIME))
315 0 : goto bad;
316 :
317 : return;
318 0 : bad:
319 0 : xchk_ino_set_corrupt(sc, ino);
320 : }
321 :
322 : /* Make sure the di_flags2 make sense for the inode. */
323 : STATIC void
324 78135292 : xchk_inode_flags2(
325 : struct xfs_scrub *sc,
326 : struct xfs_dinode *dip,
327 : xfs_ino_t ino,
328 : uint16_t mode,
329 : uint16_t flags,
330 : uint64_t flags2)
331 : {
332 78135292 : struct xfs_mount *mp = sc->mp;
333 :
334 : /* Unknown di_flags2 could be from a future kernel */
335 78135292 : if (flags2 & ~XFS_DIFLAG2_ANY)
336 0 : xchk_ino_set_warning(sc, ino);
337 :
338 : /* reflink flag requires reflink feature */
339 78135292 : if ((flags2 & XFS_DIFLAG2_REFLINK) &&
340 : !xfs_has_reflink(mp))
341 0 : goto bad;
342 :
343 : /* cowextsize flag is checked w.r.t. mode separately */
344 :
345 : /* file/dir-only flags */
346 78135292 : if ((flags2 & XFS_DIFLAG2_DAX) && !(S_ISREG(mode) || S_ISDIR(mode)))
347 0 : goto bad;
348 :
349 : /* file-only flags */
350 78135292 : if ((flags2 & XFS_DIFLAG2_REFLINK) && !S_ISREG(mode))
351 0 : goto bad;
352 :
353 : /* realtime and reflink don't always go together */
354 78135292 : if ((flags & XFS_DIFLAG_REALTIME) && (flags2 & XFS_DIFLAG2_REFLINK) &&
355 1256786 : !xfs_has_rtreflink(mp))
356 0 : goto bad;
357 :
358 : /* no bigtime iflag without the bigtime feature */
359 156270584 : if (xfs_dinode_has_bigtime(dip) && !xfs_has_bigtime(mp))
360 0 : goto bad;
361 :
362 : /* no large extent counts without the filesystem feature */
363 78135292 : if ((flags2 & XFS_DIFLAG2_NREXT64) && !xfs_has_large_extent_counts(mp))
364 0 : goto bad;
365 :
366 : return;
367 0 : bad:
368 0 : xchk_ino_set_corrupt(sc, ino);
369 : }
370 :
371 : static inline void
372 312529530 : xchk_dinode_nsec(
373 : struct xfs_scrub *sc,
374 : xfs_ino_t ino,
375 : struct xfs_dinode *dip,
376 : const xfs_timestamp_t ts)
377 : {
378 312529530 : struct timespec64 tv;
379 :
380 312529530 : tv = xfs_inode_from_disk_ts(dip, ts);
381 312528075 : if (tv.tv_nsec < 0 || tv.tv_nsec >= NSEC_PER_SEC)
382 0 : xchk_ino_set_corrupt(sc, ino);
383 312528075 : }
384 :
385 : /* Scrub all the ondisk inode fields. */
386 : STATIC void
387 78137200 : xchk_dinode(
388 : struct xfs_scrub *sc,
389 : struct xfs_dinode *dip,
390 : xfs_ino_t ino)
391 : {
392 78137200 : struct xfs_mount *mp = sc->mp;
393 78137200 : size_t fork_recs;
394 78137200 : unsigned long long isize;
395 78137200 : uint64_t flags2;
396 78137200 : xfs_extnum_t nextents;
397 78137200 : xfs_extnum_t naextents;
398 78137200 : prid_t prid;
399 78137200 : uint16_t flags;
400 78137200 : uint16_t mode;
401 :
402 78137200 : flags = be16_to_cpu(dip->di_flags);
403 78137200 : if (dip->di_version >= 3)
404 78137147 : flags2 = be64_to_cpu(dip->di_flags2);
405 : else
406 : flags2 = 0;
407 :
408 : /* di_mode */
409 78137200 : mode = be16_to_cpu(dip->di_mode);
410 78137200 : switch (mode & S_IFMT) {
411 : case S_IFLNK:
412 : case S_IFREG:
413 : case S_IFDIR:
414 : case S_IFCHR:
415 : case S_IFBLK:
416 : case S_IFIFO:
417 : case S_IFSOCK:
418 : /* mode is recognized */
419 : break;
420 0 : default:
421 0 : xchk_ino_set_corrupt(sc, ino);
422 0 : break;
423 : }
424 :
425 : /* v1/v2 fields */
426 78137200 : switch (dip->di_version) {
427 0 : case 1:
428 : /*
429 : * We autoconvert v1 inodes into v2 inodes on writeout,
430 : * so just mark this inode for preening.
431 : */
432 0 : xchk_ino_set_preen(sc, ino);
433 0 : prid = 0;
434 0 : break;
435 78137200 : case 2:
436 : case 3:
437 78137200 : if (dip->di_onlink != 0)
438 0 : xchk_ino_set_corrupt(sc, ino);
439 :
440 78137200 : if (dip->di_mode == 0 && sc->ip)
441 0 : xchk_ino_set_corrupt(sc, ino);
442 :
443 78137200 : if (dip->di_projid_hi != 0 &&
444 : !xfs_has_projid32(mp))
445 0 : xchk_ino_set_corrupt(sc, ino);
446 :
447 78137200 : prid = be16_to_cpu(dip->di_projid_lo);
448 : break;
449 0 : default:
450 0 : xchk_ino_set_corrupt(sc, ino);
451 0 : return;
452 : }
453 :
454 78137200 : if (xfs_has_projid32(mp))
455 78137729 : prid |= (prid_t)be16_to_cpu(dip->di_projid_hi) << 16;
456 :
457 : /*
458 : * di_uid/di_gid -- -1 isn't invalid, but there's no way that
459 : * userspace could have created that.
460 : */
461 78137200 : if (dip->di_uid == cpu_to_be32(-1U) ||
462 78137200 : dip->di_gid == cpu_to_be32(-1U))
463 0 : xchk_ino_set_warning(sc, ino);
464 :
465 : /*
466 : * project id of -1 isn't supposed to be valid, but the kernel didn't
467 : * always validate that.
468 : */
469 78138665 : if (prid == -1U)
470 0 : xchk_ino_set_warning(sc, ino);
471 :
472 : /* di_format */
473 78138665 : switch (dip->di_format) {
474 32877479 : case XFS_DINODE_FMT_DEV:
475 32877479 : if (!S_ISCHR(mode) && !S_ISBLK(mode) &&
476 0 : !S_ISFIFO(mode) && !S_ISSOCK(mode))
477 0 : xchk_ino_set_corrupt(sc, ino);
478 : break;
479 13202436 : case XFS_DINODE_FMT_LOCAL:
480 13202436 : if (!S_ISDIR(mode) && !S_ISLNK(mode))
481 0 : xchk_ino_set_corrupt(sc, ino);
482 : break;
483 30482042 : case XFS_DINODE_FMT_EXTENTS:
484 30482042 : if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode))
485 0 : xchk_ino_set_corrupt(sc, ino);
486 : break;
487 1415344 : case XFS_DINODE_FMT_BTREE:
488 1415344 : if (!S_ISREG(mode) && !S_ISDIR(mode))
489 0 : xchk_ino_set_corrupt(sc, ino);
490 : break;
491 161364 : case XFS_DINODE_FMT_RMAP:
492 : case XFS_DINODE_FMT_REFCOUNT:
493 161364 : if (!S_ISREG(mode))
494 0 : xchk_ino_set_corrupt(sc, ino);
495 : break;
496 0 : case XFS_DINODE_FMT_UUID:
497 : default:
498 0 : xchk_ino_set_corrupt(sc, ino);
499 0 : break;
500 : }
501 :
502 : /* di_[amc]time.nsec */
503 78138665 : xchk_dinode_nsec(sc, ino, dip, dip->di_atime);
504 78137269 : xchk_dinode_nsec(sc, ino, dip, dip->di_mtime);
505 78137792 : xchk_dinode_nsec(sc, ino, dip, dip->di_ctime);
506 :
507 : /*
508 : * di_size. xfs_dinode_verify checks for things that screw up
509 : * the VFS such as the upper bit being set and zero-length
510 : * symlinks/directories, but we can do more here.
511 : */
512 78137587 : isize = be64_to_cpu(dip->di_size);
513 78137587 : if (isize & (1ULL << 63))
514 0 : xchk_ino_set_corrupt(sc, ino);
515 :
516 : /* Devices, fifos, and sockets must have zero size */
517 78137587 : if (!S_ISDIR(mode) && !S_ISREG(mode) && !S_ISLNK(mode) && isize != 0)
518 0 : xchk_ino_set_corrupt(sc, ino);
519 :
520 : /* Directories can't be larger than the data section size (32G) */
521 78137587 : if (S_ISDIR(mode) && (isize == 0 || isize >= XFS_DIR2_SPACE_SIZE))
522 0 : xchk_ino_set_corrupt(sc, ino);
523 :
524 : /* Symlinks can't be larger than SYMLINK_MAXLEN */
525 78137587 : if (S_ISLNK(mode) && (isize == 0 || isize >= XFS_SYMLINK_MAXLEN))
526 0 : xchk_ino_set_corrupt(sc, ino);
527 :
528 : /*
529 : * Warn if the running kernel can't handle the kinds of offsets
530 : * needed to deal with the file size. In other words, if the
531 : * pagecache can't cache all the blocks in this file due to
532 : * overly large offsets, flag the inode for admin review.
533 : */
534 78137587 : if (isize > mp->m_super->s_maxbytes)
535 0 : xchk_ino_set_warning(sc, ino);
536 :
537 : /* di_nblocks */
538 78137587 : if (flags2 & XFS_DIFLAG2_REFLINK) {
539 : ; /* nblocks can exceed dblocks */
540 73571399 : } else if (flags & XFS_DIFLAG_REALTIME) {
541 : /*
542 : * nblocks is the sum of data extents (in the rtdev),
543 : * attr extents (in the datadev), and both forks' bmbt
544 : * blocks (in the datadev). This clumsy check is the
545 : * best we can do without cross-referencing with the
546 : * inode forks.
547 : */
548 5226970 : if (be64_to_cpu(dip->di_nblocks) >=
549 5226970 : mp->m_sb.sb_dblocks + mp->m_sb.sb_rblocks)
550 0 : xchk_ino_set_corrupt(sc, ino);
551 : } else {
552 68344429 : if (be64_to_cpu(dip->di_nblocks) >= mp->m_sb.sb_dblocks)
553 0 : xchk_ino_set_corrupt(sc, ino);
554 : }
555 :
556 78137587 : xchk_inode_flags(sc, dip, ino, mode, flags);
557 :
558 78136984 : xchk_inode_extsize(sc, dip, ino, mode, flags);
559 :
560 78137972 : nextents = xfs_dfork_data_extents(dip);
561 78137972 : naextents = xfs_dfork_attr_extents(dip);
562 :
563 : /* di_nextents */
564 78137986 : fork_recs = XFS_DFORK_DSIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
565 78137972 : switch (dip->di_format) {
566 30481648 : case XFS_DINODE_FMT_EXTENTS:
567 30481648 : if (nextents > fork_recs)
568 0 : xchk_ino_set_corrupt(sc, ino);
569 : break;
570 1415332 : case XFS_DINODE_FMT_BTREE:
571 1415332 : if (nextents <= fork_recs)
572 0 : xchk_ino_set_corrupt(sc, ino);
573 : break;
574 46240992 : default:
575 46240992 : if (nextents != 0)
576 0 : xchk_ino_set_corrupt(sc, ino);
577 : break;
578 : }
579 :
580 : /* di_forkoff */
581 156274775 : if (XFS_DFORK_APTR(dip) >= (char *)dip + mp->m_sb.sb_inodesize)
582 0 : xchk_ino_set_corrupt(sc, ino);
583 78137972 : if (naextents != 0 && dip->di_forkoff == 0)
584 0 : xchk_ino_set_corrupt(sc, ino);
585 78137972 : if (dip->di_forkoff == 0 && dip->di_aformat != XFS_DINODE_FMT_EXTENTS)
586 0 : xchk_ino_set_corrupt(sc, ino);
587 :
588 : /* di_aformat */
589 78137972 : if (dip->di_aformat != XFS_DINODE_FMT_LOCAL &&
590 78137972 : dip->di_aformat != XFS_DINODE_FMT_EXTENTS &&
591 : dip->di_aformat != XFS_DINODE_FMT_BTREE)
592 0 : xchk_ino_set_corrupt(sc, ino);
593 :
594 : /* di_anextents */
595 78136851 : fork_recs = XFS_DFORK_ASIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
596 78136849 : switch (dip->di_aformat) {
597 2088594 : case XFS_DINODE_FMT_EXTENTS:
598 2088594 : if (naextents > fork_recs)
599 0 : xchk_ino_set_corrupt(sc, ino);
600 : break;
601 41 : case XFS_DINODE_FMT_BTREE:
602 41 : if (naextents <= fork_recs)
603 0 : xchk_ino_set_corrupt(sc, ino);
604 : break;
605 76048214 : default:
606 76048214 : if (naextents != 0)
607 0 : xchk_ino_set_corrupt(sc, ino);
608 : }
609 :
610 78136849 : if (dip->di_version >= 3) {
611 78134704 : xchk_dinode_nsec(sc, ino, dip, dip->di_crtime);
612 78135621 : xchk_inode_flags2(sc, dip, ino, mode, flags, flags2);
613 78136656 : xchk_inode_cowextsize(sc, dip, ino, mode, flags,
614 : flags2);
615 : }
616 : }
617 :
618 : /*
619 : * Make sure the finobt doesn't think this inode is free.
620 : * We don't have to check the inobt ourselves because we got the inode via
621 : * IGET_UNTRUSTED, which checks the inobt for us.
622 : */
623 : static void
624 78139436 : xchk_inode_xref_finobt(
625 : struct xfs_scrub *sc,
626 : xfs_ino_t ino)
627 : {
628 78139436 : struct xfs_inobt_rec_incore rec;
629 78139436 : xfs_agino_t agino;
630 78139436 : int has_record;
631 78139436 : int error;
632 :
633 78139436 : if (!sc->sa.fino_cur || xchk_skip_xref(sc->sm))
634 74236991 : return;
635 :
636 78139456 : agino = XFS_INO_TO_AGINO(sc->mp, ino);
637 :
638 : /*
639 : * Try to get the finobt record. If we can't get it, then we're
640 : * in good shape.
641 : */
642 78139456 : error = xfs_inobt_lookup(sc->sa.fino_cur, agino, XFS_LOOKUP_LE,
643 : &has_record);
644 78139810 : if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
645 78139861 : !has_record)
646 : return;
647 :
648 16905620 : error = xfs_inobt_get_rec(sc->sa.fino_cur, &rec, &has_record);
649 16905603 : if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur) ||
650 16905607 : !has_record)
651 : return;
652 :
653 : /*
654 : * Otherwise, make sure this record either doesn't cover this inode,
655 : * or that it does but it's marked present.
656 : */
657 16905607 : if (rec.ir_startino > agino ||
658 16905607 : rec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
659 : return;
660 :
661 3902837 : if (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino))
662 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.fino_cur, 0);
663 : }
664 :
665 : /* Cross reference the inode fields with the forks. */
666 : STATIC void
667 78139777 : xchk_inode_xref_bmap(
668 : struct xfs_scrub *sc,
669 : struct xfs_dinode *dip)
670 : {
671 78139777 : xfs_extnum_t nextents;
672 78139777 : xfs_filblks_t count;
673 78139777 : xfs_filblks_t acount;
674 78139777 : int error;
675 :
676 78139777 : if (xchk_skip_xref(sc->sm))
677 0 : return;
678 :
679 : /* Walk all the extents to check nextents/naextents/nblocks. */
680 78139777 : error = xchk_inode_count_blocks(sc, XFS_DATA_FORK, &nextents, &count);
681 78139624 : if (!xchk_should_check_xref(sc, &error, NULL))
682 : return;
683 78139683 : if (nextents < xfs_dfork_data_extents(dip))
684 0 : xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
685 :
686 78139683 : error = xchk_inode_count_blocks(sc, XFS_ATTR_FORK, &nextents, &acount);
687 78139617 : if (!xchk_should_check_xref(sc, &error, NULL))
688 : return;
689 78139671 : if (nextents != xfs_dfork_attr_extents(dip))
690 0 : xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
691 :
692 : /* Check nblocks against the inode. */
693 78139671 : if (count + acount != be64_to_cpu(dip->di_nblocks))
694 0 : xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
695 : }
696 :
697 : /* Cross-reference with the other btrees. */
698 : STATIC void
699 78133494 : xchk_inode_xref(
700 : struct xfs_scrub *sc,
701 : xfs_ino_t ino,
702 : struct xfs_dinode *dip)
703 : {
704 78133494 : xfs_agnumber_t agno;
705 78133494 : xfs_agblock_t agbno;
706 78133494 : int error;
707 :
708 78133494 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
709 0 : return;
710 :
711 78133494 : agno = XFS_INO_TO_AGNO(sc->mp, ino);
712 78133494 : agbno = XFS_INO_TO_AGBNO(sc->mp, ino);
713 :
714 78133494 : error = xchk_ag_init_existing(sc, agno, &sc->sa);
715 78139666 : if (!xchk_xref_process_error(sc, agno, agbno, &error))
716 1 : goto out_free;
717 :
718 78139691 : xchk_xref_is_used_space(sc, agbno, 1);
719 78139351 : xchk_inode_xref_finobt(sc, ino);
720 78139451 : xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_INODES);
721 78139518 : xchk_xref_is_not_shared(sc, agbno, 1);
722 78139826 : xchk_xref_is_not_cow_staging(sc, agbno, 1);
723 78139917 : xchk_inode_xref_bmap(sc, dip);
724 :
725 78139619 : out_free:
726 78139619 : xchk_ag_free(sc, &sc->sa);
727 : }
728 :
729 : /*
730 : * If the reflink iflag disagrees with a scan for shared data fork extents,
731 : * either flag an error (shared extents w/ no flag) or a preen (flag set w/o
732 : * any shared extents). We already checked for reflink iflag set on a non
733 : * reflink filesystem.
734 : */
735 : static void
736 22755165 : xchk_inode_check_reflink_iflag(
737 : struct xfs_scrub *sc,
738 : xfs_ino_t ino)
739 : {
740 22755165 : struct xfs_mount *mp = sc->mp;
741 22755165 : bool has_shared;
742 22755165 : int error;
743 :
744 22755165 : if (!xfs_has_reflink(mp))
745 1488 : return;
746 :
747 22753677 : error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip,
748 : &has_shared);
749 22754039 : if (!xchk_xref_process_error(sc, XFS_INO_TO_AGNO(mp, ino),
750 22753807 : XFS_INO_TO_AGBNO(mp, ino), &error))
751 : return;
752 22754039 : if (xfs_is_reflink_inode(sc->ip) && !has_shared)
753 3005283 : xchk_ino_set_preen(sc, ino);
754 19748756 : else if (!xfs_is_reflink_inode(sc->ip) && has_shared)
755 0 : xchk_ino_set_corrupt(sc, ino);
756 : }
757 :
758 : /*
759 : * If this inode has zero link count, it must be on the unlinked list. If
760 : * it has nonzero link count, it must not be on the unlinked list.
761 : */
762 : STATIC void
763 78134086 : xchk_inode_check_unlinked(
764 : struct xfs_scrub *sc)
765 : {
766 78134086 : if (VFS_I(sc->ip)->i_nlink == 0) {
767 1128 : if (!xfs_inode_on_unlinked_list(sc->ip))
768 0 : xchk_ino_set_corrupt(sc, sc->ip->i_ino);
769 : } else {
770 78132958 : if (xfs_inode_on_unlinked_list(sc->ip))
771 0 : xchk_ino_set_corrupt(sc, sc->ip->i_ino);
772 : }
773 78134086 : }
774 :
775 : /* Scrub an inode. */
776 : int
777 78138478 : xchk_inode(
778 : struct xfs_scrub *sc)
779 : {
780 78138478 : struct xfs_dinode di;
781 78138478 : int error = 0;
782 :
783 : /*
784 : * If sc->ip is NULL, that means that the setup function called
785 : * xfs_iget to look up the inode. xfs_iget returned a EFSCORRUPTED
786 : * and a NULL inode, so flag the corruption error and return.
787 : */
788 78138478 : if (!sc->ip) {
789 0 : xchk_ino_set_corrupt(sc, sc->sm->sm_ino);
790 0 : return 0;
791 : }
792 :
793 : /* Scrub the inode core. */
794 78138478 : xfs_inode_to_disk(sc->ip, &di, 0);
795 78134905 : xchk_dinode(sc, &di, sc->ip->i_ino);
796 78136054 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
797 0 : goto out;
798 :
799 : /*
800 : * Look for discrepancies between file's data blocks and the reflink
801 : * iflag. We already checked the iflag against the file mode when
802 : * we scrubbed the dinode.
803 : */
804 78136054 : if (S_ISREG(VFS_I(sc->ip)->i_mode))
805 22755205 : xchk_inode_check_reflink_iflag(sc, sc->ip->i_ino);
806 :
807 78136064 : xchk_inode_check_unlinked(sc);
808 :
809 78133923 : xchk_inode_xref(sc, sc->ip->i_ino, &di);
810 : out:
811 : return error;
812 : }
|