|
|
- commit 0fc2d46fabb2b9317daf7030162e828c7e1684d5
- Author: Christopher Faulet <cfaulet@haproxy.com>
- Date: Thu Aug 1 10:09:29 2019 +0200
-
- BUG/MEDIUM: lb-chash: Ensure the tree integrity when server weight is increased
-
- When the server weight is increased in consistant hash, extra nodes have to be
- allocated. So a realloc() is performed on the nodes array of the server. the
- previous commit 962ea7732 ("BUG/MEDIUM: lb-chash: Remove all server's entries
- before realloc() to re-insert them after") have fixed the size used during the
- realloc() to avoid segfaults. But another bug remains. After the realloc(), the
- memory area allocated for the nodes array may change, invalidating all node
- addresses in the chash tree.
-
- So, to fix the bug, we must remove all server's entries from the chash tree
- before the realloc to insert all of them after, old nodes and new ones. The
- insert will be automatically handled by the loop at the end of the function
- chash_queue_dequeue_srv().
-
- Note that if the call to realloc() failed, no new entries will be created for
- the server, so the effective server weight will be unchanged.
-
- This issue was reported on Github (#189).
-
- This patch must be backported to all versions since the 1.6.
-
- (cherry picked from commit 0a52c17f819a5b0a17718b605bdd990b9e2b58e6)
- Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
- diff --git a/src/lb_chash.c b/src/lb_chash.c
- index 0bf4e81a..23448df8 100644
- --- a/src/lb_chash.c
- +++ b/src/lb_chash.c
- @@ -84,8 +84,13 @@ static inline void chash_queue_dequeue_srv(struct server *s)
- * increased the weight beyond the original weight
- */
- if (s->lb_nodes_tot < s->next_eweight) {
- - struct tree_occ *new_nodes = realloc(s->lb_nodes, s->next_eweight * sizeof(*new_nodes));
- + struct tree_occ *new_nodes;
-
- + /* First we need to remove all server's entries from its tree
- + * because the realloc will change all nodes pointers */
- + chash_dequeue_srv(s);
- +
- + new_nodes = realloc(s->lb_nodes, s->next_eweight * sizeof(*new_nodes));
- if (new_nodes) {
- unsigned int j;
-
- @@ -494,7 +499,6 @@ void chash_init_server_tree(struct proxy *p)
- srv->lb_nodes_tot = srv->uweight * BE_WEIGHT_SCALE;
- srv->lb_nodes_now = 0;
- srv->lb_nodes = calloc(srv->lb_nodes_tot, sizeof(struct tree_occ));
- -
- for (node = 0; node < srv->lb_nodes_tot; node++) {
- srv->lb_nodes[node].server = srv;
- srv->lb_nodes[node].node.key = full_hash(srv->puid * SRV_EWGHT_RANGE + node);
|