Liburing 2026.10.29
static
YoSTEALTH/Liburing

Prep: files

Read, write, open, close, stat, rename and the other file-system operations.

io_uring_prep_splice(sqe: SQE, fd_in: int, off_in: int, fd_out: int, off_out: int, nbytes: int, splice_flags: int) -> bool#

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.
  • SPLICE_F_FD_IN_FIXED in splice_flags makes fd_in a registered file index; for a registered fd_out set IOSQE_FIXED_FILE in sqe.flags.

io_uring_prep_tee(sqe: SQE, fd_in: int, fd_out: int, nbytes: int, splice_flags: int) -> bool#

Copies nbytes between two pipes (tee(2)) without consuming the input; splice_flags are SPLICE_F_*.

Note

  • Linux 5.8+.
  • cqe.res: bytes duplicated, at most INT_MAX per request (limits as low as 65536 have been seen, as with tee(2)).
  • SPLICE_F_FD_IN_FIXED in splice_flags makes fd_in a registered file index; for a registered fd_out set IOSQE_FIXED_FILE in sqe.flags.

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: skip
def file_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 includes io_uring_prep_readv2 feature as well.
  • cqe.res: bytes read (0 at end of file).
  • offset defaults to 0; a non-seekable file (pipe, socket, ...) needs 0.
  • flags are RWF_* (preadv2(2)), default 0.
  • For a single buffer io_uring_prep_read is cheaper: no iovec state to keep.

io_uring_prep_read_fixed(sqe: SQE, fd: int, buff: Buffer, buf_index: int, offset: int | None = None) -> bool#

Reads into buff (all of it) from a registered buffer buf_index at offset (default 0). The request holds buff until its completion.

Example

>>> buffer = bytearray(5)
>>> io_uring_register_buffers(ring, [buffer])  # `buf_index` 0
0
>>> io_uring_prep_read_fixed(sqe, fd, buffer, 0)
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> buffer
bytearray(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: skip
def file_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).

io_uring_prep_readv_fixed(sqe: SQE, fd: int, bufs: Sequence[Buffer], buf_index: int, offset: int | None = None, flags: int | None = None) -> bool#

Reads into several buffers at once, from the registered buffer buf_index.

Example

>>> mem = bytearray(10)
>>> io_uring_register_buffers(ring, [mem])  # `buf_index` 0
0
>>> 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 completion
bytearray(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: skip
def file_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#

Writes several buffers at once (pwritev2).

Example

>>> io_uring_prep_writev(sqe, fd, [b'hi... ', b'bye!'])
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> io_uring_wait_cqe(ring, cqe)
0
>>> cqe[0].res  # bytes written
10
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: skip
def file_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_writev includes io_uring_prep_writev2 feature as well.
  • offset defaults to 0; a non-seekable file (pipe, socket, ...) needs 0.
  • flags are RWF_* (pwritev2(2)), default 0.
  • At most INT_MAX bytes per request. For a single buffer io_uring_prep_write is cheaper.

io_uring_prep_write_fixed(sqe: SQE, fd: int, buff: Buffer, buf_index: int, offset: int | None = None) -> bool#

Writes buff (all of it) from the registered buffer buf_index at offset (default 0). The request holds buff until its completion.

Example

>>> buffer = bytearray(b'hi...')
>>> io_uring_register_buffers(ring, [buffer])  # `buf_index` 0
0
>>> io_uring_prep_write_fixed(sqe, fd, buffer, 0)
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> io_uring_wait_cqe(ring, cqe)
0
>>> cqe[0].res  # bytes written
5
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: skip
def file_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_writev_fixed(sqe: SQE, fd: int, bufs: Sequence[Buffer], buf_index: int, offset: int | None = None, flags: int | None = None) -> bool#

Writes several buffers at once, from the registered buffer buf_index.

Example

>>> mem = bytearray(b'hi... bye!')
>>> io_uring_register_buffers(ring, [mem])  # `buf_index` 0
0
>>> view = memoryview(mem)
>>> io_uring_prep_writev_fixed(sqe, fd, [view[:6], view[6:]], 0)  # parts of the registered buffer
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> io_uring_wait_cqe(ring, cqe)
0
>>> cqe[0].res  # bytes written
10
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: skip
def file_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).
  • flags are RWF_* (pwritev2(2)), default 0.

io_uring_prep_fsync(sqe: SQE, fd: int, fsync_flags: int | None = None) -> bool#

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.

io_uring_prep_files_update(sqe: SQE, fds: FileIndex, offset: int | None = None) -> bool#

Updates the registered files table from fds, starting at slot offset (default 0). The request holds fds until its completion.

Note

  • Linux 5.6+.
  • cqe.res: the number of slots updated.
  • A slot that already holds a file is closed and replaced (as unregister then register, in one step); -1 in fds empties the slot.
  • IORING_FILE_INDEX_ALLOC as offset lets the kernel pick free slots, written back into fds, with cqe.res the number allocated.

io_uring_prep_fallocate(sqe: SQE, fd: int, mode: int, offset: int, len: int) -> bool#

Preallocates or deallocates the file range offset to offset + len (fallocate(2)).

Note

  • Linux 5.6+.
  • cqe.res: 0.
  • mode 0 allocates the range, growing the file if it ends past the current size.

Mode

FALLOC_FL_KEEP_SIZE       # default is extend size
FALLOC_FL_PUNCH_HOLE      # de-allocates range
FALLOC_FL_NO_HIDE_STALE   # reserved codepoint
FALLOC_FL_COLLAPSE_RANGE
FALLOC_FL_ZERO_RANGE
FALLOC_FL_INSERT_RANGE
FALLOC_FL_UNSHARE_RANGE

io_uring_prep_open(sqe: SQE, path: str | os.PathLike[str], flags: int | None = None, mode: int | None = None, dfd: int | None = None) -> bool#

Opens path; the new fd is returned in cqe.res.

Type

path str | os.PathLike[str]

Example

>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_open(sqe, './file.txt')
True
>>> sqe.user_data = 123
>>> io_uring_submit_and_wait(ring, 1)
1
>>> io_uring_wait_cqe(ring, cqe)
0
>>> fd = cqe[0].res  # the new fd
>>> os.read(fd, 5)
b'hi...'
Setup used to run this example
    '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: skip
def file_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=2 if ns['_name'] == 'put_sqe' else 1024)
    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.
  • io_uring_prep_open includes io_uring_prep_openat as well.
  • 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.

Type

path str | os.PathLike[str]

Example

>>> fds = FileIndex([-1, -1, -1, -1])
>>> index = 3  # position of last ---^ `fds` registered
>>> io_uring_register_files(ring, fds)
0
>>> flags = O_TMPFILE | O_WRONLY
>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_open_direct(sqe, ".", flags, index)
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> io_uring_wait_cqe(ring, cqe)
0
>>> cqe[0].res  # `0`: opened into slot `index`
0
>>> io_uring_cqe_seen(ring, cqe[0])
>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_close_direct(sqe, index)
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> io_uring_unregister_files(ring)
0
Setup used to run this example
    '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: skip
def file_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=2 if ns['_name'] == 'put_sqe' else 1024)
    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_open_direct includes io_uring_prep_openat_direct as well.

io_uring_prep_close(sqe: SQE, fd: int) -> bool#

Closes the file fd.

Example

>>> io_uring_prep_close(sqe, fd)
True
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: skip
def file_io(ns):
    '''`file_ring`, with an `sqe` of the ring.'''
    file_ring(ns)
    ns['sqe'] = io_uring_get_sqe(ns['ring'])

Note

  • Linux 5.6+.
  • cqe.res: 0.

io_uring_prep_close_direct(sqe: SQE, file_index: int) -> bool#

Closes the registered (direct) file at slot file_index.

Example

>>> io_uring_prep_close_direct(sqe, 0)  # slot 0 of the registered files
True
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: skip
def file_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.

io_uring_prep_read(sqe: SQE, fd: int, buf: Buffer, offset: int | None = None) -> bool#

Reads into buf (all of it) from fd at offset (default 0), held until the completion.

Example

>>> buf = bytearray(5)
>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_read(sqe, fd, buf)
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> io_uring_wait_cqe(ring, cqe)
0
>>> cqe[0].res  # bytes read
5
>>> buf
bytearray(b'hi...')
Setup used to run this example
    '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: skip
def file_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=2 if ns['_name'] == 'put_sqe' else 1024)
    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 offset 0.

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.

io_uring_prep_write(sqe: SQE, fd: int, buf: Buffer, offset: int | None = None) -> bool#

Writes buf (all of it) to fd at offset (default 0), held until the completion.

Example

>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_write(sqe, fd, b"hi...")
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> io_uring_wait_cqe(ring, cqe)
0
>>> cqe[0].res  # bytes written
5
Setup used to run this example
    '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: skip
def file_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=2 if ns['_name'] == 'put_sqe' else 1024)
    ns['cqe'] = Cqe()
    make_file(ns)

Note

  • Linux 5.6+.
  • At most INT_MAX bytes per request; a non-seekable file (pipe, socket, ...) needs offset 0.

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).

Type

sqe SQE
statxbuf Statx
path str | os.PathLike[str]
flags int
mask int
dfd int
return bool

Example

>>> stat = Statx()
>>> if sqe := io_uring_get_sqe(ring):
...     io_uring_prep_statx(sqe, stat, 'file.txt')
...
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> stat.isfile
True
>>> stat.size
10
Setup used to run this example
    '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: skip
def file_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=2 if ns['_name'] == 'put_sqe' else 1024)
    ns['cqe'] = Cqe()
    make_file(ns)

Flags

Mask

STATX_TYPE          # Want|got `stx_mode & S_IFMT`
STATX_MODE          # Want|got `stx_mode & ~S_IFMT`
STATX_NLINK         # Want|got `stx_nlink`
STATX_UID           # Want|got `stx_uid`
STATX_GID           # Want|got `stx_gid`
STATX_ATIME         # Want|got `stx_atime`
STATX_MTIME         # Want|got `stx_mtime`
STATX_CTIME         # Want|got `stx_ctime`
STATX_INO           # Want|got `stx_ino`
STATX_SIZE          # Want|got `stx_size`
STATX_BLOCKS        # Want|got `stx_blocks`
STATX_BASIC_STATS   # [All of the above]
STATX_BTIME         # Want|got `stx_btime`
STATX_MNT_ID        # Got `stx_mnt_id`
# note: not supported
# STATX_DIOALIGN      # Want/got direct I/O alignment info

Note

  • Linux 5.6+.
  • cqe.res: 0; the fields are in statxbuf after the completion.
  • Function arguments position has changed for C origin for better usability.
  • STATX_ALL is deprecated, use STATX_BASIC_STATS | STATX_BTIME which is set by default.
  • dfd defaults to AT_FDCWD; to stat an open fd pass it as dfd with path '' and AT_EMPTY_PATH in flags.

io_uring_prep_fadvise(sqe: SQE, fd: int, len: int, advice: int, offset: int | None = None) -> bool#

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_madvise(sqe: SQE, buf: Buffer, advice: int) -> bool#

madvise(2) advice for the memory of buf (all of it), held until the completion.

Example

>>> m = mmap.mmap(-1, 4096)
>>> io_uring_prep_madvise(sqe, m, mmap.MADV_DONTNEED)
True
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: skip
def file_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.
  • Up to 4 GiB - 1; io_uring_prep_madvise64 for more.
  • Linux 5.6+.
  • cqe.res: 0.

io_uring_prep_fadvise64(sqe: SQE, fd: int, len: int, advice: int, offset: int | None = None) -> bool#

io_uring_prep_fadvise for any len.

Note

  • Function arguments position has changed for C origin for better usability.
  • A len over 4 GiB - 1 raises OSError: EINVAL on older kernels without 64-bit length support.

io_uring_prep_madvise64(sqe: SQE, buf: Buffer, advice: int) -> bool#

io_uring_prep_madvise for any length.

Example

>>> m = mmap.mmap(-1, 4096)
>>> io_uring_prep_madvise64(sqe, m, mmap.MADV_WILLNEED)
True
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: skip
def file_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.

io_uring_prep_openat2(sqe: SQE, path: str | os.PathLike[str], how: OpenHow, dfd: int | None = None) -> bool#

Opens path as described by how (openat2(2)); the new fd is returned in cqe.res.

Note

  • Linux 5.6+.
  • Function arguments position has changed for C origin for better usability.
  • how (an OpenHow) carries the O_* flags, the mode and the RESOLVE_* path rules; dfd defaults to AT_FDCWD and is always a normal fd.

Type

path str | os.PathLike[str]

io_uring_prep_openat2_direct(sqe: SQE, path: str | os.PathLike[str], how: OpenHow, file_index: int | None = None, dfd: int | None = None) -> bool#

io_uring_prep_openat2, but the file goes into the registered files table at slot file_index (default IORING_FILE_INDEX_ALLOC) instead of becoming an fd.

Note

  • Linux 5.15+.
  • 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); see io_uring_prep_open_direct.

Type

path str | os.PathLike[str]

io_uring_prep_unlink(sqe: SQE, path: str | os.PathLike[str], flags: int | None = None, dfd: int | None = None) -> bool#

Removes the file path (unlinkat(2)); flags is 0 (default) or AT_REMOVEDIR.

Note

  • Linux 5.11+.
  • cqe.res: 0.
  • Function arguments position has changed for C origin for better usability.
  • io_uring_prep_unlink includes io_uring_prep_unlinkat feature.

Type

path str | os.PathLike[str]

io_uring_prep_rename(sqe: SQE, oldpath: str | os.PathLike[str], newpath: str | os.PathLike[str], flags: int | None = None, olddfd: int | None = None, newdfd: int | None = None) -> bool#

Renames oldpath to newpath (renameat2(2)); flags are RENAME_* (default 0: plain renameat(2)).

Note

  • Linux 5.11+.
  • cqe.res: 0.
  • Function arguments position has changed for C origin for better usability.
  • io_uring_prep_rename includes io_uring_prep_renameat feature.

Flags

Type

oldpath str | os.PathLike[str]
newpath str | os.PathLike[str]

io_uring_prep_sync_file_range(sqe: SQE, fd: int, len: int, offset: int | None = None, flags: int | None = None) -> bool#

Syncs len bytes of the file fd from offset (default 0) (sync_file_range(2)); flags are SYNC_FILE_RANGE_* (default 0).

Note

  • Linux 5.2+.
  • cqe.res: 0.
  • Function arguments position has changed for C origin for better usability.
  • len 0 means to the end of the file.

Flags

io_uring_prep_mkdir(sqe: SQE, path: str | os.PathLike[str], mode: int, dfd: int | None = None) -> bool#

Creates the directory path with mode (mkdirat(2), masked by the umask).

Note

  • Linux 5.15+.
  • cqe.res: 0.
  • Function arguments position has changed for C origin for better usability.
  • io_uring_prep_mkdir includes io_uring_prep_mkdirat feature.

Type

path str | os.PathLike[str]

io_uring_prep_symlink(sqe: SQE, target: str | os.PathLike[str], linkpath: str | os.PathLike[str], newdirfd: int | None = None) -> bool#

Creates the symbolic link linkpath (relative to newdirfd) pointing to target (symlinkat(2)).

Note

  • Linux 5.15+.
  • cqe.res: 0.
  • Function arguments position has changed for C origin for better usability.
  • io_uring_prep_symlink includes io_uring_prep_symlinkat feature.

Type

target str | os.PathLike[str]
linkpath str | os.PathLike[str]

io_uring_prep_link(sqe: SQE, oldpath: str | os.PathLike[str], newpath: str | os.PathLike[str], flags: int | None = None, olddfd: int | None = None, newdfd: int | None = None) -> bool#

Creates the hard link newpath to oldpath (linkat(2)); flags are AT_SYMLINK_FOLLOW or 0 (default).

Note

  • Linux 5.15+.
  • cqe.res: 0.
  • Function arguments position has changed for C origin for better usability.
  • io_uring_prep_link includes io_uring_prep_linkat feature.

Type

oldpath str | os.PathLike[str]
newpath str | os.PathLike[str]

io_uring_prep_getxattr(sqe: SQE, name: str, value: Buffer, path: str | os.PathLike[str], len: int) -> bool#

Reads the extended attribute name of path into value, len bytes at most (getxattr(2)).

Note

  • Linux 5.19+.
  • cqe.res: the attribute value's length (bytes written into value); OSError: ERANGE if len is too small.
  • ValueError if len is larger than value.

Type

name str
path str | os.PathLike[str]

io_uring_prep_setxattr(sqe: SQE, name: str, value: Buffer, path: str | os.PathLike[str], flags: int, len: int) -> bool#

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).

Note

  • Linux 5.19+.
  • cqe.res: 0.
  • ValueError if len is larger than value.

Type

name str
path str | os.PathLike[str]

io_uring_prep_fgetxattr(sqe: SQE, fd: int, name: str, value: Buffer, len: int) -> bool#

io_uring_prep_getxattr for the open file fd (fgetxattr(2)).

Note

  • Linux 5.19+.
  • cqe.res: the attribute value's length; OSError: ERANGE if len is too small.

Type

name str

io_uring_prep_fsetxattr(sqe: SQE, fd: int, name: str, value: Buffer, flags: int, len: int) -> bool#

io_uring_prep_setxattr for the open file fd (fsetxattr(2)).

Note

  • Linux 5.19+.
  • cqe.res: 0.

Type

name str

io_uring_prep_fixed_fd_install(sqe: SQE, fd: int, flags: int | None = None) -> bool#

Installs the registered (direct) file fd as a normal fd; the new fd is returned in cqe.res. flags is 0 (default) or IORING_FIXED_FD_NO_CLOEXEC.

Note

  • Linux 6.8+.
  • fd is the slot in the registered files table, so set IOSQE_FIXED_FILE in sqe.flags.
  • The new fd gets O_CLOEXEC unless IORING_FIXED_FD_NO_CLOEXEC; any other flags value raises OSError: EINVAL.
  • Afterwards the slot and the new fd both refer to the file; either can be closed without affecting the other.

io_uring_prep_ftruncate(sqe: SQE, fd: int, len: int | None = None) -> bool#

Truncates the file fd to len bytes (default 0) (ftruncate(2)).

Note

  • Linux 6.9+.
  • cqe.res: 0. A len past the current size extends the file with a hole.

io_uring_prep_pipe(sqe: SQE, fds: Buffer, pipe_flags: int) -> bool#

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: skip
def file_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.
  • The request holds fds until its completion.
  • pipe_flags (pipe2(2)): O_CLOEXEC, O_NONBLOCK, O_DIRECT, O_NOTIFICATION_PIPE.

io_uring_prep_pipe_direct(sqe: SQE, fds: Buffer, pipe_flags: int, file_index: int | None = None) -> bool#

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.

io_uring_prep_cmd_discard(sqe: SQE, fd: int, offset: int, nbytes: int) -> bool#

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.
Generated by tools/setu_docs.py from the docstrings of Liburing 2026.10.29 (CPython 3.14+).