]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
kernel: provide create_io_thread() helper
authorJens Axboe <axboe@kernel.dk>
Thu, 4 Mar 2021 19:21:05 +0000 (12:21 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Jan 2023 10:39:16 +0000 (11:39 +0100)
[ Upstream commit cc440e8738e5c875297ac0e90316745093be7e28 ]

Provide a generic helper for setting up an io_uring worker. Returns a
task_struct so that the caller can do whatever setup is needed, then call
wake_up_new_task() to kick it into gear.

Add a kernel_clone_args member, io_thread, which tells copy_process() to
mark the task with PF_IO_WORKER.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/sched/task.h
kernel/fork.c

index eeacb4a16fe3f2333d12904414b295fd1d597c42..4ce511437a8aa4c2cccd7cac13b05decff847080 100644 (file)
@@ -31,6 +31,7 @@ struct kernel_clone_args {
        /* Number of elements in *set_tid */
        size_t set_tid_size;
        int cgroup;
+       int io_thread;
        struct cgroup *cgrp;
        struct css_set *cset;
 };
@@ -85,6 +86,7 @@ extern void exit_files(struct task_struct *);
 extern void exit_itimers(struct task_struct *);
 
 extern pid_t kernel_clone(struct kernel_clone_args *kargs);
+struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node);
 struct task_struct *fork_idle(int);
 struct mm_struct *copy_init_mm(void);
 extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
index b877480c901f0b07bcf48d715d0c15f546b53bc6..252a40f14f72614f04520f33a9e8b08cc7124da0 100644 (file)
@@ -1949,6 +1949,8 @@ static __latent_entropy struct task_struct *copy_process(
        p = dup_task_struct(current, node);
        if (!p)
                goto fork_out;
+       if (args->io_thread)
+               p->flags |= PF_IO_WORKER;
 
        /*
         * This _must_ happen before we call free_task(), i.e. before we jump
@@ -2415,6 +2417,34 @@ struct mm_struct *copy_init_mm(void)
        return dup_mm(NULL, &init_mm);
 }
 
+/*
+ * This is like kernel_clone(), but shaved down and tailored to just
+ * creating io_uring workers. It returns a created task, or an error pointer.
+ * The returned task is inactive, and the caller must fire it up through
+ * wake_up_new_task(p). All signals are blocked in the created task.
+ */
+struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
+{
+       unsigned long flags = CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|
+                               CLONE_IO;
+       struct kernel_clone_args args = {
+               .flags          = ((lower_32_bits(flags) | CLONE_VM |
+                                   CLONE_UNTRACED) & ~CSIGNAL),
+               .exit_signal    = (lower_32_bits(flags) & CSIGNAL),
+               .stack          = (unsigned long)fn,
+               .stack_size     = (unsigned long)arg,
+               .io_thread      = 1,
+       };
+       struct task_struct *tsk;
+
+       tsk = copy_process(NULL, 0, node, &args);
+       if (!IS_ERR(tsk)) {
+               sigfillset(&tsk->blocked);
+               sigdelsetmask(&tsk->blocked, sigmask(SIGKILL));
+       }
+       return tsk;
+}
+
 /*
  *  Ok, this is the main fork-routine.
  *