]> www.infradead.org Git - users/hch/misc.git/commitdiff
xfs: adjust parent pointer scrubber for sb-rooted metadata files
authorDarrick J. Wong <djwong@kernel.org>
Thu, 27 Jun 2024 20:59:09 +0000 (13:59 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 24 Jul 2024 05:33:30 +0000 (22:33 -0700)
Starting with the metadata directory feature, we're allowed to call the
directory and parent pointer scrubbers for every metadata file,
including the ones that are children of the superblock.

For these children, checking the link count against the number of parent
pointers is a bit funny -- there's no such thing as a parent pointer for
a child of the superblock since there's no corresponding dirent.  For
purposes of validating nlink, we pretend that there is a parent pointer.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/scrub/parent.c
fs/xfs/scrub/parent_repair.c

index c84600e3ab9735f8f73f7f6a8caa9b94ef98d3c0..7125bd33314a223ec5c615fceea39a1e13f0bf6e 100644 (file)
@@ -720,6 +720,14 @@ xchk_parent_count_pptrs(
                         pp->pptrs_found == 0)
                        xchk_ino_set_corrupt(sc, sc->ip->i_ino);
        } else {
+               /*
+                * Starting with metadir, we allow checking of parent pointers
+                * of non-directory files that are children of the superblock.
+                * Pretend that we found a parent pointer attr.
+                */
+               if (xfs_has_metadir(sc->mp) && xchk_inode_is_sb_rooted(sc->ip))
+                       pp->pptrs_found++;
+
                if (VFS_I(sc->ip)->i_nlink != pp->pptrs_found)
                        xchk_ino_set_corrupt(sc, sc->ip->i_ino);
        }
index f4e4845b7ec09925589c92a4bfee3592361dd622..31bfe10be22a210910089f9edd177c677672c266 100644 (file)
@@ -1354,21 +1354,40 @@ STATIC int
 xrep_parent_rebuild_tree(
        struct xrep_parent      *rp)
 {
+       struct xfs_scrub        *sc = rp->sc;
+       bool                    try_adoption;
        int                     error;
 
-       if (xfs_has_parent(rp->sc->mp)) {
+       if (xfs_has_parent(sc->mp)) {
                error = xrep_parent_rebuild_pptrs(rp);
                if (error)
                        return error;
        }
 
-       if (rp->pscan.parent_ino == NULLFSINO) {
-               if (xrep_orphanage_can_adopt(rp->sc))
+       /*
+        * Any file with no parent could be adopted.  This check happens after
+        * rebuilding the parent pointer structure because we might have cycled
+        * the ILOCK during that process.
+        */
+       try_adoption = rp->pscan.parent_ino == NULLFSINO;
+
+       /*
+        * Starting with metadir, we allow checking of parent pointers
+        * of non-directory files that are children of the superblock.
+        * Lack of parent is ok here.
+        */
+       if (try_adoption && xfs_has_metadir(sc->mp) &&
+           xchk_inode_is_sb_rooted(sc->ip))
+               try_adoption = false;
+
+       if (try_adoption) {
+               if (xrep_orphanage_can_adopt(sc))
                        return xrep_parent_move_to_orphanage(rp);
                return -EFSCORRUPTED;
+
        }
 
-       if (S_ISDIR(VFS_I(rp->sc->ip)->i_mode))
+       if (S_ISDIR(VFS_I(sc->ip)->i_mode))
                return xrep_parent_reset_dotdot(rp);
 
        return 0;
@@ -1422,6 +1441,14 @@ xrep_parent_set_nondir_nlink(
        if (error)
                return error;
 
+       /*
+        * Starting with metadir, we allow checking of parent pointers of
+        * non-directory files that are children of the superblock.  Pretend
+        * that we found a parent pointer attr.
+        */
+       if (xfs_has_metadir(sc->mp) && xchk_inode_is_sb_rooted(sc->ip))
+               rp->parents++;
+
        if (rp->parents > 0 && xfs_inode_on_unlinked_list(ip)) {
                xfs_trans_ijoin(sc->tp, sc->ip, 0);
                joined = true;