summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2018-06-11 19:24:16 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-03 11:23:11 +0200
commit77c82917d533ce49fff2731ddaa1dbc3fbfd9551 (patch)
tree8bc2ce1267793531b16d6ffab7c1882a08794110
parent41b1d57a672f45f1d3a158cf28c24f1885201c9e (diff)
Btrfs: fix return value on rename exchange failure
commit c5b4a50b74018b3677098151ec5f4fce07d5e6a0 upstream. If we failed during a rename exchange operation after starting/joining a transaction, we would end up replacing the return value, stored in the local 'ret' variable, with the return value from btrfs_end_transaction(). So this could end up returning 0 (success) to user space despite the operation having failed and aborted the transaction, because if there are multiple tasks having a reference on the transaction at the time btrfs_end_transaction() is called by the rename exchange, that function returns 0 (otherwise it returns -EIO and not the original error value). So fix this by not overwriting the return value on error after getting a transaction handle. Fixes: cdd1fedf8261 ("btrfs: add support for RENAME_EXCHANGE and RENAME_WHITEOUT") CC: stable@vger.kernel.org # 4.9+ Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/btrfs/inode.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index f073de65e818..23ffe27e4851 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -9561,6 +9561,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
u64 new_idx = 0;
u64 root_objectid;
int ret;
+ int ret2;
bool root_log_pinned = false;
bool dest_log_pinned = false;
@@ -9751,7 +9752,8 @@ out_fail:
dest_log_pinned = false;
}
}
- ret = btrfs_end_transaction(trans, root);
+ ret2 = btrfs_end_transaction(trans, root);
+ ret = ret ? ret : ret2;
out_notrans:
if (new_ino == BTRFS_FIRST_FREE_OBJECTID)
up_read(&dest->fs_info->subvol_sem);