aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipe David Borba Manana <fdmanana@gmail.com>2014-01-31 21:00:15 -0500
committerJosef Bacik <jbacik@fb.com>2014-03-10 15:15:42 -0400
commit03cb4fb9d86d591bc8a3f66eac6fb874b50b1b4d (patch)
treec11263e6a664889b9d96952dab1fa42fb3a4216a
parent98cfee214394a3560bd4ce3209b55a71c4267783 (diff)
Btrfs: fix send dealing with file renames and directory moves
This fixes a case that the commit titled: Btrfs: fix infinite path build loops in incremental send didn't cover. If the parent-child relationship between 2 directories is inverted, both get renamed, and the former parent has a file that got renamed too (but remains a child of that directory), the incremental send operation would use the file's old path after sending an unlink operation for that old path, causing receive to fail on future operations like changing owner, permissions or utimes of the corresponding inode. This is not a regression from the commit mentioned before, as without that commit we would fall into the issues that commit fixed, so it's just one case that wasn't covered before. Simple steps to reproduce this issue are: $ mkfs.btrfs -f /dev/sdb3 $ mount /dev/sdb3 /mnt/btrfs $ mkdir -p /mnt/btrfs/a/b/c/d $ touch /mnt/btrfs/a/b/c/d/file $ mkdir -p /mnt/btrfs/a/b/x $ btrfs subvol snapshot -r /mnt/btrfs /mnt/btrfs/snap1 $ mv /mnt/btrfs/a/b/x /mnt/btrfs/a/b/c/x2 $ mv /mnt/btrfs/a/b/c/d /mnt/btrfs/a/b/c/x2/d2 $ mv /mnt/btrfs/a/b/c/x2/d2/file /mnt/btrfs/a/b/c/x2/d2/file2 $ btrfs subvol snapshot -r /mnt/btrfs /mnt/btrfs/snap2 $ btrfs send -p /mnt/btrfs/snap1 /mnt/btrfs/snap2 > /tmp/incremental.send A patch to update the test btrfs/030 from xfstests, so that it covers this case, will be submitted soon. Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com> Signed-off-by: Josef Bacik <jbacik@fb.com>
-rw-r--r--fs/btrfs/send.c10
1 files changed, 1 insertions, 9 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 70272e1d2b1e..8bd0505ee2f9 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -2131,8 +2131,6 @@ static int get_cur_path(struct send_ctx *sctx, u64 ino, u64 gen,
2131 u64 parent_inode = 0; 2131 u64 parent_inode = 0;
2132 u64 parent_gen = 0; 2132 u64 parent_gen = 0;
2133 int stop = 0; 2133 int stop = 0;
2134 u64 start_ino = ino;
2135 u64 start_gen = gen;
2136 int skip_name_cache = 0; 2134 int skip_name_cache = 0;
2137 2135
2138 name = fs_path_alloc(); 2136 name = fs_path_alloc();
@@ -2144,7 +2142,6 @@ static int get_cur_path(struct send_ctx *sctx, u64 ino, u64 gen,
2144 if (is_waiting_for_move(sctx, ino)) 2142 if (is_waiting_for_move(sctx, ino))
2145 skip_name_cache = 1; 2143 skip_name_cache = 1;
2146 2144
2147again:
2148 dest->reversed = 1; 2145 dest->reversed = 1;
2149 fs_path_reset(dest); 2146 fs_path_reset(dest);
2150 2147
@@ -2159,13 +2156,8 @@ again:
2159 stop = 1; 2156 stop = 1;
2160 2157
2161 if (!skip_name_cache && 2158 if (!skip_name_cache &&
2162 is_waiting_for_move(sctx, parent_inode)) { 2159 is_waiting_for_move(sctx, parent_inode))
2163 ino = start_ino;
2164 gen = start_gen;
2165 stop = 0;
2166 skip_name_cache = 1; 2160 skip_name_cache = 1;
2167 goto again;
2168 }
2169 2161
2170 ret = fs_path_add_path(dest, name); 2162 ret = fs_path_add_path(dest, name);
2171 if (ret < 0) 2163 if (ret < 0)