| From b1432a2a35565f538586774a03bf277c27fc267d Mon Sep 17 00:00:00 2001 |
| From: Junxiao Bi <junxiao.bi@oracle.com> |
| Date: Tue, 5 May 2015 16:24:02 -0700 |
| Subject: ocfs2: dlm: fix race between purge and get lock resource |
| |
| From: Junxiao Bi <junxiao.bi@oracle.com> |
| |
| commit b1432a2a35565f538586774a03bf277c27fc267d upstream. |
| |
| There is a race window in dlm_get_lock_resource(), which may return a |
| lock resource which has been purged. This will cause the process to |
| hang forever in dlmlock() as the ast msg can't be handled due to its |
| lock resource not existing. |
| |
| dlm_get_lock_resource { |
| ... |
| spin_lock(&dlm->spinlock); |
| tmpres = __dlm_lookup_lockres_full(dlm, lockid, namelen, hash); |
| if (tmpres) { |
| spin_unlock(&dlm->spinlock); |
| >>>>>>>> race window, dlm_run_purge_list() may run and purge |
| the lock resource |
| spin_lock(&tmpres->spinlock); |
| ... |
| spin_unlock(&tmpres->spinlock); |
| } |
| } |
| |
| Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com> |
| Cc: Joseph Qi <joseph.qi@huawei.com> |
| Cc: Mark Fasheh <mfasheh@suse.com> |
| Cc: Joel Becker <jlbec@evilplan.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ocfs2/dlm/dlmmaster.c | 13 +++++++++++++ |
| 1 file changed, 13 insertions(+) |
| |
| --- a/fs/ocfs2/dlm/dlmmaster.c |
| +++ b/fs/ocfs2/dlm/dlmmaster.c |
| @@ -757,6 +757,19 @@ lookup: |
| if (tmpres) { |
| spin_unlock(&dlm->spinlock); |
| spin_lock(&tmpres->spinlock); |
| + |
| + /* |
| + * Right after dlm spinlock was released, dlm_thread could have |
| + * purged the lockres. Check if lockres got unhashed. If so |
| + * start over. |
| + */ |
| + if (hlist_unhashed(&tmpres->hash_node)) { |
| + spin_unlock(&tmpres->spinlock); |
| + dlm_lockres_put(tmpres); |
| + tmpres = NULL; |
| + goto lookup; |
| + } |
| + |
| /* Wait on the thread that is mastering the resource */ |
| if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { |
| __dlm_wait_on_lockres(tmpres); |