summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2006-03-29 16:49:13 -0800
committerMark Fasheh <mark.fasheh@oracle.com>2006-04-07 17:39:43 -0700
commit2cd9888590c52ac7592e3607d0a3174ccd57ef86 (patch)
tree3f8ddf8bb0bb4cf1532707d613412cb98ffd9823
parentf43e6918c0e3906fd4483316f6a1a07bba615908 (diff)
downloadlinux-2cd9888590c52ac7592e3607d0a3174ccd57ef86.tar.gz
linux-2cd9888590c52ac7592e3607d0a3174ccd57ef86.tar.bz2
linux-2cd9888590c52ac7592e3607d0a3174ccd57ef86.zip
ocfs2: test and set teardown flag early in user_dlm_destroy_lock()
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
-rw-r--r--fs/ocfs2/dlm/userdlm.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c
index 808ec0527c75..74ca4e5f9765 100644
--- a/fs/ocfs2/dlm/userdlm.c
+++ b/fs/ocfs2/dlm/userdlm.c
@@ -237,9 +237,13 @@ static void user_unlock_ast(void *opaque, enum dlm_status status)
mlog(ML_ERROR, "Dlm returns status %d\n", status);
spin_lock(&lockres->l_lock);
- if (lockres->l_flags & USER_LOCK_IN_TEARDOWN)
+ /* The teardown flag gets set early during the unlock process,
+ * so test the cancel flag to make sure that this ast isn't
+ * for a concurrent cancel. */
+ if (lockres->l_flags & USER_LOCK_IN_TEARDOWN
+ && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) {
lockres->l_level = LKM_IVMODE;
- else if (status == DLM_CANCELGRANT) {
+ } else if (status == DLM_CANCELGRANT) {
mlog(0, "Lock %s, cancel fails, flags 0x%x\n",
lockres->l_name, lockres->l_flags);
/* We tried to cancel a convert request, but it was
@@ -608,6 +612,14 @@ int user_dlm_destroy_lock(struct user_lock_res *lockres)
mlog(0, "asked to destroy %s\n", lockres->l_name);
spin_lock(&lockres->l_lock);
+ if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
+ mlog(0, "Lock is already torn down\n");
+ spin_unlock(&lockres->l_lock);
+ return 0;
+ }
+
+ lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
+
while (lockres->l_flags & USER_LOCK_BUSY) {
spin_unlock(&lockres->l_lock);
@@ -633,7 +645,6 @@ int user_dlm_destroy_lock(struct user_lock_res *lockres)
lockres->l_flags &= ~USER_LOCK_ATTACHED;
lockres->l_flags |= USER_LOCK_BUSY;
- lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
spin_unlock(&lockres->l_lock);
mlog(0, "unlocking lockres %s\n", lockres->l_name);