ocfs2_dlm: Fix lockres ref counting bug
authorSunil Mushran <sunil.mushran@oracle.com>
Fri, 23 Mar 2007 00:01:07 +0000 (17:01 -0700)
committerMark Fasheh <mark.fasheh@oracle.com>
Mon, 26 Mar 2007 23:50:52 +0000 (16:50 -0700)
During umount, the umount thread migrates the lockres' and the dlm_thread
frees the empty lockres'. Due to a race, the reference counting on the
lockres goes awry leading to extra puts.

Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmthread.c

index 6087c4749feebf6b301e25d86a2ca8f797cd1672..dbbac184c261be180db1c68cce6bb6d5b81b9893 100644 (file)
@@ -138,8 +138,10 @@ static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm);
 
 void __dlm_unhash_lockres(struct dlm_lock_resource *lockres)
 {
-       hlist_del_init(&lockres->hash_node);
-       dlm_lockres_put(lockres);
+       if (!hlist_unhashed(&lockres->hash_node)) {
+               hlist_del_init(&lockres->hash_node);
+               dlm_lockres_put(lockres);
+       }
 }
 
 void __dlm_insert_lockres(struct dlm_ctxt *dlm,
index 6421a8fae1de50ce0f6ea4283e7f7013ec79e977..2b264c6ba039b72f7c103a05faecbea83082b4d0 100644 (file)
@@ -256,20 +256,14 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm,
                        break;
                }
 
-               mlog(0, "removing lockres %.*s:%p from purgelist\n",
-                    lockres->lockname.len, lockres->lockname.name, lockres);
-               list_del_init(&lockres->purge);
-               dlm_lockres_put(lockres);
-               dlm->purge_count--;
+               dlm_lockres_get(lockres);
 
                /* This may drop and reacquire the dlm spinlock if it
                 * has to do migration. */
-               mlog(0, "calling dlm_purge_lockres!\n");
-               dlm_lockres_get(lockres);
                if (dlm_purge_lockres(dlm, lockres))
                        BUG();
+
                dlm_lockres_put(lockres);
-               mlog(0, "DONE calling dlm_purge_lockres!\n");
 
                /* Avoid adding any scheduling latencies */
                cond_resched_lock(&dlm->spinlock);