size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
 
        mutex_lock(&debug_buf_lock);
+       ret = dlm_lock_recovery_try(ls);
+       if (!ret) {
+               rv = -EAGAIN;
+               goto out;
+       }
+
        mutex_lock(&ls->ls_waiters_mutex);
        memset(debug_buf, 0, sizeof(debug_buf));
 
                pos += ret;
        }
        mutex_unlock(&ls->ls_waiters_mutex);
+       dlm_unlock_recovery(ls);
 
        rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
+out:
        mutex_unlock(&debug_buf_lock);
        return rv;
 }
        if (n != 3)
                return -EINVAL;
 
+       error = dlm_lock_recovery_try(ls);
+       if (!error)
+               return -EAGAIN;
+
        error = dlm_debug_add_lkb_to_waiters(ls, lkb_id, mstype, to_nodeid);
+       dlm_unlock_recovery(ls);
        if (error)
                return error;
 
 
 
 /* Threads cannot use the lockspace while it's being recovered */
 
-static inline void dlm_lock_recovery(struct dlm_ls *ls)
+void dlm_lock_recovery(struct dlm_ls *ls)
 {
        down_read(&ls->ls_in_recovery);
 }
 }
 
 /* Handles situations where we might be processing a "fake" or "local" reply in
-   which we can't try to take waiters_mutex again. */
+ * the recovery context which stops any locking activity. Only debugfs might
+ * change the lockspace waiters but they will held the recovery lock to ensure
+ * remove_from_waiters_ms() in local case will be the only user manipulating the
+ * lockspace waiters in recovery context.
+ */
 
 static int remove_from_waiters_ms(struct dlm_lkb *lkb,
                                  const struct dlm_message *ms, bool local)
 
        if (!local)
                mutex_lock(&ls->ls_waiters_mutex);
+       else
+               WARN_ON_ONCE(!rwsem_is_locked(&ls->ls_in_recovery) ||
+                            !dlm_locking_stopped(ls));
        error = _remove_from_waiters(lkb, le32_to_cpu(ms->m_type), ms);
        if (!local)
                mutex_unlock(&ls->ls_waiters_mutex);
        if (error)
                goto out;
 
-       /* local reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms, local);
        if (error)
                goto out;
        if (error)
                goto out;
 
-       /* local reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms, local);
        if (error)
                goto out;
        if (error)
                goto out;
 
-       /* local reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms, local);
        if (error)
                goto out;
        if (!ms_local)
                return;
 
-       mutex_lock(&ls->ls_waiters_mutex);
-
        list_for_each_entry_safe(lkb, safe, &ls->ls_waiters, lkb_wait_reply) {
 
                dir_nodeid = dlm_dir_nodeid(lkb->lkb_resource);
                }
                schedule();
        }
-       mutex_unlock(&ls->ls_waiters_mutex);
        kfree(ms_local);
 }
 
 
 int dlm_put_lkb(struct dlm_lkb *lkb);
 void dlm_scan_rsbs(struct dlm_ls *ls);
 int dlm_lock_recovery_try(struct dlm_ls *ls);
+void dlm_lock_recovery(struct dlm_ls *ls);
 void dlm_unlock_recovery(struct dlm_ls *ls);
 
 int dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *name,