]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: add parent pointers when messing with /lost+found
authorDarrick J. Wong <djwong@kernel.org>
Mon, 29 Jul 2024 23:23:26 +0000 (16:23 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:12 +0000 (17:01 -0700)
Make sure that the /lost+found gets created with parent pointers, and
that lost children being put in there get new parent pointers.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/libxfs_api_defs.h
repair/phase6.c

index bf1d3c9d37f691ece90f60045f569770e7b12629..d3611e05bade7996d900dc50a7044ace8d574115 100644 (file)
@@ -52,6 +52,7 @@
 #define xfs_attr_shortform_verify      libxfs_attr_shortform_verify
 
 #define __xfs_bmap_add_free            __libxfs_bmap_add_free
+#define xfs_bmap_add_attrfork          libxfs_bmap_add_attrfork
 #define xfs_bmap_validate_extent       libxfs_bmap_validate_extent
 #define xfs_bmapi_read                 libxfs_bmapi_read
 #define xfs_bmapi_remap                        libxfs_bmapi_remap
 #define xfs_parent_addname             libxfs_parent_addname
 #define xfs_parent_finish              libxfs_parent_finish
 #define xfs_parent_hashval             libxfs_parent_hashval
+#define xfs_parent_lookup              libxfs_parent_lookup
 #define xfs_parent_removename          libxfs_parent_removename
 #define xfs_parent_start               libxfs_parent_start
 #define xfs_parent_from_attr           libxfs_parent_from_attr
index 47dd9de2741cff82d9adda4e6eed71887767b931..791f7d36fa8ac0930b452482179cbe60a71a240f 100644 (file)
@@ -903,6 +903,12 @@ mk_orphanage(xfs_mount_t *mp)
        const int       mode = 0755;
        int             nres;
        struct xfs_name xname;
+       struct xfs_parent_args *ppargs = NULL;
+
+       i = -libxfs_parent_start(mp, &ppargs);
+       if (i)
+               do_error(_("%d - couldn't allocate parent pointer for %s\n"),
+                       i, ORPHANAGE);
 
        /*
         * check for an existing lost+found first, if it exists, return
@@ -994,6 +1000,14 @@ mk_orphanage(xfs_mount_t *mp)
                _("can't make %s, createname error %d\n"),
                        ORPHANAGE, error);
 
+       if (ppargs) {
+               error = -libxfs_parent_addname(tp, ppargs, pip, &xname, ip);
+               if (error)
+                       do_error(
+ _("can't make %s, parent addname error %d\n"),
+                                       ORPHANAGE, error);
+       }
+
        /*
         * bump up the link count in the root directory to account
         * for .. in the new directory, and update the irec copy of the
@@ -1016,10 +1030,52 @@ mk_orphanage(xfs_mount_t *mp)
        libxfs_irele(ip);
 out_pip:
        libxfs_irele(pip);
+       libxfs_parent_finish(mp, ppargs);
 
        return(ino);
 }
 
+/*
+ * Add a parent pointer back to the orphanage for any file we're moving into
+ * the orphanage, being careful not to trip over any existing parent pointer.
+ * You never know when the orphanage might get corrupted.
+ */
+static void
+add_orphan_pptr(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *orphanage_ip,
+       const struct xfs_name   *xname,
+       struct xfs_inode        *ip,
+       struct xfs_parent_args  *ppargs)
+{
+       struct xfs_parent_rec   pptr = { };
+       struct xfs_da_args      scratch;
+       int                     error;
+
+       xfs_inode_to_parent_rec(&pptr, orphanage_ip);
+       error = -libxfs_parent_lookup(tp, ip, xname, &pptr, &scratch);
+       if (!error)
+               return;
+       if (error != ENOATTR)
+               do_log(
+ _("cannot look up parent pointer for '%.*s', err %d\n"),
+                               xname->len, xname->name, error);
+
+       if (!xfs_inode_has_attr_fork(ip)) {
+               error = -libxfs_bmap_add_attrfork(tp, ip,
+                               sizeof(struct xfs_attr_sf_hdr), true);
+               if (error)
+                       do_error(_("can't add attr fork to inode 0x%llx\n"),
+                                       (unsigned long long)ip->i_ino);
+       }
+
+       error = -libxfs_parent_addname(tp, ppargs, orphanage_ip, xname, ip);
+       if (error)
+               do_error(
+ _("can't add parent pointer for '%.*s', error %d\n"),
+                               xname->len, xname->name, error);
+}
+
 /*
  * move a file to the orphange.
  */
@@ -1040,6 +1096,13 @@ mv_orphanage(
        ino_tree_node_t         *irec;
        int                     ino_offset = 0;
        struct xfs_name         xname;
+       struct xfs_parent_args  *ppargs;
+
+       err = -libxfs_parent_start(mp, &ppargs);
+       if (err)
+               do_error(
+ _("%d - couldn't allocate parent pointer for lost inode\n"),
+                       err);
 
        xname.name = fname;
        xname.len = snprintf((char *)fname, sizeof(fname), "%llu",
@@ -1091,6 +1154,10 @@ mv_orphanage(
                                do_error(
        _("name create failed in %s (%d)\n"), ORPHANAGE, err);
 
+                       if (ppargs)
+                               add_orphan_pptr(tp, orphanage_ip, &xname,
+                                               ino_p, ppargs);
+
                        if (irec)
                                add_inode_ref(irec, ino_offset);
                        else
@@ -1125,6 +1192,10 @@ mv_orphanage(
                                do_error(
        _("name create failed in %s (%d)\n"), ORPHANAGE, err);
 
+                       if (ppargs)
+                               add_orphan_pptr(tp, orphanage_ip, &xname,
+                                               ino_p, ppargs);
+
                        if (irec)
                                add_inode_ref(irec, ino_offset);
                        else
@@ -1173,6 +1244,10 @@ mv_orphanage(
        _("name create failed in %s (%d)\n"), ORPHANAGE, err);
                ASSERT(err == 0);
 
+               if (ppargs)
+                       add_orphan_pptr(tp, orphanage_ip, &xname, ino_p,
+                                       ppargs);
+
                set_nlink(VFS_I(ino_p), 1);
                libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
                err = -libxfs_trans_commit(tp);
@@ -1182,6 +1257,7 @@ mv_orphanage(
        }
        libxfs_irele(ino_p);
        libxfs_irele(orphanage_ip);
+       libxfs_parent_finish(mp, ppargs);
 }
 
 static int