[Ocfs2-devel] [PATCH] ocfs2: resend master request when lost connection with someone

Xue jiufei xuejiufei at huawei.com
Fri Dec 21 23:00:33 PST 2012


  Function dlm_get_lock_resource() sends master request to all nodes in
domain_map and waits for their responses when the node(say nodeA) doesn't
known who the master is. 
  When nodeA sends the master request, it happened that network of
nodeB down for a while, and then restore. The master request
from nodeA does not reach nodeB. NodeA may wait again and again in
dlm_wait_for_lock_mastery() and never returns.
  This patch resend the mater request when a node lost connection with
some other nodes.

Signed-off-by: xuejiufei <xuejiufei at huawei.com>
---
 fs/ocfs2/dlm/dlmmaster.c |   41 +++++++++++++++++++++++++++++++++++------
 1 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index c491f97..2a99a95 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -106,7 +106,7 @@ static int dlm_do_master_request(struct dlm_lock_resource *res,
 static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm,
 				     struct dlm_lock_resource *res,
 				     struct dlm_master_list_entry *mle,
-				     int *blocked);
+				     int *blocked, int *retry, int host_down);
 static int dlm_restart_lock_mastery(struct dlm_ctxt *dlm,
 				    struct dlm_lock_resource *res,
 				    struct dlm_master_list_entry *mle,
@@ -712,6 +712,8 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
 	unsigned int hash;
 	int tries = 0;
 	int bit, wait_on_recovery = 0;
+	int retry = 0;
+	unsigned long down_nodemap[BITS_TO_LONGS(O2NM_MAX_NODES)];
 
 	BUG_ON(!lockid);
 
@@ -910,11 +912,25 @@ redo_request:
 		goto wait;
 
 	ret = -EINVAL;
-	dlm_node_iter_init(mle->vote_map, &iter);
+	if (!retry)
+		dlm_node_iter_init(mle->vote_map, &iter);
+	else {
+		mlog(0, "%s:%.*s: retrying, send master request to maybe down node\n",
+				dlm->name, res->lockname.len, res->lockname.name);
+		dlm_node_iter_init(down_nodemap, &iter);
+	}
+	memset(down_nodemap, 0, sizeof(down_nodemap));
+
 	while ((nodenum = dlm_node_iter_next(&iter)) >= 0) {
 		ret = dlm_do_master_request(res, mle, nodenum);
-		if (ret < 0)
+		if (ret < 0) {
 			mlog_errno(ret);
+			if (dlm_is_host_down(ret)) {
+				mlog(0, "%s:%.*s: node %u maybe dead, set down_nodemap\n",
+						dlm->name, res->lockname.len, res->lockname.name, nodenum);
+				set_bit(nodenum, down_nodemap);
+			}
+		}
 		if (mle->master != O2NM_MAX_NODES) {
 			/* found a master ! */
 			if (mle->master <= nodenum)
@@ -931,9 +947,11 @@ redo_request:
 
 wait:
 	/* keep going until the response map includes all nodes */
-	ret = dlm_wait_for_lock_mastery(dlm, res, mle, &blocked);
+	ret = dlm_wait_for_lock_mastery(dlm, res, mle, &blocked, &retry,
+			find_next_bit(down_nodemap, O2NM_MAX_NODES, 0) < O2NM_MAX_NODES);
 	if (ret < 0) {
-		wait_on_recovery = 1;
+		if (!retry)
+			wait_on_recovery = 1;
 		mlog(0, "%s: res %.*s, Node map changed, redo the master "
 		     "request now, blocked=%d\n", dlm->name, res->lockname.len,
 		     res->lockname.name, blocked);
@@ -980,7 +998,7 @@ leave:
 static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm,
 				     struct dlm_lock_resource *res,
 				     struct dlm_master_list_entry *mle,
-				     int *blocked)
+				     int *blocked, int *retry, int host_down)
 {
 	u8 m;
 	int ret, bit;
@@ -990,6 +1008,7 @@ static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm,
 recheck:
 	ret = 0;
 	assert = 0;
+	*retry = 0;
 
 	/* check if another node has already become the owner */
 	spin_lock(&res->spinlock);
@@ -1043,6 +1062,16 @@ recheck:
 		     res->lockname.name);
 		goto recheck;
 	} else {
+		if (host_down && (m == O2NM_MAX_NODES)) {
+			mlog(0, "map not changed but some one may lost connection, "
+					"rechecking\n");
+			*retry = 1;
+			spin_unlock(&mle->spinlock);
+			msleep(DLM_NODE_DEATH_WAIT_MAX);
+			ret = -EAGAIN;
+			goto leave;
+		}
+
 		if (!voting_done) {
 			mlog(0, "map not changed and voting not done "
 			     "for %s:%.*s\n", dlm->name, res->lockname.len,
-- 
1.7.8.6



More information about the Ocfs2-devel mailing list