Moves nbytes from fd_in at off_in to fd_out at off_out (splice(2)), one of them a pipe. -1 as an offset means the fd's own position; splice_flags are SPLICE_F_*.
Note
Linux 5.7+.
cqe.res: bytes spliced.
A pipe's offset must be -1; the other fd's -1 reads/writes at its file position and advances it.
io_uring_prep_readv(sqe: SQE, fd: int, bufs: Sequence[Buffer], offset: int | None = None, flags: int | None = None) -> bool#
Reads into several buffers at once (preadv2).
Example
>>> bufs = [bytearray(6),bytearray(4)]>>>io_uring_prep_readv(sqe, fd, bufs)True>>>io_uring_submit_and_wait(ring,1)1>>> bufs # after the completion[bytearray(b'hi... '), bytearray(b'bye!')]
Setup used to run this example
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
bufs: 1 to IOV_MAX writable buffers (bytearray, memoryview, array.array, ...); the request holds them (locked: no resize) and their struct iovec array until its completion.
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
cqe.res: bytes read.
buff must lie inside the registered buffer buf_index (OSError: EFAULT otherwise); it need not start at its beginning (a memoryview slice of it works).
Reads into several buffers at once, from the registered buffer buf_index.
Example
>>> mem =bytearray(10)>>>io_uring_register_buffers(ring, [mem]) # `buf_index` 00>>> view =memoryview(mem)>>> bufs = [view[:6], view[6:]] # parts of the registered buffer>>>io_uring_prep_readv_fixed(sqe, fd, bufs,0)True>>>io_uring_submit_and_wait(ring,1)1>>> mem # after the completionbytearray(b'hi... bye!')
Setup used to run this example
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
Linux 6.15+.
cqe.res: bytes read.
bufs: as io_uring_prep_readv, held until the completion; every buffer must lie inside the registered buffer buf_index.
flags are RWF_* (preadv2(2)), default 0.
io_uring_prep_writev(sqe: SQE, fd: int, bufs: Sequence[Buffer], offset: int | None = None, flags: int | None = None) -> bool#
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
bufs: 1 to IOV_MAX buffers (bytes too); the request holds them and their struct iovec array until its completion.
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
cqe.res: bytes written, at most INT_MAX per request.
buff must lie inside the registered buffer buf_index (OSError: EFAULT otherwise): a bytes object can not. It need not start at its beginning (a memoryview slice of it works).
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
Linux 6.15+.
cqe.res: bytes written, at most INT_MAX per request.
bufs: as io_uring_prep_writev, held until the completion; every buffer must lie inside the registered buffer buf_index (so no bytes).
Syncs the file fd to disk (fsync(2)); fsync_flags is 0 (default) or IORING_FSYNC_DATASYNC (fdatasync(2)).
Note
cqe.res: 0.
Requests run in parallel: an fsync submitted after a write does not cover that write unless they are linked (IOSQE_IO_LINK on the write), IOSQE_IO_DRAIN is set, or the write's CQE arrived first.
Syncs the whole file: the C range fields (sqe.off, sqe.len) are not settable from Python.
'Sqe','put_sqe','io_uring_prep_open','io_uring_prep_open_direct','io_uring_prep_read','io_uring_prep_write','io_uring_prep_statx','Statx','io_uring_register_files','io_uring_register_files_tags',) # fmt: skipdeffile_ring(ns):'''A ring (2 entries for `put_sqe`, to show a full one), an empty `cqe` and `fd` of `./file.txt` (`hi... bye!`).'''make_ring(ns,entries=2if ns['_name'] =='put_sqe'else1024) ns['cqe'] =Cqe()make_file(ns)
Note
Linux 5.6+.
Function argument dfd has been moved to end from how it is in C function.
flags defaults to 0 (O_RDONLY), mode to 0o777 (used with O_CREAT, masked by the umask), dfd to AT_FDCWD; dfd is always a normal fd, never a registered one.
io_uring_prep_open_direct(sqe: SQE, path: str | os.PathLike[str], flags: int | None = None, file_index: int | None = None, mode: int | None = None, dfd: int | None = None) -> bool#
Opens path into the registered files table at slot file_index instead of returning an fd.
'Sqe','put_sqe','io_uring_prep_open','io_uring_prep_open_direct','io_uring_prep_read','io_uring_prep_write','io_uring_prep_statx','Statx','io_uring_register_files','io_uring_register_files_tags',) # fmt: skipdeffile_ring(ns):'''A ring (2 entries for `put_sqe`, to show a full one), an empty `cqe` and `fd` of `./file.txt` (`hi... bye!`).'''make_ring(ns,entries=2if ns['_name'] =='put_sqe'else1024) ns['cqe'] =Cqe()make_file(ns)
Note
Linux 5.15+.
Open direct does not use fd but index
file_index defaults to IORING_FILE_INDEX_ALLOC: a free direct descriptor is auto assigned. The allocated descriptor is returned in the cqe.res; OSError: ENFILE when the table has no free slot. With an explicit slot cqe.res is 0; a slot that already holds a file is closed and replaced.
Needs a registered files table (io_uring_register_files, sparse -1 entries are fine); the slot is then used as fd with IOSQE_FIXED_FILE in sqe.flags, only by io_uring requests.
flags defaults to O_RDONLY, mode to 0o777, dfd to AT_FDCWD (always a normal fd).
Function arguments position has changed for C origin for better usability.
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
Linux 5.15+.
cqe.res: 0. Same as unregistering the slot; fails only on an invalid slot or out of memory.
Do not set IOSQE_FIXED_FILE in sqe.flags here: the request would raise OSError: EBADF.
'Sqe','put_sqe','io_uring_prep_open','io_uring_prep_open_direct','io_uring_prep_read','io_uring_prep_write','io_uring_prep_statx','Statx','io_uring_register_files','io_uring_register_files_tags',) # fmt: skipdeffile_ring(ns):'''A ring (2 entries for `put_sqe`, to show a full one), an empty `cqe` and `fd` of `./file.txt` (`hi... bye!`).'''make_ring(ns,entries=2if ns['_name'] =='put_sqe'else1024) ns['cqe'] =Cqe()make_file(ns)
Note
Linux 5.6+.
cqe.res: bytes read (0 at end of file); a non-seekable file (pipe, socket, ...) needs offset0.
io_uring_prep_read_multishot(sqe: SQE, fd: int, buf_group: int, nbytes: int | None = None, offset: int | None = None) -> bool#
Reads from fd repeatedly, each time into a buffer the kernel picks from the provided buffer group buf_group; nbytes of 0 (default) reads up to the buffer's size.
Note
Linux 6.7+.
Function arguments position has changed for C origin for better usability.
Pollable files only (pipes, tun devices, ...): a regular file raises OSError: EBADFD.
Each CQE: cqe.res the bytes read, IORING_CQE_F_BUFFER in cqe.flags with the buffer id, and IORING_CQE_F_MORE while the request stays armed; a CQE without it (or an error) ends the request.
nbytes larger than the group's buffers is clamped to the buffer size.
'Sqe','put_sqe','io_uring_prep_open','io_uring_prep_open_direct','io_uring_prep_read','io_uring_prep_write','io_uring_prep_statx','Statx','io_uring_register_files','io_uring_register_files_tags',) # fmt: skipdeffile_ring(ns):'''A ring (2 entries for `put_sqe`, to show a full one), an empty `cqe` and `fd` of `./file.txt` (`hi... bye!`).'''make_ring(ns,entries=2if ns['_name'] =='put_sqe'else1024) ns['cqe'] =Cqe()make_file(ns)
Note
Linux 5.6+.
At most INT_MAX bytes per request; a non-seekable file (pipe, socket, ...) needs offset0.
io_uring_prep_statx(sqe: SQE, statxbuf: Statx, path: str | os.PathLike[str], flags: int | None = None, mask: int | None = None, dfd: int | None = None) -> bool#
Gets the file's statx(2) info into statxbuf (held until the completion).
'Sqe','put_sqe','io_uring_prep_open','io_uring_prep_open_direct','io_uring_prep_read','io_uring_prep_write','io_uring_prep_statx','Statx','io_uring_register_files','io_uring_register_files_tags',) # fmt: skipdeffile_ring(ns):'''A ring (2 entries for `put_sqe`, to show a full one), an empty `cqe` and `fd` of `./file.txt` (`hi... bye!`).'''make_ring(ns,entries=2if ns['_name'] =='put_sqe'else1024) ns['cqe'] =Cqe()make_file(ns)
Advises the kernel on the file use of len bytes from offset (default 0) (posix_fadvise(2)); advice is POSIX_FADV_*. Up to 4 GiB - 1; io_uring_prep_fadvise64 for more.
Note
Linux 5.6+.
cqe.res: 0.
Function arguments position has changed for C origin for better usability.
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
buf: writable (an mmap.mmap, or a memoryview slice of one): advice like MADV_DONTNEED changes its contents. It must start on a page boundary (OSError: EINVAL otherwise), as madvise(2) asks.
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
A buf over 4 GiB - 1 raises OSError: EINVAL on older kernels without 64-bit length support.
file_index defaults to IORING_FILE_INDEX_ALLOC: a free direct descriptor is auto assigned. The allocated descriptor is returned in the cqe.res; OSError: ENFILE when the table has no free slot. With an explicit slot cqe.res is 0; a slot that already holds a file is closed and replaced.
Sets the extended attribute name of path to value, len bytes (setxattr(2)); flags is 0 (create or replace), XATTR_CREATE (OSError: EEXIST if it exists) or XATTR_REPLACE (OSError: ENODATA if it does not).
The two fds of the new pipe are written into fds (read end, then write end) when the request completes.
Example
>>> fds = array.array("i", [-1,-1]) # or a `bytearray(8)`>>>io_uring_prep_pipe(sqe, fds,O_CLOEXEC)True>>>io_uring_submit_and_wait(ring,1)1>>> os.write(fds[1],b'hi'), os.read(fds[0],2) # after the completion: read end, write end(2, b'hi')
Setup used to run this example
'io_uring_prep_readv','io_uring_prep_read_fixed','io_uring_prep_readv_fixed','io_uring_prep_writev','io_uring_prep_write_fixed','io_uring_prep_writev_fixed','io_uring_prep_close','io_uring_prep_close_direct','io_uring_prep_madvise','io_uring_prep_madvise64','io_uring_prep_pipe','OpenHow',) # fmt: skipdeffile_io(ns):'''`file_ring`, with an `sqe` of the ring.'''file_ring(ns) ns['sqe'] =io_uring_get_sqe(ns['ring'])
Note
Linux 6.16+.
cqe.res: 0; the fds are valid only after the completion.
Like io_uring_prep_pipe, but the pipe's fds go into the registered file table: fds gets the two slots (file_index for the read end and the next slot for the write end; IORING_FILE_INDEX_ALLOC lets the kernel pick both).
Note
Linux 6.16+.
Needs a registered files table (io_uring_register_files); with an explicit file_index both slots must be free or the request fails.
cqe.res: 0; fds holds the two slots after the completion, used as fd with IOSQE_FIXED_FILE.
Discards nbytes of the block device fd from offset (BLOCK_URING_CMD_DISCARD).
Note
Linux 6.12+.
cqe.res is 0, or the negated errno.
Unlike the ioctl, several discards may run at once and reads / writes of the range are not held off: keep your own I/O off the range, or the data and the page cache (invalidated best-effort) may go stale.