diff options
author | Jens Axboe <axboe@kernel.dk> | 2020-04-03 11:10:14 -0600 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2020-04-03 11:35:48 -0600 |
commit | a6ba632d2c249a4390289727c07b8b55eb02a41d (patch) | |
tree | a672727c41cae975ace50616232c8b4964e3fb65 /fs | |
parent | 10bea96dcc13ad841d53bdcc9d8e731e9e0ad58f (diff) | |
download | linux-a6ba632d2c249a4390289727c07b8b55eb02a41d.tar.bz2 |
io_uring: retry poll if we got woken with non-matching mask
If we get woken and the poll doesn't match our mask, re-add the task
to the poll waitqueue and try again instead of completing the request
with a mask of 0.
Reported-by: Dan Melnic <dmm@fb.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/io_uring.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index 10645077d6b4..8ad4a151994d 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -4412,8 +4412,20 @@ static void io_poll_complete(struct io_kiocb *req, __poll_t mask, int error) static void io_poll_task_handler(struct io_kiocb *req, struct io_kiocb **nxt) { struct io_ring_ctx *ctx = req->ctx; + struct io_poll_iocb *poll = &req->poll; + + if (!req->result && !READ_ONCE(poll->canceled)) { + struct poll_table_struct pt = { ._key = poll->events }; + + req->result = vfs_poll(req->file, &pt) & poll->events; + } spin_lock_irq(&ctx->completion_lock); + if (!req->result && !READ_ONCE(poll->canceled)) { + add_wait_queue(poll->head, &poll->wait); + spin_unlock_irq(&ctx->completion_lock); + return; + } hash_del(&req->hash_node); io_poll_complete(req, req->result, 0); req->flags |= REQ_F_COMP_LOCKED; |