cluster: RHEL6 - fenced: fix handling of startup partition merge

David Teigland teigland at fedoraproject.org
Thu Mar 1 22:08:44 UTC 2012


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=5457043e975ba4c44c17138b3751150b974aa35c
Commit:        5457043e975ba4c44c17138b3751150b974aa35c
Parent:        af612b16a8b565a0e3543850367e0b58a43922cd
Author:        David Teigland <teigland at redhat.com>
AuthorDate:    Mon Oct 31 12:06:41 2011 -0500
Committer:     David Teigland <teigland at redhat.com>
CommitterDate: Thu Mar 1 16:07:29 2012 -0600

fenced: fix handling of startup partition merge

The victims created on each side of a partition are cleared after
a merge in the receive_complete function, which is meant to clear
"initial victims".  Clearing the victims is the correct end result,
but the code arrives there through an unintended shortcut.  Change
the code so it clears the victims in a "more correct", and probably
safer way:

2 is blocked doing startup fencing
1 joins fence domain
partition between 1,2
1 sees confchg for partition, adds victim 2 (and sets init_victim
  per this patch, since 1 hasn't finished a start cycle yet)
partition removed
2 completes startup fencing
2 sees confchg for partition, adds victim 1
1 sees confchg for merge, adds node 2
2 sees confchg for merge, adds node 1
1 processing the merge confchg
2 reduces victim 1 from partition, since 1 had no state (had not yet
  completed a start cycle)
2 processing the merge confchg
1,2 finish start cycle for merge confchg
2 sends complete for merge confchg
1 clears victim 2 in receive_complete because it set init_victim

bz 750314

Signed-off-by: David Teigland <teigland at redhat.com>
---
 fence/fenced/cpg.c |   36 ++++++++++++++++++++++++++++++++++--
 1 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/fence/fenced/cpg.c b/fence/fenced/cpg.c
index 99e16a0..6634f8c 100644
--- a/fence/fenced/cpg.c
+++ b/fence/fenced/cpg.c
@@ -1132,8 +1132,11 @@ static void receive_complete(struct fd *fd, struct fd_header *hd, int len)
 	list_for_each_entry_safe(node, safe, &fd->victims, list) {
 		log_debug("receive_complete clear victim nodeid %d init %d",
 			  node->nodeid, node->init_victim);
-		list_del(&node->list);
-		free(node);
+
+		if (node->init_victim) {
+			list_del(&node->list);
+			free(node);
+		}
 	}
 }
 
@@ -1319,6 +1322,35 @@ static void add_victims(struct fd *fd, struct change *cg)
 			return;
 		list_add(&node->list, &fd->victims);
 		log_debug("add_victims node %d", node->nodeid);
+
+		/*
+		 * If we haven't completed a start cycle yet, set
+		 * init_victim on any failed node so that receive_complete
+		 * will clear it.  This is a hack for one specific scenario:
+		 *
+		 * - node 2 joins domain, blocks in startup fencing
+		 * - node 1 joins domain, waiting for messages in start cycle
+		 * - partition between 1,2
+		 * - 1 adds victim 2
+		 *   (and sets init_victim below since 1 hasn't completed
+		 *    a start cycle yet)
+		 * - partition removed
+		 * - node 2 completes startup fencing
+		 * - 2 gets confchg for partition
+		 * - 2 adds victim 1 (due to partition)
+		 * - 2 gets confchg for merge
+		 * - 2 does join for 1 (due to merge), begins start cycle
+		 * - start cycle adding node 1 finishes, 2 sends complete
+		 * - 2 reduces victim 1
+		 * - 1 receives complete for its join start cycle,
+		 *   and clears victim 2 because we've set init_victim here
+		 */
+
+		if (!fd->started_count) {
+			log_debug("add_victims node %d set init_victim",
+				  node->nodeid);
+			node->init_victim = 1;
+		}
 	}
 }
 


More information about the cluster-commits mailing list