From: Liam R. Howlett Date: Thu, 16 Sep 2021 15:04:39 +0000 (-0400) Subject: maple_tree: Detangle part 1 of many X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=07b38a067e5444c49e0d99ef201c72ca2458a0f4;p=users%2Fjedix%2Flinux-maple.git maple_tree: Detangle part 1 of many Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 820285e3b432..27d61ce2b4f6 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -3917,16 +3917,6 @@ static inline bool mas_slot_store(struct ma_state *mas, void *entry, unsigned long lmax; /* Logical max. */ unsigned char offset = mas->offset; - if (min == mas->index && max == mas->last) { - /* exact fit. */ - rcu_assign_pointer(slots[offset], entry); - goto done; - } - - /* out of room. */ - if (unlikely(offset + 1 >= mt_slots[mt])) - return false; - if (max > mas->last) { if ((min != mas->index) || (offset != end)) goto try_node_store; @@ -3998,13 +3988,16 @@ try_node_store: */ static inline void *_mas_store(struct ma_state *mas, void *entry, bool overwrite) { - unsigned long r_max, r_min; + unsigned long r_max, r_min; /* Ranges */ + unsigned long end_piv; unsigned char end, zero; void *content = NULL; struct maple_big_node b_node; void __rcu **slots; enum maple_type mt; struct maple_node *node; + unsigned long *pivots; + unsigned char offset_end; int ret = 0; @@ -4039,32 +4032,36 @@ static inline void *_mas_store(struct ma_state *mas, void *entry, bool overwrite mas_set_err(mas, -EEXIST); return content; } + + pivots = ma_pivots(node, mt); + offset_end = mas->offset; + end_piv = r_max; + end = mas_data_end(mas); + while ((mas->last > end_piv) && (offset_end < end)) + end_piv = pivots[++offset_end]; + + if (mas->last > end_piv) + end_piv = mas->max; + + // FIXME: Try finding end offset out here and passing it through. // Maybe a struct for writes? // lmax and offset_end ? if (!entry) { - unsigned char offset_end = mas->offset; + /* Check next slot(s) if we are overwriting the end */ + if ((mas->last == end_piv) && !slots[offset_end + 1]) { + if (offset_end + 1 == end) + mas->last = mas->max; + else + mas->last = pivots[offset_end + 1]; + } else if ((mas->last > end_piv) && !slots[offset_end]) + mas->last = end_piv; if (!content) { /* If this one is null, the next and prev are not */ mas->index = r_min; - if (mas->last < r_max) - mas->last = r_max; } else { - unsigned long *pivots = ma_pivots(node, mt); - unsigned long piv = r_max; - - /* Check next slot(s) if we are overwriting the end */ - if (mas->last >= piv) { - while (mas->last >= piv && mas->last != ULONG_MAX) - piv = mas_logical_pivot(mas, pivots, - ++offset_end, mt); - - if (!slots[offset_end]) - mas->last = piv; - } - /* Check prev slot if we are overwriting the start */ if (mas->index == r_min && mas->offset && !slots[mas->offset - 1]) { @@ -4076,14 +4073,27 @@ static inline void *_mas_store(struct ma_state *mas, void *entry, bool overwrite } } - end = mas_data_end(mas); - if (mas_slot_store(mas, entry, r_min, r_max, end, content, mt, slots)) + if (r_min == mas->index && r_max == mas->last) { + rcu_assign_pointer(slots[mas->offset], entry); + if (!!entry ^ !!content) + mas_update_gap(mas); + return content; + } + + if (unlikely(mas->offset + 1 >= mt_slots[mt])) + goto slow_path; + + if ((offset_end - mas->offset <= 1) && + mas_slot_store(mas, entry, r_min, r_max, end, content, mt, slots)) return content; + else if ((mas->offset + 1 >= mt_slots[mt]) && + mas_node_store(mas, entry, r_min, r_max, end, content, mt, slots, pivots)) + return content; if (mas_is_err(mas)) return content; - /* Slow path. */ +slow_path: b_node.type = mte_node_type(mas->node); b_node.b_end = mas_store_b_node(mas, &b_node, entry, end); b_node.min = mas->min;