summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/send.c100
1 files changed, 95 insertions, 5 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index b71dd298385c..993e1bab0a6b 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -231,7 +231,6 @@ struct pending_dir_move {
231 u64 parent_ino; 231 u64 parent_ino;
232 u64 ino; 232 u64 ino;
233 u64 gen; 233 u64 gen;
234 bool is_orphan;
235 struct list_head update_refs; 234 struct list_head update_refs;
236}; 235};
237 236
@@ -1861,7 +1860,8 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
1861 * was already unlinked/moved, so we can safely assume that we will not 1860 * was already unlinked/moved, so we can safely assume that we will not
1862 * overwrite anything at this point in time. 1861 * overwrite anything at this point in time.
1863 */ 1862 */
1864 if (other_inode > sctx->send_progress) { 1863 if (other_inode > sctx->send_progress ||
1864 is_waiting_for_move(sctx, other_inode)) {
1865 ret = get_inode_info(sctx->parent_root, other_inode, NULL, 1865 ret = get_inode_info(sctx->parent_root, other_inode, NULL,
1866 who_gen, NULL, NULL, NULL, NULL); 1866 who_gen, NULL, NULL, NULL, NULL);
1867 if (ret < 0) 1867 if (ret < 0)
@@ -3047,7 +3047,6 @@ static int add_pending_dir_move(struct send_ctx *sctx,
3047 pm->parent_ino = parent_ino; 3047 pm->parent_ino = parent_ino;
3048 pm->ino = ino; 3048 pm->ino = ino;
3049 pm->gen = ino_gen; 3049 pm->gen = ino_gen;
3050 pm->is_orphan = is_orphan;
3051 INIT_LIST_HEAD(&pm->list); 3050 INIT_LIST_HEAD(&pm->list);
3052 INIT_LIST_HEAD(&pm->update_refs); 3051 INIT_LIST_HEAD(&pm->update_refs);
3053 RB_CLEAR_NODE(&pm->node); 3052 RB_CLEAR_NODE(&pm->node);
@@ -3113,6 +3112,48 @@ static struct pending_dir_move *get_pending_dir_moves(struct send_ctx *sctx,
3113 return NULL; 3112 return NULL;
3114} 3113}
3115 3114
3115static int path_loop(struct send_ctx *sctx, struct fs_path *name,
3116 u64 ino, u64 gen, u64 *ancestor_ino)
3117{
3118 int ret = 0;
3119 u64 parent_inode = 0;
3120 u64 parent_gen = 0;
3121 u64 start_ino = ino;
3122
3123 *ancestor_ino = 0;
3124 while (ino != BTRFS_FIRST_FREE_OBJECTID) {
3125 fs_path_reset(name);
3126
3127 if (is_waiting_for_rm(sctx, ino))
3128 break;
3129 if (is_waiting_for_move(sctx, ino)) {
3130 if (*ancestor_ino == 0)
3131 *ancestor_ino = ino;
3132 ret = get_first_ref(sctx->parent_root, ino,
3133 &parent_inode, &parent_gen, name);
3134 } else {
3135 ret = __get_cur_name_and_parent(sctx, ino, gen,
3136 &parent_inode,
3137 &parent_gen, name);
3138 if (ret > 0) {
3139 ret = 0;
3140 break;
3141 }
3142 }
3143 if (ret < 0)
3144 break;
3145 if (parent_inode == start_ino) {
3146 ret = 1;
3147 if (*ancestor_ino == 0)
3148 *ancestor_ino = ino;
3149 break;
3150 }
3151 ino = parent_inode;
3152 gen = parent_gen;
3153 }
3154 return ret;
3155}
3156
3116static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) 3157static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
3117{ 3158{
3118 struct fs_path *from_path = NULL; 3159 struct fs_path *from_path = NULL;
@@ -3123,6 +3164,8 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
3123 u64 parent_ino, parent_gen; 3164 u64 parent_ino, parent_gen;
3124 struct waiting_dir_move *dm = NULL; 3165 struct waiting_dir_move *dm = NULL;
3125 u64 rmdir_ino = 0; 3166 u64 rmdir_ino = 0;
3167 u64 ancestor;
3168 bool is_orphan;
3126 int ret; 3169 int ret;
3127 3170
3128 name = fs_path_alloc(); 3171 name = fs_path_alloc();
@@ -3135,9 +3178,10 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
3135 dm = get_waiting_dir_move(sctx, pm->ino); 3178 dm = get_waiting_dir_move(sctx, pm->ino);
3136 ASSERT(dm); 3179 ASSERT(dm);
3137 rmdir_ino = dm->rmdir_ino; 3180 rmdir_ino = dm->rmdir_ino;
3181 is_orphan = dm->orphanized;
3138 free_waiting_dir_move(sctx, dm); 3182 free_waiting_dir_move(sctx, dm);
3139 3183
3140 if (pm->is_orphan) { 3184 if (is_orphan) {
3141 ret = gen_unique_name(sctx, pm->ino, 3185 ret = gen_unique_name(sctx, pm->ino,
3142 pm->gen, from_path); 3186 pm->gen, from_path);
3143 } else { 3187 } else {
@@ -3155,6 +3199,22 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
3155 goto out; 3199 goto out;
3156 3200
3157 sctx->send_progress = sctx->cur_ino + 1; 3201 sctx->send_progress = sctx->cur_ino + 1;
3202 ret = path_loop(sctx, name, pm->ino, pm->gen, &ancestor);
3203 if (ret) {
3204 LIST_HEAD(deleted_refs);
3205 ASSERT(ancestor > BTRFS_FIRST_FREE_OBJECTID);
3206 ret = add_pending_dir_move(sctx, pm->ino, pm->gen, ancestor,
3207 &pm->update_refs, &deleted_refs,
3208 is_orphan);
3209 if (ret < 0)
3210 goto out;
3211 if (rmdir_ino) {
3212 dm = get_waiting_dir_move(sctx, pm->ino);
3213 ASSERT(dm);
3214 dm->rmdir_ino = rmdir_ino;
3215 }
3216 goto out;
3217 }
3158 fs_path_reset(name); 3218 fs_path_reset(name);
3159 to_path = name; 3219 to_path = name;
3160 name = NULL; 3220 name = NULL;
@@ -3325,6 +3385,7 @@ static int wait_for_dest_dir_move(struct send_ctx *sctx,
3325 u64 left_gen; 3385 u64 left_gen;
3326 u64 right_gen; 3386 u64 right_gen;
3327 int ret = 0; 3387 int ret = 0;
3388 struct waiting_dir_move *wdm;
3328 3389
3329 if (RB_EMPTY_ROOT(&sctx->waiting_dir_moves)) 3390 if (RB_EMPTY_ROOT(&sctx->waiting_dir_moves))
3330 return 0; 3391 return 0;
@@ -3383,7 +3444,8 @@ static int wait_for_dest_dir_move(struct send_ctx *sctx,
3383 goto out; 3444 goto out;
3384 } 3445 }
3385 3446
3386 if (is_waiting_for_move(sctx, di_key.objectid)) { 3447 wdm = get_waiting_dir_move(sctx, di_key.objectid);
3448 if (wdm && !wdm->orphanized) {
3387 ret = add_pending_dir_move(sctx, 3449 ret = add_pending_dir_move(sctx,
3388 sctx->cur_ino, 3450 sctx->cur_ino,
3389 sctx->cur_inode_gen, 3451 sctx->cur_inode_gen,
@@ -3643,11 +3705,26 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
3643 goto out; 3705 goto out;
3644 if (ret) { 3706 if (ret) {
3645 struct name_cache_entry *nce; 3707 struct name_cache_entry *nce;
3708 struct waiting_dir_move *wdm;
3646 3709
3647 ret = orphanize_inode(sctx, ow_inode, ow_gen, 3710 ret = orphanize_inode(sctx, ow_inode, ow_gen,
3648 cur->full_path); 3711 cur->full_path);
3649 if (ret < 0) 3712 if (ret < 0)
3650 goto out; 3713 goto out;
3714
3715 /*
3716 * If ow_inode has its rename operation delayed
3717 * make sure that its orphanized name is used in
3718 * the source path when performing its rename
3719 * operation.
3720 */
3721 if (is_waiting_for_move(sctx, ow_inode)) {
3722 wdm = get_waiting_dir_move(sctx,
3723 ow_inode);
3724 ASSERT(wdm);
3725 wdm->orphanized = true;
3726 }
3727
3651 /* 3728 /*
3652 * Make sure we clear our orphanized inode's 3729 * Make sure we clear our orphanized inode's
3653 * name from the name cache. This is because the 3730 * name from the name cache. This is because the
@@ -3663,6 +3740,19 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
3663 name_cache_delete(sctx, nce); 3740 name_cache_delete(sctx, nce);
3664 kfree(nce); 3741 kfree(nce);
3665 } 3742 }
3743
3744 /*
3745 * ow_inode might currently be an ancestor of
3746 * cur_ino, therefore compute valid_path (the
3747 * current path of cur_ino) again because it
3748 * might contain the pre-orphanization name of
3749 * ow_inode, which is no longer valid.
3750 */
3751 fs_path_reset(valid_path);
3752 ret = get_cur_path(sctx, sctx->cur_ino,
3753 sctx->cur_inode_gen, valid_path);
3754 if (ret < 0)
3755 goto out;
3666 } else { 3756 } else {
3667 ret = send_unlink(sctx, cur->full_path); 3757 ret = send_unlink(sctx, cur->full_path);
3668 if (ret < 0) 3758 if (ret < 0)