]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: update ondisk parent pointer records
authorDarrick J. Wong <djwong@kernel.org>
Mon, 29 Jul 2024 23:23:27 +0000 (16:23 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:13 +0000 (17:01 -0700)
Update the ondisk parent pointer records as necessary.

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

index e12f0a40b00a2ebf73c966767e6284d61f8c1218..df316727bd624cf80276da5683c9258b6cf7b794 100644 (file)
 #define xfs_parent_hashval             libxfs_parent_hashval
 #define xfs_parent_lookup              libxfs_parent_lookup
 #define xfs_parent_removename          libxfs_parent_removename
+#define xfs_parent_set                 libxfs_parent_set
 #define xfs_parent_start               libxfs_parent_start
 #define xfs_parent_from_attr           libxfs_parent_from_attr
+#define xfs_parent_unset               libxfs_parent_unset
 #define xfs_perag_get                  libxfs_perag_get
 #define xfs_perag_hold                 libxfs_perag_hold
 #define xfs_perag_put                  libxfs_perag_put
index 61466009d88b5862954fdab9a8ee97d452158e58..94d6d834627cddfabaeecc77b2c47b8ae61c6b5c 100644 (file)
@@ -673,6 +673,44 @@ load_file_pptr_name(
                        name, file_pptr->namelen);
 }
 
+/* Add an on disk parent pointer to a file. */
+static int
+add_file_pptr(
+       struct xfs_inode                *ip,
+       const struct ag_pptr            *ag_pptr,
+       const unsigned char             *name)
+{
+       struct xfs_name                 xname = {
+               .name                   = name,
+               .len                    = ag_pptr->namelen,
+       };
+       struct xfs_parent_rec           pptr_rec = { };
+       struct xfs_da_args              scratch;
+
+       xfs_parent_rec_init(&pptr_rec, ag_pptr->parent_ino,
+                       ag_pptr->parent_gen);
+       return -libxfs_parent_set(ip, ip->i_ino, &xname, &pptr_rec, &scratch);
+}
+
+/* Remove an on disk parent pointer from a file. */
+static int
+remove_file_pptr(
+       struct xfs_inode                *ip,
+       const struct file_pptr          *file_pptr,
+       const unsigned char             *name)
+{
+       struct xfs_name                 xname = {
+               .name                   = name,
+               .len                    = file_pptr->namelen,
+       };
+       struct xfs_parent_rec           pptr_rec = { };
+       struct xfs_da_args              scratch;
+
+       xfs_parent_rec_init(&pptr_rec, file_pptr->parent_ino,
+                       file_pptr->parent_gen);
+       return -libxfs_parent_unset(ip, ip->i_ino, &xname, &pptr_rec, &scratch);
+}
+
 /* Remove all pptrs from @ip. */
 static void
 clear_all_pptrs(
@@ -729,7 +767,16 @@ add_missing_parent_ptr(
                                name);
        }
 
-       /* XXX actually do the work */
+       error = add_file_pptr(ip, ag_pptr, name);
+       if (error)
+               do_error(
+ _("adding ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"),
+                       (unsigned long long)ip->i_ino,
+                       (unsigned long long)ag_pptr->parent_ino,
+                       ag_pptr->parent_gen,
+                       ag_pptr->namelen,
+                       name,
+                       strerror(error));
 }
 
 /* Remove @file_pptr from @ip. */
@@ -771,7 +818,16 @@ remove_incorrect_parent_ptr(
                        file_pptr->namelen,
                        name);
 
-       /* XXX actually do the work */
+       error = remove_file_pptr(ip, file_pptr, name);
+       if (error)
+               do_error(
+ _("removing ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"),
+                       (unsigned long long)ip->i_ino,
+                       (unsigned long long)file_pptr->parent_ino,
+                       file_pptr->parent_gen,
+                       file_pptr->namelen,
+                       name,
+                       strerror(error));
 }
 
 /*
@@ -851,7 +907,33 @@ reset:
                        ag_pptr->namelen,
                        name1);
 
-       /* XXX do the work */
+       /* Remove the parent pointer that we don't want. */
+       error = remove_file_pptr(ip, file_pptr, name2);
+       if (error)
+               do_error(
+_("erasing ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"),
+                       (unsigned long long)ip->i_ino,
+                       (unsigned long long)file_pptr->parent_ino,
+                       file_pptr->parent_gen,
+                       file_pptr->namelen,
+                       name2,
+                       strerror(error));
+
+       /*
+        * Add the parent pointer that we do want.  It's possible that this
+        * parent pointer already exists but we haven't gotten that far in the
+        * scan, so we'll keep going on EEXIST.
+        */
+       error = add_file_pptr(ip, ag_pptr, name1);
+       if (error && error != EEXIST)
+               do_error(
+ _("updating ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"),
+                       (unsigned long long)ip->i_ino,
+                       (unsigned long long)ag_pptr->parent_ino,
+                       ag_pptr->parent_gen,
+                       ag_pptr->namelen,
+                       name1,
+                       strerror(error));
 }
 
 static int