io_submit(2)
โจ io_submit(2) โจ โ the Linux syscall manual, but make it make sense ๐
okay bestie, sit down, hydrate, and let's talk about io_submit(2) โ that's the syscall page from the Linux man-pages, and yes it's giving "kernel internals" but honestly? it's iconic. ๐ฆ
๐ธ NAME ๐ธ
io_submit โ submit asynchronous I/O blocks for processing. that's it, that's the whole vibe. you hand the kernel a pile of I/O requests and it goes "bet, I'll get to those." ๐
๐ LIBRARY ๐
Standard C library (libc, -lc). the basics, no cap.
๐ SYNOPSIS ๐
#include <linux/aio_abi.h>
#include <sys/syscall.h> /* Definition of SYS_* constants */
#include <unistd.h>
int syscall(SYS_io_submit, aio_context_t ctx_id,
long n, struct iocb *iocbpp[n]);
yes it's the raw syscall(2) route. we'll talk about the glow-up version in VERSIONS, don't worry. ๐
๐ DESCRIPTION ๐
not me about to say the most important thing first: you probably want to use theio_setup(3)wrapper function provided bylibaioinstead. see VERSIONS for the tea. ๐
the actual tea โ
io_submit() queues up n I/O request blocks for processing in the AIO context ctx_id. the iocbpp argument should be an array of n AIO control blocks, and those bad boys get submitted to context ctx_id. it's giving "batch submit, no small talk." โจ
the iocb structure ๐
the iocb (I/O control block) structure, defined over in linux/aio_abi.h, is literally the blueprint โ it defines the parameters that control the I/O operation. main character energy fr fr.
#include <linux/aio_abi.h>
struct iocb {
__u64 aio_data;
__u32 PADDED(aio_key, aio_rw_flags);
__u16 aio_lio_opcode;
__s16 aio_reqprio;
__u32 aio_fildes;
__u64 aio_buf;
__u64 aio_nbytes;
__s64 aio_offset;
__u64 aio_reserved2;
__u32 aio_flags;
__u32 aio_resfd;
};
the fields, one by one ๐ง
aio_dataโ this data gets copied into thedatafield of theio_eventstructure when the I/O completes (peepio_getevents(2)). it's your little note-to-self that comes back to you. ๐ซถaio_keyโ internal kernel field. do NOT modify this field after anio_submit()call. hands off, bestie, that one's not yours. ๐ซaio_rw_flagsโ this defines the R/W flags passed with the structure. the valid values are:RWF_APPEND(since Linux 4.16) โ append data to the end of the file. check the description of the flag with the same name inpwritev2(2), plus theO_APPENDdescription inopen(2). theaio_offsetfield is ignored, and the file offset is not changed. no cap.RWF_DSYNC(since Linux 4.13) โ write operation completes according to the requirement of synchronized I/O data integrity. see the same-name flag inpwritev2(2)and theO_DSYNCbit inopen(2).RWF_HIPRI(since Linux 4.13) โ high priority request, poll if possible. VIP treatment, literally. ๐RWF_NOWAIT(since Linux 4.14) โ don't wait if the I/O will block for operations like file block allocations, dirty page flush, mutex locks, or a congested block device inside the kernel. if any of those conditions are met, the control block is returned immediately with a return value of-EAGAINin theresfield of theio_eventstructure (seeio_getevents(2)). it's the "I'm not waiting in line" flag. ๐RWF_SYNC(since Linux 4.13) โ write operation completes according to the requirement of synchronized I/O file integrity. see the same-name flag inpwritev2(2)and theO_SYNCdescription inopen(2).RWF_NOAPPEND(since Linux 6.9) โ do not honor theO_APPENDopen(2)flag. see theRWF_NOAPPENDdescription inpwritev2(2).RWF_ATOMIC(since Linux 6.11) โ write a block of data such that a write will never be torn from power fail or similar. see theRWF_ATOMICdescription inpwritev2(2). for usage withIOCB_CMD_PWRITEV, the upper vector limit isstx_atomic_write_segments_maxโ check theSTATX_WRITE_ATOMICandstx_atomic_write_segments_maxdescriptions instatx(2). atomicity is the moment. ๐ฅ
aio_lio_opcodeโ this defines the type of I/O to be performed by theiocbstructure. the valid values come from the enum defined inlinux/aio_abi.h:
enum {
IOCB_CMD_PREAD = 0,
IOCB_CMD_PWRITE = 1,
IOCB_CMD_FSYNC = 2,
IOCB_CMD_FDSYNC = 3,
IOCB_CMD_POLL = 5,
IOCB_CMD_NOOP = 6,
IOCB_CMD_PREADV = 7,
IOCB_CMD_PWRITEV = 8,
};
aio_reqprioโ this defines the requests priority.aio_fildesโ the file descriptor on which the I/O operation is to be performed.aio_bufโ this is the buffer used to transfer data for a read or write operation.aio_nbytesโ this is the size of the buffer pointed to byaio_buf.aio_offsetโ this is the file offset at which the I/O operation is to be performed.aio_flagsโ this is the set of flags associated with theiocbstructure. the valid values are:IOCB_FLAG_RESFDโ asynchronous I/O control must signal the file descriptor mentioned inaio_resfdupon completion. it's a little "ding! done ๐" notification.IOCB_FLAG_IOPRIO(since Linux 4.18) โ interpret theaio_reqpriofield as anIOPRIO_VALUEas defined bylinux/ioprio.h.
aio_resfdโ the file descriptor to signal in the event of asynchronous I/O completion.
โญ RETURN VALUE โญ
On success, io_submit() returns the number of iocbs submitted โ and heads up, that number may be less than n, or 0 if n is zero. so yeah, partial submissions are a real thing, it's not lying to you. ๐ญ
On error, -1 is returned, and errno is set to indicate the error.
๐ ERRORS ๐
EAGAINโ insufficient resources are available to queue anyiocbs. the queue said "we're full bestie." ๐ซEBADFโ the file descriptor specified in the firstiocbis invalid.EFAULTโ one of the data structures points to invalid data.EINVALโ the AIO context specified byctx_idis invalid.EINVALโnis less than 0.EINVALโ theiocbat*iocbpp[0]is not properly initialized.EINVALโ the operation specified is invalid for the file descriptor in theiocb.EINVALโ the value in theaio_reqpriofield is invalid.ENOSYSโio_submit()is not implemented on this architecture. (this arch said "not my problem.") ๐EPERMโ theaio_reqpriofield is set with the classIOPRIO_CLASS_RT, but the submitting context does not have theCAP_SYS_ADMINcapability. permission check said no. ๐ซ
๐ VERSIONS ๐
libaio provides a wrapper function with the same name, but a different prototype and return value. you probably want to use that wrapper. (this is me, gently, taking your hand and steering you toward the wrapper.) ๐ซถ
๐ STANDARDS ๐
Linux.
๐ฆ HISTORY ๐ฆ
Linux 2.5. vintage, honestly.
๐ SEE ALSO ๐
io_cancel(2), io_destroy(2), io_getevents(2), io_setup(2), io_submit(3), aio(7)
and that's the page, bestie!! ๐ this little writeup came from Linux man-pages 6.20, dated 2026-04-11 โ so if the kernel did a glow-up since then, that's between you and the source tree. go submit some I/O, you're doing amazing, periodt. ๐ โจ
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: GPL-1.0-or-later
- Copyright 2003, Free Software Foundation, Inc
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms