Patch "ocfs2/dlm: fix deadlock when dispatch assert master" has been added to the 4.1-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
ocfs2/dlm: fix deadlock when dispatch assert master
to the 4.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ocfs2-dlm-fix-deadlock-when-dispatch-assert-master.patch
and it can be found in the queue-4.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
012572d4fc2e4ddd5c8ec8614d51414ec6cae02aMon Sep 17 00:00:00 2001
From: Joseph Qi <[email protected]>
Date: Tue, 22 Sep 2015 14:59:20 -0700
Subject: ocfs2/dlm: fix deadlock when dispatch assert master
From: Joseph Qi <[email protected]>
commit 012572d4fc2e4ddd5c8ec8614d51414ec6cae02a upstream.
The order of the following three spinlocks should be:dlm_domain_lock < dlm_ctxt->spinlock < dlm_lock_resource->spinlock
But dlm_dispatch_assert_master() is called while holding dlm_ctxt->spinlock and dlm_lock_resource->spinlock, and then it calls dlm_grab() which will take dlm_domain_lock.
Once another thread (for example, dlm_query_join_handler) has already taken dlm_domain_lock, and tries to take dlm_ctxt->spinlock deadlock happens.
--- fs/ocfs2/dlm/dlmmaster.c | 9 ++++++--- fs/ocfs2/dlm/dlmrecovery.c | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-)
fs/ocfs2/dlm/dlmmaster.c +6 -3
@@ -1439,6 +1439,7 @@ int dlm_master_request_handler(struct o2int found, ret;int set_maybe;int dispatch_assert =0 ; +int dispatched =0 ;if (!dlm_grab (dlm))return DLM_MASTER_RESP_NO ;
@@ -1658,15 +1659,18 @@ send_response:mlog (ML_ERROR ,"failed to dispatch assert master work\n" ); response =DLM_MASTER_RESP_ERROR ;dlm_lockres_put (res); - }else + }else { + dispatched =1 ;__dlm_lockres_grab_inflight_worker (dlm, res); + }spin_unlock (&res->spinlock); }else {if (res)dlm_lockres_put (res); } -dlm_put (dlm); +if (!dispatched) +dlm_put (dlm);return response; }
@@ -2090,7 +2094,6 @@ int dlm_dispatch_assert_master(struct dl/* queue up work for dlm_assert_master_worker */ -dlm_grab (dlm);/* get an extra ref for the work item */ dlm_init_work_item (dlm, item, dlm_assert_master_worker,NULL ); item->u.am.lockres = res;/* already have a ref */ /* can optionally ignore node numbers higher than this node */
fs/ocfs2/dlm/dlmrecovery.c +6 -2
@@ -1694,6 +1694,7 @@ int dlm_master_requery_handler(struct o2unsigned int hash;int master =DLM_LOCK_RES_OWNER_UNKNOWN ;u32 flags =DLM_ASSERT_MASTER_REQUERY ; +int dispatched =0 ;if (!dlm_grab (dlm)) {/* since the domain has gone away on this
@@ -1719,8 +1720,10 @@ int dlm_master_requery_handler(struct o2dlm_put (dlm);/* sender will take care of this and retry */ return ret; - }else + }else { + dispatched =1 ;__dlm_lockres_grab_inflight_worker (dlm, res); + }spin_unlock (&res->spinlock); }else {/* put.. incase we are not the master */
@@ -1730,7 +1733,8 @@ int dlm_master_requery_handler(struct o2 }spin_unlock (&dlm->spinlock); -dlm_put (dlm); +if (!dispatched) +dlm_put (dlm);return master; }
Patches currently in stable-queue which might be from [email protected] are
queue-4.1/ocfs2-dlm-fix-deadlock-when-dispatch-assert-master.patch