On 20/12/2020 00:25, Jens Axboe wrote: > On 12/19/20 4:42 PM, Pavel Begunkov wrote: >> On 19/12/2020 23:13, Jens Axboe wrote: >>> On 12/19/20 2:54 PM, Jens Axboe wrote: >>>> On 12/19/20 1:51 PM, Josef wrote: >>>>>> And even more so, it's IOSQE_ASYNC on the IORING_OP_READ on an eventfd >>>>>> file descriptor. You probably don't want/mean to do that as it's >>>>>> pollable, I guess it's done because you just set it on all reads for the >>>>>> test? >>>>> >>>>> yes exactly, eventfd fd is blocking, so it actually makes no sense to >>>>> use IOSQE_ASYNC >>>> >>>> Right, and it's pollable too. >>>> >>>>> I just tested eventfd without the IOSQE_ASYNC flag, it seems to work >>>>> in my tests, thanks a lot :) >>>>> >>>>>> In any case, it should of course work. This is the leftover trace when >>>>>> we should be exiting, but an io-wq worker is still trying to get data >>>>>> from the eventfd: >>>>> >>>>> interesting, btw what kind of tool do you use for kernel debugging? >>>> >>>> Just poking at it and thinking about it, no hidden magic I'm afraid... >>> >>> Josef, can you try with this added? Looks bigger than it is, most of it >>> is just moving one function below another. >> >> Hmm, which kernel revision are you poking? Seems it doesn't match >> io_uring-5.10, and for 5.11 io_uring_cancel_files() is never called with >> NULL files. >> >> if (!files) >> __io_uring_cancel_task_requests(ctx, task); >> else >> io_uring_cancel_files(ctx, task, files); > > Yeah, I think I messed up. If files == NULL, then the task is going away. > So we should cancel all requests that match 'task', not just ones that > match task && files. > > Not sure I have much more time to look into this before next week, but > something like that. > > The problem case is the async worker being queued, long before the task > is killed and the contexts go away. But from exit_files(), we're only > concerned with canceling if we have inflight. Doesn't look right to me. Josef, can you test the patch below instead? Following Jens' idea it cancels more aggressively when a task is killed or exits. It's based on [1] but would probably apply fine to for-next. [1] git://git.kernel.dk/linux-block branch io_uring-5.11, commit dd20166236953c8cd14f4c668bf972af32f0c6be diff --git a/fs/io_uring.c b/fs/io_uring.c index f3690dfdd564..3a98e6dd71c0 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -8919,8 +8919,6 @@ void __io_uring_files_cancel(struct files_struct *files) struct io_ring_ctx *ctx = file->private_data; io_uring_cancel_task_requests(ctx, files); - if (files) - io_uring_del_task_file(file); } atomic_dec(&tctx->in_idle); @@ -8960,6 +8958,8 @@ static s64 tctx_inflight(struct io_uring_task *tctx) void __io_uring_task_cancel(void) { struct io_uring_task *tctx = current->io_uring; + struct file *file; + unsigned long index; DEFINE_WAIT(wait); s64 inflight; @@ -8986,6 +8986,9 @@ void __io_uring_task_cancel(void) finish_wait(&tctx->wait, &wait); atomic_dec(&tctx->in_idle); + + xa_for_each(&tctx->xa, index, file) + io_uring_del_task_file(file); } static int io_uring_flush(struct file *file, void *data) diff --git a/include/linux/io_uring.h b/include/linux/io_uring.h index 35b2d845704d..54925c74aa88 100644 --- a/include/linux/io_uring.h +++ b/include/linux/io_uring.h @@ -48,7 +48,7 @@ static inline void io_uring_task_cancel(void) static inline void io_uring_files_cancel(struct files_struct *files) { if (current->io_uring && !xa_empty(¤t->io_uring->xa)) - __io_uring_files_cancel(files); + __io_uring_task_cancel(); } static inline void io_uring_free(struct task_struct *tsk) { -- Pavel Begunkov