Skip to content

io_uring — Opcode & Flag Reference

A complete lookup table for the io_uring UABI: every IORING_OP_* opcode, every SQE/CQE/setup/feature/enter flag, the io_uring_register(2) opcode space, the per-op flag enums, and the liburing helper surface that builds it all.

Scope. This is the reference companion to the io_uring feature catalog and the io_uring timeline. It enumerates the on-the-wire interface directly from the kernel UABI header and the kernel opcode dispatch table — it is ground-truth rather than narrative. Where the feature/timeline docs explain why and when, this doc answers what is the exact name, value, flag bit, and helper. Higher-level event loops that drive these primitives — Tokio's io-uring backend, Glommio, Monoio, Seastar, and the effects-based OCaml Eio eio_linux backend — all bottom out in the symbols tabulated here.

The interface tables below are transcribed from a specific source snapshot:

SourceVersion / commitRepo-relative path
Kernel UABI header (all enums/flags)Linux v7.1-rc6linux/include/uapi/linux/io_uring.h
Kernel opcode dispatch table (handler/attrs)Linux v7.1-rc6linux/io_uring/opdef.c
liburing user-space helpers (prep_*, register_*)liburing 2.15-dev (40999f52, post-2.14 tag)liburing/src/include/liburing.h

The interface is append-only and ABI-stable: every value below has the same numeric meaning on every kernel that defines it. Newer kernels add opcodes/flags at the end of each enum; they never renumber existing entries. The "Since" columns give the kernel release that first shipped each symbol (verified against io_uring_enter(2), kernel.dk and LWN — see Sources). A current kernel will reject an unknown opcode with -EINVAL and report support via IORING_REGISTER_PROBE, so probe rather than assume.


1. IORING_OP_* — submission opcodes

The opcode is sqe->opcode (a __u8). Values are the ordinal position in enum io_uring_op (io_uring.h:255). The terminal sentinel is IORING_OP_LAST. The kernel maps each opcode to a prep/issue handler pair in the io_issue_defs[] table (opdef.c:54) and to a human-readable name + cleanup/fail hooks in io_cold_defs[] (opdef.c:594). io_uring_get_opcode() (opdef.c:852) returns the name; io_uring_op_supported() (opdef.c:859) reports whether a prep other than io_eopnotsupp_prep is wired up (opcodes behind CONFIG_NET/CONFIG_FUTEX/CONFIG_EPOLL compile out to -EOPNOTSUPP).

The "Kernel handler" column is the .issue function from io_issue_defs[]; the "liburing prep" column is the primary io_uring_prep_* helper. Many ops also have _direct/_fixed/_multishot variant helpers (see §10).

ValIORING_OP_*Purpose (one-line)SinceKernel handler (opdef.c)liburing prep
0NOPNo-op; useful for ring testing/fencing5.1io_nopio_uring_prep_nop
1READVVectored read (preadv2)5.1io_readio_uring_prep_readv / readv2
2WRITEVVectored write (pwritev2)5.1io_writeio_uring_prep_writev / writev2
3FSYNCfsync/fdatasync of a file5.1io_fsyncio_uring_prep_fsync
4READ_FIXEDRead into a pre-registered buffer5.1io_read_fixedio_uring_prep_read_fixed
5WRITE_FIXEDWrite from a pre-registered buffer5.1io_write_fixedio_uring_prep_write_fixed
6POLL_ADDArm a poll on an fd (one-shot or multishot)5.1io_poll_addio_uring_prep_poll_add
7POLL_REMOVERemove/update an existing poll5.1io_poll_removeio_uring_prep_poll_remove
8SYNC_FILE_RANGEsync_file_range(2)5.2io_sync_file_rangeio_uring_prep_sync_file_range
9SENDMSGsendmsg(2) on a socket5.3io_sendmsgio_uring_prep_sendmsg
10RECVMSGrecvmsg(2) on a socket5.3io_recvmsgio_uring_prep_recvmsg
11TIMEOUTFire a CQE after a timeout / N completions5.4io_timeoutio_uring_prep_timeout
12TIMEOUT_REMOVERemove or update a pending timeout5.5io_timeout_removeio_uring_prep_timeout_remove / _update
13ACCEPTaccept4(2); one-shot or multishot5.5io_acceptio_uring_prep_accept
14ASYNC_CANCELCancel an in-flight request by user_data/fd5.5io_async_cancelio_uring_prep_cancel / cancel64
15LINK_TIMEOUTAttach a timeout to the next linked SQE5.5(none — io_no_issue)io_uring_prep_link_timeout
16CONNECTconnect(2) on a socket5.5io_connectio_uring_prep_connect
17FALLOCATEfallocate(2)5.6io_fallocateio_uring_prep_fallocate
18OPENATopenat(2)5.6io_openatio_uring_prep_openat
19CLOSEclose(2) (incl. fixed-fd slot)5.6io_closeio_uring_prep_close
20FILES_UPDATEUpdate fixed-file table slots5.6io_files_updateio_uring_prep_files_update
21STATXstatx(2)5.6io_statxio_uring_prep_statx
22READpread(2) (non-vectored)5.6io_readio_uring_prep_read
23WRITEpwrite(2) (non-vectored)5.6io_writeio_uring_prep_write
24FADVISEposix_fadvise(2)5.6io_fadviseio_uring_prep_fadvise / fadvise64
25MADVISEmadvise(2)5.6io_madviseio_uring_prep_madvise / madvise64
26SENDsend(2) on a socket5.6io_sendio_uring_prep_send / sendto
27RECVrecv(2) on a socket5.6io_recvio_uring_prep_recv
28OPENAT2openat2(2) with struct open_how5.6io_openat2io_uring_prep_openat2
29EPOLL_CTLepoll_ctl(2)5.6io_epoll_ctlio_uring_prep_epoll_ctl
30SPLICEsplice(2) between two fds5.7io_spliceio_uring_prep_splice
31PROVIDE_BUFFERSDonate buffers to a legacy buffer group5.7io_manage_buffers_legacyio_uring_prep_provide_buffers
32REMOVE_BUFFERSRemove buffers from a legacy buffer group5.7io_manage_buffers_legacyio_uring_prep_remove_buffers
33TEEtee(2) (pipe duplication)5.8io_teeio_uring_prep_tee
34SHUTDOWNshutdown(2) on a socket5.11io_shutdownio_uring_prep_shutdown
35RENAMEATrenameat2(2)5.11io_renameatio_uring_prep_renameat / rename
36UNLINKATunlinkat(2)5.11io_unlinkatio_uring_prep_unlinkat / unlink
37MKDIRATmkdirat(2)5.15io_mkdiratio_uring_prep_mkdirat / mkdir
38SYMLINKATsymlinkat(2)5.15io_symlinkatio_uring_prep_symlinkat / symlink
39LINKATlinkat(2)5.15io_linkatio_uring_prep_linkat / link
40MSG_RINGPost a message/fd to another ring5.18io_msg_ringio_uring_prep_msg_ring / msg_ring_fd
41FSETXATTRfsetxattr(2)5.19io_fsetxattrio_uring_prep_fsetxattr
42SETXATTRsetxattr(2)5.19io_setxattrio_uring_prep_setxattr
43FGETXATTRfgetxattr(2)5.19io_fgetxattrio_uring_prep_fgetxattr
44GETXATTRgetxattr(2)5.19io_getxattrio_uring_prep_getxattr
45SOCKETsocket(2) (incl. direct/fixed-fd)5.19io_socketio_uring_prep_socket / socket_direct
46URING_CMDPass-through driver command (NVMe, sockets, …)5.19io_uring_cmdio_uring_prep_uring_cmd
47SEND_ZCZero-copy send6.0io_sendmsg_zcio_uring_prep_send_zc / _fixed
48SENDMSG_ZCZero-copy sendmsg6.1io_sendmsg_zcio_uring_prep_sendmsg_zc
49READ_MULTISHOTMultishot read using provided buffers6.7io_read_mshotio_uring_prep_read_multishot
50WAITIDwaitid(2) (async child wait)6.7io_waitidio_uring_prep_waitid
51FUTEX_WAITfutex wait6.7io_futex_waitio_uring_prep_futex_wait
52FUTEX_WAKEfutex wake6.7io_futex_wakeio_uring_prep_futex_wake
53FUTEX_WAITVVectored futex wait (futex_waitv)6.7io_futexv_waitio_uring_prep_futex_waitv
54FIXED_FD_INSTALLInstall a fixed-fd slot into the real fd table6.8io_install_fixed_fdio_uring_prep_fixed_fd_install
55FTRUNCATEftruncate(2)6.9io_ftruncateio_uring_prep_ftruncate
56BINDbind(2) (needed for direct-fd sockets)6.11io_bindio_uring_prep_bind
57LISTENlisten(2) (needed for direct-fd sockets)6.11io_listenio_uring_prep_listen
58RECV_ZCZero-copy receive via registered ifq6.15io_recvzc(uring_cmd / zcrx path)
59EPOLL_WAITepoll_wait(2) (unify legacy epoll into the ring)6.15io_epoll_waitio_uring_prep_epoll_wait
60READV_FIXEDVectored read into registered buffers6.15io_readio_uring_prep_readv_fixed
61WRITEV_FIXEDVectored write from registered buffers6.15io_writeio_uring_prep_writev_fixed
62PIPEpipe2(2) (incl. direct-fd variant)6.16io_pipeio_uring_prep_pipe
63NOP128No-op that consumes a 128-byte SQE (mixed-SQE test)6.19io_nopio_uring_prep_nop128
64URING_CMD128URING_CMD that always uses a 128-byte SQE6.19io_uring_cmdio_uring_prep_uring_cmd128
65LASTSentinel — count of defined opcodes

Per-opcode dispatch attributes (selected fields from io_issue_defs[], opdef.c). These govern how the core loop treats each request and explain which ops can be async-poll-driven, buffer-selected, or IO-polled:

Attribute (io_issue_def)MeaningExample opcodes
needs_fileSQE must reference a valid fd (or fixed-fd slot)READV, SEND, ACCEPT, MSG_RING, URING_CMD
unbound_nonreg_fileMay run on an io-wq unbound worker if the fd is non-regularREADV, RECV, ACCEPT, CONNECT
pollin / polloutEligible for fast-poll arming on -EAGAIN (read-ready / write-ready)pollin: READ,RECV,ACCEPT; pollout: WRITE,SEND,CONNECT
buffer_selectHonors IOSQE_BUFFER_SELECT (provided/ring buffers)READV, READ, RECV, RECVMSG, SEND, URING_CMD
iopriosqe->ioprio carries op flags rather than I/O prioritySEND/RECV (RECVSEND flags), ACCEPT (accept flags), POLL
iopollSupports IORING_SETUP_IOPOLL (busy-poll completion)READ, WRITE, READ_FIXED, NOP, URING_CMD
vectoredVectored variant (iovec array)READV, WRITEV, READV_FIXED, WRITEV_FIXED
hash_reg_fileSerialize writes to the same registered file via io-wq hashingWRITEV, WRITE, WRITE_FIXED, FALLOCATE, FTRUNCATE
plugWrap issue in a block-layer plug for batchingREADV, WRITE, READ_FIXED, URING_CMD
poll_exclusiveUse exclusive poll wakeups (thundering-herd avoidance)ACCEPT
audit_skipSkip the syscall audit hook (hot path)NOP, READ, SEND, TIMEOUT, POLL_ADD
is_128Request always consumes a 128-byte SQENOP128, URING_CMD128
async_sizeBytes of per-request async state preallocatedREADVio_async_rw; SENDMSGio_async_msghdr

LINK_TIMEOUT is unique: its .issue is io_no_issue (opdef.c:42), which WARNs and returns -ECANCELED — the request is never issued directly. It only takes effect as the timeout attached to a preceding IOSQE_IO_LINKed SQE, consumed by the link-handling fast path.


2. IOSQE_* — per-SQE submission flags (sqe->flags, __u8)

Bit positions come from enum io_uring_sqe_flags_bit (io_uring.h:143); the macros (io_uring.h:157) are (1U << bit). Set via io_uring_sqe_set_flags().

BitMacroEffectSince
0IOSQE_FIXED_FILEsqe->fd is an index into the registered fixed-file table, not a real fd5.1
1IOSQE_IO_DRAINWait for all prior in-flight requests to finish before issuing this one5.2
2IOSQE_IO_LINKLink the next SQE; it starts only after this one completes successfully5.3
3IOSQE_IO_HARDLINKLike IO_LINK, but the chain continues even if this request fails5.5
4IOSQE_ASYNCForce issue on an io-wq worker instead of attempting inline + poll5.6
5IOSQE_BUFFER_SELECTPick a buffer from the group in sqe->buf_group (requires buffer_select op)5.7
6IOSQE_CQE_SKIP_SUCCESSDon't post a CQE if the request succeeds (only on failure)5.17

IOSQE_CQE_SKIP_SUCCESS requires the IORING_FEAT_CQE_SKIP feature bit (§4) to be present in io_uring_params.features.


3. IORING_SETUP_*io_uring_setup(2) flags (io_uring_params.flags)

From io_uring.h:172. Passed via struct io_uring_params (or io_uring_queue_init_params()).

BitMacroEffectSince
0IORING_SETUP_IOPOLLBusy-poll for completions (storage); no interrupts/CQE events5.1
1IORING_SETUP_SQPOLLKernel SQ-poll thread submits SQEs without io_uring_enter5.1
2IORING_SETUP_SQ_AFFsq_thread_cpu pins the SQPOLL thread to a CPU5.1
3IORING_SETUP_CQSIZEApp sizes the CQ ring via cq_entries5.5
4IORING_SETUP_CLAMPClamp SQ/CQ sizes to the kernel max instead of erroring5.6
5IORING_SETUP_ATTACH_WQShare the io-wq backend of an existing ring (wq_fd)5.6
6IORING_SETUP_R_DISABLEDCreate the ring disabled; enable later with IORING_REGISTER_ENABLE_RINGS5.10
7IORING_SETUP_SUBMIT_ALLContinue submitting the batch even if one SQE fails prep5.18
8IORING_SETUP_COOP_TASKRUNRun completion task-work on the next kernel transition; skip the IPI5.19
9IORING_SETUP_TASKRUN_FLAGSurface pending task-work via IORING_SQ_TASKRUN (needs COOP_TASKRUN/DEFER_TASKRUN)5.19
10IORING_SETUP_SQE128SQEs are 128 bytes (for URING_CMD pass-through payloads)5.19
11IORING_SETUP_CQE32CQEs are 32 bytes (extra big_cqe[] payload)5.19
12IORING_SETUP_SINGLE_ISSUERPromise only one task submits — enables scheduling fast paths6.0
13IORING_SETUP_DEFER_TASKRUNDefer task-work until the app calls io_uring_enter(GETEVENTS) (needs SINGLE_ISSUER)6.1
14IORING_SETUP_NO_MMAPApp supplies ring memory; no mmap of magic offsets6.5
15IORING_SETUP_REGISTERED_FD_ONLYReturn a registered ring-fd index instead of a real fd6.5
16IORING_SETUP_NO_SQARRAYDrop the SQ index indirection array; SQEs submitted in ring order6.6
17IORING_SETUP_HYBRID_IOPOLLHybrid (sleep-then-poll) IOPOLL to cut busy-poll CPU6.13
18IORING_SETUP_CQE_MIXEDAllow both 16- and 32-byte CQEs; big CQEs flagged IORING_CQE_F_326.18
19IORING_SETUP_SQE_MIXEDAllow both 64- and 128-byte SQEs (128b ops use the *128 opcodes)6.19
20IORING_SETUP_SQ_REWINDIgnore SQ head/tail; always fetch SQEs from index 0 (needs NO_SQARRAY, excl. SQPOLL)7.0

See features.md for the COOP/DEFER taskrun and SINGLE_ISSUER scheduling story, and timeline.md for how SQPOLL → COOP_TASKRUNDEFER_TASKRUN evolved.


4. IORING_FEAT_* — feature flags (io_uring_params.features, output)

From io_uring.h:629. The kernel fills features on a successful io_uring_setup(2); applications must check these bits before relying on the corresponding behavior.

BitMacroWhat it advertisesSince
0IORING_FEAT_SINGLE_MMAPSQ and CQ rings can share one mmap (offsets coincide)5.4
1IORING_FEAT_NODROPCQEs are never silently dropped on overflow; overflow is tracked5.5
2IORING_FEAT_SUBMIT_STABLESQE data is fully consumed at submit; app may reuse the SQE immediately5.5
3IORING_FEAT_RW_CUR_POSOffset -1 means "use the file's current position" for read/write5.6
4IORING_FEAT_CUR_PERSONALITYRequests run with the personality of the submitting task by default5.6
5IORING_FEAT_FAST_POLLInternal async poll for non-ready fds (the "fast poll" backbone of network I/O)5.7
6IORING_FEAT_POLL_32BITSpoll_add accepts 32-bit (EPOLLEXCLUSIVE etc.) poll masks5.9
7IORING_FEAT_SQPOLL_NONFIXEDSQPOLL works with non-registered files5.11
8IORING_FEAT_EXT_ARGio_uring_enter(2) accepts the extended-arg struct (timeout + sigmask)5.11
9IORING_FEAT_NATIVE_WORKERSio-wq workers are native kernel threads (not kthreads)5.12
10IORING_FEAT_RSRC_TAGSRegistered resources support update tags for lifetime tracking5.13
11IORING_FEAT_CQE_SKIPIOSQE_CQE_SKIP_SUCCESS is honored5.17
12IORING_FEAT_LINKED_FILELinked SQEs resolve the file lazily, after the prior link completes5.18
13IORING_FEAT_REG_REG_RINGA registered ring-fd may itself be used for IORING_REGISTER_*6.3
14IORING_FEAT_RECVSEND_BUNDLEIORING_RECVSEND_BUNDLE (grab many provided buffers per send/recv)6.10
15IORING_FEAT_MIN_TIMEOUTWait supports a "min-wait" window (min_wait_usec)6.12
16IORING_FEAT_RW_ATTRRead/write attribute pointer (attr_ptr/attr_type_mask, e.g. PI metadata)6.14
17IORING_FEAT_NO_IOWAITIORING_ENTER_NO_IOWAIT is honored (skip iowait accounting on wait)6.15

5. IORING_ENTER_*io_uring_enter(2) flags

From io_uring.h:600. Passed as the flags argument of the io_uring_enter(2) syscall (liburing's io_uring_submit* / io_uring_wait_cqe* wrap these).

BitMacroEffectSince
0IORING_ENTER_GETEVENTSBlock until at least min_complete CQEs are available5.1
1IORING_ENTER_SQ_WAKEUPWake the SQPOLL thread if it has gone to sleep5.1
2IORING_ENTER_SQ_WAITWait for the SQPOLL thread to consume the SQ before returning5.10
3IORING_ENTER_EXT_ARGarg/argsz point at struct io_uring_getevents_arg (timeout + sigmask)5.11
4IORING_ENTER_REGISTERED_RINGfd is a registered ring index, not a real fd5.18
5IORING_ENTER_ABS_TIMERTreat the wait timeout as an absolute time6.12
6IORING_ENTER_EXT_ARG_REGarg is an index into a pre-registered fixed wait region (io_uring_reg_wait)6.13
7IORING_ENTER_NO_IOWAITDon't account the wait as iowait (avoids inflating load averages)6.15

6. IORING_CQE_F_* — completion flags (cqe->flags, __u32)

From io_uring.h:538. The upper 16 bits of cqe->flags carry the buffer ID when IORING_CQE_F_BUFFER is set (IORING_CQE_BUFFER_SHIFT == 16, io_uring.h:546).

BitMacroMeaningSince
0IORING_CQE_F_BUFFERUpper 16 bits hold the provided-buffer ID that was consumed5.7
1IORING_CQE_F_MOREThe parent SQE will generate more CQEs (multishot still armed)5.13
2IORING_CQE_F_SOCK_NONEMPTYAfter a socket recv, more data remains to be read5.19
3IORING_CQE_F_NOTIFThis is the zero-copy notification CQE (distinct from the send CQE)6.0
4IORING_CQE_F_BUF_MOREAn incremental (IOU_PBUF_RING_INC) buffer is partially consumed; more to come6.12
5IORING_CQE_F_SKIPPadding CQE — the application/liburing must ignore it6.18
15IORING_CQE_F_32This is a 32-byte (big) CQE, posted in a IORING_SETUP_CQE_MIXED ring6.18

A related socket-timestamp flag, IORING_CQE_F_TSTAMP_HW (io_uring.h:1054), lives at bit 16 (IORING_TIMESTAMP_HW_SHIFT) and is only meaningful for SOCKET_URING_OP_TX_TIMESTAMP URING_CMD completions, where it overlaps the buffer-ID region.

sq_ring->flags (io_uring.h:576) and cq_ring->flags (io_uring.h:597) carry the kernel-side ring status bits the app polls without a syscall:

MacroRingMeaning
IORING_SQ_NEED_WAKEUPSQSQPOLL thread sleeping — call enter with SQ_WAKEUP
IORING_SQ_CQ_OVERFLOWSQCQ overflowed; enter the kernel to flush the overflow list
IORING_SQ_TASKRUNSQTask-work pending (set when TASKRUN_FLAG is on)
IORING_CQ_EVENTFD_DISABLEDCQeventfd notifications are currently suppressed

7. IORING_REGISTER_*io_uring_register(2) opcodes

From enum io_uring_register_op (io_uring.h:652). The high bit IORING_REGISTER_USE_REGISTERED_RING (1U << 31) is OR-ed into the opcode to operate on a registered ring-fd index instead of a real fd. The sentinel is IORING_REGISTER_LAST.

ValIORING_REGISTER_*PurposeSince
0REGISTER_BUFFERSRegister fixed I/O buffers5.1
1UNREGISTER_BUFFERSDrop all fixed buffers5.1
2REGISTER_FILESRegister a fixed-file table5.1
3UNREGISTER_FILESDrop the fixed-file table5.1
4REGISTER_EVENTFDAttach an eventfd for completion notifications5.2
5UNREGISTER_EVENTFDDetach the eventfd5.2
6REGISTER_FILES_UPDATEUpdate slots in the fixed-file table5.5
7REGISTER_EVENTFD_ASYNCeventfd notifications only for async (io-wq) completions5.6
8REGISTER_PROBEQuery which opcodes the kernel supports5.6
9REGISTER_PERSONALITYRegister a credential set; returns a personality ID5.6
10UNREGISTER_PERSONALITYDrop a personality5.6
11REGISTER_RESTRICTIONSRestrict allowed ops/flags (for sandboxing a ring)5.10
12REGISTER_ENABLE_RINGSEnable a ring created with IORING_SETUP_R_DISABLED5.10
13REGISTER_FILES2Register files with resource tags5.13
14REGISTER_FILES_UPDATE2Tagged fixed-file update5.13
15REGISTER_BUFFERS2Register buffers with resource tags5.13
16REGISTER_BUFFERS_UPDATETagged fixed-buffer update5.13
17REGISTER_IOWQ_AFFSet io-wq worker CPU affinity5.14
18UNREGISTER_IOWQ_AFFClear io-wq worker affinity5.14
19REGISTER_IOWQ_MAX_WORKERSGet/set max bound & unbound io-wq workers5.15
20REGISTER_RING_FDSRegister ring-fds for IORING_ENTER_REGISTERED_RING5.18
21UNREGISTER_RING_FDSUnregister ring-fds5.18
22REGISTER_PBUF_RINGRegister a provided-buffer ring (the modern fast path)5.19
23UNREGISTER_PBUF_RINGUnregister a provided-buffer ring5.19
24REGISTER_SYNC_CANCELSynchronous cancel API (cancel from the register path)6.0
25REGISTER_FILE_ALLOC_RANGEReserve a fixed-file slot range for auto-allocation6.0
26REGISTER_PBUF_STATUSQuery head/consumption status of a provided-buffer group6.8
27REGISTER_NAPIConfigure NAPI busy-poll for the ring6.9
28UNREGISTER_NAPIDisable NAPI busy-poll6.9
29REGISTER_CLOCKChoose the clock source for ring timeouts6.12
30REGISTER_CLONE_BUFFERSClone registered buffers from another ring6.12
31REGISTER_SEND_MSG_RINGSend an MSG_RING without owning a source ring6.13
32REGISTER_ZCRX_IFQRegister a netdev hw RX queue for zero-copy receive6.15
33REGISTER_RESIZE_RINGSResize the SQ/CQ rings in place6.13
34REGISTER_MEM_REGIONRegister a user memory region (e.g. fixed wait args)6.13
35REGISTER_QUERYQuery io_uring attributes (linux/io_uring/query.h)6.18
36REGISTER_ZCRX_CTRLAuxiliary zero-copy-RX control (enum zcrx_ctrl_op)6.19
37REGISTER_BPF_FILTERRegister a BPF filtering program for the ring7.0
38REGISTER_LASTSentinel

Auxiliary register-path enums:

Enum / flagWhere (io_uring.h)Meaning
IO_WQ_BOUND / IO_WQ_UNBOUND:734io-wq worker categories for REGISTER_IOWQ_MAX_WORKERS
IORING_RSRC_REGISTER_SPARSE:775Register an all-sparse (placeholder) resource table
IORING_REGISTER_FILES_SKIP (-2):801"Leave this fd-table slot unchanged" sentinel in an update
IO_URING_OP_SUPPORTED (1U << 0):803io_uring_probe_op.flags bit set when an opcode is supported
IORING_REGISTER_SRC_REGISTERED / _DST_REPLACE:843Flags for REGISTER_CLONE_BUFFERS
IORING_MEM_REGION_TYPE_USER (1):746Memory region backed by user-provided memory
IORING_MEM_REGION_REG_WAIT_ARG (1):760Expose the region as registered wait arguments
IORING_REG_WAIT_TS (1U << 0):975io_uring_reg_wait.flags: the embedded timespec is valid

enum io_uring_register_restriction_op (io_uring.h:958) drives REGISTER_RESTRICTIONS:

ValMacroRestriction
0IORING_RESTRICTION_REGISTER_OPWhitelist a io_uring_register(2) opcode
1IORING_RESTRICTION_SQE_OPWhitelist an SQE opcode
2IORING_RESTRICTION_SQE_FLAGS_ALLOWEDWhitelist SQE flags
3IORING_RESTRICTION_SQE_FLAGS_REQUIREDRequire these SQE flags on every submission

8. Per-op flag enums

Each op family squeezes its own flags into a free SQE field. The table below records which field each lives in — a common source of bugs, since the same field is unioned across opcodes (struct io_uring_sqe, io_uring.h:32).

8.1 recv / send — sqe->ioprio (io_uring.h:437)

BitMacroEffectSince
0IORING_RECVSEND_POLL_FIRSTArm poll up-front; skip the initial transfer attempt5.19
1IORING_RECV_MULTISHOTMultishot recv — keep posting CQEs (sets IORING_CQE_F_MORE)6.0
2IORING_RECVSEND_FIXED_BUFUse a registered buffer (buf_index) for the transfer6.0
3IORING_SEND_ZC_REPORT_USAGEReport zero-copy usage in the notification cqe->res6.2
4IORING_RECVSEND_BUNDLEWith BUFFER_SELECT, grab many contiguous provided buffers in one op6.10
5IORING_SEND_VECTORIZEDSEND[_ZC] takes an iovec pointer for vectored sends6.17

Companion: IORING_NOTIF_USAGE_ZC_COPIED (1U << 31, io_uring.h:451) in the notification cqe->res means data was copied (zero-copy did not happen).

8.2 accept — sqe->ioprio (io_uring.h:456)

BitMacroEffectSince
0IORING_ACCEPT_MULTISHOTKeep accepting connections from one SQE5.19
1IORING_ACCEPT_DONTWAITNon-blocking accept (-EAGAIN if none pending)6.10
2IORING_ACCEPT_POLL_FIRSTArm poll up-front before the first accept attempt6.10

8.3 poll — sqe->len (io_uring.h:380)

POLL_ADD puts the poll mask in sqe->poll32_events (the flag field), so its command flags live in sqe->len:

BitMacroEffectSince
0IORING_POLL_ADD_MULTIMultishot poll (sets IORING_CQE_F_MORE)5.13
1IORING_POLL_UPDATE_EVENTSUpdate the event mask of an existing poll5.13
2IORING_POLL_UPDATE_USER_DATAUpdate the user_data of an existing poll5.13
3IORING_POLL_ADD_LEVELLevel-triggered (vs. edge-triggered) poll6.0

8.4 timeout — sqe->timeout_flags (io_uring.h:351)

BitMacroEffectSince
0IORING_TIMEOUT_ABSTimeout value is absolute, not relative5.5
1IORING_TIMEOUT_UPDATEThis is a timeout update, not a new timeout5.11
2IORING_TIMEOUT_BOOTTIMEUse CLOCK_BOOTTIME5.15
3IORING_TIMEOUT_REALTIMEUse CLOCK_REALTIME5.15
4IORING_LINK_TIMEOUT_UPDATEUpdate a linked timeout5.15
5IORING_TIMEOUT_ETIME_SUCCESSReport -ETIME expiry as a success completion5.16
6IORING_TIMEOUT_MULTISHOTRepeating timeout (fires periodically)6.4
7IORING_TIMEOUT_IMMEDIATE_ARGsqe->addr is the nanosecond value, not a timespec ptr7.1

Masks: IORING_TIMEOUT_CLOCK_MASK (BOOTTIME|REALTIME), IORING_TIMEOUT_UPDATE_MASK (UPDATE|LINK_TIMEOUT_UPDATE).

8.5 async-cancel — sqe->cancel_flags (io_uring.h:396)

Also used by struct io_uring_sync_cancel_reg.flags for REGISTER_SYNC_CANCEL.

BitMacroMatch keySince
0IORING_ASYNC_CANCEL_ALLCancel all requests matching the key, not just the first5.19
1IORING_ASYNC_CANCEL_FDMatch on sqe->fd instead of user_data5.19
2IORING_ASYNC_CANCEL_ANYMatch any in-flight request5.19
3IORING_ASYNC_CANCEL_FD_FIXEDThe fd to match is a fixed-fd slot6.0
4IORING_ASYNC_CANCEL_USERDATAMatch on user_data (the default if no other key)6.6
5IORING_ASYNC_CANCEL_OPMatch on opcode6.6

8.6 provided-buffer ring — enum io_uring_register_pbuf_ring_flags (io_uring.h:897)

struct io_uring_buf_reg.flags for REGISTER_PBUF_RING:

ValMacroEffectSince
1IOU_PBUF_RING_MMAPKernel allocates the ring; app mmaps it at IORING_OFF_PBUF_RING|(bgid<<16)6.4
2IOU_PBUF_RING_INCBuffers may be incrementally consumed (pairs with IORING_CQE_F_BUF_MORE)6.12

8.7 other per-op flags

Field / enumMacro(s)Where
sqe->uring_cmd_flagsIORING_URING_CMD_FIXED, IORING_URING_CMD_MULTISHOT (mask _MASK):334
sqe->fsync_flagsIORING_FSYNC_DATASYNC:342
sqe->splice_flagsSPLICE_F_FD_IN_FIXED (1U << 31):365
sqe->msg_ring_flagsIORING_MSG_RING_CQE_SKIP, IORING_MSG_RING_FLAGS_PASS:474
sqe->addr (MSG_RING command)IORING_MSG_DATA (0), IORING_MSG_SEND_FD (1):463
sqe->install_fd_flagsIORING_FIXED_FD_NO_CLOEXEC:483
sqe->nop_flagsIORING_NOP_INJECT_RESULT, _FILE, _FIXED_FILE, _FIXED_BUFFER, _TW, _CQE32:490
sqe->attr_type_mask (PI)IORING_RW_ATTR_FLAG_PI:123
socket URING_CMD sub-opSOCKET_URING_OP_SIOCINQ/SIOCOUTQ/GETSOCKOPT/SETSOCKOPT/TX_TIMESTAMP/GETSOCKNAME:1037
NAPI op / trackingIO_URING_NAPI_REGISTER_OP/STATIC_ADD_ID/STATIC_DEL_ID; ..._TRACKING_DYNAMIC/STATIC/INACTIVE:919,:928

IORING_FILE_INDEX_ALLOC (~0U, io_uring.h:141) in sqe->file_index asks the kernel to auto-pick a free fixed-fd slot for opcodes that instantiate one (OPENAT, ACCEPT, SOCKET, …); the chosen slot is returned in cqe->res.


9. mmap offsets & ring memory

The SQ ring, CQ ring, SQE array, and provided-buffer rings live at magic mmap(2) offsets (io_uring.h:551). These are the addresses liburing maps internally during io_uring_queue_init():

MacroOffsetMaps
IORING_OFF_SQ_RING0SQ ring header + index array
IORING_OFF_CQ_RING0x8000000CQ ring header + CQE array
IORING_OFF_SQES0x10000000The SQE array itself
IORING_OFF_PBUF_RING0x80000000A provided-buffer ring; OR in bgid << IORING_OFF_PBUF_SHIFT (16)
IORING_OFF_MMAP_MASK0xf8000000Mask selecting which region an offset refers to

10. liburing io_uring_prep_* helper families

User space rarely fills struct io_uring_sqe by hand. liburing/src/include/liburing.h provides static inline setters; all of them ultimately call the workhorse io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, const void *addr, unsigned len, __u64 offset) (liburing.h:592), which sets only opcode/fd/off/addr/len. The remaining fields are cleared separately by io_uring_initialize_sqe() (liburing.h:579), which io_uring_get_sqe() invokes when handing out a fresh SQE. Families:

FamilyRepresentative helpersNotes
Read/Writeread, write, readv/readv2, writev/writev2, read_fixed, write_fixed, readv_fixed, writev_fixed, read_multishot*_fixed set buf_index; *2 take RWF flags
File syncfsync, sync_file_range, fallocate, ftruncatefsync sets fsync_flags
Open/Closeopenat, openat2, open, close, plus *_direct / close_direct for fixed-fd slots_direct set file_index (or IORING_FILE_INDEX_ALLOC)
FS namespacerenameat/rename, unlinkat/unlink, mkdirat/mkdir, symlinkat/symlink, linkat/linkthin wrappers over the *at syscalls
Metadatastatx, fadvise/fadvise64, madvise/madvise6464 variants take a 64-bit length
xattrsetxattr, fsetxattr, getxattr, fgetxattr
Network — connectsocket, socket_direct, socket_direct_alloc, bind, listen, connect, accept, accept_direct, multishot_accept, multishot_accept_direct, shutdown_direct create fixed-fd slots
Network — transfersend, sendto, send_bundle, send_set_addr, sendmsg, recv, recv_multishot, recvmsg, recvmsg_multishotset msg_flags / RECVSEND flags
Network — zero-copysend_zc, send_zc_fixed, sendmsg_zc, sendmsg_zc_fixedpost a IORING_CQE_F_NOTIF CQE
Pollpoll_add, poll_multishot, poll_remove, poll_update, poll_mask (internal mask byte-swap)set poll32_events + IORING_POLL_* in len
Timeouttimeout, timeout_remove, timeout_update, link_timeoutset timeout_flags
Cancelcancel, cancel64, cancel_fdset cancel_flags (IORING_ASYNC_CANCEL_*)
epollepoll_ctl, epoll_wait
Splice/Teesplice, teeset splice_fd_in / splice_off_in
Buffers (legacy)provide_buffers, remove_bufferssuperseded by register_buf_ring
Files updatefiles_update, fixed_fd_installmanage the fixed-file table inline
Pipepipe, pipe_direct_direct installs fixed-fd slots
futex / waitidfutex_wait, futex_wake, futex_waitv, waitid
Message ringmsg_ring, msg_ring_cqe_flags, msg_ring_fd, msg_ring_fd_alloccross-ring messaging
Pass-through cmduring_cmd, uring_cmd128, cmd_sock, cmd_discard, cmd_getsocknameNVMe / socket control via URING_CMD
No-opnop, nop128nop128 exercises 128-byte SQEs

Queue, submit, completion & data helpers

HelperRole
io_uring_queue_init / _params / _memSet up the ring (flags / full params / app-supplied memory)
io_uring_queue_exitTear down the ring
io_uring_get_sqeGrab the next free SQE
io_uring_sqe_set_data / _data64 / set_flagsStash user_data / set IOSQE_*
io_uring_submitio_uring_enter to submit pending SQEs
io_uring_submit_and_wait / _timeout / _min_timeoutSubmit, then block for completions (optionally bounded)
io_uring_submit_and_get_events / _and_wait_regSubmit + flush; registered-wait-region variant
io_uring_wait_cqe / _nr / _timeout / wait_cqesBlock for one / N / time-bounded / batched completions
io_uring_peek_cqeNon-blocking CQE peek
io_uring_cqe_get_data / _data64 / cqe_seenRead back user_data / mark a CQE consumed

Register API surface

These wrap the §7 opcodes:

HelperBacking opcode(s)
io_uring_register_buffers / _sparse / _tags / _update_tagREGISTER_BUFFERS, BUFFERS2, BUFFERS_UPDATE
io_uring_register_files / _sparse / _tags / _update / _update_tagREGISTER_FILES, FILES2, FILES_UPDATE(2)
io_uring_register_file_alloc_rangeREGISTER_FILE_ALLOC_RANGE
io_uring_register_eventfd / _asyncREGISTER_EVENTFD, EVENTFD_ASYNC
io_uring_register_probeREGISTER_PROBE
io_uring_register_personalityREGISTER_PERSONALITY
io_uring_register_restrictionsREGISTER_RESTRICTIONS
io_uring_register_buf_ringREGISTER_PBUF_RING
io_uring_register_ring_fdREGISTER_RING_FDS
io_uring_register_iowq_aff / _max_workersREGISTER_IOWQ_AFF, IOWQ_MAX_WORKERS
io_uring_register_sync_cancel / _sync_msgREGISTER_SYNC_CANCEL, SEND_MSG_RING
io_uring_register_napiREGISTER_NAPI
io_uring_register_clockREGISTER_CLOCK
io_uring_register_region / _wait_regREGISTER_MEM_REGION (+ fixed wait args)
io_uring_register_ifqREGISTER_ZCRX_IFQ
io_uring_register_bpf_filter / _taskREGISTER_BPF_FILTER

Provided-buffer ring helpers

For the modern ring-based provided-buffer fast path (no per-batch syscall):

HelperRole
io_uring_buf_ring_initInitialize the io_uring_buf_ring tail
io_uring_buf_ring_maskCompute the ring index mask
io_uring_buf_ring_addAdd a buffer entry
io_uring_buf_ring_advance / _cq_advancePublish added buffers to the kernel
io_uring_buf_ring_head / _availableInspect head / count of available buffers

Field-overlap cheat sheet

The single biggest UABI footgun is the struct io_uring_sqe unions: the same byte range means different things per opcode. The most-used overlaps:

FieldPlain meaningReused by
sqe->offfile offsetaddr2; cmd_op+__pad1 (for URING_CMD)
sqe->addrbuffer / iovec pointersplice_off_in; level+optname (socket cmd)
sqe->ioprioI/O priorityRECVSEND flags, ACCEPT flags, poll command flags
*_flags union (rw_flags)per-op flagsfsync_flags, timeout_flags, accept_flags, cancel_flags, msg_ring_flags, nop_flags, …
buf_indexfixed-buffer indexbuf_group (for IOSQE_BUFFER_SELECT)
splice_fd_insplice source fdfile_index, zcrx_ifq_idx, optlen, addr_len
addr3third addressattr_ptr+attr_type_mask (PI), optval, cmd[] (SQE128)

For the design rationale behind these primitives — submission/completion rings, fixed files/buffers, multishot, provided buffers, zero-copy, and the io-wq fallback — see the feature catalog; for the chronological "when did X land" view, see the timeline. For how language runtimes consume this UABI, see Tokio, Glommio, Monoio, Seastar, and the effects-based OCaml Eio.


Sources