xfs: Add parent pointers to xfs_cross_rename
authorAllison Henderson <allison.henderson@oracle.com>
Mon, 22 Apr 2024 16:47:51 +0000 (09:47 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 23 Apr 2024 14:46:59 +0000 (07:46 -0700)
Cross renames are handled separately from standard renames, and
need different handling to update the parent attributes correctly.

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_inode.c

index 59488c17e1c1c36a163916e04274f4ab3617c65b..ebe2ce9bd9eeefe4e53ac89b846c685702d53967 100644 (file)
@@ -2972,15 +2972,17 @@ xfs_cross_rename(
        struct xfs_inode        *dp1,
        struct xfs_name         *name1,
        struct xfs_inode        *ip1,
+       struct xfs_parent_args  *ip1_ppargs,
        struct xfs_inode        *dp2,
        struct xfs_name         *name2,
        struct xfs_inode        *ip2,
+       struct xfs_parent_args  *ip2_ppargs,
        int                     spaceres)
 {
-       int             error = 0;
-       int             ip1_flags = 0;
-       int             ip2_flags = 0;
-       int             dp2_flags = 0;
+       int                     error = 0;
+       int                     ip1_flags = 0;
+       int                     ip2_flags = 0;
+       int                     dp2_flags = 0;
 
        /* Swap inode number for dirent in first parent */
        error = xfs_dir_replace(tp, dp1, name1, ip2->i_ino, spaceres);
@@ -3049,6 +3051,21 @@ xfs_cross_rename(
                }
        }
 
+       /* Schedule parent pointer replacements */
+       if (ip1_ppargs) {
+               error = xfs_parent_replacename(tp, ip1_ppargs, dp1, name1, dp2,
+                               name2, ip1);
+               if (error)
+                       goto out_trans_abort;
+       }
+
+       if (ip2_ppargs) {
+               error = xfs_parent_replacename(tp, ip2_ppargs, dp2, name2, dp1,
+                               name1, ip2);
+               if (error)
+                       goto out_trans_abort;
+       }
+
        if (ip1_flags) {
                xfs_trans_ichgtime(tp, ip1, ip1_flags);
                xfs_trans_log_inode(tp, ip1, XFS_ILOG_CORE);
@@ -3265,10 +3282,10 @@ retry:
        /* RENAME_EXCHANGE is unique from here on. */
        if (flags & RENAME_EXCHANGE) {
                error = xfs_cross_rename(tp, src_dp, src_name, src_ip,
-                                       target_dp, target_name, target_ip,
-                                       spaceres);
-               xfs_iunlock_rename(inodes, num_inodes);
-               return error;
+                               src_ppargs, target_dp, target_name, target_ip,
+                               tgt_ppargs, spaceres);
+               nospace_error = 0;
+               goto out_unlock;
        }
 
        /*