diff options
author | Dave Chinner <dchinner@redhat.com> | 2015-03-24 23:08:07 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-03-24 23:08:07 -0400 |
commit | eeacd3217b8fa8143f5dc27ded405790c74f01e8 (patch) | |
tree | ed74419ea4aa2b4825a5f48ee9585aad860808ef /fs/xfs/xfs_inode.c | |
parent | 310606b0c7e385e9dd3533d168413ad2c579d961 (diff) |
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/xfs_inode.c')
-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( | |||
2703 | ip2->i_ino, | 2703 | ip2->i_ino, |
2704 | first_block, free_list, spaceres); | 2704 | first_block, free_list, spaceres); |
2705 | if (error) | 2705 | if (error) |
2706 | goto out; | 2706 | goto out_trans_abort; |
2707 | 2707 | ||
2708 | /* Swap inode number for dirent in second parent */ | 2708 | /* Swap inode number for dirent in second parent */ |
2709 | error = xfs_dir_replace(tp, dp2, name2, | 2709 | error = xfs_dir_replace(tp, dp2, name2, |
2710 | ip1->i_ino, | 2710 | ip1->i_ino, |
2711 | first_block, free_list, spaceres); | 2711 | first_block, free_list, spaceres); |
2712 | if (error) | 2712 | if (error) |
2713 | goto out; | 2713 | goto out_trans_abort; |
2714 | 2714 | ||
2715 | /* | 2715 | /* |
2716 | * If we're renaming one or more directories across different parents, | 2716 | * If we're renaming one or more directories across different parents, |
@@ -2725,16 +2725,16 @@ xfs_cross_rename( | |||
2725 | dp1->i_ino, first_block, | 2725 | dp1->i_ino, first_block, |
2726 | free_list, spaceres); | 2726 | free_list, spaceres); |
2727 | if (error) | 2727 | if (error) |
2728 | goto out; | 2728 | goto out_trans_abort; |
2729 | 2729 | ||
2730 | /* transfer ip2 ".." reference to dp1 */ | 2730 | /* transfer ip2 ".." reference to dp1 */ |
2731 | if (!S_ISDIR(ip1->i_d.di_mode)) { | 2731 | if (!S_ISDIR(ip1->i_d.di_mode)) { |
2732 | error = xfs_droplink(tp, dp2); | 2732 | error = xfs_droplink(tp, dp2); |
2733 | if (error) | 2733 | if (error) |
2734 | goto out; | 2734 | goto out_trans_abort; |
2735 | error = xfs_bumplink(tp, dp1); | 2735 | error = xfs_bumplink(tp, dp1); |
2736 | if (error) | 2736 | if (error) |
2737 | goto out; | 2737 | goto out_trans_abort; |
2738 | } | 2738 | } |
2739 | 2739 | ||
2740 | /* | 2740 | /* |
@@ -2752,16 +2752,16 @@ xfs_cross_rename( | |||
2752 | dp2->i_ino, first_block, | 2752 | dp2->i_ino, first_block, |
2753 | free_list, spaceres); | 2753 | free_list, spaceres); |
2754 | if (error) | 2754 | if (error) |
2755 | goto out; | 2755 | goto out_trans_abort; |
2756 | 2756 | ||
2757 | /* transfer ip1 ".." reference to dp2 */ | 2757 | /* transfer ip1 ".." reference to dp2 */ |
2758 | if (!S_ISDIR(ip2->i_d.di_mode)) { | 2758 | if (!S_ISDIR(ip2->i_d.di_mode)) { |
2759 | error = xfs_droplink(tp, dp1); | 2759 | error = xfs_droplink(tp, dp1); |
2760 | if (error) | 2760 | if (error) |
2761 | goto out; | 2761 | goto out_trans_abort; |
2762 | error = xfs_bumplink(tp, dp2); | 2762 | error = xfs_bumplink(tp, dp2); |
2763 | if (error) | 2763 | if (error) |
2764 | goto out; | 2764 | goto out_trans_abort; |
2765 | } | 2765 | } |
2766 | 2766 | ||
2767 | /* | 2767 | /* |
@@ -2789,7 +2789,11 @@ xfs_cross_rename( | |||
2789 | } | 2789 | } |
2790 | xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 2790 | xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
2791 | xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE); | 2791 | xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE); |
2792 | out: | 2792 | return xfs_finish_rename(tp, free_list); |
2793 | |||
2794 | out_trans_abort: | ||
2795 | xfs_bmap_cancel(free_list); | ||
2796 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); | ||
2793 | return error; | 2797 | return error; |
2794 | } | 2798 | } |
2795 | 2799 | ||
@@ -2820,6 +2824,9 @@ xfs_rename( | |||
2820 | 2824 | ||
2821 | trace_xfs_rename(src_dp, target_dp, src_name, target_name); | 2825 | trace_xfs_rename(src_dp, target_dp, src_name, target_name); |
2822 | 2826 | ||
2827 | if ((flags & RENAME_EXCHANGE) && !target_ip) | ||
2828 | return -EINVAL; | ||
2829 | |||
2823 | new_parent = (src_dp != target_dp); | 2830 | new_parent = (src_dp != target_dp); |
2824 | src_is_directory = S_ISDIR(src_ip->i_d.di_mode); | 2831 | src_is_directory = S_ISDIR(src_ip->i_d.di_mode); |
2825 | 2832 | ||
@@ -2877,17 +2884,11 @@ xfs_rename( | |||
2877 | 2884 | ||
2878 | xfs_bmap_init(&free_list, &first_block); | 2885 | xfs_bmap_init(&free_list, &first_block); |
2879 | 2886 | ||
2880 | /* | 2887 | /* RENAME_EXCHANGE is unique from here on. */ |
2881 | * Handle RENAME_EXCHANGE flags | 2888 | if (flags & RENAME_EXCHANGE) |
2882 | */ | 2889 | return xfs_cross_rename(tp, src_dp, src_name, src_ip, |
2883 | if (flags & RENAME_EXCHANGE) { | 2890 | target_dp, target_name, target_ip, |
2884 | error = xfs_cross_rename(tp, src_dp, src_name, src_ip, | 2891 | &free_list, &first_block, spaceres); |
2885 | target_dp, target_name, target_ip, | ||
2886 | &free_list, &first_block, spaceres); | ||
2887 | if (error) | ||
2888 | goto out_trans_abort; | ||
2889 | return xfs_finish_rename(tp, &free_list); | ||
2890 | } | ||
2891 | 2892 | ||
2892 | /* | 2893 | /* |
2893 | * Set up the target. | 2894 | * Set up the target. |