The branch main has been updated by wulf:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=1b2f43a7427ebf51561867f6c497833268014512

commit 1b2f43a7427ebf51561867f6c497833268014512
Author:     Vladimir Kondratyev <w...@freebsd.org>
AuthorDate: 2023-12-24 08:19:59 +0000
Commit:     Vladimir Kondratyev <w...@freebsd.org>
CommitDate: 2023-12-24 08:19:59 +0000

    LinuxKPI: Add cancel_work() function.
    
    Cancel a work not waiting for it to finish.
    
    Sponsored by:   Serenity Cyber Security, LLC
    Reviewed by:    manu, kib
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D42811
---
 .../linuxkpi/common/include/linux/workqueue.h      |  4 +++
 sys/compat/linuxkpi/common/src/linux_work.c        | 32 ++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/workqueue.h 
b/sys/compat/linuxkpi/common/include/linux/workqueue.h
index 226c2d1f4f0c..1c9df9fcb74d 100644
--- a/sys/compat/linuxkpi/common/include/linux/workqueue.h
+++ b/sys/compat/linuxkpi/common/include/linux/workqueue.h
@@ -188,6 +188,9 @@ do {                                                        
                \
 #define        delayed_work_pending(dwork) \
        linux_work_pending(&(dwork)->work)
 
+#define        cancel_work(work) \
+       linux_cancel_work(work)
+
 #define        cancel_delayed_work(dwork) \
        linux_cancel_delayed_work(dwork)
 
@@ -243,6 +246,7 @@ extern void linux_destroy_workqueue(struct workqueue_struct 
*);
 extern bool linux_queue_work_on(int cpu, struct workqueue_struct *, struct 
work_struct *);
 extern bool linux_queue_delayed_work_on(int cpu, struct workqueue_struct *,
     struct delayed_work *, unsigned delay);
+extern bool linux_cancel_work(struct work_struct *);
 extern bool linux_cancel_delayed_work(struct delayed_work *);
 extern bool linux_cancel_work_sync(struct work_struct *);
 extern bool linux_cancel_delayed_work_sync(struct delayed_work *);
diff --git a/sys/compat/linuxkpi/common/src/linux_work.c 
b/sys/compat/linuxkpi/common/src/linux_work.c
index c62302ad2346..939bdbbc1434 100644
--- a/sys/compat/linuxkpi/common/src/linux_work.c
+++ b/sys/compat/linuxkpi/common/src/linux_work.c
@@ -360,6 +360,38 @@ linux_delayed_work_timer_fn(void *arg)
        }
 }
 
+/*
+ * This function cancels the given work structure in a
+ * non-blocking fashion. It returns non-zero if the work was
+ * successfully cancelled. Else the work may still be busy or already
+ * cancelled.
+ */
+bool
+linux_cancel_work(struct work_struct *work)
+{
+       static const uint8_t states[WORK_ST_MAX] __aligned(8) = {
+               [WORK_ST_IDLE] = WORK_ST_IDLE,          /* NOP */
+               [WORK_ST_TIMER] = WORK_ST_TIMER,        /* can't happen */
+               [WORK_ST_TASK] = WORK_ST_IDLE,          /* cancel */
+               [WORK_ST_EXEC] = WORK_ST_EXEC,          /* NOP */
+               [WORK_ST_CANCEL] = WORK_ST_IDLE,        /* can't happen */
+       };
+       struct taskqueue *tq;
+
+       MPASS(atomic_read(&work->state) != WORK_ST_TIMER);
+       MPASS(atomic_read(&work->state) != WORK_ST_CANCEL);
+
+       switch (linux_update_state(&work->state, states)) {
+       case WORK_ST_TASK:
+               tq = work->work_queue->taskqueue;
+               if (taskqueue_cancel(tq, &work->work_task, NULL) == 0)
+                       return (true);
+               /* FALLTHROUGH */
+       default:
+               return (false);
+       }
+}
+
 /*
  * This function cancels the given work structure in a synchronous
  * fashion. It returns non-zero if the work was successfully

Reply via email to