• Pavel Begunkov's avatar
    io_uring: tighten task exit cancellations · f8b632e8
    Pavel Begunkov authored
    io_uring_cancel_generic() should retry if any state changes like a
    request is completed, however in case of a task exit it only goes for
    another loop and avoids schedule() if any tracked (i.e. REQ_F_INFLIGHT)
    request got completed.
    
    Let's assume we have a non-tracked request executing in iowq and a
    tracked request linked to it. Let's also assume
    io_uring_cancel_generic() fails to find and cancel the request, i.e.
    via io_run_local_work(), which may happen as io-wq has gaps.
    Next, the request logically completes, io-wq still hold a ref but queues
    it for completion via tw, which happens in
    io_uring_try_cancel_requests(). After, right before prepare_to_wait()
    io-wq puts the request, grabs the linked one and tries executes it, e.g.
    arms polling. Finally the cancellation loop calls prepare_to_wait(),
    there are no tw to run, no tracked request was completed, so the
    tctx_inflight() check passes and the task is put to indefinite sleep.
    
    Cc: stable@vger.kernel.org
    Fixes: 3f48cf18 ("io_uring: unify files and task cancel")
    Signed-off-by: default avatarPavel Begunkov <asml.silence@gmail.com>
    Link: https://lore.kernel.org/r/acac7311f4e02ce3c43293f8f1fda9c705d158f1.1721819383.git.asml.silence@gmail.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
    f8b632e8
io_uring.c 100 KB