mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-10-26 10:57:38 +08:00
When a task exits, io_uring only cancels and waits for the few request types that must not outlive it, and leaves everything else to be torn down whenever the ring itself goes away. This happens from a kernel workqueue, and may be some time after the final fput of the ring has been completed. This sometimes causes application issues, where a task that was doing IO on a file in /mnt, for example, will leave /mnt busy for a brief period of time after close(ring_fd) is done. If the whole thread group is exiting, no thread is left to reap completions or care about those requests. For this case, tear everything down. This is basically what exec does today. Two types of requests are ignored, as they never pin any files and will always complete on their own. One is armed timeouts, which may still be required to trigger if a ring is being shared, and the other is SEND_ZC notifications, which can take almost an unbounded time to complete. io_uring_try_cancel_requests() now takes flags to manage that behavior. While in there, fix up the wait loop for the exit case. A task that is exiting because of a fatal signal still has that signal pending, which turns the interruptible sleep into a busy loop. Use short uninterruptible sleeps in that case instead, task_work still gets run in between. Signed-off-by: Jens Axboe <axboe@kernel.dk>
26 lines
1007 B
C
26 lines
1007 B
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
struct io_timeout_data {
|
|
struct io_kiocb *req;
|
|
struct hrtimer timer;
|
|
ktime_t time;
|
|
enum hrtimer_mode mode;
|
|
u32 flags;
|
|
};
|
|
|
|
__cold void io_flush_timeouts(struct io_ring_ctx *ctx);
|
|
struct io_cancel_data;
|
|
int io_timeout_cancel(struct io_ring_ctx *ctx, struct io_cancel_data *cd);
|
|
__cold unsigned int io_timeouts_armed(struct io_ring_ctx *ctx,
|
|
struct io_uring_task *tctx);
|
|
__cold bool io_kill_timeouts(struct io_ring_ctx *ctx, struct io_uring_task *tctx,
|
|
bool cancel_all);
|
|
void io_queue_linked_timeout(struct io_kiocb *req);
|
|
void io_disarm_next(struct io_kiocb *req);
|
|
|
|
int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
|
|
int io_link_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
|
|
int io_timeout(struct io_kiocb *req, unsigned int issue_flags);
|
|
int io_timeout_remove_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
|
|
int io_timeout_remove(struct io_kiocb *req, unsigned int issue_flags);
|