On 7/8/20 7:15 PM, Xiaoguang Wang wrote: > For those applications which are not willing to use io_uring_enter() > to reap and handle cqes, they may completely rely on liburing's > io_uring_peek_cqe(), but if cq ring has overflowed, currently because > io_uring_peek_cqe() is not aware of this overflow, it won't enter > kernel to flush cqes, below test program can reveal this bug: > > static void test_cq_overflow(struct io_uring *ring) > { > struct io_uring_cqe *cqe; > struct io_uring_sqe *sqe; > int issued = 0; > int ret = 0; > > do { > sqe = io_uring_get_sqe(ring); > if (!sqe) { > fprintf(stderr, "get sqe failed\n"); > break;; > } > ret = io_uring_submit(ring); > if (ret <= 0) { > if (ret != -EBUSY) > fprintf(stderr, "sqe submit failed: %d\n", ret); > break; > } > issued++; > } while (ret > 0); > assert(ret == -EBUSY); > > printf("issued requests: %d\n", issued); > > while (issued) { > ret = io_uring_peek_cqe(ring, &cqe); > if (ret) { > if (ret != -EAGAIN) { > fprintf(stderr, "peek completion failed: %s\n", > strerror(ret)); > break; > } > printf("left requets: %d\n", issued); > continue; > } > io_uring_cqe_seen(ring, cqe); > issued--; > printf("left requets: %d\n", issued); > } > } > > int main(int argc, char *argv[]) > { > int ret; > struct io_uring ring; > > ret = io_uring_queue_init(16, &ring, 0); > if (ret) { > fprintf(stderr, "ring setup failed: %d\n", ret); > return 1; > } > > test_cq_overflow(&ring); > return 0; > } > > To fix this issue, export cq overflow status to userspace by adding new > IORING_SQ_CQ_OVERFLOW flag, then helper functions() in liburing, such as > io_uring_peek_cqe, can be aware of this cq overflow and do flush accordingly. Applied, thanks. -- Jens Axboe