]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Add ma_peek() interface maple_for6.4_big
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Tue, 25 Apr 2023 20:10:31 +0000 (16:10 -0400)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Tue, 25 Apr 2023 20:20:56 +0000 (16:20 -0400)
Add a thin lookup which uses minimal state.

Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
include/linux/maple_tree.h
lib/maple_tree.c
lib/test_maple_tree.c

index bddced4ec7f2c305986a0a71c269940bda8e6a28..dcb3ec36568f4bd75fe7688c870a21fdf57a8b58 100644 (file)
@@ -465,6 +465,7 @@ void maple_tree_init(void);
 void mas_destroy(struct ma_state *mas);
 int mas_expected_entries(struct ma_state *mas, unsigned long nr_entries);
 
+void *ma_peek(struct maple_tree *mt, unsigned long addr);
 void *mas_prev(struct ma_state *mas, unsigned long min);
 void *mas_prev_range(struct ma_state *mas, unsigned long max);
 void *mas_next(struct ma_state *mas, unsigned long max);
index 04b73499baffacd078d13e7b265964b914f2a98f..9a01cd7dd449bd708ca36cb88334de8b8d82744c 100644 (file)
@@ -5025,6 +5025,62 @@ done:
        return found;
 }
 
+/* ma_peek() - Cheaper version of walking to a specific address with minimal
+ * state.
+ * @mt: The maple tree
+ * @addr: The address
+ *
+ * Note: Only works holding the write lock.
+ */
+void *ma_peek(struct maple_tree *mt, unsigned long addr)
+{
+       struct maple_enode *enode;
+       struct maple_node *node;
+       unsigned long max;
+       unsigned long *pivots;
+       unsigned char offset, end;
+       enum maple_type type;
+       void __rcu **slots;
+
+       enode = rcu_dereference_protected(mt->ma_root, mt_locked(mt));
+
+       if (unlikely(!enode))
+               return NULL;
+
+       if (unlikely(!xa_is_node(enode))) {
+               if (addr == 0)
+                       return (void *)enode;
+
+               return NULL;
+       }
+
+       enode = mte_safe_root(enode);
+       max = ULONG_MAX;
+       do {
+               offset = 0;
+               node = mte_to_node(enode);
+               type = mte_node_type(enode);
+               pivots = ma_pivots(node, type);
+
+               if (pivots[0] >= addr)
+                       goto descend;
+
+               end = ma_data_end(node, type, pivots, max);
+               do {
+                       offset++;
+               } while ((offset < end) && (pivots[offset] < addr));
+
+descend:
+               if (pivots[offset])
+                       max = pivots[offset];
+               slots = ma_slots(node, type);
+               enode = mt_slot_locked(mt, slots, offset);
+       } while (!ma_is_leaf(type));
+
+       return (void *) enode;
+}
+EXPORT_SYMBOL_GPL(ma_peek);
+
 /**
  * mas_walk() - Search for @mas->index in the tree.
  * @mas: The maple state.
index adbf59542951b6346ceee862a7934f1634cde284..0f2874b9598010c64e9b20913260f2a127b94a8a 100644 (file)
@@ -3500,6 +3500,33 @@ static noinline void __init check_slot_iterators(struct maple_tree *mt)
        mt_set_non_kernel(0);
 }
 
+static noinline void __init check_peek(struct maple_tree *mt)
+{
+       MA_STATE(mas, mt, 0, 0);
+       unsigned long i, index = 40;
+       void *tmp;
+
+       mt_set_non_kernel(99999);
+
+       mas_lock(&mas);
+       for (i = 0; i <= index; i++) {
+               unsigned long end = 5;
+               if (i > 18 && i < 35)
+                       end = 9;
+               mas_set_range(&mas, i*10, i*10 + end);
+               mas_store_gfp(&mas, xa_mk_value(i), GFP_KERNEL);
+       }
+
+       mas_set_range(&mas, 18*10, 18*10 + 2);
+       mas_store_gfp(&mas, xa_mk_value(18), GFP_KERNEL);
+       mas_set(&mas, 0);
+       mas_for_each(&mas, tmp, ULONG_MAX)
+               MAS_BUG_ON(&mas, tmp != ma_peek(mt, mas.index));
+
+       mas_unlock(&mas);
+       mt_set_non_kernel(0);
+}
+
 static DEFINE_MTREE(tree);
 static int __init maple_tree_seed(void)
 {
@@ -3769,6 +3796,10 @@ static int __init maple_tree_seed(void)
        check_slot_iterators(&tree);
        mtree_destroy(&tree);
 
+       mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
+       check_peek(&tree);
+       mtree_destroy(&tree);
+
 #if defined(BENCH)
 skip:
 #endif