On 8/13/20 10:07 AM, Josef wrote: > On Thu, 13 Aug 2020 at 01:32, Jens Axboe <axboe@xxxxxxxxx> wrote: >> Yeah I think you're right. How about something like the below? That'll >> potentially cancel more than just the one we're looking for, but seems >> kind of silly to only cancel from the file table holding request and to >> the end. >> >> >> diff --git a/fs/io_uring.c b/fs/io_uring.c >> index 8a2afd8c33c9..0630a9622baa 100644 >> --- a/fs/io_uring.c >> +++ b/fs/io_uring.c >> @@ -4937,6 +5003,7 @@ static bool io_poll_remove_one(struct io_kiocb *req) >> io_cqring_fill_event(req, -ECANCELED); >> io_commit_cqring(req->ctx); >> req->flags |= REQ_F_COMP_LOCKED; >> + req_set_fail_links(req); >> io_put_req(req); >> } >> >> @@ -7935,6 +8002,47 @@ static bool io_wq_files_match(struct io_wq_work *work, void *data) >> return work->files == files; >> } >> >> +static bool __io_poll_remove_link(struct io_kiocb *preq, struct io_kiocb *req) >> +{ >> + struct io_kiocb *link; >> + >> + if (!(preq->flags & REQ_F_LINK_HEAD)) >> + return false; >> + >> + list_for_each_entry(link, &preq->link_list, link_list) { >> + if (link != req) >> + break; >> + io_poll_remove_one(preq); >> + return true; >> + } >> + >> + return false; >> +} >> + >> +/* >> + * We're looking to cancel 'req' because it's holding on to our files, but >> + * 'req' could be a link to another request. See if it is, and cancel that >> + * parent request if so. >> + */ >> +static void io_poll_remove_link(struct io_ring_ctx *ctx, struct io_kiocb *req) >> +{ >> + struct hlist_node *tmp; >> + struct io_kiocb *preq; >> + int i; >> + >> + spin_lock_irq(&ctx->completion_lock); >> + for (i = 0; i < (1U << ctx->cancel_hash_bits); i++) { >> + struct hlist_head *list; >> + >> + list = &ctx->cancel_hash[i]; >> + hlist_for_each_entry_safe(preq, tmp, list, hash_node) { >> + if (__io_poll_remove_link(preq, req)) >> + break; >> + } >> + } >> + spin_unlock_irq(&ctx->completion_lock); >> +} >> + >> static void io_uring_cancel_files(struct io_ring_ctx *ctx, >> struct files_struct *files) >> { >> @@ -7989,6 +8097,8 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx, >> } >> } else { >> io_wq_cancel_work(ctx->io_wq, &cancel_req->work); >> + /* could be a link, check and remove if it is */ >> + io_poll_remove_link(ctx, cancel_req); >> io_put_req(cancel_req); >> } >> >> > > btw it works for me thanks Thanks for testing, I've committed an updated version that also ensures we find timeout based links: https://git.kernel.dk/cgit/linux-block/commit/?h=io_uring-5.9&id=f254ac04c8744cf7bfed012717eac34eacc65dfb -- Jens Axboe