]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Btrfs: add helper for tree enumeration
authorArne Jansen <sensille@gmx.net>
Tue, 13 Sep 2011 09:18:10 +0000 (11:18 +0200)
committerJan Schmidt <list.btrfs@jan-o-sch.net>
Tue, 10 Jul 2012 13:14:42 +0000 (15:14 +0200)
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>
fs/btrfs/ctree.c
fs/btrfs/ctree.h

index bef68ab3220466756ed590afb812b00b1401254b..fb21431fe4e045f507c0b5f0974c7f4afbfa2797 100644 (file)
@@ -2788,6 +2788,78 @@ done:
        return ret;
 }
 
+/*
+ * helper to use instead of search slot if no exact match is needed but
+ * instead the next or previous item should be returned.
+ * When find_higher is true, the next higher item is returned, the next lower
+ * otherwise.
+ * When return_any and find_higher are both true, and no higher item is found,
+ * return the next lower instead.
+ * When return_any is true and find_higher is false, and no lower item is found,
+ * return the next higher instead.
+ * It returns 0 if any item is found, 1 if none is found (tree empty), and
+ * < 0 on error
+ */
+int btrfs_search_slot_for_read(struct btrfs_root *root,
+                              struct btrfs_key *key, struct btrfs_path *p,
+                              int find_higher, int return_any)
+{
+       int ret;
+       struct extent_buffer *leaf;
+
+again:
+       ret = btrfs_search_slot(NULL, root, key, p, 0, 0);
+       if (ret <= 0)
+               return ret;
+       /*
+        * a return value of 1 means the path is at the position where the
+        * item should be inserted. Normally this is the next bigger item,
+        * but in case the previous item is the last in a leaf, path points
+        * to the first free slot in the previous leaf, i.e. at an invalid
+        * item.
+        */
+       leaf = p->nodes[0];
+
+       if (find_higher) {
+               if (p->slots[0] >= btrfs_header_nritems(leaf)) {
+                       ret = btrfs_next_leaf(root, p);
+                       if (ret <= 0)
+                               return ret;
+                       if (!return_any)
+                               return 1;
+                       /*
+                        * no higher item found, return the next
+                        * lower instead
+                        */
+                       return_any = 0;
+                       find_higher = 0;
+                       btrfs_release_path(p);
+                       goto again;
+               }
+       } else {
+               if (p->slots[0] >= btrfs_header_nritems(leaf)) {
+                       /* we're sitting on an invalid slot */
+                       if (p->slots[0] == 0) {
+                               ret = btrfs_prev_leaf(root, p);
+                               if (ret <= 0)
+                                       return ret;
+                               if (!return_any)
+                                       return 1;
+                               /*
+                                * no lower item found, return the next
+                                * higher instead
+                                */
+                               return_any = 0;
+                               find_higher = 1;
+                               btrfs_release_path(p);
+                               goto again;
+                       }
+                       --p->slots[0];
+               }
+       }
+       return 0;
+}
+
 /*
  * adjust the pointers going up the tree, starting at level
  * making sure the right key of each node is points to 'key'.
index 33088b0dbf3fdfdc47dd4ca7fd395ae3d2bf4fc8..27cf995564ed82586cb12c3818d09fe51db3d549 100644 (file)
@@ -2856,6 +2856,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
                      ins_len, int cow);
 int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key,
                          struct btrfs_path *p, u64 time_seq);
+int btrfs_search_slot_for_read(struct btrfs_root *root,
+                              struct btrfs_key *key, struct btrfs_path *p,
+                              int find_higher, int return_any);
 int btrfs_realloc_node(struct btrfs_trans_handle *trans,
                       struct btrfs_root *root, struct extent_buffer *parent,
                       int start_slot, int cache_only, u64 *last_ret,