]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Rework mas_ascend()
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Wed, 9 Dec 2020 21:59:32 +0000 (16:59 -0500)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Tue, 5 Jan 2021 17:33:36 +0000 (12:33 -0500)
Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
lib/maple_tree.c

index da299ebde6164c8e040c4afe8ba8de11ecd24735..9369487497a6bdf17cf47bc9a0c46cc1282c9624 100644 (file)
@@ -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)