Skip to content

Commit 60c19ed

Browse files
committed
Merge branch 'fix/io_uring-cq-reap' of https://github.com/calebsander/fio
* 'fix/io_uring-cq-reap' of https://github.com/calebsander/fio: engines/io_uring: relax CQ head atomic store ordering arch: add atomic_store_relaxed() engines/io_uring: simplify getevents control flow engines/io_uring: return unsigned from fio_ioring_cqring_reap() engines/io_uring: remove loop over CQEs in fio_ioring_cqring_reap() engines/io_uring: consolidate fio_ioring_cqring_reap() arguments Revert "engines/io_uring: update getevents max to reflect previously seen events"
2 parents 34fa726 + a9af54b commit 60c19ed

File tree

2 files changed

+28
-23
lines changed

2 files changed

+28
-23
lines changed

arch/arch.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ extern unsigned long arch_flags;
5353
#define atomic_load_acquire(p) \
5454
std::atomic_load_explicit(p, \
5555
std::memory_order_acquire)
56+
#define atomic_store_relaxed(p, v) \
57+
std::atomic_store_explicit((p), (v), std::memory_order_relaxed)
5658
#define atomic_store_release(p, v) \
5759
std::atomic_store_explicit(p, (v), \
5860
std::memory_order_release)
@@ -67,6 +69,9 @@ extern unsigned long arch_flags;
6769
#define atomic_load_acquire(p) \
6870
atomic_load_explicit((_Atomic typeof(*(p)) *)(p), \
6971
memory_order_acquire)
72+
#define atomic_store_relaxed(p, v) \
73+
atomic_store_explicit((_Atomic typeof(*(p)) *)(p), (v), \
74+
memory_order_relaxed)
7075
#define atomic_store_release(p, v) \
7176
atomic_store_explicit((_Atomic typeof(*(p)) *)(p), (v), \
7277
memory_order_release)

engines/io_uring.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -674,25 +674,26 @@ static char *fio_ioring_cmd_errdetails(struct thread_data *td,
674674
return msg;
675675
}
676676

677-
static int fio_ioring_cqring_reap(struct thread_data *td, unsigned int events,
678-
unsigned int max)
677+
static unsigned fio_ioring_cqring_reap(struct thread_data *td, unsigned int max)
679678
{
680679
struct ioring_data *ld = td->io_ops_data;
681680
struct io_cq_ring *ring = &ld->cq_ring;
682-
unsigned head, reaped = 0;
681+
unsigned head = *ring->head;
682+
unsigned available = atomic_load_acquire(ring->tail) - head;
683683

684-
head = *ring->head;
685-
do {
686-
if (head == atomic_load_acquire(ring->tail))
687-
break;
688-
reaped++;
689-
head++;
690-
} while (reaped + events < max);
691-
692-
if (reaped)
693-
atomic_store_release(ring->head, head);
684+
if (!available)
685+
return 0;
694686

695-
return reaped;
687+
available = min(available, max);
688+
/*
689+
* The CQ consumer index is advanced before the CQEs are actually read.
690+
* This is generally unsafe, as it lets the kernel reuse the CQE slots.
691+
* However, the CQ is sized large enough for the maximum iodepth and a
692+
* new SQE won't be submitted until the CQE is processed, so the CQE
693+
* slot won't actually be reused until it has been processed.
694+
*/
695+
atomic_store_relaxed(ring->head, head + available);
696+
return available;
696697
}
697698

698699
static int fio_ioring_getevents(struct thread_data *td, unsigned int min,
@@ -706,14 +707,15 @@ static int fio_ioring_getevents(struct thread_data *td, unsigned int min,
706707
int r;
707708

708709
ld->cq_ring_off = *ring->head;
709-
do {
710-
r = fio_ioring_cqring_reap(td, events, max);
710+
for (;;) {
711+
r = fio_ioring_cqring_reap(td, max - events);
711712
if (r) {
712713
events += r;
713-
max -= r;
714+
if (events >= min)
715+
return events;
716+
714717
if (actual_min != 0)
715718
actual_min -= r;
716-
continue;
717719
}
718720

719721
if (!o->sqpoll_thread) {
@@ -724,12 +726,10 @@ static int fio_ioring_getevents(struct thread_data *td, unsigned int min,
724726
continue;
725727
r = -errno;
726728
td_verror(td, errno, "io_uring_enter");
727-
break;
729+
return r;
728730
}
729731
}
730-
} while (events < min);
731-
732-
return r < 0 ? r : events;
732+
}
733733
}
734734

735735
static inline void fio_ioring_cmd_nvme_pi(struct thread_data *td,
@@ -884,7 +884,7 @@ static int fio_ioring_commit(struct thread_data *td)
884884
continue;
885885
} else {
886886
if (errno == EAGAIN || errno == EINTR) {
887-
ret = fio_ioring_cqring_reap(td, 0, ld->queued);
887+
ret = fio_ioring_cqring_reap(td, ld->queued);
888888
if (ret)
889889
continue;
890890
/* Shouldn't happen */

0 commit comments

Comments
 (0)