From e8ff433c4666c75d099e7e5eab0f569ff6285c5e Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Mon, 23 May 2016 20:23:18 +1000 Subject: [PATCH] ctdb-ipalloc: Move create_merged_ip_list() into ipalloc How the existing IP layout is constructed and how the merged IP list is sorted are important aspects of the IP allocation algorithm. Construct the merged IP list when known and available IPs are assigned. Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs --- ctdb/server/ctdb_takeover.c | 99 ++-------------------------- ctdb/server/ipalloc.c | 92 +++++++++++++++++++++++++- ctdb/tests/src/ctdb_takeover_tests.c | 2 - 3 files changed, 96 insertions(+), 97 deletions(-) diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c index b40bbadbf56..c45b218cc38 100644 --- a/ctdb/server/ctdb_takeover.c +++ b/ctdb/server/ctdb_takeover.c @@ -1129,31 +1129,6 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, bool check_addresses) return 0; } -static void *add_ip_callback(void *parm, void *data) -{ - struct public_ip_list *this_ip = parm; - struct public_ip_list *prev_ip = data; - - if (prev_ip == NULL) { - return parm; - } - if (this_ip->pnn == -1) { - this_ip->pnn = prev_ip->pnn; - } - - return parm; -} - -static int getips_count_callback(void *param, void *data) -{ - struct public_ip_list **ip_list = (struct public_ip_list **)param; - struct public_ip_list *new_ip = (struct public_ip_list *)data; - - new_ip->next = *ip_list; - *ip_list = new_ip; - return 0; -} - static struct ctdb_public_ip_list * ctdb_fetch_remote_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, @@ -1210,61 +1185,6 @@ ctdb_fetch_remote_public_ips(struct ctdb_context *ctdb, return public_ips; } -static struct public_ip_list * -create_merged_ip_list(struct ipalloc_state *ipalloc_state) -{ - int i, j; - struct public_ip_list *ip_list; - struct ctdb_public_ip_list *public_ips; - struct trbt_tree *ip_tree; - - ip_tree = trbt_create(ipalloc_state, 0); - - if (ipalloc_state->known_public_ips == NULL) { - DEBUG(DEBUG_ERR, ("Known public IPs not set\n")); - return NULL; - } - - for (i=0; i < ipalloc_state->num; i++) { - - public_ips = &ipalloc_state->known_public_ips[i]; - - for (j=0; j < public_ips->num; j++) { - struct public_ip_list *tmp_ip; - - /* This is returned as part of ip_list */ - tmp_ip = talloc_zero(ipalloc_state, struct public_ip_list); - if (tmp_ip == NULL) { - DEBUG(DEBUG_ERR, - (__location__ " out of memory\n")); - talloc_free(ip_tree); - return NULL; - } - - /* Do not use information about IP addresses hosted - * on other nodes, it may not be accurate */ - if (public_ips->ip[j].pnn == i) { - tmp_ip->pnn = public_ips->ip[j].pnn; - } else { - tmp_ip->pnn = -1; - } - tmp_ip->addr = public_ips->ip[j].addr; - tmp_ip->next = NULL; - - trbt_insertarray32_callback(ip_tree, - IP_KEYLEN, ip_key(&public_ips->ip[j].addr), - add_ip_callback, - tmp_ip); - } - } - - ip_list = NULL; - trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &ip_list); - talloc_free(ip_tree); - - return ip_list; -} - static bool all_nodes_are_disabled(struct ctdb_node_map_old *nodemap) { int i; @@ -1624,7 +1544,6 @@ static void takeover_run_process_failures(struct ctdb_context *ctdb, * - Use ipalloc_set_public_ips() to set known and available IP addresses for allocation * - If no available IP addresses then early exit - * - Build list of (known IPs, currently assigned node) * - Populate list of nodes to force rebalance - internal structure, * currently no way to fetch, only used by LCP2 for nodes that have * had new IP addresses added @@ -1717,23 +1636,15 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map_old *nodem goto ipreallocated; } - /* since nodes only know about those public addresses that - can be served by that particular node, no single node has - a full list of all public addresses that exist in the cluster. - Walk over all node structures and create a merged list of - all public addresses that exist in the cluster. - */ - all_ips = create_merged_ip_list(ipalloc_state); - if (all_ips == NULL) { - talloc_free(tmp_ctx); - return -1; - } - ipalloc_state->all_ips = all_ips; - ipalloc_state->force_rebalance_nodes = force_rebalance_nodes; /* Do the IP reassignment calculations */ ipalloc(ipalloc_state); + if (ipalloc_state->all_ips == NULL) { + talloc_free(tmp_ctx); + return -1; + } + all_ips = ipalloc_state->all_ips; /* Now tell all nodes to release any public IPs should not * host. This will be a NOOP on nodes that don't currently diff --git a/ctdb/server/ipalloc.c b/ctdb/server/ipalloc.c index fa2503db42b..d60da0315c8 100644 --- a/ctdb/server/ipalloc.c +++ b/ctdb/server/ipalloc.c @@ -19,15 +19,103 @@ along with this program; if not, see . */ +#include + #include "replace.h" #include "system/network.h" #include "lib/util/debug.h" #include "common/logging.h" +#include "common/rb_tree.h" #include "server/ipalloc_private.h" +static void *add_ip_callback(void *parm, void *data) +{ + struct public_ip_list *this_ip = parm; + struct public_ip_list *prev_ip = data; + + if (prev_ip == NULL) { + return parm; + } + if (this_ip->pnn == -1) { + this_ip->pnn = prev_ip->pnn; + } + + return parm; +} + +static int getips_count_callback(void *param, void *data) +{ + struct public_ip_list **ip_list = (struct public_ip_list **)param; + struct public_ip_list *new_ip = (struct public_ip_list *)data; + + new_ip->next = *ip_list; + *ip_list = new_ip; + return 0; +} + +/* Nodes only know about those public addresses that they are + * configured to serve and no individual node has a full list of all + * public addresses configured across the cluster. Therefore, a + * merged list of all public addresses needs to be built so that IP + * allocation can be done. */ +static struct public_ip_list * +create_merged_ip_list(struct ipalloc_state *ipalloc_state) +{ + int i, j; + struct public_ip_list *ip_list; + struct ctdb_public_ip_list *public_ips; + struct trbt_tree *ip_tree; + + ip_tree = trbt_create(ipalloc_state, 0); + + if (ipalloc_state->known_public_ips == NULL) { + DEBUG(DEBUG_ERR, ("Known public IPs not set\n")); + return NULL; + } + + for (i=0; i < ipalloc_state->num; i++) { + + public_ips = &ipalloc_state->known_public_ips[i]; + + for (j=0; j < public_ips->num; j++) { + struct public_ip_list *tmp_ip; + + /* This is returned as part of ip_list */ + tmp_ip = talloc_zero(ipalloc_state, struct public_ip_list); + if (tmp_ip == NULL) { + DEBUG(DEBUG_ERR, + (__location__ " out of memory\n")); + talloc_free(ip_tree); + return NULL; + } + + /* Do not use information about IP addresses hosted + * on other nodes, it may not be accurate */ + if (public_ips->ip[j].pnn == i) { + tmp_ip->pnn = public_ips->ip[j].pnn; + } else { + tmp_ip->pnn = -1; + } + tmp_ip->addr = public_ips->ip[j].addr; + tmp_ip->next = NULL; + + trbt_insertarray32_callback(ip_tree, + IP_KEYLEN, ip_key(&public_ips->ip[j].addr), + add_ip_callback, + tmp_ip); + } + } + + ip_list = NULL; + trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &ip_list); + talloc_free(ip_tree); + + return ip_list; +} + bool ipalloc_set_public_ips(struct ipalloc_state *ipalloc_state, struct ctdb_public_ip_list *known_ips, struct ctdb_public_ip_list *available_ips) @@ -35,7 +123,9 @@ bool ipalloc_set_public_ips(struct ipalloc_state *ipalloc_state, ipalloc_state->known_public_ips = known_ips; ipalloc_state->available_public_ips = available_ips; - return true; + ipalloc_state->all_ips = create_merged_ip_list(ipalloc_state); + + return (ipalloc_state->all_ips != NULL); } /* The calculation part of the IP allocation algorithm. */ diff --git a/ctdb/tests/src/ctdb_takeover_tests.c b/ctdb/tests/src/ctdb_takeover_tests.c index 162de2b7359..5189e252728 100644 --- a/ctdb/tests/src/ctdb_takeover_tests.c +++ b/ctdb/tests/src/ctdb_takeover_tests.c @@ -318,8 +318,6 @@ static void ctdb_test_init(const char nodestates[], tval_noiptakeover, tval_noiptakeoverondisabled); - (*ipalloc_state)->all_ips = create_merged_ip_list(*ipalloc_state); - (*ipalloc_state)->force_rebalance_nodes = NULL; } -- 2.34.1