Uring

Struct Uring 

Source
pub struct Uring { /* private fields */ }
Expand description

Handle to a shared io_uring instance.

This is the main entry point for performing async I/O operations via io_uring. It is cheap to clone (just clones an Arc internally) and safe to share across threads and async tasks.

§Example

use uring_file::uring::{Uring, UringCfg};
use std::fs::File;

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let uring = Uring::new(UringCfg::default())?;
    let file = File::open("test.txt")?;
     
    let result = uring.read_at(&file, 0, 1024).await?;
    println!("Read {} bytes", result.bytes_read);
    Ok(())
}

§Architecture Notes

Internally, Uring spawns two background threads:

  1. Submission thread: Receives requests via a channel, batches them, and submits them to the kernel.
  2. Completion thread: Polls the completion queue and dispatches results back to waiting async tasks.

This design allows for efficient batching of submissions while maintaining a simple async API.

Implementations§

Source§

impl Uring

Source

pub fn new(cfg: UringCfg) -> Result<Self>

Create a new io_uring instance with the given configuration.

This spawns two background threads for submission and completion handling. The threads will automatically stop when all Uring handles are dropped.

§Errors

Returns an error if the io_uring cannot be created (e.g., kernel too old, resource limits exceeded, or insufficient permissions).

Source

pub async fn read_at( &self, file: &impl AsRawFd, offset: u64, len: u64, ) -> Result<ReadResult>

Read from a file at the specified offset. Returns the buffer and the number of bytes actually read. The number of bytes read may be less than requested if the file is smaller or if EOF is reached.

Source

pub async fn write_at( &self, file: &impl AsRawFd, offset: u64, data: Vec<u8>, ) -> Result<WriteResult>

Write to a file at the specified offset. Returns the original buffer and number of bytes written. For regular files, bytes_written will typically equal data.len(). For pipes, sockets, etc., short writes are possible and normal.

Source

pub async fn sync(&self, file: &impl AsRawFd) -> Result<()>

Synchronize file data and metadata to disk (fsync). This ensures that all data and metadata modifications are flushed to the underlying storage device. Even when using direct I/O, this is necessary to ensure the device itself has flushed any internal caches.

Note on ordering: io_uring does not guarantee ordering between operations. If you need to ensure writes complete before fsync, you should await the write first, then call fsync.

Source

pub async fn datasync(&self, file: &impl AsRawFd) -> Result<()>

Synchronize file data to disk (fdatasync). Like sync, but only flushes data, not metadata (unless the metadata is required to retrieve the data). This can be faster than a full fsync.

Source

pub async fn statx(&self, file: &impl AsRawFd) -> Result<Metadata>

Get file status information (statx). This is the io_uring equivalent of fstat/statx. It returns metadata about the file including size, permissions, timestamps, etc. Requires Linux 5.6+. On older kernels, this will fail with EINVAL.

Source

pub async fn fallocate( &self, file: &impl AsRawFd, offset: u64, len: u64, mode: i32, ) -> Result<()>

Pre-allocate or deallocate space for a file (fallocate). This can be used to pre-allocate space to avoid fragmentation, punch holes in sparse files, or zero-fill regions. See falloc module for mode flags. Requires Linux 5.6+.

Source

pub async fn fadvise( &self, file: &impl AsRawFd, offset: u64, len: u32, advice: i32, ) -> Result<()>

Advise the kernel about expected file access patterns (fadvise). This is a hint to the kernel about how you intend to access a file region. The kernel may use this to optimize readahead, caching, etc. See advice module for advice values. Requires Linux 5.6+.

Source

pub async fn ftruncate(&self, file: &impl AsRawFd, len: u64) -> Result<()>

Truncate a file to a specified length (ftruncate). If the file is larger than the specified length, the extra data is lost. If the file is smaller, it is extended and the extended part reads as zeros. Requires Linux 6.9+. On older kernels, this will fail with EINVAL.

Trait Implementations§

Source§

impl Clone for Uring

Source§

fn clone(&self) -> Uring

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl Freeze for Uring

§

impl RefUnwindSafe for Uring

§

impl Send for Uring

§

impl Sync for Uring

§

impl Unpin for Uring

§

impl UnwindSafe for Uring

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.