[SCM] CTDB repository - branch 1.2.39 updated - ctdb-1.9.1-493-g2f73114

Ronnie Sahlberg sahlberg at samba.org
Wed Feb 15 16:23:28 MST 2012


The branch, 1.2.39 has been updated
       via  2f73114265b6523d6ceed54e70fd042c3738c6a2 (commit)
       via  91028144aa281a8f2ee915048c7c35d6c8a1d8df (commit)
       via  d9579c2971659f1ebc218a339d28f15132dd5718 (commit)
      from  0a626cef2547bbd3ea5c80da5ee2fb65691e0d88 (commit)

http://gitweb.samba.org/?p=ctdb.git;a=shortlog;h=1.2.39


- Log -----------------------------------------------------------------
commit 2f73114265b6523d6ceed54e70fd042c3738c6a2
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Tue Feb 14 12:21:09 2012 +1100

    New version 1.2.39-2
    
    This version contains one single change:
    Fix ip reallocation for LCP2 where it sometimes resulted
    in poor balancing of the addresses across the nodes.
    
    S1032414

commit 91028144aa281a8f2ee915048c7c35d6c8a1d8df
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Nov 1 20:52:57 2011 +1100

    LCP IP allocation algorithm - try harder to find a candidate source node
    
    There's a bug in LCP2.  Selecting the node with the highest imbalance
    doesn't always work.  Some nodes can have a high imbalance metric
    because they have a lot of IPs.  However, these nodes can be part of a
    group that is perfectly balanced.  Nodes in another group with less
    IPs might actually be imbalanced.
    
    Instead of just trying the source node with the highest imbalance this
    tries them in descending order of imbalance until it finds one where
    an IP can be moved to another node.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>

commit d9579c2971659f1ebc218a339d28f15132dd5718
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Nov 1 19:49:38 2011 +1100

    LCP IP allocation algorithm - new function lcp2_failback_candidate()
    
    There's a bug in LCP2.  Selecting the node with the highest imbalance
    doesn't always work.  Some nodes can have a high imbalance metric
    because they have a lot of IPs.  However, these nodes can be part of a
    group that is perfectly balanced.  Nodes in another group with less
    IPs might actually be imbalanced.
    
    Factor out the code from lcp2_failback() that actually takes a node
    and decides which address should be moved to which node.
    
    This is the first step in fixing the above bug.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>

-----------------------------------------------------------------------

Summary of changes:
 packaging/RPM/ctdb.spec.in |    4 +-
 server/ctdb_takeover.c     |  150 ++++++++++++++++++++++++++++++--------------
 2 files changed, 106 insertions(+), 48 deletions(-)


Changeset truncated at 500 lines:

diff --git a/packaging/RPM/ctdb.spec.in b/packaging/RPM/ctdb.spec.in
index 08719d0..7dd61bf 100644
--- a/packaging/RPM/ctdb.spec.in
+++ b/packaging/RPM/ctdb.spec.in
@@ -4,7 +4,7 @@ Summary: Clustered TDB
 Vendor: Samba Team
 Packager: Samba Team <samba at samba.org>
 Version: 1.2.39
-Release: 1GITHASH
+Release: 2GITHASH
 Epoch: 0
 License: GNU GPL version 3
 Group: System Environment/Daemons
@@ -144,6 +144,8 @@ development libraries for ctdb
 %{_libdir}/libctdb.a
 
 %changelog
+* Tue Feb 14 2012 : Version 1.2.39-2
+ - Fix for ip reallocation bug resulting in poor istribution of addresses
 * Thu Nov 17 2011 : Version 1.2.39
  - Handle canceled monitor events better, dont assume they are always status==OK
 * Mon Oct 17 2011 : Version 1.2.38
diff --git a/server/ctdb_takeover.c b/server/ctdb_takeover.c
index 5865a17..b2e1a8d 100644
--- a/server/ctdb_takeover.c
+++ b/server/ctdb_takeover.c
@@ -1607,57 +1607,26 @@ void lcp2_allocate_unassigned(struct ctdb_context *ctdb,
 	}
 }
 
-/* LCP2 algorithm for rebalancing the cluster.  This finds the source
- * node with the highest LCP2 imbalance, and then determines the best
- * IP/destination node combination to move from the source node.
+/* LCP2 algorithm for rebalancing the cluster.  Given a candidate node
+ * to move IPs from, determines the best IP/destination node
+ * combination to move from the source node.
  *
  * Not static, so we can easily link it into a unit test.
  */
-bool lcp2_failback(struct ctdb_context *ctdb,
-		   struct ctdb_node_map *nodemap,
-		   uint32_t mask,
-		   struct ctdb_public_ip_list *all_ips,
-		   uint32_t *lcp2_imbalances,
-		   bool *newly_healthy)
-{
-	int srcnode, dstnode, mindstnode, i, num_newly_healthy;
-	uint32_t srcimbl, srcdsum, maximbl, dstimbl, dstdsum;
-	uint32_t minsrcimbl, mindstimbl, b;
+bool lcp2_failback_candidate(struct ctdb_context *ctdb,
+			     struct ctdb_node_map *nodemap,
+			     struct ctdb_public_ip_list *all_ips,
+			     int srcnode,
+			     uint32_t candimbl,
+			     uint32_t *lcp2_imbalances,
+			     bool *newly_healthy)
+{
+	int dstnode, mindstnode;
+	uint32_t srcimbl, srcdsum, dstimbl, dstdsum;
+	uint32_t minsrcimbl, mindstimbl;
 	struct ctdb_public_ip_list *minip;
 	struct ctdb_public_ip_list *tmp_ip;
 
-	/* It is only worth continuing if we have suitable target
-	 * nodes to transfer IPs to.  This check is much cheaper than
-	 * continuing on...
-	 */
-	num_newly_healthy = 0;
-	for (i = 0; i < nodemap->num; i++) {
-		if (newly_healthy[i]) {
-			num_newly_healthy++;
-		}
-	}
-	if (num_newly_healthy == 0) {
-		return false;
-	}
-
-        /* Get the node with the highest imbalance metric. */
-        srcnode = -1;
-        maximbl = 0;
-	for (i=0; i < nodemap->num; i++) {
-		b = lcp2_imbalances[i];
-		if ((srcnode == -1) || (b > maximbl)) {
-			srcnode = i;
-			maximbl = b;
-		}
-	}
-
-        /* This means that all nodes had 0 or 1 addresses, so can't be
-	 * imbalanced.
-	 */
-        if (maximbl == 0) {
-		return false;
-	}
-
 	/* Find an IP and destination node that best reduces imbalance. */
 	minip = NULL;
 	minsrcimbl = 0;
@@ -1665,7 +1634,7 @@ bool lcp2_failback(struct ctdb_context *ctdb,
 	mindstimbl = 0;
 
 	DEBUG(DEBUG_DEBUG,(" ----------------------------------------\n"));
-	DEBUG(DEBUG_DEBUG,(" CONSIDERING MOVES FROM %d [%d]\n", srcnode, maximbl));
+	DEBUG(DEBUG_DEBUG,(" CONSIDERING MOVES FROM %d [%d]\n", srcnode, candimbl));
 
 	for (tmp_ip=all_ips; tmp_ip; tmp_ip=tmp_ip->next) {
 		/* Only consider addresses on srcnode. */
@@ -1675,7 +1644,7 @@ bool lcp2_failback(struct ctdb_context *ctdb,
 
 		/* What is this IP address costing the source node? */
 		srcdsum = ip_distance_2_sum(&(tmp_ip->addr), all_ips, srcnode);
-		srcimbl = maximbl - srcdsum;
+		srcimbl = candimbl - srcdsum;
 
 		/* Consider this IP address would cost each potential
 		 * destination node.  Destination nodes are limited to
@@ -1700,7 +1669,7 @@ bool lcp2_failback(struct ctdb_context *ctdb,
 					   ctdb_addr_to_str(&(tmp_ip->addr)),
 					   dstnode, dstimbl - lcp2_imbalances[dstnode]));
 
-			if ((dstimbl < maximbl) && (dstdsum < srcdsum) && \
+			if ((dstimbl < candimbl) && (dstdsum < srcdsum) && \
 			    ((mindstnode == -1) ||				\
 			     ((srcimbl + dstimbl) < (minsrcimbl + mindstimbl)))) {
 
@@ -1732,6 +1701,93 @@ bool lcp2_failback(struct ctdb_context *ctdb,
 	
 }
 
+struct lcp2_imbalance_pnn {
+	uint32_t imbalance;
+	int pnn;
+};
+
+int lcp2_cmp_imbalance_pnn(const void * a, const void * b)
+{
+	const struct lcp2_imbalance_pnn * lipa = (const struct lcp2_imbalance_pnn *) a;
+	const struct lcp2_imbalance_pnn * lipb = (const struct lcp2_imbalance_pnn *) b;
+
+	if (lipa->imbalance > lipb->imbalance) {
+		return -1;
+	} else if (lipa->imbalance == lipb->imbalance) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+/* LCP2 algorithm for rebalancing the cluster.  This finds the source
+ * node with the highest LCP2 imbalance, and then determines the best
+ * IP/destination node combination to move from the source node.
+ *
+ * Not static, so we can easily link it into a unit test.
+ */
+bool lcp2_failback(struct ctdb_context *ctdb,
+		   struct ctdb_node_map *nodemap,
+		   uint32_t mask,
+		   struct ctdb_public_ip_list *all_ips,
+		   uint32_t *lcp2_imbalances,
+		   bool *newly_healthy)
+{
+	int i, num_newly_healthy;
+	struct lcp2_imbalance_pnn * lips;
+	bool ret;
+
+	/* It is only worth continuing if we have suitable target
+	 * nodes to transfer IPs to.  This check is much cheaper than
+	 * continuing on...
+	 */
+	num_newly_healthy = 0;
+	for (i = 0; i < nodemap->num; i++) {
+		if (newly_healthy[i]) {
+			num_newly_healthy++;
+		}
+	}
+	if (num_newly_healthy == 0) {
+		return false;
+	}
+
+	/* Put the imbalances and nodes into an array, sort them and
+	 * iterate through candidates.  Usually the 1st one will be
+	 * used, so this doesn't cost much...
+	 */
+	lips = talloc_array(ctdb, struct lcp2_imbalance_pnn, nodemap->num);
+	for (i = 0; i < nodemap->num; i++) {
+		lips[i].imbalance = lcp2_imbalances[i];
+		lips[i].pnn = i;
+	}
+	qsort(lips, nodemap->num, sizeof(struct lcp2_imbalance_pnn),
+	      lcp2_cmp_imbalance_pnn);
+
+	ret = false;
+	for (i = 0; i < nodemap->num; i++) {
+		/* This means that all nodes had 0 or 1 addresses, so
+		 * can't be imbalanced.
+		 */
+		if (lips[i].imbalance == 0) {
+			break;
+		}
+
+		if (lcp2_failback_candidate(ctdb,
+					    nodemap,
+					    all_ips,
+					    lips[i].pnn,
+					    lips[i].imbalance,
+					    lcp2_imbalances,
+					    newly_healthy)) {
+			ret = true;
+			break;
+		}
+	}
+
+	talloc_free(lips);
+	return ret;
+}
+
 /* The calculation part of the IP allocation algorithm.
  * Not static, so we can easily link it into a unit test.
  */


-- 
CTDB repository


More information about the samba-cvs mailing list