* We set the OCFS2_LOCK_UPCONVERT_FINISHING flag before clearing
         * the OCFS2_LOCK_BUSY flag to prevent the dc thread from
         * downconverting the lock before the upconvert has fully completed.
+        * Do not prevent the dc thread from downconverting if NONBLOCK lock
+        * had already returned.
         */
-       lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
+       if (!(lockres->l_flags & OCFS2_LOCK_NONBLOCK_FINISHED))
+               lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
+       else
+               lockres_clear_flags(lockres, OCFS2_LOCK_NONBLOCK_FINISHED);
 
        lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
 }
 
 /* returns 0 if the mw that was removed was already satisfied, -EBUSY
  * if the mask still hadn't reached its goal */
-static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres,
+static int __lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres,
                                      struct ocfs2_mask_waiter *mw)
 {
-       unsigned long flags;
        int ret = 0;
 
-       spin_lock_irqsave(&lockres->l_lock, flags);
+       assert_spin_locked(&lockres->l_lock);
        if (!list_empty(&mw->mw_item)) {
                if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
                        ret = -EBUSY;
                list_del_init(&mw->mw_item);
                init_completion(&mw->mw_complete);
        }
+
+       return ret;
+}
+
+static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres,
+                                     struct ocfs2_mask_waiter *mw)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&lockres->l_lock, flags);
+       ret = __lockres_remove_mask_waiter(lockres, mw);
        spin_unlock_irqrestore(&lockres->l_lock, flags);
 
        return ret;
        unsigned long flags;
        unsigned int gen;
        int noqueue_attempted = 0;
+       int dlm_locked = 0;
 
        ocfs2_init_mask_waiter(&mw);
 
                        ocfs2_recover_from_dlm_error(lockres, 1);
                        goto out;
                }
+               dlm_locked = 1;
 
                mlog(0, "lock %s, successful return from ocfs2_dlm_lock\n",
                     lockres->l_name);
        if (wait && arg_flags & OCFS2_LOCK_NONBLOCK &&
            mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKED)) {
                wait = 0;
-               if (lockres_remove_mask_waiter(lockres, &mw))
+               spin_lock_irqsave(&lockres->l_lock, flags);
+               if (__lockres_remove_mask_waiter(lockres, &mw)) {
+                       if (dlm_locked)
+                               lockres_or_flags(lockres,
+                                       OCFS2_LOCK_NONBLOCK_FINISHED);
+                       spin_unlock_irqrestore(&lockres->l_lock, flags);
                        ret = -EAGAIN;
-               else
+               } else {
+                       spin_unlock_irqrestore(&lockres->l_lock, flags);
                        goto again;
+               }
        }
        if (wait) {
                ret = ocfs2_wait_for_mask(&mw);