1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017-2023 Oracle. All Rights Reserved.
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;