This patch implements DLM_PLOCK_OP_CANCEL to try to delete waiters for a
lock request which are waiting to being granted. If the waiter can be
deleted the reply to the kernel will be replaced from
DLM_PLOCK_OP_LOCK to the sent DLM_PLOCK_OP_CANCEL and clearing the
DLM_PLOCK_FL_NO_REPLY flag.
---
 dlm_controld/plock.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/dlm_controld/plock.c b/dlm_controld/plock.c
index ab19e8d7..fd2bd2cf 100644
--- a/dlm_controld/plock.c
+++ b/dlm_controld/plock.c
@@ -9,6 +9,10 @@
 #include "dlm_daemon.h"
 #include <linux/dlm_plock.h>
 
+#ifndef DLM_PLOCK_OP_CANCEL
+#define DLM_PLOCK_OP_CANCEL 4
+#endif
+
 #ifndef DLM_PLOCK_FL_NO_REPLY
 #define DLM_PLOCK_FL_NO_REPLY 2
 #endif
@@ -136,6 +140,8 @@ static const char *op_str(int optype)
        switch (optype) {
        case DLM_PLOCK_OP_LOCK:
                return "LK";
+       case DLM_PLOCK_OP_CANCEL:
+               return "CL";
        case DLM_PLOCK_OP_UNLOCK:
                return "UN";
        case DLM_PLOCK_OP_GET:
@@ -751,6 +757,43 @@ static void do_lock(struct lockspace *ls, struct 
dlm_plock_info *in,
        put_resource(ls, r);
 }
 
+static int remove_waiter(const struct resource *r, struct dlm_plock_info *in)
+{
+       struct lock_waiter *w;
+
+       list_for_each_entry(w, &r->waiters, list) {
+               if (w->info.nodeid == in->nodeid &&
+                   w->info.fsid == in->fsid &&
+                   w->info.number == in->number &&
+                   w->info.owner == in->owner &&
+                   w->info.pid == in->pid &&
+                   w->info.start == in->start &&
+                   w->info.end == in->end &&
+                   w->info.ex == in->ex) {
+                       list_del(&w->list);
+                       free(w);
+                       return 0;
+               }
+       }
+
+       return -ENOENT;
+}
+
+static void do_cancel(struct lockspace *ls, struct dlm_plock_info *in,
+                     struct resource *r)
+{
+       int rv;
+
+       rv = remove_waiter(r, in);
+       if (in->nodeid == our_nodeid && rv == 0) {
+               /* we replacing a reply because we canceled waiter */
+               in->flags &= ~DLM_PLOCK_FL_NO_REPLY;
+               write_result(in, rv);
+       }
+
+       put_resource(ls, r);
+}
+
 static void do_unlock(struct lockspace *ls, struct dlm_plock_info *in,
                      struct resource *r)
 {
@@ -816,6 +859,10 @@ static void __receive_plock(struct lockspace *ls, struct 
dlm_plock_info *in,
                ls->last_plock_time = monotime();
                do_lock(ls, in, r);
                break;
+       case DLM_PLOCK_OP_CANCEL:
+               ls->last_plock_time = monotime();
+               do_cancel(ls, in, r);
+               break;
        case DLM_PLOCK_OP_UNLOCK:
                ls->last_plock_time = monotime();
                do_unlock(ls, in, r);
-- 
2.31.1

Reply via email to