maple_tree: add bulk parent set helper

Instead of calculating the parent pointer each time for a child, cache the
majority of the parent pointer and only change the slot per child.

Drop the mas_set_parent() function since the last user has been removed.

Testing on a tree containing 2048 entries of height 4 had an increased
gain of 3.51% on nodes tracking gaps.

Link: https://lore.kernel.org/20260821192627.4085470-12-liam@infradead.org
Signed-off-by: Liam R. Howlett (Oracle) <liam@infradead.org>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Breno Leitao <leitao@debian.org>
Cc: Chris Mason <clm@meta.com>
Cc: Chuck Lever <cel@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Joe Perches <joe@perches.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@surriel.com>
Cc: Waiman Long <longman@redhat.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Liam R. Howlett (Oracle)
2026-08-21 15:26:19 -04:00
committed by Andrew Morton
parent f0a3892cd7
commit cf1f9bae5d

View File

@@ -450,46 +450,6 @@ enum maple_type mas_parent_type(struct ma_state *mas, struct maple_enode *enode)
return 0;
}
/*
* mas_set_parent() - Set the parent node and encode the slot
* @mas: The maple state
* @enode: The encoded maple node.
* @parent: The encoded maple node that is the parent of @enode.
* @slot: The slot that @enode resides in @parent.
*
* Slot number is encoded in the enode->parent bit 3-6 or 2-6, depending on the
* parent type.
*/
static inline
void mas_set_parent(struct ma_state *mas, struct maple_enode *enode,
const struct maple_enode *parent, unsigned char slot)
{
unsigned long val = (unsigned long)parent;
unsigned long shift;
unsigned long type;
enum maple_type p_type = mte_node_type(parent);
MAS_BUG_ON(mas, p_type == maple_dense);
MAS_BUG_ON(mas, p_type == maple_leaf_64);
switch (p_type) {
case maple_range_64:
case maple_arange_64:
shift = MAPLE_PARENT_SLOT_SHIFT;
type = MAPLE_PARENT_RANGE64;
break;
default:
case maple_dense:
case maple_leaf_64:
shift = type = 0;
break;
}
val &= ~MAPLE_NODE_MASK; /* Clear all node metadata in parent */
val |= (slot << shift) | type;
mte_to_node(enode)->parent = ma_parent_ptr(val);
}
/*
* mte_parent_slot() - get the parent slot of @enode.
* @enode: The encoded maple node.
@@ -871,6 +831,42 @@ static inline void ma_set_meta_gap(struct maple_node *mn, enum maple_type mt,
meta->gap = offset;
}
/*
* mas_set_parent_slots() - Bulk operation to set many slot parent pointers
* @mas: The maple state
* @parent: The encoded maple node that is the parent of @enode.
* @slot: The slot that of the @enode.
* @start_slot: The offset into @slot
* @count: The number of slots to set (eg: exclusive)
*/
static inline
void mas_set_parent_slots(struct ma_state *mas, struct maple_enode *parent,
void __rcu **slots, unsigned char start_slot, unsigned char count)
{
unsigned long val;
unsigned long shift;
unsigned long type;
enum maple_type p_type = mte_node_type(parent);
unsigned char i;
MAS_BUG_ON(mas, p_type != maple_range_64 &&
p_type != maple_arange_64);
shift = MAPLE_PARENT_SLOT_SHIFT;
type = MAPLE_PARENT_RANGE64;
val = (unsigned long)parent;
val &= ~MAPLE_NODE_MASK;
for (i = 0; i < count; i++) {
unsigned long pval = val | ((start_slot + i) << shift) | type;
struct maple_enode *child;
child = mt_slot_locked(mas->tree, slots, i);
mte_to_node(child)->parent = ma_parent_ptr(pval);
}
}
/*
* mat_add() - Add a @dead_enode to the ma_topiary of a list of dead nodes.
* @mat: the ma_topiary, a linked list of dead nodes.
@@ -1609,14 +1605,10 @@ static inline void mas_adopt_children(struct ma_state *mas,
struct maple_node *node = mte_to_node(parent);
void __rcu **slots = ma_slots(node, type);
unsigned long *pivots = ma_pivots(node, type);
struct maple_enode *child;
unsigned char offset;
unsigned char end;
offset = ma_data_end(node, type, pivots, mas->max);
do {
child = mas_slot_locked(mas, slots, offset);
mas_set_parent(mas, child, parent, offset);
} while (offset--);
end = ma_data_end(node, type, pivots, mas->max);
mas_set_parent_slots(mas, parent, slots, 0, end + 1);
}
/*
@@ -1998,15 +1990,10 @@ unsigned long node_copy(struct ma_state *mas, struct maple_node *src,
s_slots = ma_slots(src, s_mt) + start;
s_pivots = ma_pivots(src, s_mt) + start;
memcpy(d_slots, s_slots, size * sizeof(void __rcu *));
if (!ma_is_leaf(d_mt) && s_mt == maple_copy) {
struct maple_enode *edst = mt_mk_node(dst, d_mt);
for (int i = 0; i < size; i++)
mas_set_parent(mas,
mt_slot_locked(mas->tree, d_slots, i),
edst, d_start + i);
}
if (!ma_is_leaf(d_mt) && s_mt == maple_copy)
mas_set_parent_slots(mas, mt_mk_node(dst, d_mt),
d_slots, d_start, size);
d_gaps = ma_gaps(dst, d_mt);
if (d_gaps) {