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_log_format.h"
13 #include "xfs_trans.h"
14 #include "xfs_inode.h"
15 #include "xfs_icache.h"
16 #include "xfs_dir2.h"
17 #include "xfs_dir2_priv.h"
18 #include "xfs_attr.h"
19 #include "xfs_parent.h"
20 #include "scrub/scrub.h"
21 #include "scrub/common.h"
22 #include "scrub/readdir.h"
23 #include "scrub/tempfile.h"
24 #include "scrub/repair.h"
25 #include "scrub/listxattr.h"
26 #include "scrub/xfile.h"
27 #include "scrub/xfarray.h"
28 #include "scrub/xfblob.h"
29 #include "scrub/trace.h"
30
31 /* Set us up to scrub parents. */
32 int
xchk_setup_parent(struct xfs_scrub * sc)33 xchk_setup_parent(
34 struct xfs_scrub *sc)
35 {
36 int error;
37
38 if (xchk_could_repair(sc)) {
39 error = xrep_setup_parent(sc);
40 if (error)
41 return error;
42 }
43
44 return xchk_setup_inode_contents(sc, 0);
45 }
46
47 /* Parent pointers */
48
49 /* Look for an entry in a parent pointing to this inode. */
50
51 struct xchk_parent_ctx {
52 struct xfs_scrub *sc;
53 xfs_nlink_t nlink;
54 };
55
56 /* Look for a single entry in a directory pointing to an inode. */
57 STATIC int
xchk_parent_actor(struct xfs_scrub * sc,struct xfs_inode * dp,xfs_dir2_dataptr_t dapos,const struct xfs_name * name,xfs_ino_t ino,void * priv)58 xchk_parent_actor(
59 struct xfs_scrub *sc,
60 struct xfs_inode *dp,
61 xfs_dir2_dataptr_t dapos,
62 const struct xfs_name *name,
63 xfs_ino_t ino,
64 void *priv)
65 {
66 struct xchk_parent_ctx *spc = priv;
67 int error = 0;
68
69 /* Does this name make sense? */
70 if (!xfs_dir2_namecheck(name->name, name->len))
71 error = -EFSCORRUPTED;
72 if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
73 return error;
74
75 if (sc->ip->i_ino == ino)
76 spc->nlink++;
77
78 if (xchk_should_terminate(spc->sc, &error))
79 return error;
80
81 return 0;
82 }
83
84 /*
85 * Try to lock a parent directory for checking dirents. Returns the inode
86 * flags for the locks we now hold, or zero if we failed.
87 */
88 STATIC unsigned int
xchk_parent_ilock_dir(struct xfs_inode * dp)89 xchk_parent_ilock_dir(
90 struct xfs_inode *dp)
91 {
92 if (!xfs_ilock_nowait(dp, XFS_ILOCK_SHARED))
93 return 0;
94
95 if (!xfs_need_iread_extents(&dp->i_df))
96 return XFS_ILOCK_SHARED;
97
98 xfs_iunlock(dp, XFS_ILOCK_SHARED);
99
100 if (!xfs_ilock_nowait(dp, XFS_ILOCK_EXCL))
101 return 0;
102
103 return XFS_ILOCK_EXCL;
104 }
105
106 /*
107 * Given the inode number of the alleged parent of the inode being scrubbed,
108 * try to validate that the parent has exactly one directory entry pointing
109 * back to the inode being scrubbed. Returns -EAGAIN if we need to revalidate
110 * the dotdot entry.
111 */
112 STATIC int
xchk_parent_validate(struct xfs_scrub * sc,xfs_ino_t parent_ino)113 xchk_parent_validate(
114 struct xfs_scrub *sc,
115 xfs_ino_t parent_ino)
116 {
117 struct xchk_parent_ctx spc = {
118 .sc = sc,
119 .nlink = 0,
120 };
121 struct xfs_mount *mp = sc->mp;
122 struct xfs_inode *dp = NULL;
123 xfs_nlink_t expected_nlink;
124 unsigned int lock_mode;
125 int error = 0;
126
127 /* Is this the root dir? Then '..' must point to itself. */
128 if (sc->ip == mp->m_rootip) {
129 if (sc->ip->i_ino != mp->m_sb.sb_rootino ||
130 sc->ip->i_ino != parent_ino)
131 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
132 return 0;
133 }
134
135 /* '..' must not point to ourselves. */
136 if (sc->ip->i_ino == parent_ino) {
137 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
138 return 0;
139 }
140
141 /*
142 * If we're an unlinked directory, the parent /won't/ have a link
143 * to us. Otherwise, it should have one link.
144 */
145 expected_nlink = VFS_I(sc->ip)->i_nlink == 0 ? 0 : 1;
146
147 /*
148 * Grab the parent directory inode. This must be released before we
149 * cancel the scrub transaction.
150 *
151 * If _iget returns -EINVAL or -ENOENT then the parent inode number is
152 * garbage and the directory is corrupt. If the _iget returns
153 * -EFSCORRUPTED or -EFSBADCRC then the parent is corrupt which is a
154 * cross referencing error. Any other error is an operational error.
155 */
156 error = xchk_iget(sc, parent_ino, &dp);
157 if (error == -EINVAL || error == -ENOENT) {
158 error = -EFSCORRUPTED;
159 xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error);
160 return error;
161 }
162 if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
163 return error;
164 if (dp == sc->ip || xrep_is_tempfile(dp) ||
165 !S_ISDIR(VFS_I(dp)->i_mode)) {
166 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
167 goto out_rele;
168 }
169
170 lock_mode = xchk_parent_ilock_dir(dp);
171 if (!lock_mode) {
172 xchk_iunlock(sc, XFS_ILOCK_EXCL);
173 xchk_ilock(sc, XFS_ILOCK_EXCL);
174 error = -EAGAIN;
175 goto out_rele;
176 }
177
178 /*
179 * We cannot yet validate this parent pointer if the directory looks as
180 * though it has been zapped by the inode record repair code.
181 */
182 if (xchk_dir_looks_zapped(dp)) {
183 error = -EBUSY;
184 xchk_set_incomplete(sc);
185 goto out_unlock;
186 }
187
188 /* Look for a directory entry in the parent pointing to the child. */
189 error = xchk_dir_walk(sc, dp, xchk_parent_actor, &spc);
190 if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
191 goto out_unlock;
192
193 /*
194 * Ensure that the parent has as many links to the child as the child
195 * thinks it has to the parent.
196 */
197 if (spc.nlink != expected_nlink)
198 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
199
200 out_unlock:
201 xfs_iunlock(dp, lock_mode);
202 out_rele:
203 xchk_irele(sc, dp);
204 return error;
205 }
206
207 /*
208 * Checking of Parent Pointers
209 * ===========================
210 *
211 * On filesystems with directory parent pointers, we check the referential
212 * integrity by visiting each parent pointer of a child file and checking that
213 * the directory referenced by the pointer actually has a dirent pointing
214 * forward to the child file.
215 */
216
217 /* Deferred parent pointer entry that we saved for later. */
218 struct xchk_pptr {
219 /* Cookie for retrieval of the pptr name. */
220 xfblob_cookie name_cookie;
221
222 /* Parent pointer record. */
223 struct xfs_parent_rec pptr_rec;
224
225 /* Length of the pptr name. */
226 uint8_t namelen;
227 };
228
229 struct xchk_pptrs {
230 struct xfs_scrub *sc;
231
232 /* How many parent pointers did we find at the end? */
233 unsigned long long pptrs_found;
234
235 /* Parent of this directory. */
236 xfs_ino_t parent_ino;
237
238 /* Fixed-size array of xchk_pptr structures. */
239 struct xfarray *pptr_entries;
240
241 /* Blobs containing parent pointer names. */
242 struct xfblob *pptr_names;
243
244 /* Scratch buffer for scanning pptr xattrs */
245 struct xfs_da_args pptr_args;
246
247 /* If we've cycled the ILOCK, we must revalidate all deferred pptrs. */
248 bool need_revalidate;
249
250 /* Name buffer */
251 struct xfs_name xname;
252 char namebuf[MAXNAMELEN];
253 };
254
255 /* Does this parent pointer match the dotdot entry? */
256 STATIC int
xchk_parent_scan_dotdot(struct xfs_scrub * sc,struct xfs_inode * ip,unsigned int attr_flags,const unsigned char * name,unsigned int namelen,const void * value,unsigned int valuelen,void * priv)257 xchk_parent_scan_dotdot(
258 struct xfs_scrub *sc,
259 struct xfs_inode *ip,
260 unsigned int attr_flags,
261 const unsigned char *name,
262 unsigned int namelen,
263 const void *value,
264 unsigned int valuelen,
265 void *priv)
266 {
267 struct xchk_pptrs *pp = priv;
268 xfs_ino_t parent_ino;
269 int error;
270
271 if (!(attr_flags & XFS_ATTR_PARENT))
272 return 0;
273
274 error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
275 valuelen, &parent_ino, NULL);
276 if (error)
277 return error;
278
279 if (pp->parent_ino == parent_ino)
280 return -ECANCELED;
281
282 return 0;
283 }
284
285 /* Look up the dotdot entry so that we can check it as we walk the pptrs. */
286 STATIC int
xchk_parent_pptr_and_dotdot(struct xchk_pptrs * pp)287 xchk_parent_pptr_and_dotdot(
288 struct xchk_pptrs *pp)
289 {
290 struct xfs_scrub *sc = pp->sc;
291 int error;
292
293 /* Look up '..' */
294 error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot, &pp->parent_ino);
295 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
296 return error;
297 if (!xfs_verify_dir_ino(sc->mp, pp->parent_ino)) {
298 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
299 return 0;
300 }
301
302 /* Is this the root dir? Then '..' must point to itself. */
303 if (sc->ip == sc->mp->m_rootip) {
304 if (sc->ip->i_ino != pp->parent_ino)
305 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
306 return 0;
307 }
308
309 /*
310 * If this is now an unlinked directory, the dotdot value is
311 * meaningless as long as it points to a valid inode.
312 */
313 if (VFS_I(sc->ip)->i_nlink == 0)
314 return 0;
315
316 if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
317 return 0;
318
319 /* Otherwise, walk the pptrs again, and check. */
320 error = xchk_xattr_walk(sc, sc->ip, xchk_parent_scan_dotdot, NULL, pp);
321 if (error == -ECANCELED) {
322 /* Found a parent pointer that matches dotdot. */
323 return 0;
324 }
325 if (!error || error == -EFSCORRUPTED) {
326 /* Found a broken parent pointer or no match. */
327 xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
328 return 0;
329 }
330 return error;
331 }
332
333 /*
334 * Try to lock a parent directory for checking dirents. Returns the inode
335 * flags for the locks we now hold, or zero if we failed.
336 */
337 STATIC unsigned int
xchk_parent_lock_dir(struct xfs_scrub * sc,struct xfs_inode * dp)338 xchk_parent_lock_dir(
339 struct xfs_scrub *sc,
340 struct xfs_inode *dp)
341 {
342 if (!xfs_ilock_nowait(dp, XFS_IOLOCK_SHARED))
343 return 0;
344
345 if (!xfs_ilock_nowait(dp, XFS_ILOCK_SHARED)) {
346 xfs_iunlock(dp, XFS_IOLOCK_SHARED);
347 return 0;
348 }
349
350 if (!xfs_need_iread_extents(&dp->i_df))
351 return XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED;
352
353 xfs_iunlock(dp, XFS_ILOCK_SHARED);
354
355 if (!xfs_ilock_nowait(dp, XFS_ILOCK_EXCL)) {
356 xfs_iunlock(dp, XFS_IOLOCK_SHARED);
357 return 0;
358 }
359
360 return XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;
361 }
362
363 /* Check the forward link (dirent) associated with this parent pointer. */
364 STATIC int
xchk_parent_dirent(struct xchk_pptrs * pp,const struct xfs_name * xname,struct xfs_inode * dp)365 xchk_parent_dirent(
366 struct xchk_pptrs *pp,
367 const struct xfs_name *xname,
368 struct xfs_inode *dp)
369 {
370 struct xfs_scrub *sc = pp->sc;
371 xfs_ino_t child_ino;
372 int error;
373
374 /*
375 * Use the name attached to this parent pointer to look up the
376 * directory entry in the alleged parent.
377 */
378 error = xchk_dir_lookup(sc, dp, xname, &child_ino);
379 if (error == -ENOENT) {
380 xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
381 return 0;
382 }
383 if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
384 return error;
385
386 /* Does the inode number match? */
387 if (child_ino != sc->ip->i_ino) {
388 xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
389 return 0;
390 }
391
392 return 0;
393 }
394
395 /* Try to grab a parent directory. */
396 STATIC int
xchk_parent_iget(struct xchk_pptrs * pp,const struct xfs_parent_rec * pptr,struct xfs_inode ** dpp)397 xchk_parent_iget(
398 struct xchk_pptrs *pp,
399 const struct xfs_parent_rec *pptr,
400 struct xfs_inode **dpp)
401 {
402 struct xfs_scrub *sc = pp->sc;
403 struct xfs_inode *ip;
404 xfs_ino_t parent_ino = be64_to_cpu(pptr->p_ino);
405 int error;
406
407 /* Validate inode number. */
408 error = xfs_dir_ino_validate(sc->mp, parent_ino);
409 if (error) {
410 xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
411 return -ECANCELED;
412 }
413
414 error = xchk_iget(sc, parent_ino, &ip);
415 if (error == -EINVAL || error == -ENOENT) {
416 xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
417 return -ECANCELED;
418 }
419 if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
420 return error;
421
422 /* The parent must be a directory. */
423 if (!S_ISDIR(VFS_I(ip)->i_mode)) {
424 xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
425 goto out_rele;
426 }
427
428 /* Validate generation number. */
429 if (VFS_I(ip)->i_generation != be32_to_cpu(pptr->p_gen)) {
430 xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
431 goto out_rele;
432 }
433
434 *dpp = ip;
435 return 0;
436 out_rele:
437 xchk_irele(sc, ip);
438 return 0;
439 }
440
441 /*
442 * Walk an xattr of a file. If this xattr is a parent pointer, follow it up
443 * to a parent directory and check that the parent has a dirent pointing back
444 * to us.
445 */
446 STATIC int
xchk_parent_scan_attr(struct xfs_scrub * sc,struct xfs_inode * ip,unsigned int attr_flags,const unsigned char * name,unsigned int namelen,const void * value,unsigned int valuelen,void * priv)447 xchk_parent_scan_attr(
448 struct xfs_scrub *sc,
449 struct xfs_inode *ip,
450 unsigned int attr_flags,
451 const unsigned char *name,
452 unsigned int namelen,
453 const void *value,
454 unsigned int valuelen,
455 void *priv)
456 {
457 struct xfs_name xname = {
458 .name = name,
459 .len = namelen,
460 };
461 struct xchk_pptrs *pp = priv;
462 struct xfs_inode *dp = NULL;
463 const struct xfs_parent_rec *pptr_rec = value;
464 xfs_ino_t parent_ino;
465 unsigned int lockmode;
466 int error;
467
468 if (!(attr_flags & XFS_ATTR_PARENT))
469 return 0;
470
471 error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
472 valuelen, &parent_ino, NULL);
473 if (error) {
474 xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
475 return error;
476 }
477
478 /* No self-referential parent pointers. */
479 if (parent_ino == sc->ip->i_ino) {
480 xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
481 return -ECANCELED;
482 }
483
484 pp->pptrs_found++;
485
486 error = xchk_parent_iget(pp, pptr_rec, &dp);
487 if (error)
488 return error;
489 if (!dp)
490 return 0;
491
492 /* Try to lock the inode. */
493 lockmode = xchk_parent_lock_dir(sc, dp);
494 if (!lockmode) {
495 struct xchk_pptr save_pp = {
496 .pptr_rec = *pptr_rec, /* struct copy */
497 .namelen = namelen,
498 };
499
500 /* Couldn't lock the inode, so save the pptr for later. */
501 trace_xchk_parent_defer(sc->ip, &xname, dp->i_ino);
502
503 error = xfblob_storename(pp->pptr_names, &save_pp.name_cookie,
504 &xname);
505 if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
506 &error))
507 goto out_rele;
508
509 error = xfarray_append(pp->pptr_entries, &save_pp);
510 if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
511 &error))
512 goto out_rele;
513
514 goto out_rele;
515 }
516
517 error = xchk_parent_dirent(pp, &xname, dp);
518 if (error)
519 goto out_unlock;
520
521 out_unlock:
522 xfs_iunlock(dp, lockmode);
523 out_rele:
524 xchk_irele(sc, dp);
525 return error;
526 }
527
528 /*
529 * Revalidate a parent pointer that we collected in the past but couldn't check
530 * because of lock contention. Returns 0 if the parent pointer is still valid,
531 * -ENOENT if it has gone away on us, or a negative errno.
532 */
533 STATIC int
xchk_parent_revalidate_pptr(struct xchk_pptrs * pp,const struct xfs_name * xname,struct xfs_parent_rec * pptr)534 xchk_parent_revalidate_pptr(
535 struct xchk_pptrs *pp,
536 const struct xfs_name *xname,
537 struct xfs_parent_rec *pptr)
538 {
539 struct xfs_scrub *sc = pp->sc;
540 int error;
541
542 error = xfs_parent_lookup(sc->tp, sc->ip, xname, pptr, &pp->pptr_args);
543 if (error == -ENOATTR) {
544 /* Parent pointer went away, nothing to revalidate. */
545 return -ENOENT;
546 }
547
548 return error;
549 }
550
551 /*
552 * Check a parent pointer the slow way, which means we cycle locks a bunch
553 * and put up with revalidation until we get it done.
554 */
555 STATIC int
xchk_parent_slow_pptr(struct xchk_pptrs * pp,const struct xfs_name * xname,struct xfs_parent_rec * pptr)556 xchk_parent_slow_pptr(
557 struct xchk_pptrs *pp,
558 const struct xfs_name *xname,
559 struct xfs_parent_rec *pptr)
560 {
561 struct xfs_scrub *sc = pp->sc;
562 struct xfs_inode *dp = NULL;
563 unsigned int lockmode;
564 int error;
565
566 /* Check that the deferred parent pointer still exists. */
567 if (pp->need_revalidate) {
568 error = xchk_parent_revalidate_pptr(pp, xname, pptr);
569 if (error == -ENOENT)
570 return 0;
571 if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
572 &error))
573 return error;
574 }
575
576 error = xchk_parent_iget(pp, pptr, &dp);
577 if (error)
578 return error;
579 if (!dp)
580 return 0;
581
582 /*
583 * If we can grab both IOLOCK and ILOCK of the alleged parent, we
584 * can proceed with the validation.
585 */
586 lockmode = xchk_parent_lock_dir(sc, dp);
587 if (lockmode) {
588 trace_xchk_parent_slowpath(sc->ip, xname, dp->i_ino);
589 goto check_dirent;
590 }
591
592 /*
593 * We couldn't lock the parent dir. Drop all the locks and try to
594 * get them again, one at a time.
595 */
596 xchk_iunlock(sc, sc->ilock_flags);
597 pp->need_revalidate = true;
598
599 trace_xchk_parent_ultraslowpath(sc->ip, xname, dp->i_ino);
600
601 error = xchk_dir_trylock_for_pptrs(sc, dp, &lockmode);
602 if (error)
603 goto out_rele;
604
605 /* Revalidate the parent pointer now that we cycled locks. */
606 error = xchk_parent_revalidate_pptr(pp, xname, pptr);
607 if (error == -ENOENT) {
608 error = 0;
609 goto out_unlock;
610 }
611 if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
612 goto out_unlock;
613
614 check_dirent:
615 error = xchk_parent_dirent(pp, xname, dp);
616 out_unlock:
617 xfs_iunlock(dp, lockmode);
618 out_rele:
619 xchk_irele(sc, dp);
620 return error;
621 }
622
623 /* Check all the parent pointers that we deferred the first time around. */
624 STATIC int
xchk_parent_finish_slow_pptrs(struct xchk_pptrs * pp)625 xchk_parent_finish_slow_pptrs(
626 struct xchk_pptrs *pp)
627 {
628 xfarray_idx_t array_cur;
629 int error;
630
631 foreach_xfarray_idx(pp->pptr_entries, array_cur) {
632 struct xchk_pptr pptr;
633
634 if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
635 return 0;
636
637 error = xfarray_load(pp->pptr_entries, array_cur, &pptr);
638 if (error)
639 return error;
640
641 error = xfblob_loadname(pp->pptr_names, pptr.name_cookie,
642 &pp->xname, pptr.namelen);
643 if (error)
644 return error;
645
646 error = xchk_parent_slow_pptr(pp, &pp->xname, &pptr.pptr_rec);
647 if (error)
648 return error;
649 }
650
651 /* Empty out both xfiles now that we've checked everything. */
652 xfarray_truncate(pp->pptr_entries);
653 xfblob_truncate(pp->pptr_names);
654 return 0;
655 }
656
657 /* Count the number of parent pointers. */
658 STATIC int
xchk_parent_count_pptr(struct xfs_scrub * sc,struct xfs_inode * ip,unsigned int attr_flags,const unsigned char * name,unsigned int namelen,const void * value,unsigned int valuelen,void * priv)659 xchk_parent_count_pptr(
660 struct xfs_scrub *sc,
661 struct xfs_inode *ip,
662 unsigned int attr_flags,
663 const unsigned char *name,
664 unsigned int namelen,
665 const void *value,
666 unsigned int valuelen,
667 void *priv)
668 {
669 struct xchk_pptrs *pp = priv;
670 int error;
671
672 if (!(attr_flags & XFS_ATTR_PARENT))
673 return 0;
674
675 error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
676 valuelen, NULL, NULL);
677 if (error)
678 return error;
679
680 pp->pptrs_found++;
681 return 0;
682 }
683
684 /*
685 * Compare the number of parent pointers to the link count. For
686 * non-directories these should be the same. For unlinked directories the
687 * count should be zero; for linked directories, it should be nonzero.
688 */
689 STATIC int
xchk_parent_count_pptrs(struct xchk_pptrs * pp)690 xchk_parent_count_pptrs(
691 struct xchk_pptrs *pp)
692 {
693 struct xfs_scrub *sc = pp->sc;
694 int error;
695
696 /*
697 * If we cycled the ILOCK while cross-checking parent pointers with
698 * dirents, then we need to recalculate the number of parent pointers.
699 */
700 if (pp->need_revalidate) {
701 pp->pptrs_found = 0;
702 error = xchk_xattr_walk(sc, sc->ip, xchk_parent_count_pptr,
703 NULL, pp);
704 if (error == -EFSCORRUPTED) {
705 /* Found a bad parent pointer */
706 xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
707 return 0;
708 }
709 if (error)
710 return error;
711 }
712
713 if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {
714 if (sc->ip == sc->mp->m_rootip)
715 pp->pptrs_found++;
716
717 if (VFS_I(sc->ip)->i_nlink == 0 && pp->pptrs_found > 0)
718 xchk_ino_set_corrupt(sc, sc->ip->i_ino);
719 else if (VFS_I(sc->ip)->i_nlink > 0 &&
720 pp->pptrs_found == 0)
721 xchk_ino_set_corrupt(sc, sc->ip->i_ino);
722 } else {
723 if (VFS_I(sc->ip)->i_nlink != pp->pptrs_found)
724 xchk_ino_set_corrupt(sc, sc->ip->i_ino);
725 }
726
727 return 0;
728 }
729
730 /* Check parent pointers of a file. */
731 STATIC int
xchk_parent_pptr(struct xfs_scrub * sc)732 xchk_parent_pptr(
733 struct xfs_scrub *sc)
734 {
735 struct xchk_pptrs *pp;
736 char *descr;
737 int error;
738
739 pp = kvzalloc(sizeof(struct xchk_pptrs), XCHK_GFP_FLAGS);
740 if (!pp)
741 return -ENOMEM;
742 pp->sc = sc;
743 pp->xname.name = pp->namebuf;
744
745 /*
746 * Set up some staging memory for parent pointers that we can't check
747 * due to locking contention.
748 */
749 descr = xchk_xfile_ino_descr(sc, "slow parent pointer entries");
750 error = xfarray_create(descr, 0, sizeof(struct xchk_pptr),
751 &pp->pptr_entries);
752 kfree(descr);
753 if (error)
754 goto out_pp;
755
756 descr = xchk_xfile_ino_descr(sc, "slow parent pointer names");
757 error = xfblob_create(descr, &pp->pptr_names);
758 kfree(descr);
759 if (error)
760 goto out_entries;
761
762 error = xchk_xattr_walk(sc, sc->ip, xchk_parent_scan_attr, NULL, pp);
763 if (error == -ECANCELED) {
764 error = 0;
765 goto out_names;
766 }
767 if (error)
768 goto out_names;
769
770 error = xchk_parent_finish_slow_pptrs(pp);
771 if (error == -ETIMEDOUT) {
772 /* Couldn't grab a lock, scrub was marked incomplete */
773 error = 0;
774 goto out_names;
775 }
776 if (error)
777 goto out_names;
778
779 if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
780 goto out_names;
781
782 /*
783 * For subdirectories, make sure the dotdot entry references the same
784 * inode as the parent pointers.
785 *
786 * If we're scanning a /consistent/ directory, there should only be
787 * one parent pointer, and it should point to the same directory as
788 * the dotdot entry.
789 *
790 * However, a corrupt directory tree might feature a subdirectory with
791 * multiple parents. The directory loop scanner is responsible for
792 * correcting that kind of problem, so for now we only validate that
793 * the dotdot entry matches /one/ of the parents.
794 */
795 if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {
796 error = xchk_parent_pptr_and_dotdot(pp);
797 if (error)
798 goto out_names;
799 }
800
801 if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
802 goto out_names;
803
804 /*
805 * Complain if the number of parent pointers doesn't match the link
806 * count. This could be a sign of missing parent pointers (or an
807 * incorrect link count).
808 */
809 error = xchk_parent_count_pptrs(pp);
810 if (error)
811 goto out_names;
812
813 out_names:
814 xfblob_destroy(pp->pptr_names);
815 out_entries:
816 xfarray_destroy(pp->pptr_entries);
817 out_pp:
818 kvfree(pp);
819 return error;
820 }
821
822 /* Scrub a parent pointer. */
823 int
xchk_parent(struct xfs_scrub * sc)824 xchk_parent(
825 struct xfs_scrub *sc)
826 {
827 struct xfs_mount *mp = sc->mp;
828 xfs_ino_t parent_ino;
829 int error = 0;
830
831 if (xfs_has_parent(mp))
832 return xchk_parent_pptr(sc);
833
834 /*
835 * If we're a directory, check that the '..' link points up to
836 * a directory that has one entry pointing to us.
837 */
838 if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
839 return -ENOENT;
840
841 /* We're not a special inode, are we? */
842 if (!xfs_verify_dir_ino(mp, sc->ip->i_ino)) {
843 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
844 return 0;
845 }
846
847 do {
848 if (xchk_should_terminate(sc, &error))
849 break;
850
851 /* Look up '..' */
852 error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot,
853 &parent_ino);
854 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
855 return error;
856 if (!xfs_verify_dir_ino(mp, parent_ino)) {
857 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
858 return 0;
859 }
860
861 /*
862 * Check that the dotdot entry points to a parent directory
863 * containing a dirent pointing to this subdirectory.
864 */
865 error = xchk_parent_validate(sc, parent_ino);
866 } while (error == -EAGAIN);
867 if (error == -EBUSY) {
868 /*
869 * We could not scan a directory, so we marked the check
870 * incomplete. No further error return is necessary.
871 */
872 return 0;
873 }
874
875 return error;
876 }
877
878 /*
879 * Decide if this file's extended attributes (and therefore its parent
880 * pointers) have been zapped to satisfy the inode and ifork verifiers.
881 * Checking and repairing should be postponed until the extended attribute
882 * structure is fixed.
883 */
884 bool
xchk_pptr_looks_zapped(struct xfs_inode * ip)885 xchk_pptr_looks_zapped(
886 struct xfs_inode *ip)
887 {
888 struct xfs_mount *mp = ip->i_mount;
889 struct inode *inode = VFS_I(ip);
890
891 ASSERT(xfs_has_parent(mp));
892
893 /*
894 * Temporary files that cannot be linked into the directory tree do not
895 * have attr forks because they cannot ever have parents.
896 */
897 if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
898 return false;
899
900 /*
901 * Directory tree roots do not have parents, so the expected outcome
902 * of a parent pointer scan is always the empty set. It's safe to scan
903 * them even if the attr fork was zapped.
904 */
905 if (ip == mp->m_rootip)
906 return false;
907
908 /*
909 * Metadata inodes are all rooted in the superblock and do not have
910 * any parents. Hence the attr fork will not be initialized, but
911 * there are no parent pointers that might have been zapped.
912 */
913 if (xfs_is_metadata_inode(ip))
914 return false;
915
916 /*
917 * Linked and linkable non-rootdir files should always have an
918 * attribute fork because that is where parent pointers are
919 * stored. If the fork is absent, something is amiss.
920 */
921 if (!xfs_inode_has_attr_fork(ip))
922 return true;
923
924 /* Repair zapped this file's attr fork a short time ago */
925 if (xfs_ifork_zapped(ip, XFS_ATTR_FORK))
926 return true;
927
928 /*
929 * If the dinode repair found a bad attr fork, it will reset the fork
930 * to extents format with zero records and wait for the bmapbta
931 * scrubber to reconstruct the block mappings. The extended attribute
932 * structure always contain some content when parent pointers are
933 * enabled, so this is a clear sign of a zapped attr fork.
934 */
935 return ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
936 ip->i_af.if_nextents == 0;
937 }
938