summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2020-03-02 08:33:17 -0700
committerJens Axboe <axboe@kernel.dk>2020-03-02 08:33:17 -0700
commitdc14e30a086082b6aebc3130948e2453e3bd3b2a (patch)
tree633474d03f4627ae04883fad39e0f5527b54ab4e
parent0edcef5700fd558d2548532e0e5db26cb74d19ca (diff)
downloadliburing-dc14e30a086082b6aebc3130948e2453e3bd3b2a.tar.gz
liburing-dc14e30a086082b6aebc3130948e2453e3bd3b2a.tar.bz2
__io_uring_get_cqe: fix spurious -EAGAIN
A previous patch always cleared the number to wait for once we'd done on io_uring_enter(), but we need to be sure that we've actually waited for the right amount before doing so. Check this by matching the return value with what we asked to submit - if it matches, we know we can safely clear 'wait_nr'. We also need to ensure that the original wait_nr is retained for the peek test. Fixes: 8a031500a304 ("__io_uring_get_cqe: eliminate unnecessary io_uring_enter() syscalls") Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--src/queue.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/src/queue.c b/src/queue.c
index 16edd16..de2d002 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -35,6 +35,7 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
unsigned submit, unsigned wait_nr, sigset_t *sigmask)
{
struct io_uring_cqe *cqe = NULL;
+ const int to_wait = wait_nr;
int ret = 0, err;
do {
@@ -43,7 +44,7 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
err = __io_uring_peek_cqe(ring, &cqe);
if (err)
break;
- if (!cqe && !wait_nr && !submit) {
+ if (!cqe && !to_wait && !submit) {
err = -EAGAIN;
break;
}
@@ -56,10 +57,14 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
wait_nr, flags, sigmask);
if (wait_nr)
wait_nr = 0;
- if (ret < 0)
+ if (ret < 0) {
err = -errno;
- else
+ } else if (ret == submit) {
+ submit = 0;
+ wait_nr = 0;
+ } else {
submit -= ret;
+ }
if (cqe)
break;
} while (!err);