diff options
| -rw-r--r-- | fs/btrfs/send.c | 56 |
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 | ||
| 248 | struct orphan_dir_info { | 249 | struct 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 | ||
| 2926 | static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino) | 2938 | static 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 | ||
| 3387 | static int wait_for_parent_move(struct send_ctx *sctx, | 3400 | static 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 { |
