summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2019-11-15 15:43:06 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-12-17 20:34:49 +0100
commit8862b80bd517ff64b93e65a6288114bda51d34ab (patch)
tree80fb333adcd48b6d752e80dacd3e04913217234f
parentf80318536150968ae29b03cc7e9bcc57c392642f (diff)
downloadlinux-stable-8862b80bd517ff64b93e65a6288114bda51d34ab.tar.gz
linux-stable-8862b80bd517ff64b93e65a6288114bda51d34ab.tar.bz2
linux-stable-8862b80bd517ff64b93e65a6288114bda51d34ab.zip
btrfs: record all roots for rename exchange on a subvol
commit 3e1740993e43116b3bc71b0aad1e6872f6ccf341 upstream. Testing with the new fsstress support for subvolumes uncovered a pretty bad problem with rename exchange on subvolumes. We're modifying two different subvolumes, but we only start the transaction on one of them, so the other one is not added to the dirty root list. This is caught by btrfs_cow_block() with a warning because the root has not been updated, however if we do not modify this root again we'll end up pointing at an invalid root because the root item is never updated. Fix this by making sure we add the destination root to the trans list, the same as we do with normal renames. This fixes the corruption. Fixes: cdd1fedf8261 ("btrfs: add support for RENAME_EXCHANGE and RENAME_WHITEOUT") CC: stable@vger.kernel.org # 4.9+ Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/btrfs/inode.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 50ceb273f9da..7fd4458cf0a7 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -9510,6 +9510,9 @@ static int btrfs_rename_exchange(struct inode *old_dir,
goto out_notrans;
}
+ if (dest != root)
+ btrfs_record_root_in_trans(trans, dest);
+
/*
* We need to find a free sequence number both in the source and
* in the destination directory for the exchange.