]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: ebtree/scope: properly tag upper nodes during insertion
authorWilly Tarreau <w@1wt.eu>
Wed, 15 Nov 2017 18:38:29 +0000 (19:38 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 15 Nov 2017 18:43:05 +0000 (19:43 +0100)
Christopher found a case where some tasks would remain unseen in the run
queue and would spontaneously appear after certain apparently unrelated
operations performed by the other thread.

It's in fact the insertion which is not correct, the node serving as the
top of duplicate tree wasn't properly updated, just like the each top of
subtree in a duplicate tree. This had the effect that after some removals,
the incorrectly tagged node would hide the underlying ones, which would
then suddenly re-appear once they were removed.

This is 1.8-specific, no backport is needed.

ebtree/eb32sctree.c

index a8a38f8ce506816fc85fb21b4dc294620702850e..e7034343504158088bf84002bda1febbf98da15d 100644 (file)
@@ -57,6 +57,8 @@ REGPRM1 struct eb32sc_node *eb32sc_insert_dup(struct eb_node *sub, struct eb_nod
                }
 
                eb32 = container_of(head, struct eb32sc_node, node);
+               if (!(eb32->node_s & scope))
+                       eb32->node_s |= scope;
        }
 
        /* Here we have a leaf attached to (head)->b[EB_RGHT] */
@@ -154,6 +156,10 @@ REGPRM2 struct eb32sc_node *eb32sc_insert(struct eb_root *root, struct eb32sc_no
                                    struct eb32sc_node, node.branches);
                old_node_bit = old->node.bit;
 
+               /* our new node will be found through this one, we must mark it */
+               if ((old->node_s | scope) != old->node_s)
+                       old->node_s |= scope;
+
                /* Stop going down when we don't have common bits anymore. We
                 * also stop in front of a duplicates tree because it means we
                 * have to insert above.
@@ -172,9 +178,6 @@ REGPRM2 struct eb32sc_node *eb32sc_insert(struct eb_root *root, struct eb32sc_no
                }
 
                /* walk down */
-               if ((old->node_s | scope) != old->node_s)
-                       old->node_s |= scope;
-
                root = &old->node.branches;
                side = (newkey >> old_node_bit) & EB_NODE_BRANCH_MASK;
                troot = root->b[side];