linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] task_work: add helper for more targeted task_work canceling
@ 2021-04-04 23:00 Jens Axboe
  2021-04-06 17:47 ` Oleg Nesterov
  0 siblings, 1 reply; 3+ messages in thread
From: Jens Axboe @ 2021-04-04 23:00 UTC (permalink / raw)
  To: Oleg Nesterov, LKML

The only exported helper we have right now is task_work_cancel(), which
cancels any task_work from a given task where func matches the queued
work item. This is a bit too coarse for some use cases. Add a
task_work_cancel_match() that allows to more specifically target
individual work items outside of purely the callback function used.

task_work_cancel() can be trivially implemented on top of that, hence do
so.

Signed-off-by: Jens Axboe <axboe@kernel.dk>

---

I've got a patch on top of this that uses task_work_cancel_match(), but
sending this one out separately. There should be no functional changes
in this patch, it just allows someone to build func == func && data ==
data matches on top.

diff --git a/include/linux/task_work.h b/include/linux/task_work.h
index 0d848a1e9e62..5b8a93f288bb 100644
--- a/include/linux/task_work.h
+++ b/include/linux/task_work.h
@@ -22,6 +22,8 @@ enum task_work_notify_mode {
 int task_work_add(struct task_struct *task, struct callback_head *twork,
 			enum task_work_notify_mode mode);
 
+struct callback_head *task_work_cancel_match(struct task_struct *task,
+	bool (*match)(struct callback_head *, void *data), void *data);
 struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
 void task_work_run(void);
 
diff --git a/kernel/task_work.c b/kernel/task_work.c
index 9cde961875c0..e9316198c64b 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -59,18 +59,17 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
 }
 
 /**
- * task_work_cancel - cancel a pending work added by task_work_add()
+ * task_work_cancel_match - cancel a pending work added by task_work_add()
  * @task: the task which should execute the work
- * @func: identifies the work to remove
- *
- * Find the last queued pending work with ->func == @func and remove
- * it from queue.
+ * @match: match function to call
  *
  * RETURNS:
  * The found work or NULL if not found.
  */
 struct callback_head *
-task_work_cancel(struct task_struct *task, task_work_func_t func)
+task_work_cancel_match(struct task_struct *task,
+		       bool (*match)(struct callback_head *, void *data),
+		       void *data)
 {
 	struct callback_head **pprev = &task->task_works;
 	struct callback_head *work;
@@ -86,7 +85,7 @@ task_work_cancel(struct task_struct *task, task_work_func_t func)
 	 */
 	raw_spin_lock_irqsave(&task->pi_lock, flags);
 	while ((work = READ_ONCE(*pprev))) {
-		if (work->func != func)
+		if (!match(work, data))
 			pprev = &work->next;
 		else if (cmpxchg(pprev, work, work->next) == work)
 			break;
@@ -96,6 +95,28 @@ task_work_cancel(struct task_struct *task, task_work_func_t func)
 	return work;
 }
 
+static bool task_work_func_match(struct callback_head *cb, void *data)
+{
+	return cb->func == data;
+}
+
+/**
+ * task_work_cancel - cancel a pending work added by task_work_add()
+ * @task: the task which should execute the work
+ * @func: identifies the work to remove
+ *
+ * Find the last queued pending work with ->func == @func and remove
+ * it from queue.
+ *
+ * RETURNS:
+ * The found work or NULL if not found.
+ */
+struct callback_head *
+task_work_cancel(struct task_struct *task, task_work_func_t func)
+{
+	return task_work_cancel_match(task, task_work_func_match, func);
+}
+
 /**
  * task_work_run - execute the works added by task_work_add()
  *

-- 
Jens Axboe


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] task_work: add helper for more targeted task_work canceling
  2021-04-04 23:00 [PATCH] task_work: add helper for more targeted task_work canceling Jens Axboe
@ 2021-04-06 17:47 ` Oleg Nesterov
  2021-04-07 15:37   ` Jens Axboe
  0 siblings, 1 reply; 3+ messages in thread
From: Oleg Nesterov @ 2021-04-06 17:47 UTC (permalink / raw)
  To: Jens Axboe; +Cc: LKML

On 04/04, Jens Axboe wrote:
>
> +struct callback_head *task_work_cancel_match(struct task_struct *task,
> +	bool (*match)(struct callback_head *, void *data), void *data);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Feel free to ignore, but how about "typedef task_work_match_t" ?

Either way,

Reviewed-by: Oleg Nesterov <oleg@redhat.com>


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] task_work: add helper for more targeted task_work canceling
  2021-04-06 17:47 ` Oleg Nesterov
@ 2021-04-07 15:37   ` Jens Axboe
  0 siblings, 0 replies; 3+ messages in thread
From: Jens Axboe @ 2021-04-07 15:37 UTC (permalink / raw)
  To: Oleg Nesterov; +Cc: LKML

On 4/6/21 11:47 AM, Oleg Nesterov wrote:
> On 04/04, Jens Axboe wrote:
>>
>> +struct callback_head *task_work_cancel_match(struct task_struct *task,
>> +	bool (*match)(struct callback_head *, void *data), void *data);
>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> Feel free to ignore, but how about "typedef task_work_match_t" ?
> 
> Either way,
> 
> Reviewed-by: Oleg Nesterov <oleg@redhat.com>

Thanks! I actually didn't add that deliberately, as I think they just
tend to hide it. If I see the above, I know what the callback func
looks like without having to find the definition of task_work_match_t.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-04-07 15:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-04 23:00 [PATCH] task_work: add helper for more targeted task_work canceling Jens Axboe
2021-04-06 17:47 ` Oleg Nesterov
2021-04-07 15:37   ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).