1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017-2023 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <djwong@kernel.org>
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"
17 #include "xfs_dir2_priv.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"
31 /* Set us up to scrub parents. */
38 if (xchk_could_repair(sc
)) {
39 error
= xrep_setup_parent(sc
);
44 return xchk_setup_inode_contents(sc
, 0);
49 /* Look for an entry in a parent pointing to this inode. */
51 struct xchk_parent_ctx
{
56 /* Look for a single entry in a directory pointing to an inode. */
61 xfs_dir2_dataptr_t dapos
,
62 const struct xfs_name
*name
,
66 struct xchk_parent_ctx
*spc
= priv
;
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
))
75 if (sc
->ip
->i_ino
== ino
)
78 if (xchk_should_terminate(spc
->sc
, &error
))
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.
89 xchk_parent_ilock_dir(
92 if (!xfs_ilock_nowait(dp
, XFS_ILOCK_SHARED
))
95 if (!xfs_need_iread_extents(&dp
->i_df
))
96 return XFS_ILOCK_SHARED
;
98 xfs_iunlock(dp
, XFS_ILOCK_SHARED
);
100 if (!xfs_ilock_nowait(dp
, XFS_ILOCK_EXCL
))
103 return XFS_ILOCK_EXCL
;
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
113 xchk_parent_validate(
114 struct xfs_scrub
*sc
,
115 xfs_ino_t parent_ino
)
117 struct xchk_parent_ctx spc
= {
121 struct xfs_mount
*mp
= sc
->mp
;
122 struct xfs_inode
*dp
= NULL
;
123 xfs_nlink_t expected_nlink
;
124 unsigned int lock_mode
;
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);
135 /* Is this the metadata root dir? Then '..' must point to itself. */
136 if (sc
->ip
== mp
->m_metadirip
) {
137 if (sc
->ip
->i_ino
!= mp
->m_sb
.sb_metadirino
||
138 sc
->ip
->i_ino
!= parent_ino
)
139 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
143 /* '..' must not point to ourselves. */
144 if (sc
->ip
->i_ino
== parent_ino
) {
145 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
150 * If we're an unlinked directory, the parent /won't/ have a link
151 * to us. Otherwise, it should have one link.
153 expected_nlink
= VFS_I(sc
->ip
)->i_nlink
== 0 ? 0 : 1;
156 * Grab the parent directory inode. This must be released before we
157 * cancel the scrub transaction.
159 * If _iget returns -EINVAL or -ENOENT then the parent inode number is
160 * garbage and the directory is corrupt. If the _iget returns
161 * -EFSCORRUPTED or -EFSBADCRC then the parent is corrupt which is a
162 * cross referencing error. Any other error is an operational error.
164 error
= xchk_iget(sc
, parent_ino
, &dp
);
165 if (error
== -EINVAL
|| error
== -ENOENT
) {
166 error
= -EFSCORRUPTED
;
167 xchk_fblock_process_error(sc
, XFS_DATA_FORK
, 0, &error
);
170 if (!xchk_fblock_xref_process_error(sc
, XFS_DATA_FORK
, 0, &error
))
172 if (dp
== sc
->ip
|| xrep_is_tempfile(dp
) ||
173 !S_ISDIR(VFS_I(dp
)->i_mode
)) {
174 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
178 lock_mode
= xchk_parent_ilock_dir(dp
);
180 xchk_iunlock(sc
, XFS_ILOCK_EXCL
);
181 xchk_ilock(sc
, XFS_ILOCK_EXCL
);
187 * We cannot yet validate this parent pointer if the directory looks as
188 * though it has been zapped by the inode record repair code.
190 if (xchk_dir_looks_zapped(dp
)) {
192 xchk_set_incomplete(sc
);
196 /* Metadata and regular inodes cannot cross trees. */
197 if (xfs_is_metadir_inode(dp
) != xfs_is_metadir_inode(sc
->ip
)) {
198 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
202 /* Look for a directory entry in the parent pointing to the child. */
203 error
= xchk_dir_walk(sc
, dp
, xchk_parent_actor
, &spc
);
204 if (!xchk_fblock_xref_process_error(sc
, XFS_DATA_FORK
, 0, &error
))
208 * Ensure that the parent has as many links to the child as the child
209 * thinks it has to the parent.
211 if (spc
.nlink
!= expected_nlink
)
212 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
215 xfs_iunlock(dp
, lock_mode
);
222 * Checking of Parent Pointers
223 * ===========================
225 * On filesystems with directory parent pointers, we check the referential
226 * integrity by visiting each parent pointer of a child file and checking that
227 * the directory referenced by the pointer actually has a dirent pointing
228 * forward to the child file.
231 /* Deferred parent pointer entry that we saved for later. */
233 /* Cookie for retrieval of the pptr name. */
234 xfblob_cookie name_cookie
;
236 /* Parent pointer record. */
237 struct xfs_parent_rec pptr_rec
;
239 /* Length of the pptr name. */
244 struct xfs_scrub
*sc
;
246 /* How many parent pointers did we find at the end? */
247 unsigned long long pptrs_found
;
249 /* Parent of this directory. */
250 xfs_ino_t parent_ino
;
252 /* Fixed-size array of xchk_pptr structures. */
253 struct xfarray
*pptr_entries
;
255 /* Blobs containing parent pointer names. */
256 struct xfblob
*pptr_names
;
258 /* Scratch buffer for scanning pptr xattrs */
259 struct xfs_da_args pptr_args
;
261 /* If we've cycled the ILOCK, we must revalidate all deferred pptrs. */
262 bool need_revalidate
;
265 struct xfs_name xname
;
266 char namebuf
[MAXNAMELEN
];
269 /* Does this parent pointer match the dotdot entry? */
271 xchk_parent_scan_dotdot(
272 struct xfs_scrub
*sc
,
273 struct xfs_inode
*ip
,
274 unsigned int attr_flags
,
275 const unsigned char *name
,
276 unsigned int namelen
,
278 unsigned int valuelen
,
281 struct xchk_pptrs
*pp
= priv
;
282 xfs_ino_t parent_ino
;
285 if (!(attr_flags
& XFS_ATTR_PARENT
))
288 error
= xfs_parent_from_attr(sc
->mp
, attr_flags
, name
, namelen
, value
,
289 valuelen
, &parent_ino
, NULL
);
293 if (pp
->parent_ino
== parent_ino
)
299 /* Look up the dotdot entry so that we can check it as we walk the pptrs. */
301 xchk_parent_pptr_and_dotdot(
302 struct xchk_pptrs
*pp
)
304 struct xfs_scrub
*sc
= pp
->sc
;
308 error
= xchk_dir_lookup(sc
, sc
->ip
, &xfs_name_dotdot
, &pp
->parent_ino
);
309 if (!xchk_fblock_process_error(sc
, XFS_DATA_FORK
, 0, &error
))
311 if (!xfs_verify_dir_ino(sc
->mp
, pp
->parent_ino
)) {
312 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
316 /* Is this the root dir? Then '..' must point to itself. */
317 if (xchk_inode_is_dirtree_root(sc
->ip
)) {
318 if (sc
->ip
->i_ino
!= pp
->parent_ino
)
319 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
324 * If this is now an unlinked directory, the dotdot value is
325 * meaningless as long as it points to a valid inode.
327 if (VFS_I(sc
->ip
)->i_nlink
== 0)
330 if (pp
->sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
)
333 /* Otherwise, walk the pptrs again, and check. */
334 error
= xchk_xattr_walk(sc
, sc
->ip
, xchk_parent_scan_dotdot
, NULL
, pp
);
335 if (error
== -ECANCELED
) {
336 /* Found a parent pointer that matches dotdot. */
339 if (!error
|| error
== -EFSCORRUPTED
) {
340 /* Found a broken parent pointer or no match. */
341 xchk_fblock_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
348 * Try to lock a parent directory for checking dirents. Returns the inode
349 * flags for the locks we now hold, or zero if we failed.
352 xchk_parent_lock_dir(
353 struct xfs_scrub
*sc
,
354 struct xfs_inode
*dp
)
356 if (!xfs_ilock_nowait(dp
, XFS_IOLOCK_SHARED
))
359 if (!xfs_ilock_nowait(dp
, XFS_ILOCK_SHARED
)) {
360 xfs_iunlock(dp
, XFS_IOLOCK_SHARED
);
364 if (!xfs_need_iread_extents(&dp
->i_df
))
365 return XFS_IOLOCK_SHARED
| XFS_ILOCK_SHARED
;
367 xfs_iunlock(dp
, XFS_ILOCK_SHARED
);
369 if (!xfs_ilock_nowait(dp
, XFS_ILOCK_EXCL
)) {
370 xfs_iunlock(dp
, XFS_IOLOCK_SHARED
);
374 return XFS_IOLOCK_SHARED
| XFS_ILOCK_EXCL
;
377 /* Check the forward link (dirent) associated with this parent pointer. */
380 struct xchk_pptrs
*pp
,
381 const struct xfs_name
*xname
,
382 struct xfs_inode
*dp
)
384 struct xfs_scrub
*sc
= pp
->sc
;
389 * Use the name attached to this parent pointer to look up the
390 * directory entry in the alleged parent.
392 error
= xchk_dir_lookup(sc
, dp
, xname
, &child_ino
);
393 if (error
== -ENOENT
) {
394 xchk_fblock_xref_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
397 if (!xchk_fblock_xref_process_error(sc
, XFS_ATTR_FORK
, 0, &error
))
400 /* Does the inode number match? */
401 if (child_ino
!= sc
->ip
->i_ino
) {
402 xchk_fblock_xref_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
409 /* Try to grab a parent directory. */
412 struct xchk_pptrs
*pp
,
413 const struct xfs_parent_rec
*pptr
,
414 struct xfs_inode
**dpp
)
416 struct xfs_scrub
*sc
= pp
->sc
;
417 struct xfs_inode
*ip
;
418 xfs_ino_t parent_ino
= be64_to_cpu(pptr
->p_ino
);
421 /* Validate inode number. */
422 error
= xfs_dir_ino_validate(sc
->mp
, parent_ino
);
424 xchk_fblock_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
428 error
= xchk_iget(sc
, parent_ino
, &ip
);
429 if (error
== -EINVAL
|| error
== -ENOENT
) {
430 xchk_fblock_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
433 if (!xchk_fblock_xref_process_error(sc
, XFS_ATTR_FORK
, 0, &error
))
436 /* The parent must be a directory. */
437 if (!S_ISDIR(VFS_I(ip
)->i_mode
)) {
438 xchk_fblock_xref_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
442 /* Validate generation number. */
443 if (VFS_I(ip
)->i_generation
!= be32_to_cpu(pptr
->p_gen
)) {
444 xchk_fblock_xref_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
456 * Walk an xattr of a file. If this xattr is a parent pointer, follow it up
457 * to a parent directory and check that the parent has a dirent pointing back
461 xchk_parent_scan_attr(
462 struct xfs_scrub
*sc
,
463 struct xfs_inode
*ip
,
464 unsigned int attr_flags
,
465 const unsigned char *name
,
466 unsigned int namelen
,
468 unsigned int valuelen
,
471 struct xfs_name xname
= {
475 struct xchk_pptrs
*pp
= priv
;
476 struct xfs_inode
*dp
= NULL
;
477 const struct xfs_parent_rec
*pptr_rec
= value
;
478 xfs_ino_t parent_ino
;
479 unsigned int lockmode
;
482 if (!(attr_flags
& XFS_ATTR_PARENT
))
485 error
= xfs_parent_from_attr(sc
->mp
, attr_flags
, name
, namelen
, value
,
486 valuelen
, &parent_ino
, NULL
);
488 xchk_fblock_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
492 /* No self-referential parent pointers. */
493 if (parent_ino
== sc
->ip
->i_ino
) {
494 xchk_fblock_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
500 error
= xchk_parent_iget(pp
, pptr_rec
, &dp
);
506 /* Try to lock the inode. */
507 lockmode
= xchk_parent_lock_dir(sc
, dp
);
509 struct xchk_pptr save_pp
= {
510 .pptr_rec
= *pptr_rec
, /* struct copy */
514 /* Couldn't lock the inode, so save the pptr for later. */
515 trace_xchk_parent_defer(sc
->ip
, &xname
, dp
->i_ino
);
517 error
= xfblob_storename(pp
->pptr_names
, &save_pp
.name_cookie
,
519 if (!xchk_fblock_xref_process_error(sc
, XFS_ATTR_FORK
, 0,
523 error
= xfarray_append(pp
->pptr_entries
, &save_pp
);
524 if (!xchk_fblock_xref_process_error(sc
, XFS_ATTR_FORK
, 0,
531 error
= xchk_parent_dirent(pp
, &xname
, dp
);
536 xfs_iunlock(dp
, lockmode
);
543 * Revalidate a parent pointer that we collected in the past but couldn't check
544 * because of lock contention. Returns 0 if the parent pointer is still valid,
545 * -ENOENT if it has gone away on us, or a negative errno.
548 xchk_parent_revalidate_pptr(
549 struct xchk_pptrs
*pp
,
550 const struct xfs_name
*xname
,
551 struct xfs_parent_rec
*pptr
)
553 struct xfs_scrub
*sc
= pp
->sc
;
556 error
= xfs_parent_lookup(sc
->tp
, sc
->ip
, xname
, pptr
, &pp
->pptr_args
);
557 if (error
== -ENOATTR
) {
558 /* Parent pointer went away, nothing to revalidate. */
566 * Check a parent pointer the slow way, which means we cycle locks a bunch
567 * and put up with revalidation until we get it done.
570 xchk_parent_slow_pptr(
571 struct xchk_pptrs
*pp
,
572 const struct xfs_name
*xname
,
573 struct xfs_parent_rec
*pptr
)
575 struct xfs_scrub
*sc
= pp
->sc
;
576 struct xfs_inode
*dp
= NULL
;
577 unsigned int lockmode
;
580 /* Check that the deferred parent pointer still exists. */
581 if (pp
->need_revalidate
) {
582 error
= xchk_parent_revalidate_pptr(pp
, xname
, pptr
);
583 if (error
== -ENOENT
)
585 if (!xchk_fblock_xref_process_error(sc
, XFS_ATTR_FORK
, 0,
590 error
= xchk_parent_iget(pp
, pptr
, &dp
);
597 * If we can grab both IOLOCK and ILOCK of the alleged parent, we
598 * can proceed with the validation.
600 lockmode
= xchk_parent_lock_dir(sc
, dp
);
602 trace_xchk_parent_slowpath(sc
->ip
, xname
, dp
->i_ino
);
607 * We couldn't lock the parent dir. Drop all the locks and try to
608 * get them again, one at a time.
610 xchk_iunlock(sc
, sc
->ilock_flags
);
611 pp
->need_revalidate
= true;
613 trace_xchk_parent_ultraslowpath(sc
->ip
, xname
, dp
->i_ino
);
615 error
= xchk_dir_trylock_for_pptrs(sc
, dp
, &lockmode
);
619 /* Revalidate the parent pointer now that we cycled locks. */
620 error
= xchk_parent_revalidate_pptr(pp
, xname
, pptr
);
621 if (error
== -ENOENT
) {
625 if (!xchk_fblock_xref_process_error(sc
, XFS_ATTR_FORK
, 0, &error
))
629 error
= xchk_parent_dirent(pp
, xname
, dp
);
631 xfs_iunlock(dp
, lockmode
);
637 /* Check all the parent pointers that we deferred the first time around. */
639 xchk_parent_finish_slow_pptrs(
640 struct xchk_pptrs
*pp
)
642 xfarray_idx_t array_cur
;
645 foreach_xfarray_idx(pp
->pptr_entries
, array_cur
) {
646 struct xchk_pptr pptr
;
648 if (pp
->sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
)
651 error
= xfarray_load(pp
->pptr_entries
, array_cur
, &pptr
);
655 error
= xfblob_loadname(pp
->pptr_names
, pptr
.name_cookie
,
656 &pp
->xname
, pptr
.namelen
);
660 error
= xchk_parent_slow_pptr(pp
, &pp
->xname
, &pptr
.pptr_rec
);
665 /* Empty out both xfiles now that we've checked everything. */
666 xfarray_truncate(pp
->pptr_entries
);
667 xfblob_truncate(pp
->pptr_names
);
671 /* Count the number of parent pointers. */
673 xchk_parent_count_pptr(
674 struct xfs_scrub
*sc
,
675 struct xfs_inode
*ip
,
676 unsigned int attr_flags
,
677 const unsigned char *name
,
678 unsigned int namelen
,
680 unsigned int valuelen
,
683 struct xchk_pptrs
*pp
= priv
;
686 if (!(attr_flags
& XFS_ATTR_PARENT
))
689 error
= xfs_parent_from_attr(sc
->mp
, attr_flags
, name
, namelen
, value
,
690 valuelen
, NULL
, NULL
);
699 * Compare the number of parent pointers to the link count. For
700 * non-directories these should be the same. For unlinked directories the
701 * count should be zero; for linked directories, it should be nonzero.
704 xchk_parent_count_pptrs(
705 struct xchk_pptrs
*pp
)
707 struct xfs_scrub
*sc
= pp
->sc
;
711 * If we cycled the ILOCK while cross-checking parent pointers with
712 * dirents, then we need to recalculate the number of parent pointers.
714 if (pp
->need_revalidate
) {
716 error
= xchk_xattr_walk(sc
, sc
->ip
, xchk_parent_count_pptr
,
718 if (error
== -EFSCORRUPTED
) {
719 /* Found a bad parent pointer */
720 xchk_fblock_set_corrupt(sc
, XFS_ATTR_FORK
, 0);
727 if (S_ISDIR(VFS_I(sc
->ip
)->i_mode
)) {
728 if (xchk_inode_is_dirtree_root(sc
->ip
))
731 if (VFS_I(sc
->ip
)->i_nlink
== 0 && pp
->pptrs_found
> 0)
732 xchk_ino_set_corrupt(sc
, sc
->ip
->i_ino
);
733 else if (VFS_I(sc
->ip
)->i_nlink
> 0 &&
734 pp
->pptrs_found
== 0)
735 xchk_ino_set_corrupt(sc
, sc
->ip
->i_ino
);
738 * Starting with metadir, we allow checking of parent pointers
739 * of non-directory files that are children of the superblock.
740 * Pretend that we found a parent pointer attr.
742 if (xfs_has_metadir(sc
->mp
) && xchk_inode_is_sb_rooted(sc
->ip
))
745 if (VFS_I(sc
->ip
)->i_nlink
!= pp
->pptrs_found
)
746 xchk_ino_set_corrupt(sc
, sc
->ip
->i_ino
);
752 /* Check parent pointers of a file. */
755 struct xfs_scrub
*sc
)
757 struct xchk_pptrs
*pp
;
761 pp
= kvzalloc(sizeof(struct xchk_pptrs
), XCHK_GFP_FLAGS
);
765 pp
->xname
.name
= pp
->namebuf
;
768 * Set up some staging memory for parent pointers that we can't check
769 * due to locking contention.
771 descr
= xchk_xfile_ino_descr(sc
, "slow parent pointer entries");
772 error
= xfarray_create(descr
, 0, sizeof(struct xchk_pptr
),
778 descr
= xchk_xfile_ino_descr(sc
, "slow parent pointer names");
779 error
= xfblob_create(descr
, &pp
->pptr_names
);
784 error
= xchk_xattr_walk(sc
, sc
->ip
, xchk_parent_scan_attr
, NULL
, pp
);
785 if (error
== -ECANCELED
) {
792 error
= xchk_parent_finish_slow_pptrs(pp
);
793 if (error
== -ETIMEDOUT
) {
794 /* Couldn't grab a lock, scrub was marked incomplete */
801 if (pp
->sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
)
805 * For subdirectories, make sure the dotdot entry references the same
806 * inode as the parent pointers.
808 * If we're scanning a /consistent/ directory, there should only be
809 * one parent pointer, and it should point to the same directory as
812 * However, a corrupt directory tree might feature a subdirectory with
813 * multiple parents. The directory loop scanner is responsible for
814 * correcting that kind of problem, so for now we only validate that
815 * the dotdot entry matches /one/ of the parents.
817 if (S_ISDIR(VFS_I(sc
->ip
)->i_mode
)) {
818 error
= xchk_parent_pptr_and_dotdot(pp
);
823 if (pp
->sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
)
827 * Complain if the number of parent pointers doesn't match the link
828 * count. This could be a sign of missing parent pointers (or an
829 * incorrect link count).
831 error
= xchk_parent_count_pptrs(pp
);
836 xfblob_destroy(pp
->pptr_names
);
838 xfarray_destroy(pp
->pptr_entries
);
844 /* Scrub a parent pointer. */
847 struct xfs_scrub
*sc
)
849 struct xfs_mount
*mp
= sc
->mp
;
850 xfs_ino_t parent_ino
;
853 if (xfs_has_parent(mp
))
854 return xchk_parent_pptr(sc
);
857 * If we're a directory, check that the '..' link points up to
858 * a directory that has one entry pointing to us.
860 if (!S_ISDIR(VFS_I(sc
->ip
)->i_mode
))
863 /* We're not a special inode, are we? */
864 if (!xfs_verify_dir_ino(mp
, sc
->ip
->i_ino
)) {
865 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
870 if (xchk_should_terminate(sc
, &error
))
874 error
= xchk_dir_lookup(sc
, sc
->ip
, &xfs_name_dotdot
,
876 if (!xchk_fblock_process_error(sc
, XFS_DATA_FORK
, 0, &error
))
878 if (!xfs_verify_dir_ino(mp
, parent_ino
)) {
879 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
884 * Check that the dotdot entry points to a parent directory
885 * containing a dirent pointing to this subdirectory.
887 error
= xchk_parent_validate(sc
, parent_ino
);
888 } while (error
== -EAGAIN
);
889 if (error
== -EBUSY
) {
891 * We could not scan a directory, so we marked the check
892 * incomplete. No further error return is necessary.
901 * Decide if this file's extended attributes (and therefore its parent
902 * pointers) have been zapped to satisfy the inode and ifork verifiers.
903 * Checking and repairing should be postponed until the extended attribute
904 * structure is fixed.
907 xchk_pptr_looks_zapped(
908 struct xfs_inode
*ip
)
910 struct inode
*inode
= VFS_I(ip
);
912 ASSERT(xfs_has_parent(ip
->i_mount
));
915 * Temporary files that cannot be linked into the directory tree do not
916 * have attr forks because they cannot ever have parents.
918 if (inode
->i_nlink
== 0 && !(inode
->i_state
& I_LINKABLE
))
922 * Directory tree roots do not have parents, so the expected outcome
923 * of a parent pointer scan is always the empty set. It's safe to scan
924 * them even if the attr fork was zapped.
926 if (xchk_inode_is_dirtree_root(ip
))
930 * Metadata inodes that are rooted in the superblock do not have any
931 * parents. Hence the attr fork will not be initialized, but there are
932 * no parent pointers that might have been zapped.
934 if (xchk_inode_is_sb_rooted(ip
))
938 * Linked and linkable non-rootdir files should always have an
939 * attribute fork because that is where parent pointers are
940 * stored. If the fork is absent, something is amiss.
942 if (!xfs_inode_has_attr_fork(ip
))
945 /* Repair zapped this file's attr fork a short time ago */
946 if (xfs_ifork_zapped(ip
, XFS_ATTR_FORK
))
950 * If the dinode repair found a bad attr fork, it will reset the fork
951 * to extents format with zero records and wait for the bmapbta
952 * scrubber to reconstruct the block mappings. The extended attribute
953 * structure always contain some content when parent pointers are
954 * enabled, so this is a clear sign of a zapped attr fork.
956 return ip
->i_af
.if_format
== XFS_DINODE_FMT_EXTENTS
&&
957 ip
->i_af
.if_nextents
== 0;