diff options
author | David Teigland <teigland@redhat.com> | 2006-10-31 12:56:08 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-11-30 10:35:16 -0500 |
commit | 2cdc98aaf072d573df10c503d3b3b0b74e2a6d06 (patch) | |
tree | c8f0ed478c6384da504026ce2668ed916b01a6af /fs/dlm/recoverd.c | |
parent | 91c0dc93a1a6bbdd79707ed311e48b4397df177f (diff) |
[DLM] fix stopping unstarted recovery
Red Hat BZ 211914
When many nodes are joining a lockspace simultaneously, the dlm gets a
quick sequence of stop/start events, a pair for adding each node.
dlm_controld in user space sends dlm_recoverd in the kernel each stop and
start event. dlm_controld will sometimes send the stop before
dlm_recoverd has had a chance to take up the previously queued start. The
stop aborts the processing of the previous start by setting the
RECOVERY_STOP flag. dlm_recoverd is erroneously clearing this flag and
ignoring the stop/abort if it happens to take up the start after the stop
meant to abort it. The fix is to check the sequence number that's
incremented for each stop/start before clearing the flag.
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/dlm/recoverd.c')
-rw-r--r-- | fs/dlm/recoverd.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 4a1d6023fd9b..6e4ee94ce7df 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c | |||
@@ -219,6 +219,10 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
219 | return error; | 219 | return error; |
220 | } | 220 | } |
221 | 221 | ||
222 | /* The dlm_ls_start() that created the rv we take here may already have been | ||
223 | stopped via dlm_ls_stop(); in that case we need to leave the RECOVERY_STOP | ||
224 | flag set. */ | ||
225 | |||
222 | static void do_ls_recovery(struct dlm_ls *ls) | 226 | static void do_ls_recovery(struct dlm_ls *ls) |
223 | { | 227 | { |
224 | struct dlm_recover *rv = NULL; | 228 | struct dlm_recover *rv = NULL; |
@@ -226,7 +230,8 @@ static void do_ls_recovery(struct dlm_ls *ls) | |||
226 | spin_lock(&ls->ls_recover_lock); | 230 | spin_lock(&ls->ls_recover_lock); |
227 | rv = ls->ls_recover_args; | 231 | rv = ls->ls_recover_args; |
228 | ls->ls_recover_args = NULL; | 232 | ls->ls_recover_args = NULL; |
229 | clear_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); | 233 | if (rv && ls->ls_recover_seq == rv->seq) |
234 | clear_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); | ||
230 | spin_unlock(&ls->ls_recover_lock); | 235 | spin_unlock(&ls->ls_recover_lock); |
231 | 236 | ||
232 | if (rv) { | 237 | if (rv) { |