$RodHat_
Syscall reference · Filesystem

preadv2 / pwritev2(2)

Scatter/gather I/O at an offset with per-call flags: RWF_NOWAIT, RWF_HIPRI, RWF_DSYNC, RWF_SYNC, RWF_APPEND.

Since
Linux 4.6check your kernel →
glibc
glibc 2.26
System
Linux
Man page
preadv2 / pwritev2(2)

Synopsis

#include <sys/uio.h>

ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt,
                off_t offset, int flags);
ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt,
                 off_t offset, int flags);

Rod's take

preadv2/pwritev2 extend preadv/pwritev with a flags argument that applies to a single call. RWF_NOWAIT is the standout: it returns EAGAIN instead of blocking on a page cache miss, enabling a polling fast-path without io_uring. RWF_DSYNC/RWF_SYNC give per-call durability without setting O_DSYNC globally on the fd. RWF_HIPRI requests polled NVMe delivery but silently falls back on unsupported devices. Pass flags=0 and behavior is identical to preadv/pwritev.

Flags and arguments that matter

NameWhat it does
RWF_NOWAITLinux 4.14Return EAGAIN immediately if the operation would block (page cache miss, lock contention). Only effective on regular files and some block devices; returns EOPNOTSUPP on pipes/sockets.
RWF_HIPRIRequest polled I/O delivery instead of interrupt-driven completion. Reduces tail latency on NVMe devices with polled queues (/sys/block/.../queue/io_poll). Degrades silently to normal I/O on unsupported devices. Most effective with O_DIRECT.
RWF_DSYNCPer-call O_DSYNC: data and enough metadata for recovery are written to stable storage before the call returns. Does not affect other writes on the same fd.
RWF_SYNCPer-call O_SYNC: all data and all metadata are written to stable storage before return. Stricter than RWF_DSYNC.
RWF_APPENDLinux 4.16Atomic append regardless of fd flags: seek-to-end and write are atomic with respect to other O_APPEND/RWF_APPEND writers. The offset argument is ignored.

Errors you will actually hit

errnoMeaning
EAGAINRWF_NOWAIT set and the operation would block.
EOPNOTSUPPRWF_NOWAIT used on a file type that does not support it (pipe, socket, etc.).
EINVALUnknown flag, or offset is -1 and the fd has no current position.

Example

#include <sys/uio.h>

struct iovec iov = { .iov_base = buf, .iov_len = len };

/* non-blocking read: fast-path from page cache only */
ssize_t n = preadv2(fd, &iov, 1, offset, RWF_NOWAIT);
if (n < 0 && errno == EAGAIN) {
    /* cache miss: queue blocking read or io_uring sqe */
}

/* single durable write without O_DSYNC on the fd */
n = pwritev2(fd, &iov, 1, offset, RWF_DSYNC);

Trimmed from the full walkthrough in preadv2(2): per-call I/O flags without reopening the fd.

BSD equivalent

FreeBSD has preadv/pwritev (FreeBSD 6, 2005) but no preadv2/pwritev2 and no RWF_* flags. Per-call durability requires explicit fdatasync(2)/fsync(2). Polled I/O is handled at the GEOM/cam_iosched layer, not via fd flags.

The long version, from the console

Sources

  1. pread(2) / preadv2, man7.org
  2. preadv2/pwritev2 added in Linux 4.6, LWN.net

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