xfs
[Top] [All Lists]

[PATCH 4/5] xfs: make xfs_cross_rename() complete fully

To: xfs@xxxxxxxxxxx
Subject: [PATCH 4/5] xfs: make xfs_cross_rename() complete fully
From: Dave Chinner <david@xxxxxxxxxxxxx>
Date: Tue, 24 Mar 2015 21:59:30 +1100
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1427194771-3105-1-git-send-email-david@xxxxxxxxxxxxx>
References: <1427194771-3105-1-git-send-email-david@xxxxxxxxxxxxx>
From: Dave Chinner <dchinner@xxxxxxxxxx>

Now that xfs_finish_rename() exists, there is no reason for
xfs_cross_rename() to return to xfs_rename() to finish off the
rename transaction. Drive the completion code into
xfs_cross_rename() and handle all errors there so as to simplify
the xfs_rename() code.

Further, push the rename exchange target_ip check to early in the
rename code so as to make the error handling easy and obviously
correct.

Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
---
 fs/xfs/xfs_inode.c | 45 +++++++++++++++++++++------------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 4a13a48..1ea05be 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2769,14 +2769,14 @@ xfs_cross_rename(
                                ip2->i_ino,
                                first_block, free_list, spaceres);
        if (error)
-               goto out;
+               goto out_trans_abort;
 
        /* Swap inode number for dirent in second parent */
        error = xfs_dir_replace(tp, dp2, name2,
                                ip1->i_ino,
                                first_block, free_list, spaceres);
        if (error)
-               goto out;
+               goto out_trans_abort;
 
        /*
         * If we're renaming one or more directories across different parents,
@@ -2791,16 +2791,16 @@ xfs_cross_rename(
                                                dp1->i_ino, first_block,
                                                free_list, spaceres);
                        if (error)
-                               goto out;
+                               goto out_trans_abort;
 
                        /* transfer ip2 ".." reference to dp1 */
                        if (!S_ISDIR(ip1->i_d.di_mode)) {
                                error = xfs_droplink(tp, dp2);
                                if (error)
-                                       goto out;
+                                       goto out_trans_abort;
                                error = xfs_bumplink(tp, dp1);
                                if (error)
-                                       goto out;
+                                       goto out_trans_abort;
                        }
 
                        /*
@@ -2818,16 +2818,16 @@ xfs_cross_rename(
                                                dp2->i_ino, first_block,
                                                free_list, spaceres);
                        if (error)
-                               goto out;
+                               goto out_trans_abort;
 
                        /* transfer ip1 ".." reference to dp2 */
                        if (!S_ISDIR(ip2->i_d.di_mode)) {
                                error = xfs_droplink(tp, dp1);
                                if (error)
-                                       goto out;
+                                       goto out_trans_abort;
                                error = xfs_bumplink(tp, dp2);
                                if (error)
-                                       goto out;
+                                       goto out_trans_abort;
                        }
 
                        /*
@@ -2855,7 +2855,11 @@ xfs_cross_rename(
        }
        xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
        xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE);
-out:
+       return xfs_finish_rename(tp, free_list);
+
+out_trans_abort:
+       xfs_bmap_cancel(free_list);
+       xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
        return error;
 }
 
@@ -2886,6 +2890,9 @@ xfs_rename(
 
        trace_xfs_rename(src_dp, target_dp, src_name, target_name);
 
+       if ((flags & RENAME_EXCHANGE) && !target_ip)
+               return -EINVAL;
+
        new_parent = (src_dp != target_dp);
        src_is_directory = S_ISDIR(src_ip->i_d.di_mode);
 
@@ -2943,21 +2950,11 @@ xfs_rename(
 
        xfs_bmap_init(&free_list, &first_block);
 
-       /*
-        * Handle RENAME_EXCHANGE flags
-        */
-       if (flags & RENAME_EXCHANGE) {
-               if (target_ip == NULL) {
-                       error = -EINVAL;
-                       goto out_trans_cancel;
-               }
-               error = xfs_cross_rename(tp, src_dp, src_name, src_ip,
-                                        target_dp, target_name, target_ip,
-                                        &free_list, &first_block, spaceres);
-               if (error)
-                       goto out_trans_abort;
-               return xfs_finish_rename(tp, &free_list);
-       }
+       /* RENAME_EXCHANGE is unique from here on. */
+       if (flags & RENAME_EXCHANGE)
+               return xfs_cross_rename(tp, src_dp, src_name, src_ip,
+                                       target_dp, target_name, target_ip,
+                                       &free_list, &first_block, spaceres);
 
        /*
         * Set up the target.
-- 
2.0.0

<Prev in Thread] Current Thread [Next in Thread>