]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Add mt_lookup() with no state support for faster lookups
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Wed, 10 Nov 2021 03:17:05 +0000 (22:17 -0500)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Wed, 10 Nov 2021 16:05:04 +0000 (11:05 -0500)
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
lib/maple_tree.c
lib/test_maple_tree.c

index 8f4d044f73f4edaa3f82705f467cd7081457b078..ae2c2b58fa4917473662bf391799bbec93dd7792 100644 (file)
@@ -3708,6 +3708,86 @@ done:
                mas->min = min;
        }
 }
+
+/*
+ * mas_lookup_walk() - Internal quick lookup that does not keep maple state up
+ * to date.
+ *
+ * @mas: The maple state.
+ *
+ * Return: The entry for @mas->index or %NULL on dead node.
+ */
+static inline void *mas_lookup_walk(struct ma_state *mas)
+{
+       unsigned long *pivots;
+       unsigned char offset;
+       struct maple_node *node;
+       struct maple_enode *next;
+       enum maple_type type;
+       void __rcu **slots;
+       unsigned char end;
+       unsigned long max;
+
+       next = mas->node;
+       max = ULONG_MAX;
+       do {
+               offset = 0;
+               node = mte_to_node(next);
+               type = mte_node_type(next);
+               pivots = ma_pivots(node, type);
+               end = ma_data_end(node, type, pivots, max);
+               if (unlikely(ma_dead_node(node)))
+                       goto dead_node;
+
+               while((offset < end) &&
+                     (pivots[offset] < mas->index))
+                       offset++;
+
+               if (likely(offset > mt_pivots[type]) && pivots[offset])
+                       max = pivots[offset];
+
+               slots = ma_slots(node, type);
+               next = mt_slot(mas->tree, slots, offset);
+               if (unlikely(ma_dead_node(node)))
+                       goto dead_node;
+       } while (!ma_is_leaf(type));
+
+       return (void *) next;
+
+dead_node:
+       mas_reset(mas);
+       return NULL;
+}
+
+/*
+ * mt_lookup() - Fast value lookup.
+ *
+ */
+void *mt_lookup(struct maple_tree *mt, unsigned long index)
+{
+       MA_STATE(mas, mt, index, index);
+       void *entry;
+
+retry:
+       entry = mas_start(&mas);
+       if (unlikely(mas_is_none(&mas)))
+               return NULL;
+
+       if (unlikely(mas_is_ptr(&mas))) {
+               if (!index)
+                       return entry;
+
+               return NULL;
+       }
+
+       entry = mas_lookup_walk(&mas);
+       if (!entry && unlikely(mas_is_start(&mas)))
+               goto retry;
+
+       return entry;
+}
+EXPORT_SYMBOL_GPL(mt_lookup);
+
 /*
  * mas_descend_walk(): Locates a value and sets the mas->node and slot
  * accordingly.  range_min and range_max are set to the range which the entry is
index 1a54902b4eca5aede20095b16245ebc548e128f6..0a9d128b9d8586c702d04720d84affa6dba5b9b1 100644 (file)
@@ -97,6 +97,11 @@ static noinline void check_load(struct maple_tree *mt, unsigned long index,
 {
        void *ret = mtree_test_load(mt, index);
 
+       if (ret != mt_lookup(mt, index)) {
+               pr_err("lookup of %lu %p expected %p\n", index, mt_lookup(mt, index), ret);
+       }
+       MT_BUG_ON(mt, ret != mt_lookup(mt, index));
+
        if (ret != ptr)
                pr_err("Load %lu returned %p expect %p\n", index, ret, ptr);
        MT_BUG_ON(mt, ret != ptr);