Skip to main content

StorageIo

Trait StorageIo 

Source
pub trait StorageIo: Send {
    // Required methods
    fn register_fd(&mut self, file: File) -> Result<IoFd, StorageIoError>;
    fn deregister_fd(&mut self, fd: IoFd) -> Result<(), StorageIoError>;
    fn submit_write(
        &mut self,
        fd: IoFd,
        data: &[u8],
        offset: u64,
    ) -> Result<u64, StorageIoError>;
    fn submit_append(
        &mut self,
        fd: IoFd,
        data: &[u8],
    ) -> Result<u64, StorageIoError>;
    fn submit_datasync(&mut self, fd: IoFd) -> Result<u64, StorageIoError>;
    fn flush(&mut self) -> Result<usize, StorageIoError>;
    fn poll_completions(&mut self, out: &mut Vec<IoCompletion>);
    fn pending_count(&self) -> usize;
}
Expand description

Non-blocking storage I/O backend for Ring 0.

All submit_* methods are non-blocking. They enqueue work and return a token immediately. The caller polls for completions on the next loop iteration via poll_completions.

§Ring 0 contract

Implementations must not:

  • Block (no mutexes, no condition variables)
  • Allocate on submit/poll hot path (pre-allocate in new)
  • Panic (return errors instead)

The sync backend executes I/O inline in submit_* and stages completions for the next poll_completions call. The io_uring backend pushes SQEs and polls CQEs.

Required Methods§

Source

fn register_fd(&mut self, file: File) -> Result<IoFd, StorageIoError>

Register an already-opened file with this backend.

Called on the cold path (init / checkpoint setup). Returns an opaque IoFd used for subsequent I/O operations.

Returns StorageIoError::QueueFull if the fd table is full.

§Platform notes

On Unix the backend extracts RawFd via AsRawFd. On Windows the backend extracts RawHandle via AsRawHandle.

Source

fn deregister_fd(&mut self, fd: IoFd) -> Result<(), StorageIoError>

Deregister and close a previously registered file.

Called on the cold path (shutdown / WAL truncate-and-reopen). Returns StorageIoError::BadFd if the fd is not registered.

Source

fn submit_write( &mut self, fd: IoFd, data: &[u8], offset: u64, ) -> Result<u64, StorageIoError>

Submit a write at the given file offset. Non-blocking.

data is copied into backend-managed storage before returning. The caller’s buffer is free to reuse immediately.

Returns a token for tracking completion, or StorageIoError::BadFd / StorageIoError::BufferExhausted on failure.

Source

fn submit_append( &mut self, fd: IoFd, data: &[u8], ) -> Result<u64, StorageIoError>

Submit an append (write at current end-of-file). Non-blocking.

Semantically equivalent to submit_write at offset = current_size. The sync backend uses the file’s append mode. The io_uring backend passes offset = u64::MAX which means “append” in Linux 6.0+.

Returns a token for tracking completion, or StorageIoError::BadFd / StorageIoError::BufferExhausted on failure.

Source

fn submit_datasync(&mut self, fd: IoFd) -> Result<u64, StorageIoError>

Submit an fdatasync (data-only sync, no metadata). Non-blocking.

Returns a token for tracking completion, or StorageIoError::BadFd on failure.

Source

fn flush(&mut self) -> Result<usize, StorageIoError>

Flush pending submissions to the kernel.

  • io_uring (SQPOLL): no-op — kernel polls the SQ automatically.
  • io_uring (standard): calls ring.submit().
  • Sync backend: no-op — I/O was executed inline in submit_*.

Returns the number of operations submitted, or StorageIoError::Closed if the backend is shut down.

Source

fn poll_completions(&mut self, out: &mut Vec<IoCompletion>)

Poll for completed operations. Non-blocking.

Appends completions to out. The caller owns the Vec and should clear it between iterations to reuse capacity (zero-alloc pattern).

Source

fn pending_count(&self) -> usize

Returns the number of operations submitted but not yet completed.

Implementors§