Commit 079afb08 authored by Jens Axboe's avatar Jens Axboe
Browse files

io_uring/futex: mark wait requests as inflight

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: 80367ad0 ("futex: Add basic infrastructure for local task local hash")
Link: https://lore.kernel.org/io-uring/38053.1749045482@localhost/


Reported-by: default avatarRobert Morris <rtm@csail.mit.edu>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 6a8118a7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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;
+6 −1
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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);