From: Josh Triplett <josh@xxxxxxxxxxxxxxxx> Introduce a helper to fork a new process from io_uring. This is different from the io_uring io_worker in multiple ways: First, it can return to userspace following a execve, doesn't have PF_USER_WORKER set, and doesn't share most process structures with the the parent. It shares the MM though, allowing the helper to do limited io_uring operations. The sole use of this is the io_uring OP_CLONE command, which prepares the ground for EXECVE from io_uring. Signed-off-by: Josh Triplett <josh@xxxxxxxxxxxxxxxx> Co-developed-by: Gabriel Krisman Bertazi <krisman@xxxxxxx> Signed-off-by: Gabriel Krisman Bertazi <krisman@xxxxxxx> --- include/linux/sched/task.h | 1 + kernel/fork.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index 0f2aeb37bbb0..a76f05a886ad 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -98,6 +98,7 @@ extern pid_t kernel_clone(struct kernel_clone_args *kargs); struct task_struct *copy_process(struct pid *pid, int trace, int node, struct kernel_clone_args *args); struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node); +struct task_struct *create_io_uring_spawn_task(int (*fn)(void *), void *arg); struct task_struct *fork_idle(int); extern pid_t kernel_thread(int (*fn)(void *), void *arg, const char *name, unsigned long flags); diff --git a/kernel/fork.c b/kernel/fork.c index 56baa320a720..fa983a0614ce 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2757,6 +2757,25 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node) return copy_process(NULL, 0, node, &args); } +/* + * This is like kernel_clone(), but shaved down and tailored for io_uring_spawn. + * 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). + */ +struct task_struct *create_io_uring_spawn_task(int (*fn)(void *), void *arg) +{ + unsigned long flags = CLONE_CLEAR_SIGHAND; + struct kernel_clone_args args = { + .flags = ((lower_32_bits(flags) | CLONE_VM | + CLONE_UNTRACED) & ~CSIGNAL), + .exit_signal = (lower_32_bits(flags) & CSIGNAL), + .fn = fn, + .fn_arg = arg, + }; + + return copy_process(NULL, 0, NUMA_NO_NODE, &args); +} + /* * Ok, this is the main fork-routine. * -- 2.47.0