$RodHat_
Syscall reference · I/O

io_uring_setup(2)

Create an io_uring instance: shared submission/completion rings for async I/O.

Since
Linux 5.1check your kernel →
glibc
none (use syscall(2))
System
Linux
Man page
io_uring_setup(2)

Synopsis

#include <liburing.h>

int io_uring_setup(u32 entries, struct io_uring_params *params);

Rod's take

Every older async I/O interface on Linux is broken somehow: aio(7) really wants O_DIRECT, and POSIX AIO is a thread pool in a trench coat. io_uring is two rings in shared memory, and with SQPOLL you submit without a syscall at all. The design is right. The implementation has also coughed up a pile of kernel escapes, and a seccomp filter only ever sees io_uring_enter, never what's in the ring. Use it on trusted servers you control. For everything else, turn it off with io_uring_disabled or restrict the ring before the fd leaves your hands.

Flags and arguments that matter

NameWhat it does
IORING_SETUP_IOPOLLBusy-poll for completions instead of IRQs; storage only, typically O_DIRECT on a polling-capable device.
IORING_SETUP_SQPOLLA kernel thread polls the SQ ring so submission needs no syscall; it parks after sq_thread_idle ms.
IORING_SETUP_SQ_AFFPin the SQPOLL thread to sq_thread_cpu. Only meaningful with IORING_SETUP_SQPOLL.
IORING_SETUP_CQSIZESize the completion queue from params.cq_entries instead of the default.
IORING_SETUP_R_DISABLEDLinux 5.10Start the ring disabled so restrictions can be registered before submissions are allowed.
IORING_SETUP_SUBMIT_ALLLinux 5.18Keep submitting the batch even if one request errors during submission.
IORING_SETUP_COOP_TASKRUNLinux 5.19Don't interrupt the task with IPIs on completion; process at the next kernel transition.
IORING_SETUP_SINGLE_ISSUERLinux 6.0Only one task may submit; violations fail with -EEXIST.
IORING_SETUP_DEFER_TASKRUNLinux 6.1Defer completion work until io_uring_enter(2) with GETEVENTS. Requires SINGLE_ISSUER.
IORING_SETUP_NO_MMAPLinux 6.5Use caller-allocated memory for the rings instead of mmap(2)-ing kernel memory.

Errors you will actually hit

errnoMeaning
EPERMio_uring_disabled is 2, or 1 and caller lacks CAP_SYS_ADMIN and isn't in io_uring_group.
EPERMIORING_SETUP_SQPOLL requested without sufficient privileges.
EINVALNon-zero resv, unsupported flag, entries out of bounds, or inconsistent flag combination.
ENOMEMInsufficient kernel resources.
ENXIOIORING_SETUP_ATTACH_WQ given but wq_fd isn't a live io_uring instance.

Example

struct io_uring ring;
int ret = io_uring_queue_init(32, &ring, 0);   /* io_uring_setup(2) */
if (ret < 0)
    errx(1, "io_uring_queue_init: %s", strerror(-ret));

struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_read(sqe, fd, buf, sizeof(buf), 0);
io_uring_submit(&ring);

struct io_uring_cqe *cqe;
if (io_uring_wait_cqe(&ring, &cqe) == 0) {
    printf("res = %d\n", cqe->res);           /* bytes or -errno */
    io_uring_cqe_seen(&ring, cqe);
}
io_uring_queue_exit(&ring);

Trimmed from the full walkthrough in io_uring: why Jens Axboe's ring buffer is annoying to disagree with.

BSD equivalent

FreeBSD: aio(4) (kernel option since FreeBSD 3.0, in all kernels since FreeBSD 11.0), with completions deliverable through kqueue(2) EVFILT_AIO. OpenBSD: none.

The long version, from the console

Sources

  1. io_uring_setup(2), man7.org
  2. io_uring(7), man7.org
  3. Linux 5.1, kernelnewbies.org
  4. aio(4), FreeBSD
  5. kqueue(2), FreeBSD

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.