diff options
author | Dave Chinner <dchinner@redhat.com> | 2015-03-25 14:08:07 +1100 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-03-25 14:08:07 +1100 |
commit | eeacd3217b8fa8143f5dc27ded405790c74f01e8 (patch) | |
tree | ed74419ea4aa2b4825a5f48ee9585aad860808ef /fs/xfs | |
parent | 310606b0c7e385e9dd3533d168413ad2c579d961 (diff) | |
download | linux-stable-eeacd3217b8fa8143f5dc27ded405790c74f01e8.tar.gz linux-stable-eeacd3217b8fa8143f5dc27ded405790c74f01e8.tar.bz2 linux-stable-eeacd3217b8fa8143f5dc27ded405790c74f01e8.zip |
xfs: make xfs_cross_rename() complete fully
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@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_inode.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c3fe00cb19e4..b376ebe5fad9 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2703,14 +2703,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, @@ -2725,16 +2725,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; } /* @@ -2752,16 +2752,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; } /* @@ -2789,7 +2789,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; } @@ -2820,6 +2824,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); @@ -2877,17 +2884,11 @@ xfs_rename( xfs_bmap_init(&free_list, &first_block); - /* - * Handle RENAME_EXCHANGE flags - */ - if (flags & RENAME_EXCHANGE) { - 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. |