]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring: add task fork hook
authorJens Axboe <axboe@kernel.dk>
Fri, 16 Jan 2026 22:28:58 +0000 (15:28 -0700)
committerJens Axboe <axboe@kernel.dk>
Fri, 6 Feb 2026 14:29:14 +0000 (07:29 -0700)
Called when copy_process() is called to copy state to a new child.
Right now this is just a stub, but will be used shortly to properly
handle fork'ing of task based io_uring restrictions.

Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/io_uring.h
include/linux/sched.h
io_uring/tctx.c
kernel/fork.c

index 85fe4e6b275c7de260ea9a8552b8e1c3e7f7e5ec..d1aa4edfc2a59adf4aa0c074247ba65cc1618398 100644 (file)
@@ -12,6 +12,7 @@ void __io_uring_free(struct task_struct *tsk);
 void io_uring_unreg_ringfd(void);
 const char *io_uring_get_opcode(u8 opcode);
 bool io_is_uring_fops(struct file *file);
+int __io_uring_fork(struct task_struct *tsk);
 
 static inline void io_uring_files_cancel(void)
 {
@@ -25,9 +26,16 @@ static inline void io_uring_task_cancel(void)
 }
 static inline void io_uring_free(struct task_struct *tsk)
 {
-       if (tsk->io_uring)
+       if (tsk->io_uring || tsk->io_uring_restrict)
                __io_uring_free(tsk);
 }
+static inline int io_uring_fork(struct task_struct *tsk)
+{
+       if (tsk->io_uring_restrict)
+               return __io_uring_fork(tsk);
+
+       return 0;
+}
 #else
 static inline void io_uring_task_cancel(void)
 {
@@ -46,6 +54,10 @@ static inline bool io_is_uring_fops(struct file *file)
 {
        return false;
 }
+static inline int io_uring_fork(struct task_struct *tsk)
+{
+       return 0;
+}
 #endif
 
 #endif
index d395f2810facbe5dc450d010eceba0746eeb1826..9abbd11bb87c33ebb6fbf42933b5cafee366d0ac 100644 (file)
@@ -1190,6 +1190,7 @@ struct task_struct {
 
 #ifdef CONFIG_IO_URING
        struct io_uring_task            *io_uring;
+       struct io_restriction           *io_uring_restrict;
 #endif
 
        /* Namespaces: */
index 5b66755579c08fac74b77b3f76e51bdd6f5abf35..d4f7698805e4468e920f4f5950af089cf16fcbc2 100644 (file)
@@ -54,16 +54,18 @@ void __io_uring_free(struct task_struct *tsk)
         * node is stored in the xarray. Until that gets sorted out, attempt
         * an iteration here and warn if any entries are found.
         */
-       xa_for_each(&tctx->xa, index, node) {
-               WARN_ON_ONCE(1);
-               break;
-       }
-       WARN_ON_ONCE(tctx->io_wq);
-       WARN_ON_ONCE(tctx->cached_refs);
+       if (tctx) {
+               xa_for_each(&tctx->xa, index, node) {
+                       WARN_ON_ONCE(1);
+                       break;
+               }
+               WARN_ON_ONCE(tctx->io_wq);
+               WARN_ON_ONCE(tctx->cached_refs);
 
-       percpu_counter_destroy(&tctx->inflight);
-       kfree(tctx);
-       tsk->io_uring = NULL;
+               percpu_counter_destroy(&tctx->inflight);
+               kfree(tctx);
+               tsk->io_uring = NULL;
+       }
 }
 
 __cold int io_uring_alloc_task_context(struct task_struct *task,
@@ -351,3 +353,8 @@ int io_ringfd_unregister(struct io_ring_ctx *ctx, void __user *__arg,
 
        return i ? i : ret;
 }
+
+int __io_uring_fork(struct task_struct *tsk)
+{
+       return 0;
+}
index b1f3915d5f8ec887b96a59b799797c34be91c231..1605ee9bf83566ad0890461aef46a50ccbeab8f8 100644 (file)
@@ -97,6 +97,7 @@
 #include <linux/kasan.h>
 #include <linux/scs.h>
 #include <linux/io_uring.h>
+#include <linux/io_uring_types.h>
 #include <linux/bpf.h>
 #include <linux/stackprotector.h>
 #include <linux/user_events.h>
@@ -2129,6 +2130,10 @@ __latent_entropy struct task_struct *copy_process(
 
 #ifdef CONFIG_IO_URING
        p->io_uring = NULL;
+       retval = io_uring_fork(p);
+       if (unlikely(retval))
+               goto bad_fork_cleanup_delayacct;
+       retval = -EAGAIN;
 #endif
 
        p->default_timer_slack_ns = current->timer_slack_ns;
@@ -2525,6 +2530,7 @@ bad_fork_cleanup_policy:
        mpol_put(p->mempolicy);
 #endif
 bad_fork_cleanup_delayacct:
+       io_uring_free(p);
        delayacct_tsk_free(p);
 bad_fork_cleanup_count:
        dec_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1);