aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@gmail.com>2014-03-22 13:15:24 -0400
committerChris Mason <clm@fb.com>2014-06-09 20:20:38 -0400
commitc992ec94f24c3e7135d6c23860615f269f0b1d87 (patch)
treec927bac013f58152fc5262c012ce02a684f1b461
parentb46ab97bcd4ae7954b3a150f642a82cdd1434f40 (diff)
Btrfs: send, account for orphan directories when building path strings
If we have directories with a pending move/rename operation, we must take into account any orphan directories that got created before executing the pending move/rename. Those orphan directories are directories with an inode number higher then the current send progress and that don't exist in the parent snapshot, they are created before current progress reaches their inode number, with a generated name of the form oN-M-I and at the root of the filesystem tree, and later when progress matches their inode number, moved/renamed to their final location. Reproducer: $ mkfs.btrfs -f /dev/sdd $ mount /dev/sdd /mnt $ mkdir -p /mnt/a/b/c/d $ mkdir /mnt/a/b/e $ mv /mnt/a/b/c /mnt/a/b/e/CC $ mkdir /mnt/a/b/e/CC/d/f $ mkdir /mnt/a/g $ btrfs subvolume snapshot -r /mnt /mnt/snap1 $ btrfs send /mnt/snap1 -f /tmp/base.send $ mkdir /mnt/a/g/h $ mv /mnt/a/b/e /mnt/a/g/h/EE $ mv /mnt/a/g/h/EE/CC/d /mnt/a/g/h/EE/DD $ btrfs subvolume snapshot -r /mnt /mnt/snap2 $ btrfs send -p /mnt/snap1 /mnt/snap2 -f /tmp/incremental.send The second receive command failed with the following error: ERROR: rename a/b/e/CC/d -> o264-7-0/EE/DD failed. No such file or directory A test case for xfstests follows soon. Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/send.c33
1 files changed, 9 insertions, 24 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 98e9e0cf7e8e..c2bfd60ba245 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -3055,33 +3055,18 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
3055 if (ret < 0) 3055 if (ret < 0)
3056 goto out; 3056 goto out;
3057 3057
3058 if (parent_ino == sctx->cur_ino) { 3058 ret = get_cur_path(sctx, parent_ino, parent_gen,
3059 /* child only renamed, not moved */ 3059 from_path);
3060 ASSERT(parent_gen == sctx->cur_inode_gen); 3060 if (ret < 0)
3061 ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, 3061 goto out;
3062 from_path); 3062 ret = fs_path_add_path(from_path, name);
3063 if (ret < 0) 3063 if (ret < 0)
3064 goto out; 3064 goto out;
3065 ret = fs_path_add_path(from_path, name);
3066 if (ret < 0)
3067 goto out;
3068 } else {
3069 /* child moved and maybe renamed too */
3070 sctx->send_progress = pm->ino;
3071 ret = get_cur_path(sctx, pm->ino, pm->gen, from_path);
3072 if (ret < 0)
3073 goto out;
3074 }
3075 3065
3076 fs_path_free(name); 3066 fs_path_reset(name);
3067 to_path = name;
3077 name = NULL; 3068 name = NULL;
3078 3069
3079 to_path = fs_path_alloc();
3080 if (!to_path) {
3081 ret = -ENOMEM;
3082 goto out;
3083 }
3084
3085 sctx->send_progress = sctx->cur_ino + 1; 3070 sctx->send_progress = sctx->cur_ino + 1;
3086 ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); 3071 ret = get_cur_path(sctx, pm->ino, pm->gen, to_path);
3087 if (ret < 0) 3072 if (ret < 0)