• Dylan Yudaken's avatar
    io_uring: calculate CQEs from the user visible value · 0fc8c2ac
    Dylan Yudaken authored
    io_cqring_wait (and it's wake function io_has_work) used cached_cq_tail in
    order to calculate the number of CQEs. cached_cq_tail is set strictly
    before the user visible rings->cq.tail
    
    However as far as userspace is concerned,  if io_uring_enter(2) is called
    with a minimum number of events, they will verify by checking
    rings->cq.tail.
    
    It is therefore possible for io_uring_enter(2) to return early with fewer
    events visible to the user.
    
    Instead make the wait functions read from the user visible value, so there
    will be no discrepency.
    
    This is triggered eventually by the following reproducer:
    
    struct io_uring_sqe *sqe;
    struct io_uring_cqe *cqe;
    unsigned int cqe_ready;
    struct io_uring ring;
    int ret, i;
    
    ret = io_uring_queue_init(N, &ring, 0);
    assert(!ret);
    while(true) {
    	for (i = 0; i < N; i++) {
    		sqe = io_uring_get_sqe(&ring);
    		io_uring_prep_nop(sqe);
    		sqe->flags |= IOSQE_ASYNC;
    	}
    	ret = io_uring_submit(&ring);
    	assert(ret == N);
    
    	do {
    		ret = io_uring_wait_cqes(&ring, &cqe, N, NULL, NULL);
    	} while(ret == -EINTR);
    	cqe_ready = io_uring_cq_ready(&ring);
    	assert(!ret);
    	assert(cqe_ready == N);
    	io_uring_cq_advance(&ring, N);
    }
    
    Fixes: ad3eb2c8 ("io_uring: split overflow state into SQ and CQ side")
    Signed-off-by: default avatarDylan Yudaken <dylany@meta.com>
    Link: https://lore.kernel.org/r/20221108153016.1854297-1-dylany@meta.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
    0fc8c2ac
io_uring.c 106 KB