summaryrefslogtreecommitdiffstats
path: root/fs/dlm/rcom.c
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2006-11-27 20:19:28 +0100
committerSteven Whitehouse <swhiteho@redhat.com>2006-11-30 16:37:14 +0100
commit98f176fb32f33795b6d0f83856008b932123ab38 (patch)
tree0565bd70a23546469a985b93c34509f7938fbd5b /fs/dlm/rcom.c
parent[DLM] fix size of STATUS_REPLY message (diff)
downloadlinux-98f176fb32f33795b6d0f83856008b932123ab38.tar.xz
linux-98f176fb32f33795b6d0f83856008b932123ab38.zip
[DLM] don't accept replies to old recovery messages
We often abort a recovery after sending a status request to a remote node. We want to ignore any potential status reply we get from the remote node. If we get one of these unwanted replies, we've often moved on to the next recovery message and incremented the message sequence counter, so the reply will be ignored due to the seq number. In some cases, we've not moved on to the next message so the seq number of the reply we want to ignore is still correct, causing the reply to be accepted. The next recovery message will then mistake this old reply as a new one. To fix this, we add the flag RCOM_WAIT to indicate when we can accept a new reply. We clear this flag if we abort recovery while waiting for a reply. Before the flag is set again (to allow new replies) we know that any old replies will be rejected due to their sequence number. We also initialize the recovery-message sequence number to a random value when a lockspace is first created. This makes it clear when messages are being rejected from an old instance of a lockspace that has since been recreated. Signed-off-by: David Teigland <teigland@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/dlm/rcom.c')
-rw-r--r--fs/dlm/rcom.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 6ac195cec027..c42f2db6c4b4 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -90,13 +90,28 @@ static int check_config(struct dlm_ls *ls, struct rcom_config *rf, int nodeid)
return 0;
}
+static void allow_sync_reply(struct dlm_ls *ls, uint64_t *new_seq)
+{
+ spin_lock(&ls->ls_rcom_spin);
+ *new_seq = ++ls->ls_rcom_seq;
+ set_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
+ spin_unlock(&ls->ls_rcom_spin);
+}
+
+static void disallow_sync_reply(struct dlm_ls *ls)
+{
+ spin_lock(&ls->ls_rcom_spin);
+ clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
+ clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
+ spin_unlock(&ls->ls_rcom_spin);
+}
+
int dlm_rcom_status(struct dlm_ls *ls, int nodeid)
{
struct dlm_rcom *rc;
struct dlm_mhandle *mh;
int error = 0;
- memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
ls->ls_recover_nodeid = nodeid;
if (nodeid == dlm_our_nodeid()) {
@@ -108,12 +123,14 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid)
error = create_rcom(ls, nodeid, DLM_RCOM_STATUS, 0, &rc, &mh);
if (error)
goto out;
- rc->rc_id = ++ls->ls_rcom_seq;
+
+ allow_sync_reply(ls, &rc->rc_id);
+ memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
send_rcom(ls, mh, rc);
error = dlm_wait_function(ls, &rcom_response);
- clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
+ disallow_sync_reply(ls);
if (error)
goto out;
@@ -150,14 +167,20 @@ static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in)
static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
{
- if (rc_in->rc_id != ls->ls_rcom_seq) {
- log_debug(ls, "reject old reply %d got %llx wanted %llx",
- rc_in->rc_type, rc_in->rc_id, ls->ls_rcom_seq);
- return;
+ spin_lock(&ls->ls_rcom_spin);
+ if (!test_bit(LSFL_RCOM_WAIT, &ls->ls_flags) ||
+ rc_in->rc_id != ls->ls_rcom_seq) {
+ log_debug(ls, "reject reply %d from %d seq %llx expect %llx",
+ rc_in->rc_type, rc_in->rc_header.h_nodeid,
+ rc_in->rc_id, ls->ls_rcom_seq);
+ goto out;
}
memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length);
set_bit(LSFL_RCOM_READY, &ls->ls_flags);
+ clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
wake_up(&ls->ls_wait_general);
+ out:
+ spin_unlock(&ls->ls_rcom_spin);
}
static void receive_rcom_status_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
@@ -171,7 +194,6 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
struct dlm_mhandle *mh;
int error = 0, len = sizeof(struct dlm_rcom);
- memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
ls->ls_recover_nodeid = nodeid;
if (nodeid == dlm_our_nodeid()) {
@@ -185,12 +207,14 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
if (error)
goto out;
memcpy(rc->rc_buf, last_name, last_len);
- rc->rc_id = ++ls->ls_rcom_seq;
+
+ allow_sync_reply(ls, &rc->rc_id);
+ memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
send_rcom(ls, mh, rc);
error = dlm_wait_function(ls, &rcom_response);
- clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
+ disallow_sync_reply(ls);
out:
return error;
}