Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
[powerpc.git] / fs / dlm / user.c
index 1f05960..c37e93e 100644 (file)
@@ -133,6 +133,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
        struct dlm_ls *ls;
        struct dlm_user_args *ua;
        struct dlm_user_proc *proc;
+       int remove_ownqueue = 0;
 
        /* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each
           lkb before dealing with it.  We need to check this
@@ -171,6 +172,14 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
                wake_up_interruptible(&proc->wait);
        }
 
+       /* noqueue requests that fail may need to be removed from the
+          proc's locks list, there should be a better way of detecting
+          this situation than checking all these things... */
+
+       if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV &&
+           ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue))
+               remove_ownqueue = 1;
+
        /* We want to copy the lvb to userspace when the completion
           ast is read if the status is 0, the lock has an lvb and
           lvb_ops says we should.  We could probably have set_lvb_lock()
@@ -185,6 +194,13 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
                ua->update_user_lvb = 0;
 
        spin_unlock(&proc->asts_spin);
+
+       if (remove_ownqueue) {
+               spin_lock(&ua->proc->locks_spin);
+               list_del_init(&lkb->lkb_ownqueue);
+               spin_unlock(&ua->proc->locks_spin);
+               dlm_put_lkb(lkb);
+       }
  out:
        mutex_unlock(&ls->ls_clear_proc_locks);
 }
@@ -309,7 +325,7 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
 {
        dlm_lockspace_t *lockspace;
        struct dlm_ls *ls;
-       int error;
+       int error, force = 0;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -325,6 +341,9 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
        }
        kfree(ls->ls_device.name);
 
+       if (params->flags & DLM_USER_LSFLG_FORCEFREE)
+               force = 2;
+
        lockspace = ls->ls_local_handle;
 
        /* dlm_release_lockspace waits for references to go to zero,
@@ -332,8 +351,8 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
           before the release will procede */
 
        dlm_put_lockspace(ls);
-       error = dlm_release_lockspace(lockspace, 0);
-out:
+       error = dlm_release_lockspace(lockspace, force);
+ out:
        return error;
 }