Commit a524812b authored by Wengang Wang's avatar Wengang Wang Committed by Joel Becker

ocfs2/dlm: avoid incorrect bit set in refmap on recovery master

In the following situation, there remains an incorrect bit in refmap on the
recovery master. Finally the recovery master will fail at purging the lockres
due to the incorrect bit in refmap.

1) node A has no interest on lockres A any longer, so it is purging it.
2) the owner of lockres A is node B, so node A is sending de-ref message
to node B.
3) at this time, node B crashed. node C becomes the recovery master. it recovers
lockres A(because the master is the dead node B).
4) node A migrated lockres A to node C with a refbit there.
5) node A failed to send de-ref message to node B because it crashed. The failure
is ignored. no other action is done for lockres A any more.

For mormal, re-send the deref message to it to recovery master can fix it. Well,
ignoring the failure of deref to the original master and not recovering the lockres
to recovery master has the same effect. And the later is simpler.
Signed-off-by: default avatarWengang Wang <wen.gang.wang@oracle.com>
Acked-by: default avatarSrinivas Eeda <srinivas.eeda@oracle.com>
Cc: stable@kernel.org
Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
parent 845b6cf3
...@@ -1997,6 +1997,8 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm, ...@@ -1997,6 +1997,8 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
struct list_head *queue; struct list_head *queue;
struct dlm_lock *lock, *next; struct dlm_lock *lock, *next;
assert_spin_locked(&dlm->spinlock);
assert_spin_locked(&res->spinlock);
res->state |= DLM_LOCK_RES_RECOVERING; res->state |= DLM_LOCK_RES_RECOVERING;
if (!list_empty(&res->recovering)) { if (!list_empty(&res->recovering)) {
mlog(0, mlog(0,
...@@ -2326,19 +2328,15 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) ...@@ -2326,19 +2328,15 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
/* zero the lvb if necessary */ /* zero the lvb if necessary */
dlm_revalidate_lvb(dlm, res, dead_node); dlm_revalidate_lvb(dlm, res, dead_node);
if (res->owner == dead_node) { if (res->owner == dead_node) {
if (res->state & DLM_LOCK_RES_DROPPING_REF) if (res->state & DLM_LOCK_RES_DROPPING_REF) {
mlog(0, "%s:%.*s: owned by " mlog(ML_NOTICE, "Ignore %.*s for "
"dead node %u, this node was " "recovery as it is being freed\n",
"dropping its ref when it died. " res->lockname.len,
"continue, dropping the flag.\n", res->lockname.name);
dlm->name, res->lockname.len, } else
res->lockname.name, dead_node); dlm_move_lockres_to_recovery_list(dlm,
res);
/* the wake_up for this will happen when the
* RECOVERING flag is dropped later */
res->state &= ~DLM_LOCK_RES_DROPPING_REF;
dlm_move_lockres_to_recovery_list(dlm, res);
} else if (res->owner == dlm->node_num) { } else if (res->owner == dlm->node_num) {
dlm_free_dead_locks(dlm, res, dead_node); dlm_free_dead_locks(dlm, res, dead_node);
__dlm_lockres_calc_usage(dlm, res); __dlm_lockres_calc_usage(dlm, res);
......
...@@ -92,19 +92,27 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res) ...@@ -92,19 +92,27 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res)
* truly ready to be freed. */ * truly ready to be freed. */
int __dlm_lockres_unused(struct dlm_lock_resource *res) int __dlm_lockres_unused(struct dlm_lock_resource *res)
{ {
if (!__dlm_lockres_has_locks(res) && int bit;
(list_empty(&res->dirty) && !(res->state & DLM_LOCK_RES_DIRTY))) {
/* try not to scan the bitmap unless the first two if (__dlm_lockres_has_locks(res))
* conditions are already true */ return 0;
int bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
if (bit >= O2NM_MAX_NODES) { if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY)
/* since the bit for dlm->node_num is not return 0;
* set, inflight_locks better be zero */
BUG_ON(res->inflight_locks != 0); if (res->state & DLM_LOCK_RES_RECOVERING)
return 1; return 0;
}
} bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
return 0; if (bit < O2NM_MAX_NODES)
return 0;
/*
* since the bit for dlm->node_num is not set, inflight_locks better
* be zero
*/
BUG_ON(res->inflight_locks != 0);
return 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment