aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/send.c
diff options
context:
space:
mode:
authorFilipe David Borba Manana <fdmanana@gmail.com>2014-02-05 11:48:56 -0500
committerJosef Bacik <jbacik@fb.com>2014-03-10 15:15:49 -0400
commitdff6d0adbe998927f72fc8d9ceee8ff72b124328 (patch)
treeb01f2349fadc31a0af2f38a69000bf41b7f29bb8 /fs/btrfs/send.c
parenta0859c0998605d2dc1b021543398cd84a40589db (diff)
Btrfs: make some tree searches in send.c more efficient
We have this pattern where we do search for a contiguous group of items in a tree and everytime we find an item, we process it, then we release our path, increment the offset of the search key, do another full tree search and repeat these steps until a tree search can't find more items we're interested in. Instead of doing these full tree searches after processing each item, just process the next item/slot in our leaf and don't release the path. Since all these trees are read only and we always use the commit root for a search and skip node/leaf locks, we're not affecting concurrency on the trees. Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com> Signed-off-by: Josef Bacik <jbacik@fb.com>
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r--fs/btrfs/send.c105
1 files changed, 64 insertions, 41 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 89fefbd955f3..a2621e7aaa5c 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -2501,17 +2501,26 @@ static int did_create_dir(struct send_ctx *sctx, u64 dir)
2501 key.objectid = dir; 2501 key.objectid = dir;
2502 key.type = BTRFS_DIR_INDEX_KEY; 2502 key.type = BTRFS_DIR_INDEX_KEY;
2503 key.offset = 0; 2503 key.offset = 0;
2504 ret = btrfs_search_slot(NULL, sctx->send_root, &key, path, 0, 0);
2505 if (ret < 0)
2506 goto out;
2507
2504 while (1) { 2508 while (1) {
2505 ret = btrfs_search_slot_for_read(sctx->send_root, &key, path, 2509 eb = path->nodes[0];
2506 1, 0); 2510 slot = path->slots[0];
2507 if (ret < 0) 2511 if (slot >= btrfs_header_nritems(eb)) {
2508 goto out; 2512 ret = btrfs_next_leaf(sctx->send_root, path);
2509 if (!ret) { 2513 if (ret < 0) {
2510 eb = path->nodes[0]; 2514 goto out;
2511 slot = path->slots[0]; 2515 } else if (ret > 0) {
2512 btrfs_item_key_to_cpu(eb, &found_key, slot); 2516 ret = 0;
2517 break;
2518 }
2519 continue;
2513 } 2520 }
2514 if (ret || found_key.objectid != key.objectid || 2521
2522 btrfs_item_key_to_cpu(eb, &found_key, slot);
2523 if (found_key.objectid != key.objectid ||
2515 found_key.type != key.type) { 2524 found_key.type != key.type) {
2516 ret = 0; 2525 ret = 0;
2517 goto out; 2526 goto out;
@@ -2526,8 +2535,7 @@ static int did_create_dir(struct send_ctx *sctx, u64 dir)
2526 goto out; 2535 goto out;
2527 } 2536 }
2528 2537
2529 key.offset = found_key.offset + 1; 2538 path->slots[0]++;
2530 btrfs_release_path(path);
2531 } 2539 }
2532 2540
2533out: 2541out:
@@ -2693,19 +2701,24 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 send_progress)
2693 key.objectid = dir; 2701 key.objectid = dir;
2694 key.type = BTRFS_DIR_INDEX_KEY; 2702 key.type = BTRFS_DIR_INDEX_KEY;
2695 key.offset = 0; 2703 key.offset = 0;
2704 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
2705 if (ret < 0)
2706 goto out;
2696 2707
2697 while (1) { 2708 while (1) {
2698 ret = btrfs_search_slot_for_read(root, &key, path, 1, 0); 2709 if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
2699 if (ret < 0) 2710 ret = btrfs_next_leaf(root, path);
2700 goto out; 2711 if (ret < 0)
2701 if (!ret) { 2712 goto out;
2702 btrfs_item_key_to_cpu(path->nodes[0], &found_key, 2713 else if (ret > 0)
2703 path->slots[0]); 2714 break;
2715 continue;
2704 } 2716 }
2705 if (ret || found_key.objectid != key.objectid || 2717 btrfs_item_key_to_cpu(path->nodes[0], &found_key,
2706 found_key.type != key.type) { 2718 path->slots[0]);
2719 if (found_key.objectid != key.objectid ||
2720 found_key.type != key.type)
2707 break; 2721 break;
2708 }
2709 2722
2710 di = btrfs_item_ptr(path->nodes[0], path->slots[0], 2723 di = btrfs_item_ptr(path->nodes[0], path->slots[0],
2711 struct btrfs_dir_item); 2724 struct btrfs_dir_item);
@@ -2716,8 +2729,7 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 send_progress)
2716 goto out; 2729 goto out;
2717 } 2730 }
2718 2731
2719 btrfs_release_path(path); 2732 path->slots[0]++;
2720 key.offset = found_key.offset + 1;
2721 } 2733 }
2722 2734
2723 ret = 1; 2735 ret = 1;
@@ -3620,15 +3632,22 @@ static int process_all_refs(struct send_ctx *sctx,
3620 key.objectid = sctx->cmp_key->objectid; 3632 key.objectid = sctx->cmp_key->objectid;
3621 key.type = BTRFS_INODE_REF_KEY; 3633 key.type = BTRFS_INODE_REF_KEY;
3622 key.offset = 0; 3634 key.offset = 0;
3623 while (1) { 3635 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
3624 ret = btrfs_search_slot_for_read(root, &key, path, 1, 0); 3636 if (ret < 0)
3625 if (ret < 0) 3637 goto out;
3626 goto out;
3627 if (ret)
3628 break;
3629 3638
3639 while (1) {
3630 eb = path->nodes[0]; 3640 eb = path->nodes[0];
3631 slot = path->slots[0]; 3641 slot = path->slots[0];
3642 if (slot >= btrfs_header_nritems(eb)) {
3643 ret = btrfs_next_leaf(root, path);
3644 if (ret < 0)
3645 goto out;
3646 else if (ret > 0)
3647 break;
3648 continue;
3649 }
3650
3632 btrfs_item_key_to_cpu(eb, &found_key, slot); 3651 btrfs_item_key_to_cpu(eb, &found_key, slot);
3633 3652
3634 if (found_key.objectid != key.objectid || 3653 if (found_key.objectid != key.objectid ||
@@ -3637,11 +3656,10 @@ static int process_all_refs(struct send_ctx *sctx,
3637 break; 3656 break;
3638 3657
3639 ret = iterate_inode_ref(root, path, &found_key, 0, cb, sctx); 3658 ret = iterate_inode_ref(root, path, &found_key, 0, cb, sctx);
3640 btrfs_release_path(path);
3641 if (ret < 0) 3659 if (ret < 0)
3642 goto out; 3660 goto out;
3643 3661
3644 key.offset = found_key.offset + 1; 3662 path->slots[0]++;
3645 } 3663 }
3646 btrfs_release_path(path); 3664 btrfs_release_path(path);
3647 3665
@@ -3922,19 +3940,25 @@ static int process_all_new_xattrs(struct send_ctx *sctx)
3922 key.objectid = sctx->cmp_key->objectid; 3940 key.objectid = sctx->cmp_key->objectid;
3923 key.type = BTRFS_XATTR_ITEM_KEY; 3941 key.type = BTRFS_XATTR_ITEM_KEY;
3924 key.offset = 0; 3942 key.offset = 0;
3925 while (1) { 3943 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
3926 ret = btrfs_search_slot_for_read(root, &key, path, 1, 0); 3944 if (ret < 0)
3927 if (ret < 0) 3945 goto out;
3928 goto out;
3929 if (ret) {
3930 ret = 0;
3931 goto out;
3932 }
3933 3946
3947 while (1) {
3934 eb = path->nodes[0]; 3948 eb = path->nodes[0];
3935 slot = path->slots[0]; 3949 slot = path->slots[0];
3936 btrfs_item_key_to_cpu(eb, &found_key, slot); 3950 if (slot >= btrfs_header_nritems(eb)) {
3951 ret = btrfs_next_leaf(root, path);
3952 if (ret < 0) {
3953 goto out;
3954 } else if (ret > 0) {
3955 ret = 0;
3956 break;
3957 }
3958 continue;
3959 }
3937 3960
3961 btrfs_item_key_to_cpu(eb, &found_key, slot);
3938 if (found_key.objectid != key.objectid || 3962 if (found_key.objectid != key.objectid ||
3939 found_key.type != key.type) { 3963 found_key.type != key.type) {
3940 ret = 0; 3964 ret = 0;
@@ -3946,8 +3970,7 @@ static int process_all_new_xattrs(struct send_ctx *sctx)
3946 if (ret < 0) 3970 if (ret < 0)
3947 goto out; 3971 goto out;
3948 3972
3949 btrfs_release_path(path); 3973 path->slots[0]++;
3950 key.offset = found_key.offset + 1;
3951 } 3974 }
3952 3975
3953out: 3976out: