aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne Jansen <sensille@gmx.net>2011-09-13 05:18:10 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-07-10 09:14:42 -0400
commit2f38b3e1900634e64a186873b3388b1bf85dabc0 (patch)
tree21017a51174be9ba31696e4e4c8daa18ce2d59f8
parent630dc772ea51bca3ec6fac609f450cbe0cafd1d6 (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>
-rw-r--r--fs/btrfs/ctree.c72
-rw-r--r--fs/btrfs/ctree.h3
2 files changed, 75 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index bef68ab32204..fb21431fe4e0 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2789,6 +2789,78 @@ done:
2789} 2789}
2790 2790
2791/* 2791/*
2792 * helper to use instead of search slot if no exact match is needed but
2793 * instead the next or previous item should be returned.
2794 * When find_higher is true, the next higher item is returned, the next lower
2795 * otherwise.
2796 * When return_any and find_higher are both true, and no higher item is found,
2797 * return the next lower instead.
2798 * When return_any is true and find_higher is false, and no lower item is found,
2799 * return the next higher instead.
2800 * It returns 0 if any item is found, 1 if none is found (tree empty), and
2801 * < 0 on error
2802 */
2803int btrfs_search_slot_for_read(struct btrfs_root *root,
2804 struct btrfs_key *key, struct btrfs_path *p,
2805 int find_higher, int return_any)
2806{
2807 int ret;
2808 struct extent_buffer *leaf;
2809
2810again:
2811 ret = btrfs_search_slot(NULL, root, key, p, 0, 0);
2812 if (ret <= 0)
2813 return ret;
2814 /*
2815 * a return value of 1 means the path is at the position where the
2816 * item should be inserted. Normally this is the next bigger item,
2817 * but in case the previous item is the last in a leaf, path points
2818 * to the first free slot in the previous leaf, i.e. at an invalid
2819 * item.
2820 */
2821 leaf = p->nodes[0];
2822
2823 if (find_higher) {
2824 if (p->slots[0] >= btrfs_header_nritems(leaf)) {
2825 ret = btrfs_next_leaf(root, p);
2826 if (ret <= 0)
2827 return ret;
2828 if (!return_any)
2829 return 1;
2830 /*
2831 * no higher item found, return the next
2832 * lower instead
2833 */
2834 return_any = 0;
2835 find_higher = 0;
2836 btrfs_release_path(p);
2837 goto again;
2838 }
2839 } else {
2840 if (p->slots[0] >= btrfs_header_nritems(leaf)) {
2841 /* we're sitting on an invalid slot */
2842 if (p->slots[0] == 0) {
2843 ret = btrfs_prev_leaf(root, p);
2844 if (ret <= 0)
2845 return ret;
2846 if (!return_any)
2847 return 1;
2848 /*
2849 * no lower item found, return the next
2850 * higher instead
2851 */
2852 return_any = 0;
2853 find_higher = 1;
2854 btrfs_release_path(p);
2855 goto again;
2856 }
2857 --p->slots[0];
2858 }
2859 }
2860 return 0;
2861}
2862
2863/*
2792 * adjust the pointers going up the tree, starting at level 2864 * adjust the pointers going up the tree, starting at level
2793 * making sure the right key of each node is points to 'key'. 2865 * making sure the right key of each node is points to 'key'.
2794 * This is used after shifting pointers to the left, so it stops 2866 * 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 33088b0dbf3f..27cf995564ed 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2856,6 +2856,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
2856 ins_len, int cow); 2856 ins_len, int cow);
2857int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, 2857int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key,
2858 struct btrfs_path *p, u64 time_seq); 2858 struct btrfs_path *p, u64 time_seq);
2859int btrfs_search_slot_for_read(struct btrfs_root *root,
2860 struct btrfs_key *key, struct btrfs_path *p,
2861 int find_higher, int return_any);
2859int btrfs_realloc_node(struct btrfs_trans_handle *trans, 2862int btrfs_realloc_node(struct btrfs_trans_handle *trans,
2860 struct btrfs_root *root, struct extent_buffer *parent, 2863 struct btrfs_root *root, struct extent_buffer *parent,
2861 int start_slot, int cache_only, u64 *last_ret, 2864 int start_slot, int cache_only, u64 *last_ret,