]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dlm: drop mutex use in waiters recovery
authorAlexander Aring <aahringo@redhat.com>
Tue, 2 Apr 2024 19:18:03 +0000 (15:18 -0400)
committerDavid Teigland <teigland@redhat.com>
Tue, 9 Apr 2024 16:44:49 +0000 (11:44 -0500)
The waiters_mutex no longer needs to be used in the waiters recovery
functions dlm_recover_waiters_pre() and dlm_recover_waiters_pre().
During recovery, ordinary locking operations are paused, and the
recovery thread is the only context accessing the waiters list,
so the lock is not needed.

Access to the waiters list from debugfs functions is avoided by
taking the top level recovery lock in the debugfs dump function.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
fs/dlm/debug_fs.c
fs/dlm/lock.c
fs/dlm/lock.h

index 19cdedd56629dd87266c018a2eee0535f29f3951..c238a9308323aa3d2f83df008b2c4d89f215ba18 100644 (file)
@@ -737,6 +737,12 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf,
        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));
 
@@ -749,8 +755,10 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf,
                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;
 }
@@ -772,7 +780,12 @@ static ssize_t waiters_write(struct file *file, const char __user *user_buf,
        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;
 
index 43a2f4d0af535100686e78522b926e0717d99f47..395b904a82f49ec94b7033c15e08d61faa5b4dc7 100644 (file)
@@ -201,7 +201,7 @@ void dlm_dump_rsb(struct dlm_rsb *r)
 
 /* 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);
 }
@@ -1556,7 +1556,11 @@ static int remove_from_waiters(struct dlm_lkb *lkb, int mstype)
 }
 
 /* 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)
@@ -1566,6 +1570,9 @@ static int remove_from_waiters_ms(struct dlm_lkb *lkb,
 
        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);
@@ -4398,7 +4405,6 @@ static void _receive_convert_reply(struct dlm_lkb *lkb,
        if (error)
                goto out;
 
-       /* local reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms, local);
        if (error)
                goto out;
@@ -4437,7 +4443,6 @@ static void _receive_unlock_reply(struct dlm_lkb *lkb,
        if (error)
                goto out;
 
-       /* local reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms, local);
        if (error)
                goto out;
@@ -4489,7 +4494,6 @@ static void _receive_cancel_reply(struct dlm_lkb *lkb,
        if (error)
                goto out;
 
-       /* local reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms, local);
        if (error)
                goto out;
@@ -4890,8 +4894,6 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
        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);
@@ -4984,7 +4986,6 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
                }
                schedule();
        }
-       mutex_unlock(&ls->ls_waiters_mutex);
        kfree(ms_local);
 }
 
index c8ff7780d3cc544e4ede4f0d2d234a9af59b46a4..b2fd74a2f8eb5712905d4f0d50b70e68165f20d6 100644 (file)
@@ -23,6 +23,7 @@ void dlm_hold_rsb(struct dlm_rsb *r);
 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,