aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2015-06-03 22:44:59 -0400
committerChris Mason <clm@fb.com>2015-06-10 10:02:41 -0400
commit1ab818b137e198e4d06e987a4b089411f2e39d40 (patch)
tree01ecdbae6c4e12ff896b27a65afd9be1980ab3a5 /fs
parent6ca0709756710c47ec604dd08b9fc45929d36390 (diff)
parent8b191a684968e24b34c9894024b37532c68e6ae8 (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.c104
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
248struct orphan_dir_info { 249struct 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
2942static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino) 2954static 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 */
3389static 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
3372static int wait_for_parent_move(struct send_ctx *sctx, 3416static 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 {