diff options
author | Arne Jansen <sensille@gmx.net> | 2011-09-13 05:18:10 -0400 |
---|---|---|
committer | Alexander Block <ablock84@googlemail.com> | 2012-07-25 11:33:18 -0400 |
commit | e679376911d016b670c8cfc1645c178f77e8d1d3 (patch) | |
tree | 0ecc36238400c974a6c94eee6cda7288d494f515 /fs/btrfs | |
parent | 362a20c5e27614739c46707d1c5f55c214d164ce (diff) |
Btrfs: add helper for tree enumeration
Often no exact match is wanted but just the next lower or
higher item. There's a lot of duplicated code throughout
btrfs to deal with the corner cases. This patch adds a
helper function that can facilitate searching.
Signed-off-by: Arne Jansen <sensille@gmx.net>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 74 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 3 |
2 files changed, 77 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 8206b3900587..c82a9e4a953e 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -2722,6 +2722,80 @@ done: | |||
2722 | } | 2722 | } |
2723 | 2723 | ||
2724 | /* | 2724 | /* |
2725 | * helper to use instead of search slot if no exact match is needed but | ||
2726 | * instead the next or previous item should be returned. | ||
2727 | * When find_higher is true, the next higher item is returned, the next lower | ||
2728 | * otherwise. | ||
2729 | * When return_any and find_higher are both true, and no higher item is found, | ||
2730 | * return the next lower instead. | ||
2731 | * When return_any is true and find_higher is false, and no lower item is found, | ||
2732 | * return the next higher instead. | ||
2733 | * It returns 0 if any item is found, 1 if none is found (tree empty), and | ||
2734 | * < 0 on error | ||
2735 | */ | ||
2736 | int btrfs_search_slot_for_read(struct btrfs_root *root, | ||
2737 | struct btrfs_key *key, struct btrfs_path *p, | ||
2738 | int find_higher, int return_any) | ||
2739 | { | ||
2740 | int ret; | ||
2741 | struct extent_buffer *leaf; | ||
2742 | |||
2743 | again: | ||
2744 | ret = btrfs_search_slot(NULL, root, key, p, 0, 0); | ||
2745 | if (ret <= 0) | ||
2746 | return ret; | ||
2747 | /* | ||
2748 | * a return value of 1 means the path is at the position where the | ||
2749 | * item should be inserted. Normally this is the next bigger item, | ||
2750 | * but in case the previous item is the last in a leaf, path points | ||
2751 | * to the first free slot in the previous leaf, i.e. at an invalid | ||
2752 | * item. | ||
2753 | */ | ||
2754 | leaf = p->nodes[0]; | ||
2755 | |||
2756 | if (find_higher) { | ||
2757 | if (p->slots[0] >= btrfs_header_nritems(leaf)) { | ||
2758 | ret = btrfs_next_leaf(root, p); | ||
2759 | if (ret <= 0) | ||
2760 | return ret; | ||
2761 | if (!return_any) | ||
2762 | return 1; | ||
2763 | /* | ||
2764 | * no higher item found, return the next | ||
2765 | * lower instead | ||
2766 | */ | ||
2767 | return_any = 0; | ||
2768 | find_higher = 0; | ||
2769 | btrfs_release_path(p); | ||
2770 | goto again; | ||
2771 | } | ||
2772 | } else { | ||
2773 | if (p->slots[0] == 0) { | ||
2774 | ret = btrfs_prev_leaf(root, p); | ||
2775 | if (ret < 0) | ||
2776 | return ret; | ||
2777 | if (!ret) { | ||
2778 | p->slots[0] = btrfs_header_nritems(leaf) - 1; | ||
2779 | return 0; | ||
2780 | } | ||
2781 | if (!return_any) | ||
2782 | return 1; | ||
2783 | /* | ||
2784 | * no lower item found, return the next | ||
2785 | * higher instead | ||
2786 | */ | ||
2787 | return_any = 0; | ||
2788 | find_higher = 1; | ||
2789 | btrfs_release_path(p); | ||
2790 | goto again; | ||
2791 | } else { | ||
2792 | --p->slots[0]; | ||
2793 | } | ||
2794 | } | ||
2795 | return 0; | ||
2796 | } | ||
2797 | |||
2798 | /* | ||
2725 | * adjust the pointers going up the tree, starting at level | 2799 | * adjust the pointers going up the tree, starting at level |
2726 | * making sure the right key of each node is points to 'key'. | 2800 | * making sure the right key of each node is points to 'key'. |
2727 | * This is used after shifting pointers to the left, so it stops | 2801 | * This is used after shifting pointers to the left, so it stops |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index fa5c45b39075..8cfde9326dd6 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2711,6 +2711,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
2711 | ins_len, int cow); | 2711 | ins_len, int cow); |
2712 | int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, | 2712 | int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, |
2713 | struct btrfs_path *p, u64 time_seq); | 2713 | struct btrfs_path *p, u64 time_seq); |
2714 | int btrfs_search_slot_for_read(struct btrfs_root *root, | ||
2715 | struct btrfs_key *key, struct btrfs_path *p, | ||
2716 | int find_higher, int return_any); | ||
2714 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, | 2717 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, |
2715 | struct btrfs_root *root, struct extent_buffer *parent, | 2718 | struct btrfs_root *root, struct extent_buffer *parent, |
2716 | int start_slot, int cache_only, u64 *last_ret, | 2719 | int start_slot, int cache_only, u64 *last_ret, |