From: Junxiao Bi <[email protected]>
Subject: ocfs2: dlm: fix race between purge and get lock resource

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 <[email protected]>
Cc: Joseph Qi <[email protected]>
Cc: Mark Fasheh <[email protected]>
Cc: Joel Becker <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
---

 fs/ocfs2/dlm/dlmmaster.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff -puN 
fs/ocfs2/dlm/dlmmaster.c~ocfs2-dlm-fix-race-between-purge-and-get-lock-resource 
fs/ocfs2/dlm/dlmmaster.c
--- 
a/fs/ocfs2/dlm/dlmmaster.c~ocfs2-dlm-fix-race-between-purge-and-get-lock-resource
+++ a/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);
_
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to