diff options
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 3ddd2bb7508..cb9502adccd 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -2857,19 +2857,48 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) { struct fs_path *from_path = NULL; struct fs_path *to_path = NULL; + struct fs_path *name = NULL; u64 orig_progress = sctx->send_progress; struct recorded_ref *cur; + u64 parent_ino, parent_gen; int ret; + name = fs_path_alloc(); from_path = fs_path_alloc(); - if (!from_path) - return -ENOMEM; + if (!name || !from_path) { + ret = -ENOMEM; + goto out; + } - sctx->send_progress = pm->ino; - ret = get_cur_path(sctx, pm->ino, pm->gen, from_path); + ret = del_waiting_dir_move(sctx, pm->ino); + ASSERT(ret == 0); + + ret = get_first_ref(sctx->parent_root, pm->ino, + &parent_ino, &parent_gen, name); if (ret < 0) goto out; + if (parent_ino == sctx->cur_ino) { + /* child only renamed, not moved */ + ASSERT(parent_gen == sctx->cur_inode_gen); + ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, + from_path); + if (ret < 0) + goto out; + ret = fs_path_add_path(from_path, name); + if (ret < 0) + goto out; + } else { + /* child moved and maybe renamed too */ + sctx->send_progress = pm->ino; + ret = get_cur_path(sctx, pm->ino, pm->gen, from_path); + if (ret < 0) + goto out; + } + + fs_path_free(name); + name = NULL; + to_path = fs_path_alloc(); if (!to_path) { ret = -ENOMEM; @@ -2877,9 +2906,6 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) } sctx->send_progress = sctx->cur_ino + 1; - ret = del_waiting_dir_move(sctx, pm->ino); - ASSERT(ret == 0); - ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); if (ret < 0) goto out; @@ -2903,6 +2929,7 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) } out: + fs_path_free(name); fs_path_free(from_path); fs_path_free(to_path); sctx->send_progress = orig_progress; |