aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/send.c56
1 files changed, 37 insertions, 19 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 2ed36af6e43a..895f1b180b2f 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -243,6 +243,7 @@ struct waiting_dir_move {
243 * after this directory is moved, we can try to rmdir the ino rmdir_ino. 243 * after this directory is moved, we can try to rmdir the ino rmdir_ino.
244 */ 244 */
245 u64 rmdir_ino; 245 u64 rmdir_ino;
246 bool orphanized;
246}; 247};
247 248
248struct orphan_dir_info { 249struct orphan_dir_info {
@@ -1900,8 +1901,13 @@ static int did_overwrite_ref(struct send_ctx *sctx,
1900 goto out; 1901 goto out;
1901 } 1902 }
1902 1903
1903 /* we know that it is or will be overwritten. check this now */ 1904 /*
1904 if (ow_inode < sctx->send_progress) 1905 * We know that it is or will be overwritten. Check this now.
1906 * The current inode being processed might have been the one that caused
1907 * inode 'ino' to be orphanized, therefore ow_inode can actually be the
1908 * same as sctx->send_progress.
1909 */
1910 if (ow_inode <= sctx->send_progress)
1905 ret = 1; 1911 ret = 1;
1906 else 1912 else
1907 ret = 0; 1913 ret = 0;
@@ -2223,6 +2229,8 @@ static int get_cur_path(struct send_ctx *sctx, u64 ino, u64 gen,
2223 fs_path_reset(dest); 2229 fs_path_reset(dest);
2224 2230
2225 while (!stop && ino != BTRFS_FIRST_FREE_OBJECTID) { 2231 while (!stop && ino != BTRFS_FIRST_FREE_OBJECTID) {
2232 struct waiting_dir_move *wdm;
2233
2226 fs_path_reset(name); 2234 fs_path_reset(name);
2227 2235
2228 if (is_waiting_for_rm(sctx, ino)) { 2236 if (is_waiting_for_rm(sctx, ino)) {
@@ -2233,7 +2241,11 @@ static int get_cur_path(struct send_ctx *sctx, u64 ino, u64 gen,
2233 break; 2241 break;
2234 } 2242 }
2235 2243
2236 if (is_waiting_for_move(sctx, ino)) { 2244 wdm = get_waiting_dir_move(sctx, ino);
2245 if (wdm && wdm->orphanized) {
2246 ret = gen_unique_name(sctx, ino, gen, name);
2247 stop = 1;
2248 } else if (wdm) {
2237 ret = get_first_ref(sctx->parent_root, ino, 2249 ret = get_first_ref(sctx->parent_root, ino,
2238 &parent_inode, &parent_gen, name); 2250 &parent_inode, &parent_gen, name);
2239 } else { 2251 } else {
@@ -2923,7 +2935,7 @@ static int is_waiting_for_move(struct send_ctx *sctx, u64 ino)
2923 return entry != NULL; 2935 return entry != NULL;
2924} 2936}
2925 2937
2926static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino) 2938static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino, bool orphanized)
2927{ 2939{
2928 struct rb_node **p = &sctx->waiting_dir_moves.rb_node; 2940 struct rb_node **p = &sctx->waiting_dir_moves.rb_node;
2929 struct rb_node *parent = NULL; 2941 struct rb_node *parent = NULL;
@@ -2934,6 +2946,7 @@ static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino)
2934 return -ENOMEM; 2946 return -ENOMEM;
2935 dm->ino = ino; 2947 dm->ino = ino;
2936 dm->rmdir_ino = 0; 2948 dm->rmdir_ino = 0;
2949 dm->orphanized = orphanized;
2937 2950
2938 while (*p) { 2951 while (*p) {
2939 parent = *p; 2952 parent = *p;
@@ -3030,7 +3043,7 @@ static int add_pending_dir_move(struct send_ctx *sctx,
3030 goto out; 3043 goto out;
3031 } 3044 }
3032 3045
3033 ret = add_waiting_dir_move(sctx, pm->ino); 3046 ret = add_waiting_dir_move(sctx, pm->ino, is_orphan);
3034 if (ret) 3047 if (ret)
3035 goto out; 3048 goto out;
3036 3049
@@ -3385,7 +3398,8 @@ static int is_ancestor(struct btrfs_root *root,
3385} 3398}
3386 3399
3387static int wait_for_parent_move(struct send_ctx *sctx, 3400static int wait_for_parent_move(struct send_ctx *sctx,
3388 struct recorded_ref *parent_ref) 3401 struct recorded_ref *parent_ref,
3402 const bool is_orphan)
3389{ 3403{
3390 int ret = 0; 3404 int ret = 0;
3391 u64 ino = parent_ref->dir; 3405 u64 ino = parent_ref->dir;
@@ -3464,7 +3478,7 @@ out:
3464 ino, 3478 ino,
3465 &sctx->new_refs, 3479 &sctx->new_refs,
3466 &sctx->deleted_refs, 3480 &sctx->deleted_refs,
3467 false); 3481 is_orphan);
3468 if (!ret) 3482 if (!ret)
3469 ret = 1; 3483 ret = 1;
3470 } 3484 }
@@ -3633,6 +3647,17 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
3633 } 3647 }
3634 } 3648 }
3635 3649
3650 if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root &&
3651 can_rename) {
3652 ret = wait_for_parent_move(sctx, cur, is_orphan);
3653 if (ret < 0)
3654 goto out;
3655 if (ret == 1) {
3656 can_rename = false;
3657 *pending_move = 1;
3658 }
3659 }
3660
3636 /* 3661 /*
3637 * link/move the ref to the new place. If we have an orphan 3662 * link/move the ref to the new place. If we have an orphan
3638 * inode, move it and update valid_path. If not, link or move 3663 * inode, move it and update valid_path. If not, link or move
@@ -3653,18 +3678,11 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
3653 * dirs, we always have one new and one deleted 3678 * dirs, we always have one new and one deleted
3654 * ref. The deleted ref is ignored later. 3679 * ref. The deleted ref is ignored later.
3655 */ 3680 */
3656 ret = wait_for_parent_move(sctx, cur); 3681 ret = send_rename(sctx, valid_path,
3657 if (ret < 0) 3682 cur->full_path);
3658 goto out; 3683 if (!ret)
3659 if (ret) { 3684 ret = fs_path_copy(valid_path,
3660 *pending_move = 1; 3685 cur->full_path);
3661 } else {
3662 ret = send_rename(sctx, valid_path,
3663 cur->full_path);
3664 if (!ret)
3665 ret = fs_path_copy(valid_path,
3666 cur->full_path);
3667 }
3668 if (ret < 0) 3686 if (ret < 0)
3669 goto out; 3687 goto out;
3670 } else { 3688 } else {