diff options
| author | Chris Mason <clm@fb.com> | 2015-06-03 22:44:59 -0400 |
|---|---|---|
| committer | Chris Mason <clm@fb.com> | 2015-06-10 10:02:41 -0400 |
| commit | 1ab818b137e198e4d06e987a4b089411f2e39d40 (patch) | |
| tree | 01ecdbae6c4e12ff896b27a65afd9be1980ab3a5 /fs | |
| parent | 6ca0709756710c47ec604dd08b9fc45929d36390 (diff) | |
| parent | 8b191a684968e24b34c9894024b37532c68e6ae8 (diff) | |
Merge branch 'send_fixes_4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/fdmanana/linux into for-linus-4.2
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/send.c | 104 |
1 files changed, 83 insertions, 21 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 5cf7838fb5e5..50ebc622a324 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 { |
| @@ -1916,8 +1917,13 @@ static int did_overwrite_ref(struct send_ctx *sctx, | |||
| 1916 | goto out; | 1917 | goto out; |
| 1917 | } | 1918 | } |
| 1918 | 1919 | ||
| 1919 | /* we know that it is or will be overwritten. check this now */ | 1920 | /* |
| 1920 | if (ow_inode < sctx->send_progress) | 1921 | * We know that it is or will be overwritten. Check this now. |
| 1922 | * The current inode being processed might have been the one that caused | ||
| 1923 | * inode 'ino' to be orphanized, therefore ow_inode can actually be the | ||
| 1924 | * same as sctx->send_progress. | ||
| 1925 | */ | ||
| 1926 | if (ow_inode <= sctx->send_progress) | ||
| 1921 | ret = 1; | 1927 | ret = 1; |
| 1922 | else | 1928 | else |
| 1923 | ret = 0; | 1929 | ret = 0; |
| @@ -2239,6 +2245,8 @@ static int get_cur_path(struct send_ctx *sctx, u64 ino, u64 gen, | |||
| 2239 | fs_path_reset(dest); | 2245 | fs_path_reset(dest); |
| 2240 | 2246 | ||
| 2241 | while (!stop && ino != BTRFS_FIRST_FREE_OBJECTID) { | 2247 | while (!stop && ino != BTRFS_FIRST_FREE_OBJECTID) { |
| 2248 | struct waiting_dir_move *wdm; | ||
| 2249 | |||
| 2242 | fs_path_reset(name); | 2250 | fs_path_reset(name); |
| 2243 | 2251 | ||
| 2244 | if (is_waiting_for_rm(sctx, ino)) { | 2252 | if (is_waiting_for_rm(sctx, ino)) { |
| @@ -2249,7 +2257,11 @@ static int get_cur_path(struct send_ctx *sctx, u64 ino, u64 gen, | |||
| 2249 | break; | 2257 | break; |
| 2250 | } | 2258 | } |
| 2251 | 2259 | ||
| 2252 | if (is_waiting_for_move(sctx, ino)) { | 2260 | wdm = get_waiting_dir_move(sctx, ino); |
| 2261 | if (wdm && wdm->orphanized) { | ||
| 2262 | ret = gen_unique_name(sctx, ino, gen, name); | ||
| 2263 | stop = 1; | ||
| 2264 | } else if (wdm) { | ||
| 2253 | ret = get_first_ref(sctx->parent_root, ino, | 2265 | ret = get_first_ref(sctx->parent_root, ino, |
| 2254 | &parent_inode, &parent_gen, name); | 2266 | &parent_inode, &parent_gen, name); |
| 2255 | } else { | 2267 | } else { |
| @@ -2939,7 +2951,7 @@ static int is_waiting_for_move(struct send_ctx *sctx, u64 ino) | |||
| 2939 | return entry != NULL; | 2951 | return entry != NULL; |
| 2940 | } | 2952 | } |
| 2941 | 2953 | ||
| 2942 | static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino) | 2954 | static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino, bool orphanized) |
| 2943 | { | 2955 | { |
| 2944 | struct rb_node **p = &sctx->waiting_dir_moves.rb_node; | 2956 | struct rb_node **p = &sctx->waiting_dir_moves.rb_node; |
| 2945 | struct rb_node *parent = NULL; | 2957 | struct rb_node *parent = NULL; |
| @@ -2950,6 +2962,7 @@ static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino) | |||
| 2950 | return -ENOMEM; | 2962 | return -ENOMEM; |
| 2951 | dm->ino = ino; | 2963 | dm->ino = ino; |
| 2952 | dm->rmdir_ino = 0; | 2964 | dm->rmdir_ino = 0; |
| 2965 | dm->orphanized = orphanized; | ||
| 2953 | 2966 | ||
| 2954 | while (*p) { | 2967 | while (*p) { |
| 2955 | parent = *p; | 2968 | parent = *p; |
| @@ -3046,7 +3059,7 @@ static int add_pending_dir_move(struct send_ctx *sctx, | |||
| 3046 | goto out; | 3059 | goto out; |
| 3047 | } | 3060 | } |
| 3048 | 3061 | ||
| 3049 | ret = add_waiting_dir_move(sctx, pm->ino); | 3062 | ret = add_waiting_dir_move(sctx, pm->ino, is_orphan); |
| 3050 | if (ret) | 3063 | if (ret) |
| 3051 | goto out; | 3064 | goto out; |
| 3052 | 3065 | ||
| @@ -3369,8 +3382,40 @@ out: | |||
| 3369 | return ret; | 3382 | return ret; |
| 3370 | } | 3383 | } |
| 3371 | 3384 | ||
| 3385 | /* | ||
| 3386 | * Check if ino ino1 is an ancestor of inode ino2 in the given root. | ||
| 3387 | * Return 1 if true, 0 if false and < 0 on error. | ||
| 3388 | */ | ||
| 3389 | static int is_ancestor(struct btrfs_root *root, | ||
| 3390 | const u64 ino1, | ||
| 3391 | const u64 ino1_gen, | ||
| 3392 | const u64 ino2, | ||
| 3393 | struct fs_path *fs_path) | ||
| 3394 | { | ||
| 3395 | u64 ino = ino2; | ||
| 3396 | |||
| 3397 | while (ino > BTRFS_FIRST_FREE_OBJECTID) { | ||
| 3398 | int ret; | ||
| 3399 | u64 parent; | ||
| 3400 | u64 parent_gen; | ||
| 3401 | |||
| 3402 | fs_path_reset(fs_path); | ||
| 3403 | ret = get_first_ref(root, ino, &parent, &parent_gen, fs_path); | ||
| 3404 | if (ret < 0) { | ||
| 3405 | if (ret == -ENOENT && ino == ino2) | ||
| 3406 | ret = 0; | ||
| 3407 | return ret; | ||
| 3408 | } | ||
| 3409 | if (parent == ino1) | ||
| 3410 | return parent_gen == ino1_gen ? 1 : 0; | ||
| 3411 | ino = parent; | ||
| 3412 | } | ||
| 3413 | return 0; | ||
| 3414 | } | ||
| 3415 | |||
| 3372 | static int wait_for_parent_move(struct send_ctx *sctx, | 3416 | static int wait_for_parent_move(struct send_ctx *sctx, |
| 3373 | struct recorded_ref *parent_ref) | 3417 | struct recorded_ref *parent_ref, |
| 3418 | const bool is_orphan) | ||
| 3374 | { | 3419 | { |
| 3375 | int ret = 0; | 3420 | int ret = 0; |
| 3376 | u64 ino = parent_ref->dir; | 3421 | u64 ino = parent_ref->dir; |
| @@ -3390,11 +3435,24 @@ static int wait_for_parent_move(struct send_ctx *sctx, | |||
| 3390 | * Our current directory inode may not yet be renamed/moved because some | 3435 | * Our current directory inode may not yet be renamed/moved because some |
| 3391 | * ancestor (immediate or not) has to be renamed/moved first. So find if | 3436 | * ancestor (immediate or not) has to be renamed/moved first. So find if |
| 3392 | * such ancestor exists and make sure our own rename/move happens after | 3437 | * such ancestor exists and make sure our own rename/move happens after |
| 3393 | * that ancestor is processed. | 3438 | * that ancestor is processed to avoid path build infinite loops (done |
| 3439 | * at get_cur_path()). | ||
| 3394 | */ | 3440 | */ |
| 3395 | while (ino > BTRFS_FIRST_FREE_OBJECTID) { | 3441 | while (ino > BTRFS_FIRST_FREE_OBJECTID) { |
| 3396 | if (is_waiting_for_move(sctx, ino)) { | 3442 | if (is_waiting_for_move(sctx, ino)) { |
| 3397 | ret = 1; | 3443 | /* |
| 3444 | * If the current inode is an ancestor of ino in the | ||
| 3445 | * parent root, we need to delay the rename of the | ||
| 3446 | * current inode, otherwise don't delayed the rename | ||
| 3447 | * because we can end up with a circular dependency | ||
| 3448 | * of renames, resulting in some directories never | ||
| 3449 | * getting the respective rename operations issued in | ||
| 3450 | * the send stream or getting into infinite path build | ||
| 3451 | * loops. | ||
| 3452 | */ | ||
| 3453 | ret = is_ancestor(sctx->parent_root, | ||
| 3454 | sctx->cur_ino, sctx->cur_inode_gen, | ||
| 3455 | ino, path_before); | ||
| 3398 | break; | 3456 | break; |
| 3399 | } | 3457 | } |
| 3400 | 3458 | ||
| @@ -3436,7 +3494,7 @@ out: | |||
| 3436 | ino, | 3494 | ino, |
| 3437 | &sctx->new_refs, | 3495 | &sctx->new_refs, |
| 3438 | &sctx->deleted_refs, | 3496 | &sctx->deleted_refs, |
| 3439 | false); | 3497 | is_orphan); |
| 3440 | if (!ret) | 3498 | if (!ret) |
| 3441 | ret = 1; | 3499 | ret = 1; |
| 3442 | } | 3500 | } |
| @@ -3605,6 +3663,17 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
| 3605 | } | 3663 | } |
| 3606 | } | 3664 | } |
| 3607 | 3665 | ||
| 3666 | if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root && | ||
| 3667 | can_rename) { | ||
| 3668 | ret = wait_for_parent_move(sctx, cur, is_orphan); | ||
| 3669 | if (ret < 0) | ||
| 3670 | goto out; | ||
| 3671 | if (ret == 1) { | ||
| 3672 | can_rename = false; | ||
| 3673 | *pending_move = 1; | ||
| 3674 | } | ||
| 3675 | } | ||
| 3676 | |||
| 3608 | /* | 3677 | /* |
| 3609 | * link/move the ref to the new place. If we have an orphan | 3678 | * link/move the ref to the new place. If we have an orphan |
| 3610 | * inode, move it and update valid_path. If not, link or move | 3679 | * inode, move it and update valid_path. If not, link or move |
| @@ -3625,18 +3694,11 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
| 3625 | * dirs, we always have one new and one deleted | 3694 | * dirs, we always have one new and one deleted |
| 3626 | * ref. The deleted ref is ignored later. | 3695 | * ref. The deleted ref is ignored later. |
| 3627 | */ | 3696 | */ |
| 3628 | ret = wait_for_parent_move(sctx, cur); | 3697 | ret = send_rename(sctx, valid_path, |
| 3629 | if (ret < 0) | 3698 | cur->full_path); |
| 3630 | goto out; | 3699 | if (!ret) |
| 3631 | if (ret) { | 3700 | ret = fs_path_copy(valid_path, |
| 3632 | *pending_move = 1; | 3701 | cur->full_path); |
| 3633 | } else { | ||
| 3634 | ret = send_rename(sctx, valid_path, | ||
| 3635 | cur->full_path); | ||
| 3636 | if (!ret) | ||
| 3637 | ret = fs_path_copy(valid_path, | ||
| 3638 | cur->full_path); | ||
| 3639 | } | ||
| 3640 | if (ret < 0) | 3702 | if (ret < 0) |
| 3641 | goto out; | 3703 | goto out; |
| 3642 | } else { | 3704 | } else { |
