fs: dlm: ls_count busy wait to event based wait
authorAlexander Aring <aahringo@redhat.com>
Tue, 2 Nov 2021 19:17:18 +0000 (15:17 -0400)
committerDavid Teigland <teigland@redhat.com>
Tue, 2 Nov 2021 19:39:20 +0000 (14:39 -0500)
This patch changes the ls_count busy wait to use atomic counter values
and wait_event() to wait until ls_count reach zero. It will slightly
reduce the number of holding lslist_lock. At remove lockspace we need to
retry the wait because it a lockspace get could interefere between
wait_event() and holding the lock which deletes the lockspace list entry.

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

index fd1c7a8..0199318 100644 (file)
@@ -548,8 +548,9 @@ struct dlm_ls {
        uint32_t                ls_generation;
        uint32_t                ls_exflags;
        int                     ls_lvblen;
-       int                     ls_count;       /* refcount of processes in
+       atomic_t                ls_count;       /* refcount of processes in
                                                   the dlm using this ls */
+       wait_queue_head_t       ls_count_wait;
        int                     ls_create_count; /* create/release refcount */
        unsigned long           ls_flags;       /* LSFL_ */
        unsigned long           ls_scan_time;
index 4e41813..2e51bd2 100644 (file)
@@ -314,7 +314,7 @@ struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
 
        list_for_each_entry(ls, &lslist, ls_list) {
                if (ls->ls_global_id == id) {
-                       ls->ls_count++;
+                       atomic_inc(&ls->ls_count);
                        goto out;
                }
        }
@@ -331,7 +331,7 @@ struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
        spin_lock(&lslist_lock);
        list_for_each_entry(ls, &lslist, ls_list) {
                if (ls->ls_local_handle == lockspace) {
-                       ls->ls_count++;
+                       atomic_inc(&ls->ls_count);
                        goto out;
                }
        }
@@ -348,7 +348,7 @@ struct dlm_ls *dlm_find_lockspace_device(int minor)
        spin_lock(&lslist_lock);
        list_for_each_entry(ls, &lslist, ls_list) {
                if (ls->ls_device.minor == minor) {
-                       ls->ls_count++;
+                       atomic_inc(&ls->ls_count);
                        goto out;
                }
        }
@@ -360,24 +360,24 @@ struct dlm_ls *dlm_find_lockspace_device(int minor)
 
 void dlm_put_lockspace(struct dlm_ls *ls)
 {
-       spin_lock(&lslist_lock);
-       ls->ls_count--;
-       spin_unlock(&lslist_lock);
+       if (atomic_dec_and_test(&ls->ls_count))
+               wake_up(&ls->ls_count_wait);
 }
 
 static void remove_lockspace(struct dlm_ls *ls)
 {
-       for (;;) {
-               spin_lock(&lslist_lock);
-               if (ls->ls_count == 0) {
-                       WARN_ON(ls->ls_create_count != 0);
-                       list_del(&ls->ls_list);
-                       spin_unlock(&lslist_lock);
-                       return;
-               }
+retry:
+       wait_event(ls->ls_count_wait, atomic_read(&ls->ls_count) == 0);
+
+       spin_lock(&lslist_lock);
+       if (atomic_read(&ls->ls_count) != 0) {
                spin_unlock(&lslist_lock);
-               ssleep(1);
+               goto retry;
        }
+
+       WARN_ON(ls->ls_create_count != 0);
+       list_del(&ls->ls_list);
+       spin_unlock(&lslist_lock);
 }
 
 static int threads_start(void)
@@ -481,7 +481,8 @@ static int new_lockspace(const char *name, const char *cluster,
        memcpy(ls->ls_name, name, namelen);
        ls->ls_namelen = namelen;
        ls->ls_lvblen = lvblen;
-       ls->ls_count = 0;
+       atomic_set(&ls->ls_count, 0);
+       init_waitqueue_head(&ls->ls_count_wait);
        ls->ls_flags = 0;
        ls->ls_scan_time = jiffies;
 
index d0cf685..ccb5307 100644 (file)
@@ -127,7 +127,7 @@ static int purge_request(struct dlm_ls *ls, struct dlm_message *ms, int nodeid)
        uint32_t type = ms->m_type;
 
        /* the ls is being cleaned up and freed by release_lockspace */
-       if (!ls->ls_count)
+       if (!atomic_read(&ls->ls_count))
                return 1;
 
        if (dlm_is_removed(ls, nodeid))