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