ocfs2/dlm: Do not purge lockres that is queued for assert master
PATCH 1/1 ocfs2/dlm: Do not purge lockres that is queued for assert master
When workqueue is delayed, it may occured that a lockres is purged while it is still queued for master assert. it may trigger BUS() as follows.
N1 N2dlm_get_lockres()
->dlm_do_master_requery
is the master of lockres, so queue assert_master work
dlm_thread() start running and purge the lockres
dlm_assert_master_worker() send assert master message to other nodes
receiving the assert_master
message, set master to N2
dlmlock_remote() sendcreate_lock message to N2,
but receive DLM_IVLOCKID,
if it is RECOVERY lockres,
it triggers the BUG().
Another BUG() is triggered when N3 become the new master and send assert_master to N1, N1 will trigger the BUG() because owner doesn't match. So we should not purge lockres when it is queued for assert master.
--- fs/ocfs2/dlm/dlmcommon.h | 4 ++++ fs/ocfs2/dlm/dlmmaster.c | 43 ++++++++++++++++++++++++++++++++++++++++++- fs/ocfs2/dlm/dlmrecovery.c | 3 ++- fs/ocfs2/dlm/dlmthread.c | 11 +++++++---- 4 files changed, 55 insertions(+), 6 deletions(-)
fs/ocfs2/dlm/dlmcommon.h +4 -0
@@ -332,6 +332,7 @@ struct dlm_lock_resourceu16 state;char lvb[DLM_LVB_LEN ];unsigned int inflight_locks; +unsigned int inflight_assert_workers;unsigned long refmap[BITS_TO_LONGS (O2NM_MAX_NODES )]; };
@@ -911,6 +912,9 @@ void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,void dlm_lockres_grab_inflight_ref (struct dlm_ctxt *dlm,struct dlm_lock_resource *res); +void __dlm_lockres_grab_inflight_worker (struct dlm_ctxt *dlm, +struct dlm_lock_resource *res); +void dlm_queue_ast (struct dlm_ctxt *dlm,struct dlm_lock *lock);void dlm_queue_bast (struct dlm_ctxt *dlm,struct dlm_lock *lock);void __dlm_queue_ast (struct dlm_ctxt *dlm,struct dlm_lock *lock);
fs/ocfs2/dlm/dlmmaster.c +42 -1
67 lines not on this page · raw message
fs/ocfs2/dlm/dlmrecovery.c +2 -1
@@ -1708,7 +1708,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,mlog_errno (-ENOMEM );/* retry!? */ BUG (); - } + }else +__dlm_lockres_grab_inflight_worker (dlm, res); }else /* put.. incase we are not the master */ dlm_lockres_put (res);spin_unlock (&res->spinlock);
fs/ocfs2/dlm/dlmthread.c +7 -4
@@ -259,11 +259,14 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm,* refs on it. */ unused =__dlm_lockres_unused (lockres);if (!unused || - (lockres->state &DLM_LOCK_RES_MIGRATING )) { + (lockres->state &DLM_LOCK_RES_MIGRATING ) || + (lockres->inflight_assert_workers !=0 )) {mlog (0 ,"%s: res %.*s is in use or being remastered, " -"used %d, state %d\n" , dlm->name, - lockres->lockname.len, lockres->lockname.name, - !unused, lockres->state); +"used %d, state %d, assert master workers %u\n" , + dlm->name, lockres->lockname.len, + lockres->lockname.name, + !unused, lockres->state, + lockres->inflight_assert_workers);list_move_tail (&dlm->purge_list, &lockres->purge);spin_unlock (&lockres->spinlock);continue ;
Signature · 1 line
1.8.3.4