Skip to content

Commit ef7dfac

Browse files
committed
io_uring/poll: serialize poll linked timer start with poll removal
We selectively grab the ctx->uring_lock for poll update/removal, but we really should grab it from the start to fully synchronize with linked timeouts. Normally this is indeed the case, but if requests are forced async by the application, we don't fully cover removal and timer disarm within the uring_lock. Make this simpler by having consistent locking state for poll removal. Cc: [email protected] # 6.1+ Reported-by: Querijn Voet <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent adeaa3f commit ef7dfac

File tree

1 file changed

+4
-5
lines changed

1 file changed

+4
-5
lines changed

io_uring/poll.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -977,8 +977,9 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
977977
struct io_hash_bucket *bucket;
978978
struct io_kiocb *preq;
979979
int ret2, ret = 0;
980-
struct io_tw_state ts = {};
980+
struct io_tw_state ts = { .locked = true };
981981

982+
io_ring_submit_lock(ctx, issue_flags);
982983
preq = io_poll_find(ctx, true, &cd, &ctx->cancel_table, &bucket);
983984
ret2 = io_poll_disarm(preq);
984985
if (bucket)
@@ -990,12 +991,10 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
990991
goto out;
991992
}
992993

993-
io_ring_submit_lock(ctx, issue_flags);
994994
preq = io_poll_find(ctx, true, &cd, &ctx->cancel_table_locked, &bucket);
995995
ret2 = io_poll_disarm(preq);
996996
if (bucket)
997997
spin_unlock(&bucket->lock);
998-
io_ring_submit_unlock(ctx, issue_flags);
999998
if (ret2) {
1000999
ret = ret2;
10011000
goto out;
@@ -1019,17 +1018,17 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
10191018
if (poll_update->update_user_data)
10201019
preq->cqe.user_data = poll_update->new_user_data;
10211020

1022-
ret2 = io_poll_add(preq, issue_flags);
1021+
ret2 = io_poll_add(preq, issue_flags & ~IO_URING_F_UNLOCKED);
10231022
/* successfully updated, don't complete poll request */
10241023
if (!ret2 || ret2 == -EIOCBQUEUED)
10251024
goto out;
10261025
}
10271026

10281027
req_set_fail(preq);
10291028
io_req_set_res(preq, -ECANCELED, 0);
1030-
ts.locked = !(issue_flags & IO_URING_F_UNLOCKED);
10311029
io_req_task_complete(preq, &ts);
10321030
out:
1031+
io_ring_submit_unlock(ctx, issue_flags);
10331032
if (ret < 0) {
10341033
req_set_fail(req);
10351034
return ret;

0 commit comments

Comments
 (0)