You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

56 lines
2.5 KiB

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