aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Bo <bo.liu@linux.alibaba.com>2018-05-17 23:00:21 -0400
committerDavid Sterba <dsterba@suse.com>2018-05-30 10:46:44 -0400
commit1fc28d8e2e9bf22044f1bacd17fe941cd0df5ba6 (patch)
treefeda6b6a30825b0c9016f516267363b72a22bd5c
parente6a1d6fd276965db0ca91e91dffc0a6fb7d89254 (diff)
Btrfs: move get root out of btrfs_search_slot to a helper
It's good to have a helper instead of having all get-root details open-coded. The new helper locks (if necessary) and sets root node of the path. Also invert the checks to make the code flow easier to read. There is no functional change in this commit. Signed-off-by: Liu Bo <bo.liu@linux.alibaba.com> Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/ctree.c110
1 files changed, 65 insertions, 45 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 46afc9743ad0..44dd1950f88a 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2598,6 +2598,70 @@ int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path,
2598 return 0; 2598 return 0;
2599} 2599}
2600 2600
2601static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
2602 struct btrfs_path *p,
2603 int write_lock_level)
2604{
2605 struct btrfs_fs_info *fs_info = root->fs_info;
2606 struct extent_buffer *b;
2607 int root_lock;
2608 int level = 0;
2609
2610 /* We try very hard to do read locks on the root */
2611 root_lock = BTRFS_READ_LOCK;
2612
2613 if (p->search_commit_root) {
2614 /* The commit roots are read only so we always do read locks */
2615 if (p->need_commit_sem)
2616 down_read(&fs_info->commit_root_sem);
2617 b = root->commit_root;
2618 extent_buffer_get(b);
2619 level = btrfs_header_level(b);
2620 if (p->need_commit_sem)
2621 up_read(&fs_info->commit_root_sem);
2622 if (!p->skip_locking)
2623 btrfs_tree_read_lock(b);
2624
2625 goto out;
2626 }
2627
2628 if (p->skip_locking) {
2629 b = btrfs_root_node(root);
2630 level = btrfs_header_level(b);
2631 goto out;
2632 }
2633
2634 /*
2635 * We don't know the level of the root node until we actually have it
2636 * read locked
2637 */
2638 b = btrfs_read_lock_root_node(root);
2639 level = btrfs_header_level(b);
2640 if (level > write_lock_level)
2641 goto out;
2642
2643 /*
2644 * whoops, must trade for write lock
2645 */
2646 btrfs_tree_read_unlock(b);
2647 free_extent_buffer(b);
2648 b = btrfs_lock_root_node(root);
2649 root_lock = BTRFS_WRITE_LOCK;
2650
2651 /* The level might have changed, check again */
2652 level = btrfs_header_level(b);
2653
2654out:
2655 p->nodes[level] = b;
2656 if (!p->skip_locking)
2657 p->locks[level] = root_lock;
2658 /*
2659 * Callers are responsible for dropping b's references.
2660 */
2661 return b;
2662}
2663
2664
2601/* 2665/*
2602 * btrfs_search_slot - look for a key in a tree and perform necessary 2666 * btrfs_search_slot - look for a key in a tree and perform necessary
2603 * modifications to preserve tree invariants. 2667 * modifications to preserve tree invariants.
@@ -2634,7 +2698,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
2634 int err; 2698 int err;
2635 int level; 2699 int level;
2636 int lowest_unlock = 1; 2700 int lowest_unlock = 1;
2637 int root_lock;
2638 /* everything at write_lock_level or lower must be write locked */ 2701 /* everything at write_lock_level or lower must be write locked */
2639 int write_lock_level = 0; 2702 int write_lock_level = 0;
2640 u8 lowest_level = 0; 2703 u8 lowest_level = 0;
@@ -2672,50 +2735,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
2672 2735
2673again: 2736again:
2674 prev_cmp = -1; 2737 prev_cmp = -1;
2675 /* 2738 b = btrfs_search_slot_get_root(root, p, write_lock_level);
2676 * we try very hard to do read locks on the root
2677 */
2678 root_lock = BTRFS_READ_LOCK;
2679 level = 0;
2680 if (p->search_commit_root) {
2681 /*
2682 * the commit roots are read only
2683 * so we always do read locks
2684 */
2685 if (p->need_commit_sem)
2686 down_read(&fs_info->commit_root_sem);
2687 b = root->commit_root;
2688 extent_buffer_get(b);
2689 level = btrfs_header_level(b);
2690 if (p->need_commit_sem)
2691 up_read(&fs_info->commit_root_sem);
2692 if (!p->skip_locking)
2693 btrfs_tree_read_lock(b);
2694 } else {
2695 if (p->skip_locking) {
2696 b = btrfs_root_node(root);
2697 level = btrfs_header_level(b);
2698 } else {
2699 /* we don't know the level of the root node
2700 * until we actually have it read locked
2701 */
2702 b = btrfs_read_lock_root_node(root);
2703 level = btrfs_header_level(b);
2704 if (level <= write_lock_level) {
2705 /* whoops, must trade for write lock */
2706 btrfs_tree_read_unlock(b);
2707 free_extent_buffer(b);
2708 b = btrfs_lock_root_node(root);
2709 root_lock = BTRFS_WRITE_LOCK;
2710
2711 /* the level might have changed, check again */
2712 level = btrfs_header_level(b);
2713 }
2714 }
2715 }
2716 p->nodes[level] = b;
2717 if (!p->skip_locking)
2718 p->locks[level] = root_lock;
2719 2739
2720 while (b) { 2740 while (b) {
2721 level = btrfs_header_level(b); 2741 level = btrfs_header_level(b);