diff options
author | Pavel Begunkov <asml.silence@gmail.com> | 2022-07-07 15:13:14 +0100 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2022-07-24 18:39:17 -0600 |
commit | 7a121ced6e6430d49fb802067b4f020f6df62362 (patch) | |
tree | b02069f47e97ff3968442b6405dd9014bfb459c6 | |
parent | cf0dd9527eee5d6d183fa724fdee6a128cb17b8d (diff) | |
download | linux-stable-7a121ced6e6430d49fb802067b4f020f6df62362.tar.gz linux-stable-7a121ced6e6430d49fb802067b4f020f6df62362.tar.bz2 linux-stable-7a121ced6e6430d49fb802067b4f020f6df62362.zip |
io_uring: don't miss setting REQ_F_DOUBLE_POLL
When adding a second poll entry we should set REQ_F_DOUBLE_POLL
unconditionally. We might race with the first entry removal but that
doesn't change the rule.
Fixes: a18427bb2d9b ("io_uring: optimise submission side poll_refs")
Reported-and-tested-by: syzbot+49950ba66096b1f0209b@syzkaller.appspotmail.com
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/8b680d83ded07424db83e8745585e7a6d72826ef.1657203020.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | io_uring/poll.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/io_uring/poll.c b/io_uring/poll.c index 57747d92bba4..3710a0a46a87 100644 --- a/io_uring/poll.c +++ b/io_uring/poll.c @@ -401,16 +401,18 @@ static void io_poll_double_prepare(struct io_kiocb *req) /* head is RCU protected, see io_poll_remove_entries() comments */ rcu_read_lock(); head = smp_load_acquire(&poll->head); - if (head) { - /* - * poll arm may not hold ownership and so race with - * io_poll_wake() by modifying req->flags. There is only one - * poll entry queued, serialise with it by taking its head lock. - */ + /* + * poll arm may not hold ownership and so race with + * io_poll_wake() by modifying req->flags. There is only one + * poll entry queued, serialise with it by taking its head lock. + */ + if (head) spin_lock_irq(&head->lock); - req->flags |= REQ_F_DOUBLE_POLL; + + req->flags |= REQ_F_DOUBLE_POLL; + + if (head) spin_unlock_irq(&head->lock); - } rcu_read_unlock(); } |