fs: dlm: use event based wait for pending remove
authorAlexander Aring <aahringo@redhat.com>
Tue, 30 Nov 2021 19:47:16 +0000 (14:47 -0500)
committerDavid Teigland <teigland@redhat.com>
Tue, 7 Dec 2021 18:42:26 +0000 (12:42 -0600)
This patch will use an event based waitqueue to wait for a possible clash
with the ls_remove_name field of dlm_ls instead of doing busy waiting.

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

index 019931804af9b47263725e6ed0713eb2ab82c20e..74a9590a4dd5bde6ee3b0409afcd268cca4eecf2 100644 (file)
@@ -576,6 +576,7 @@ struct dlm_ls {
        struct list_head        ls_new_rsb;     /* new rsb structs */
 
        spinlock_t              ls_remove_spin;
+       wait_queue_head_t       ls_remove_wait;
        char                    ls_remove_name[DLM_RESNAME_MAXLEN+1];
        char                    *ls_remove_names[DLM_REMOVE_NAMES_MAX];
        int                     ls_remove_len;
index 54705d367076b98a3a8d4c37bc0a530c07415406..bdb51d209ba257e8029c0b1dcaa4c2c4b75cd726 100644 (file)
@@ -1626,21 +1626,24 @@ static int remove_from_waiters_ms(struct dlm_lkb *lkb, struct dlm_message *ms)
 }
 
 /* If there's an rsb for the same resource being removed, ensure
-   that the remove message is sent before the new lookup message.
-   It should be rare to need a delay here, but if not, then it may
-   be worthwhile to add a proper wait mechanism rather than a delay. */
+ * that the remove message is sent before the new lookup message.
+ */
+
+#define DLM_WAIT_PENDING_COND(ls, r)           \
+       (ls->ls_remove_len &&                   \
+        !rsb_cmp(r, ls->ls_remove_name,        \
+                 ls->ls_remove_len))
 
 static void wait_pending_remove(struct dlm_rsb *r)
 {
        struct dlm_ls *ls = r->res_ls;
  restart:
        spin_lock(&ls->ls_remove_spin);
-       if (ls->ls_remove_len &&
-           !rsb_cmp(r, ls->ls_remove_name, ls->ls_remove_len)) {
+       if (DLM_WAIT_PENDING_COND(ls, r)) {
                log_debug(ls, "delay lookup for remove dir %d %s",
-                         r->res_dir_nodeid, r->res_name);
+                         r->res_dir_nodeid, r->res_name);
                spin_unlock(&ls->ls_remove_spin);
-               msleep(1);
+               wait_event(ls->ls_remove_wait, !DLM_WAIT_PENDING_COND(ls, r));
                goto restart;
        }
        spin_unlock(&ls->ls_remove_spin);
@@ -1792,6 +1795,7 @@ static void shrink_bucket(struct dlm_ls *ls, int b)
                memcpy(ls->ls_remove_name, name, DLM_RESNAME_MAXLEN);
                spin_unlock(&ls->ls_remove_spin);
                spin_unlock(&ls->ls_rsbtbl[b].lock);
+               wake_up(&ls->ls_remove_wait);
 
                send_remove(r);
 
@@ -4075,6 +4079,7 @@ static void send_repeat_remove(struct dlm_ls *ls, char *ms_name, int len)
        memcpy(ls->ls_remove_name, name, DLM_RESNAME_MAXLEN);
        spin_unlock(&ls->ls_remove_spin);
        spin_unlock(&ls->ls_rsbtbl[b].lock);
+       wake_up(&ls->ls_remove_wait);
 
        rv = _create_message(ls, sizeof(struct dlm_message) + len,
                             dir_nodeid, DLM_MSG_REMOVE, &ms, &mh);
index 2e51bd2bdacce9805ba893d0375393eb6ed86951..31384e7d6f90a14d9f1443b002ecb0907ab26508 100644 (file)
@@ -512,6 +512,7 @@ static int new_lockspace(const char *name, const char *cluster,
        }
 
        spin_lock_init(&ls->ls_remove_spin);
+       init_waitqueue_head(&ls->ls_remove_wait);
 
        for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) {
                ls->ls_remove_names[i] = kzalloc(DLM_RESNAME_MAXLEN+1,