Skip to contentSkip to conversation

dlm_controld: handle the case of network transient disconnection

PATCH New Eric Ren 2 participants 6 messages May 12, 2016 – May 16, 2016

lore
Share & tools
lore

Eric Ren

author
#0 lore raw

PATCH 1/1 dlm_controld: handle the case of network transient disconnection

DLM would be stuck in "need fencing" state, although cluster can regain quorum very quickly after a network transient disconnection.

It's possible that this process happens within one monoclock. It means "cluster_quorate_monotime" can eqaul "node->daemon_rem_time". We now skip this chance of telling corosync to kill cluster for stateful merge. As a result, any fencing cannot proceed further.

---
 dlm_controld/daemon_cpg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
dlm_controld/daemon_cpg.c +1 -1
index 356e80d..cd8a4e2 100644
@@ -1695,7 +1695,7 @@ static void receive_protocol(struct dlm_header *hd, int len)
 		node->stateful_merge = 1;
 
 		if (cluster_quorate && node->daemon_rem_time &&
-		    cluster_quorate_monotime < node->daemon_rem_time) {
+		    cluster_quorate_monotime <= node->daemon_rem_time) {
 			if (!node->killed) {
 				if (cluster_two_node) {
 					/*
Signature · 1 line
2.6.6
#1 lore raw

PATCH 1/1 dlm_controld: handle the case of network transient disconnection

Quoted 7 lines · Eric Ren

DLM would be stuck in "need fencing" state, although cluster can regain quorum very quickly after a network transient disconnection.

It's possible that this process happens within one monoclock. It means "cluster_quorate_monotime" can eqaul "node->daemon_rem_time". We now skip this chance of telling corosync to kill cluster for stateful merge. As a result, any fencing cannot proceed further.

Hi Eric, thanks for looking at this, it's a notoriously difficult situation to sort out. I'm not sure we have the same understanding of how the behavior will change with your patch, so let's look at an example, and please let me know if you think these examples don't match what you see (it's been quite a while since I actually tested this).

T = time in seconds, A,B,C = cluster nodes.

At T=1 A,B,C become members and have quorum.
At T=10 a partition creates A,B | C.
At T=11 it merges and creates A,B,C.

At T=12, A,B will have:
cluster_quorate=1
cluster_quorate_monotime=1
C->daemon_rem_time=10

At T=12, C will have:
cluster_quorate=1
cluster_quorate_monotime=11
A->daemon_rem_time=10
B->daemon_rem_time=10

Result:

A,B will kick C from the cluster because cluster_quorate_monotime (1) < C->daemon_rem_time (10), which is what we want.

C will not kick A,B from the cluster because cluster_quorate_monotime (11) > A->daemon_rem_time (10), which is what we want.

It's the simpler case, but does that sound right so far?

...

If the partition and merge occur within the same second, then:

At T=1 A,B,C become members and get quorum.
At T=10 a partition creates A,B | C.
At T=10 it merges and creates A,B,C.

At T=12, A,B will have:
cluster_quorate=1
cluster_quorate_monotime=1
C->daemon_rem_time=10

At T=12, C will have:
cluster_quorate=1
cluster_quorate_monotime=10
A->daemon_rem_time=10
B->daemon_rem_time=10

Result:

A,B will kick C from the cluster because cluster_quorate_monotime (1) < C->daemon_rem_time (10), which is what we want.

C will not kick A,B from the cluster because cluster_quorate_monotime (10) = A->daemon_rem_time (10), which is what we want.

If that's correct, there doesn't seem to be problem so far. If we apply your patch, won't it allow C to kick A,B from the cluster since cluster_quorate_monotime = A->daemon_rem_time?

...

If you're looking at a cluster with an equal partition, e.g. A,B | C,D, then it becomes messy because cluster_quorate_monotime = daemon_rem_time everywhere after the merge. In this case, no nodes will kick others from the cluster, but with your patch, each side will kick the other side from the cluster. Neither option is good. In the past we decided to let the cluster sit in this state so an admin could choose which nodes to remove. Do you prefer the alternative of kicking nodes in this case (with somewhat unpredictable results)? If so, we could make that an optional setting, but we'd want to keep the existing behavior for non-even partitions in the example above.

Quoted 15 lines
dlm_controld/daemon_cpg.c +1 -1
index 356e80d..cd8a4e2 100644
@@ -1695,7 +1695,7 @@ static void receive_protocol(struct dlm_header *hd, int len)
 		node->stateful_merge = 1;
 
 		if (cluster_quorate && node->daemon_rem_time &&
-		    cluster_quorate_monotime < node->daemon_rem_time) {
+		    cluster_quorate_monotime <= node->daemon_rem_time) {
 			if (!node->killed) {
 				if (cluster_two_node) {
 					/*
Signature · 1 line
2.6.6
author
#2 lore raw

PATCH 1/1 dlm_controld: handle the case of network transient disconnection

Hi David,

Thanks very very much for explaining this to me in such nice way;-)

Quoted 24 lines · David Teigland

T = time in seconds, A,B,C = cluster nodes.

At T=1 A,B,C become members and have quorum.
At T=10 a partition creates A,B | C.
At T=11 it merges and creates A,B,C.

At T=12, A,B will have:
cluster_quorate=1
cluster_quorate_monotime=1
C->daemon_rem_time=10

At T=12, C will have:
cluster_quorate=1
cluster_quorate_monotime=11
A->daemon_rem_time=10
B->daemon_rem_time=10

Result:

A,B will kick C from the cluster because cluster_quorate_monotime (1) < C->daemon_rem_time (10), which is what we want.

Quoted 5 lines

C will not kick A,B from the cluster because cluster_quorate_monotime (11) > A->daemon_rem_time (10), which is what we want.

It's the simpler case, but does that sound right so far?

Sure;-)

Quoted 25 lines

...

If the partition and merge occur within the same second, then:

At T=1 A,B,C become members and get quorum.
At T=10 a partition creates A,B | C.
At T=10 it merges and creates A,B,C.

At T=12, A,B will have:
cluster_quorate=1
cluster_quorate_monotime=1
C->daemon_rem_time=10

At T=12, C will have:
cluster_quorate=1
cluster_quorate_monotime=10
A->daemon_rem_time=10
B->daemon_rem_time=10

Result:

A,B will kick C from the cluster because cluster_quorate_monotime (1) < C->daemon_rem_time (10), which is what we want.

Quoted 7 lines

C will not kick A,B from the cluster because cluster_quorate_monotime (10) = A->daemon_rem_time (10), which is what we want.

If that's correct, there doesn't seem to be problem so far. If we apply your patch, won't it allow C to kick A,B from the cluster since cluster_quorate_monotime = A->daemon_rem_time?

Aha, yes! Also, this patch doesn't make any sense because it doesn't work if cluster_quorate_monotime (the time when network re-connected) > A->daemon_rem_time (when network disconnected) when there are 3 or more partitions that merge.

Quoted 13 lines

...

If you're looking at a cluster with an equal partition, e.g. A,B | C,D, then it becomes messy because cluster_quorate_monotime = daemon_rem_time everywhere after the merge. In this case, no nodes will kick others from the cluster, but with your patch, each side will kick the other side from the cluster. Neither option is good. In the past we decided to let the cluster sit in this state so an admin could choose which nodes to remove. Do you prefer the alternative of kicking nodes in this case (with somewhat unpredictable results)? If so, we could make that an optional setting, but we'd want to keep the existing behavior for non-even partitions in the example above.

Gotcha, thanks! But could you please elaborate a bit more on the meaning of "with somewhat unpredictable results"? IMHO, you mean some inconsistent problems may happen? or just worry about all the service would be interrupted because all nodes would be fenced?

Actually, the reason why I'm working on this problem is because the patch for this issue has been merged into pacemaker:

        [1] https://github.com/ClusterLabs/pacemaker/pull/839

Personally, I think it's a totally bad fix which makes careful thoughts and efforts of dlm_controld in vain, because it make pacemaker fence this node whenever dlm resource agent notices there's fencing going on by "dlm_tool ls | grep -q "wait fencing"", right?

This fix is for:

        [2] https://bugzilla.redhat.com/show_bug.cgi?id=1268313

We've seen unnecessary fence happens in two-node cluster with this fix. E.g. both of two nodes will be fenced when we kill corosync on one of nodes.

Thanks for your suggestion. So far, it looks like an optional setting is much better than this fix. I'd like to have a try;-)

Thanks,
Eric

Quoted 16 lines
Quoted 16 lines
dlm_controld/daemon_cpg.c +1 -2
index 356e80d..cd8a4e2 100644
@@ -1695,7 +1695,7 @@ static void receive_protocol(struct dlm_header *hd, int len)
  		node->stateful_merge = 1;
 
  		if (cluster_quorate && node->daemon_rem_time &&
-		    cluster_quorate_monotime < node->daemon_rem_time) {
+		    cluster_quorate_monotime <= node->daemon_rem_time) {
  			if (!node->killed) {
  				if (cluster_two_node) {
  					/*
--

2.6.6

#3 lore raw

PATCH 1/1 dlm_controld: handle the case of network transient disconnection

Quoted 11 lines · Eric Ren
Quoted 6 lines

the cluster. Neither option is good. In the past we decided to let the cluster sit in this state so an admin could choose which nodes to remove. Do you prefer the alternative of kicking nodes in this case (with somewhat unpredictable results)? If so, we could make that an optional setting, but we'd want to keep the existing behavior for non-even partitions in the example above.

Gotcha, thanks! But could you please elaborate a bit more on the meaning of "with somewhat unpredictable results"? IMHO, you mean some inconsistent problems may happen? or just worry about all the service would be interrupted because all nodes would be fenced?

If both sides of the merged partition are kicking the other out of the cluster at the same time, it's hard to predict which nodes will remain (and it could be none). To resolve an even partition merge, you need to remove/restart the nodes on one of the former halves, i.e. either A,B or C,D. I never thought of a way to do that automatically in this code (maybe higher level code would have more options to resolve it.)

Quoted 5 lines

Actually, the reason why I'm working on this problem is because the patch for this issue has been merged into pacemaker:

       [1] https://github.com/ClusterLabs/pacemaker/pull/839
Quoted 8 lines

Personally, I think it's a totally bad fix which makes careful thoughts and efforts of dlm_controld in vain, because it make pacemaker fence this node whenever dlm resource agent notices there's fencing going on by "dlm_tool ls | grep -q "wait fencing"", right?

This fix is for:

       [2] https://bugzilla.redhat.com/show_bug.cgi?id=1268313

"wait fencing" is normal. Reading those links, it appears the real issue was not identified before the patch was applied.

Quoted 3 lines

We've seen unnecessary fence happens in two-node cluster with this fix. E.g. both of two nodes will be fenced when we kill corosync on one of nodes.

Remove the bad fix and it should work better.

Quoted 2 lines

Thanks for your suggestion. So far, it looks like an optional setting is much better than this fix. I'd like to have a try;-)

Two node clusters are a special case of an even partition merge; I'm sure you've seen the lengthy comment about that. In a 2|2 partition merge, we don't kick any nodes from the cluster, as explained above, and it generally requires manual resolution.

But a 1|1 partition merge can sometimes be resolved automatically. Quorum can be disabled in a two node cluster, and the fencing system allowed to race between two partitioned nodes to select a survivor (there are caveats with that.) The area of code you've been looking at (with the long comment) uses the result of the fencing race to resolve the possible partition merge by kicking out the node that was fenced.

Dave

author
#4 lore raw

PATCH 1/1 dlm_controld: handle the case of network transient disconnection

Hi David,

Quoted 6 lines · David Teigland

If both sides of the merged partition are kicking the other out of the cluster at the same time, it's hard to predict which nodes will remain (and it could be none). To resolve an even partition merge, you need to remove/restart the nodes on one of the former halves, i.e. either A,B or C,D. I never thought of a way to do that automatically in this code (maybe higher level code would have more options to resolve it.)

Thanks! Hum, according to the long comments, you've handled the 2/2 even split by way of the low nodeid killing statefull merged numbers. we can do that because the "clean nodes" == "stateful nodes", right? I guess you're saying the case that there're 3 or more partitions that merge, and none could see enough clean nodes?

Yes, agree. But pacemaker guys may complain there's not enough info for them to judge where DLM is. Now DLM outputs log message like: "fence work wait to clear merge $merge_count clean $clean_count part $part_count gone $gone_count". I'm wondering if we can provide these info and how long DLM has been stuck by "dlm_tool $some_cmd"?

Also, I'm working an option (like enable_force_kick) as you suggested;-)

Quoted 3 lines

Remove the bad fix and it should work better.

Yes, will try to persuade pacemaker to drop that patch;-)

Quoted 6 lines

Two node clusters are a special case of an even partition merge; I'm sure you've seen the lengthy comment about that. In a 2|2 partition merge, we don't kick any nodes from the cluster, as explained above, and it generally requires manual resolution.

Quoted 6 lines

But a 1|1 partition merge can sometimes be resolved automatically. Quorum can be disabled in a two node cluster, and the fencing system allowed to race between two partitioned nodes to select a survivor (there are caveats with that.) The area of code you've been looking at (with the long comment) uses the result of the fencing race to resolve the possible partition merge by kicking out the node that was fenced.

Yes, I can understand this;-)

Thanks a lot!
Eric

Quoted 3 lines

Dave

#5 lore raw

PATCH 1/1 dlm_controld: handle the case of network transient disconnection

Quoted 3 lines · Eric Ren

Thanks! Hum, according to the long comments, you've handled the 2/2 even split by way of the low nodeid killing statefull merged numbers.

Interesting, I'd forgotten about that bit of code, so I was wrong to say that we do nothing after a 2/2 partition merge.

Quoted 3 lines

we can do that because the "clean nodes" == "stateful nodes", right? I guess you're saying the case that there're 3 or more partitions that merge, and none could see enough clean nodes?

That sounds about right, this is a fairly narrow special case that mainly helps in the case of two evenly split partitions. There could be some cases with more nodes and 3+ partitions where it might help.

Quoted 4 lines

Now DLM outputs log message like:
"fence work wait to clear merge $merge_count clean $clean_count part $part_count gone $gone_count". I'm wondering if we can provide these info and how long DLM has been stuck by "dlm_tool $some_cmd"?

Yes, that's a good idea. dlm_tool should clearly report if the dlm is blocked because of a stateful partition merge. Perhaps a new global variable printed by 'dlm_tool status -v'?

I'm not exactly sure of the condition when we'd set this new variable, could you try it out? For a start, maybe something similar to this:

static int stateful_merge_wait;
...

        if (!cluster_two_node && merge_count) {
                log_retry(retry_fencing, "fence work wait to clear merge %d clean %d part %d gone %d",
                          merge_count, clean_count, part_count, gone_count);

                if ((clean_count >= merge_count) && !part_count && (low == our_nodeid))
                        kick_stateful_merge_members();

+ if ((clean_count < merge_count) && !part_count)
+ stateful_merge_wait=1;

                retry = 1;
                goto out;
        }

(and added to print_state_daemon)

Dave