io_uring/futex: mark wait requests as inflight io_uring-6.16-20250606
authorJens Axboe <axboe@kernel.dk>
Wed, 4 Jun 2025 16:25:42 +0000 (10:25 -0600)
committerJens Axboe <axboe@kernel.dk>
Wed, 4 Jun 2025 16:50:14 +0000 (10:50 -0600)
Inflight marking is used so that do_exit() -> io_uring_files_cancel()
will find requests with files that reference an io_uring instance,
so they can get appropriately canceled before the files go away.
However, it's also called before the mm goes away.

Mark futex/futexv wait requests as being inflight, so that
io_uring_files_cancel() will prune them. This ensures that the mm stays
alive, which is important as an exiting mm will also free the futex
private hash buckets. An io_uring futex request with FUTEX2_PRIVATE
set relies on those being alive until the request has completed. A
recent commit added these futex private hashes, which get killed when
the mm goes away.

Fixes: 80367ad01d93 ("futex: Add basic infrastructure for local task local hash")
Link: https://lore.kernel.org/io-uring/38053.1749045482@localhost/
Reported-by: Robert Morris <rtm@csail.mit.edu>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/futex.c
io_uring/io_uring.c
io_uring/io_uring.h

index 5a3991b0d1a7554a96ebf73719914fa6c1cede11..692462d50c8c0c8eabfbcd75bf1323b0789f6031 100644 (file)
@@ -145,6 +145,8 @@ int io_futex_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
            !futex_validate_input(iof->futex_flags, iof->futex_mask))
                return -EINVAL;
 
+       /* Mark as inflight, so file exit cancelation will find it */
+       io_req_track_inflight(req);
        return 0;
 }
 
@@ -190,6 +192,8 @@ int io_futexv_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
                return ret;
        }
 
+       /* Mark as inflight, so file exit cancelation will find it */
+       io_req_track_inflight(req);
        iof->futexv_owned = 0;
        iof->futexv_unqueued = 0;
        req->flags |= REQ_F_ASYNC_DATA;
index c7a9cecf528ed1463bedc6486a9f76de498c4e67..cf759c172083c543207a24496042be5564a460f0 100644 (file)
@@ -408,7 +408,12 @@ static void io_clean_op(struct io_kiocb *req)
        req->flags &= ~IO_REQ_CLEAN_FLAGS;
 }
 
-static inline void io_req_track_inflight(struct io_kiocb *req)
+/*
+ * Mark the request as inflight, so that file cancelation will find it.
+ * Can be used if the file is an io_uring instance, or if the request itself
+ * relies on ->mm being alive for the duration of the request.
+ */
+inline void io_req_track_inflight(struct io_kiocb *req)
 {
        if (!(req->flags & REQ_F_INFLIGHT)) {
                req->flags |= REQ_F_INFLIGHT;
index 0ea7a435d1de55c133d38d9a733aec0e8e8df0aa..d59c12277d58ce35d072529697faec7dc7e7dd76 100644 (file)
@@ -83,6 +83,7 @@ void io_add_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags)
 bool io_req_post_cqe(struct io_kiocb *req, s32 res, u32 cflags);
 void __io_commit_cqring_flush(struct io_ring_ctx *ctx);
 
+void io_req_track_inflight(struct io_kiocb *req);
 struct file *io_file_get_normal(struct io_kiocb *req, int fd);
 struct file *io_file_get_fixed(struct io_kiocb *req, int fd,
                               unsigned issue_flags);