From: Liam R. Howlett Date: Wed, 9 Dec 2020 21:59:32 +0000 (-0500) Subject: maple_tree: Rework mas_ascend() X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ad4991f51c3e94ebe880103944210c4d0fb6e113;p=users%2Fjedix%2Flinux-maple.git maple_tree: Rework mas_ascend() Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index da299ebde616..9369487497a6 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -772,62 +772,64 @@ static inline void mte_set_gap(const struct maple_enode *mn, static void mas_ascend(struct ma_state *mas) { - struct maple_enode *p_enode = mas->node; // parent enode. - struct maple_enode *a_enode = mas->node; // ancestor enode. + struct maple_enode *p_enode; // parent enode. + struct maple_enode *a_enode; // ancestor enode. struct maple_node *a_node = mas_mn(mas); // ancestor node. - unsigned char a_slot = 0; - enum maple_type a_type = mte_node_type(mas->node); - unsigned long max = 0, min = ULONG_MAX; + unsigned char a_slot; + enum maple_type a_type; + unsigned long min, max; + unsigned long *pivots; bool set_max = false, set_min = false; if (ma_is_root(a_node)) - goto no_parent; + return; a_type = mas_parent_enum(mas, mas->node); a_enode = mt_mk_node(mte_parent(mas->node), a_type); - p_enode = a_enode; - if (mte_is_root(a_enode)) - goto parent_is_root; - - mas->node = p_enode; -ascend: - a_type = mas_parent_enum(mas, mas->node); - a_node = mte_parent(mas->node); - a_slot = mte_parent_slot(mas->node); - a_enode = mt_mk_node(a_node, a_type); - if (!set_min && a_slot) { - set_min = true; - min = mte_pivot(a_enode, a_slot - 1) + 1; - } - - if (!set_max && a_slot < mt_pivots[a_type]) { - set_max = true; - max = mte_pivot(a_enode, a_slot); - } - -no_parent: - if (unlikely(ma_is_root(a_node))) { -parent_is_root: - if (!set_min) - min = 0; - if (!set_max) - max = mt_max[a_type]; + mas->node = a_enode; + if (mte_is_root(a_enode)) { + mas->max = ULONG_MAX; + mas->min = 0; + return; } - if (!max || min == ULONG_MAX) { - if (mas->node == a_enode) { + min = 0; + max = ULONG_MAX; + p_enode = a_enode; + do { + a_type = mas_parent_enum(mas, p_enode); + a_node = mte_parent(p_enode); + a_slot = mte_parent_slot(p_enode); + pivots = ma_pivots(a_node, a_type); + a_enode = mt_mk_node(a_node, a_type); + + if (unlikely(p_enode == a_enode)) { + // Dead node. pr_err("Failed on node %p (%p)\n", mas_mn(mas), a_enode); //FIXME: Restart and retry if the lock is held. - MT_BUG_ON(mas->tree, mas->node == a_enode); + MT_BUG_ON(mas->tree, p_enode == a_enode); } - mas->node = a_enode; - goto ascend; - } + + if (!set_min && a_slot) { + set_min = true; + min = pivots[a_slot - 1] + 1; + } + + if (!set_max && a_slot < mt_pivots[a_type]) { + set_max = true; + max = pivots[a_slot]; + } + + if (unlikely(ma_is_root(a_node))) { + break; + } + + p_enode = a_enode; + } while (!set_min || !set_max); mas->max = max; mas->min = min; - mas->node = p_enode; } static inline struct maple_node *mas_pop_node(struct ma_state *mas)