pub struct UringDriver { /* private fields */ }Implementations§
Source§impl UringDriver
impl UringDriver
Sourcepub fn probe_and_start(entries: u32) -> Result<Self, ProbeFailure>
pub fn probe_and_start(entries: u32) -> Result<Self, ProbeFailure>
Create the ring AND verify a real IORING_OP_READ round-trip on a
temp file before accepting work. io_uring_setup succeeding is not
enough: gVisor/seccomp environments can create a ring whose ops then
fail with ENOSYS/EINVAL (backlog#894 probe design).
Start a single-ring driver. Identical to probe_and_start_sharded(entries, 1).
Sourcepub fn probe_and_start_sharded(
entries: u32,
shards: usize,
) -> Result<Self, ProbeFailure>
pub fn probe_and_start_sharded( entries: u32, shards: usize, ) -> Result<Self, ProbeFailure>
Start a driver backed by shards independent rings, each with entries
SQ slots and its own driver thread.
Use more than one shard when the workload hits the page cache: such reads
complete inline in io_uring_enter, so a single driver thread performs
every one of their memcpys and caps the driver at one core’s memory
bandwidth. Measured on a 16-core host (rustfs/backlog#1145): 1 ring →
4890 MB/s, 2 → 8969 MB/s, 4 → 15806 MB/s, with per-ring throughput flat.
Reads that miss the cache are device-bound and do not need sharding.
In-flight ops are capped at entries per shard (the invariant that
makes CQ overflow structurally unreachable holds per ring), so the whole
driver admits up to shards * entries concurrent reads.
shards is clamped to at least 1. Probing happens on the first shard, so
a restricted environment fails exactly as it does for a single ring; if a
later shard fails to start, the ones already running are shut down and
joined before the error is returned.
Sourcepub fn read_at(&self, file: Arc<File>, offset: u64, len: usize) -> ReadHandle
pub fn read_at(&self, file: Arc<File>, offset: u64, len: usize) -> ReadHandle
Positioned read (pread semantics) — regular files, buffered.
Sourcepub fn read_current(&self, file: Arc<File>, len: usize) -> ReadHandle
pub fn read_current(&self, file: Arc<File>, len: usize) -> ReadHandle
Read at the file’s current position (read(2) semantics) — pipes.
Sourcepub fn read_at_direct(
&self,
file: Arc<File>,
offset: u64,
len: usize,
align: usize,
) -> ReadHandle
pub fn read_at_direct( &self, file: Arc<File>, offset: u64, len: usize, align: usize, ) -> ReadHandle
Positioned read from a file opened with O_DIRECT (rustfs/backlog#1102).
align is the device’s logical block size — a power of two, typically
512 or 4096. offset and len are the caller’s logical range and need
no alignment: the driver reads the block-aligned superset range into a
block-aligned buffer and returns exactly [offset, offset + len).
Alignment padding never reaches the caller, so a BitrotReader expecting
an exact shard length never sees padded output.
The caller must have opened file with O_DIRECT; otherwise this is
just a (correct but pointless) buffered read of the superset range.
Sourcepub fn stats(&self) -> StatsSnapshot
pub fn stats(&self) -> StatsSnapshot
Counters summed across every shard. The conservation identities the
cancel-safety tests assert (submitted == delivered + orphan_reclaimed,
in_flight == 0 after a clean drain) hold per shard, so they hold for
the sum.
Sourcepub fn shutdown(self) -> StatsSnapshot
pub fn shutdown(self) -> StatsSnapshot
Stop accepting work, cancel all in-flight ops, drain every ring to
in_flight == 0, then join each driver thread. Only after that is a ring
dropped/unmapped — the shutdown ordering P2 requires, per shard.
Shards are asked to stop first and joined afterwards, so their bounded
drains overlap instead of serializing shards * DRAIN_TIMEOUT.