*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
/* If the start for which we're re-enabling locking (seq) has been superseded
- by a newer stop (ls_recover_seq), we need to leave locking disabled. */
+ by a newer stop (ls_recover_seq), we need to leave locking disabled.
+
+ We suspend dlm_recv threads here to avoid the race where dlm_recv a) sees
+ locking stopped and b) adds a message to the requestqueue, but dlm_recoverd
+ enables locking and clears the requestqueue between a and b. */
static int enable_locking(struct dlm_ls *ls, uint64_t seq)
{
int error = -EINTR;
+ down_write(&ls->ls_recv_active);
+
spin_lock(&ls->ls_recover_lock);
if (ls->ls_recover_seq == seq) {
set_bit(LSFL_RUNNING, &ls->ls_flags);
+ /* unblocks processes waiting to enter the dlm */
up_write(&ls->ls_in_recovery);
error = 0;
}
spin_unlock(&ls->ls_recover_lock);
+
+ up_write(&ls->ls_recv_active);
return error;
}
error = dlm_recover_members(ls, rv, &neg);
if (error) {
- log_error(ls, "recover_members failed %d", error);
+ log_debug(ls, "recover_members failed %d", error);
goto fail;
}
start = jiffies;
error = dlm_recover_directory(ls);
if (error) {
- log_error(ls, "recover_directory failed %d", error);
+ log_debug(ls, "recover_directory failed %d", error);
goto fail;
}
error = dlm_recover_directory_wait(ls);
if (error) {
- log_error(ls, "recover_directory_wait failed %d", error);
+ log_debug(ls, "recover_directory_wait failed %d", error);
goto fail;
}
error = dlm_recover_masters(ls);
if (error) {
- log_error(ls, "recover_masters failed %d", error);
+ log_debug(ls, "recover_masters failed %d", error);
goto fail;
}
error = dlm_recover_locks(ls);
if (error) {
- log_error(ls, "recover_locks failed %d", error);
+ log_debug(ls, "recover_locks failed %d", error);
goto fail;
}
error = dlm_recover_locks_wait(ls);
if (error) {
- log_error(ls, "recover_locks_wait failed %d", error);
+ log_debug(ls, "recover_locks_wait failed %d", error);
goto fail;
}
error = dlm_recover_locks_wait(ls);
if (error) {
- log_error(ls, "recover_locks_wait failed %d", error);
+ log_debug(ls, "recover_locks_wait failed %d", error);
goto fail;
}
}
dlm_set_recover_status(ls, DLM_RS_DONE);
error = dlm_recover_done_wait(ls);
if (error) {
- log_error(ls, "recover_done_wait failed %d", error);
+ log_debug(ls, "recover_done_wait failed %d", error);
goto fail;
}
dlm_clear_members_gone(ls);
+ dlm_adjust_timeouts(ls);
+
error = enable_locking(ls, rv->seq);
if (error) {
- log_error(ls, "enable_locking failed %d", error);
+ log_debug(ls, "enable_locking failed %d", error);
goto fail;
}
error = dlm_process_requestqueue(ls);
if (error) {
- log_error(ls, "process_requestqueue failed %d", error);
+ log_debug(ls, "process_requestqueue failed %d", error);
goto fail;
}
error = dlm_recover_waiters_post(ls);
if (error) {
- log_error(ls, "recover_waiters_post failed %d", error);
+ log_debug(ls, "recover_waiters_post failed %d", error);
goto fail;
}