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")?;
     
    // Read with library-allocated buffer
    let result = uring.read_at(&file, 0, 1024).await?;
     
    // Read into user-provided buffer (zero-copy for custom allocators)
    let buf = vec![0u8; 1024];
    let result = uring.read_into(&file, 0, buf).await?;
     
    // Register file for reduced per-operation overhead
    let registered = uring.register(&file)?;
    let result = uring.read_at(&registered, 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 fn register(&self, file: &impl AsRawFd) -> Result<RegisteredFile>

Register a file for optimized I/O operations.

Registered files use kernel-side file references, avoiding fd table lookups on each operation. This can significantly improve performance for high-frequency I/O.

§Errors

Returns an error if the maximum number of registered files has been reached, or if file registration fails (e.g., kernel too old).

§Kernel Requirements

Requires Linux 5.12+ for sparse file registration.

Source

pub async fn read_into_at<B: IoBufMut>( &self, file: &impl UringTarget, offset: impl TryInto<u64>, buf: B, ) -> Result<ReadResult<B>>

Read into a user-provided buffer. This is the primitive read operation that accepts any buffer type implementing IoBufMut.

The buffer is returned along with the number of bytes read. This allows buffer reuse and supports custom allocators (e.g., aligned buffers for O_DIRECT).

Source

pub async fn read_at( &self, file: &impl UringTarget, offset: impl TryInto<u64>, len: impl TryInto<u32>, ) -> Result<ReadResult<Vec<u8>>>

Read from a file at the specified offset, allocating a buffer internally.

This is a convenience wrapper around read_into_at that allocates a Vec<u8>. For zero-copy or custom allocators, use read_into_at directly.

Source

pub async fn write_at<B: IoBuf>( &self, file: &impl UringTarget, offset: impl TryInto<u64>, buf: B, ) -> Result<WriteResult<B>>

Write a buffer to a file at the specified offset. Accepts any buffer type implementing IoBuf.

The buffer is returned along with the number of bytes written. This allows buffer reuse and supports custom allocators.

Source

pub async fn read_exact_at( &self, file: &impl UringTarget, offset: impl TryInto<u64>, len: impl TryInto<u32>, ) -> Result<Vec<u8>>

Read exactly len bytes from a file at the specified offset.

Returns an error if fewer bytes are available (e.g., at EOF). This is useful when you know the exact size of data to read and want to fail rather than handle partial reads.

Source

pub async fn write_all_at( &self, file: &impl UringTarget, offset: impl TryInto<u64>, data: &[u8], ) -> Result<()>

Write all bytes to a file at the specified offset.

Loops on short writes until all data is written. Returns an error if a write returns 0 bytes (indicating the write cannot proceed).

Source

pub async fn sync(&self, file: &impl UringTarget) -> 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 UringTarget) -> 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 UringTarget) -> 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 UringTarget, offset: impl TryInto<u64>, len: impl TryInto<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. Use libc::FALLOC_FL_* constants for mode flags. Requires Linux 5.6+.

Source

pub async fn fadvise( &self, file: &impl UringTarget, offset: impl TryInto<u64>, len: impl TryInto<u64>, 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. Use libc::POSIX_FADV_* constants for advice values. Requires Linux 5.6+.

Source

pub async fn ftruncate( &self, file: &impl UringTarget, len: impl TryInto<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.

Source

pub async fn open( &self, path: impl AsRef<Path>, flags: i32, mode: u32, ) -> Result<OwnedFd>

Open a file asynchronously. This is the io_uring equivalent of open(2)/openat(2). Requires Linux 5.6+.

§Arguments
  • path - Path to open (any CStr-like type: &CStr, CString, c"literal").
  • flags - Open flags from libc (e.g., libc::O_RDONLY, libc::O_RDWR | libc::O_CREAT).
  • mode - File mode for creation (only used with O_CREAT).
§Returns

Returns an OwnedFd on success. The fd is automatically closed when dropped.

Source

pub async fn open_at( &self, dir_fd: RawFd, path: impl AsRef<Path>, flags: i32, mode: u32, ) -> Result<OwnedFd>

Open a file relative to a directory fd. This is useful for safe path traversal and avoiding TOCTOU races. Requires Linux 5.6+.

§Arguments
  • dir_fd - Directory fd for relative paths, or libc::AT_FDCWD for current directory.
  • path - Path to open relative to dir_fd.
  • flags - Open flags.
  • mode - File mode for creation.
Source

pub async fn statx_path(&self, path: impl AsRef<Path>) -> Result<Metadata>

Get file metadata by path without opening the file. This is the io_uring equivalent of stat(2)/statx(2). Requires Linux 5.6+.

Unlike statx() which operates on an open fd, this method stats the path directly.

Source

pub async fn statx_at( &self, dir_fd: RawFd, path: impl AsRef<Path>, flags: i32, ) -> Result<Metadata>

Get file metadata relative to a directory fd. This allows safe path traversal and additional flags for controlling symlink behavior. Requires Linux 5.6+.

§Arguments
  • dir_fd - Directory fd for relative paths, or libc::AT_FDCWD for current directory.
  • path - Path to stat relative to dir_fd.
  • flags - Flags from libc (e.g., libc::AT_SYMLINK_NOFOLLOW to not follow symlinks).
Source

pub async fn close(&self, fd: impl IntoRawFd) -> Result<()>

Close a file descriptor asynchronously. This is the io_uring equivalent of close(2). Requires Linux 5.6+.

Takes ownership of the fd to prevent the automatic synchronous close on drop. This is useful when you want to:

  • Handle close errors (which are silently ignored by OwnedFd::drop)
  • Batch close operations with other io_uring operations
  • Avoid blocking the async runtime on close
Source

pub async fn rename( &self, old_path: impl AsRef<Path>, new_path: impl AsRef<Path>, ) -> Result<()>

Rename a file asynchronously. This is the io_uring equivalent of rename(2). Requires Linux 5.11+.

Source

pub async fn rename_at( &self, old_dir_fd: RawFd, old_path: impl AsRef<Path>, new_dir_fd: RawFd, new_path: impl AsRef<Path>, flags: u32, ) -> Result<()>

Rename a file relative to directory fds. This is the io_uring equivalent of renameat2(2). Requires Linux 5.11+.

Flags can include libc::RENAME_NOREPLACE, libc::RENAME_EXCHANGE, etc.

Delete a file or empty directory. This is the io_uring equivalent of unlink(2). Requires Linux 5.11+.

Source

pub async fn rmdir(&self, path: impl AsRef<Path>) -> Result<()>

Delete a directory. This is the io_uring equivalent of rmdir(2). Requires Linux 5.11+.

Delete a file or directory relative to a directory fd. This is the io_uring equivalent of unlinkat(2). Requires Linux 5.11+.

Use libc::AT_REMOVEDIR flag to remove directories.

Source

pub async fn mkdir(&self, path: impl AsRef<Path>, mode: u32) -> Result<()>

Create a directory. This is the io_uring equivalent of mkdir(2). Requires Linux 5.15+.

Source

pub async fn mkdir_at( &self, dir_fd: RawFd, path: impl AsRef<Path>, mode: u32, ) -> Result<()>

Create a directory relative to a directory fd. This is the io_uring equivalent of mkdirat(2). Requires Linux 5.15+.

Create a symbolic link. This is the io_uring equivalent of symlink(2). Requires Linux 5.11+.

Create a symbolic link relative to a directory fd. This is the io_uring equivalent of symlinkat(2). Requires Linux 5.11+.

Create a hard link. This is the io_uring equivalent of link(2). Requires Linux 5.11+.

Create a hard link relative to directory fds. This is the io_uring equivalent of linkat(2). Requires Linux 5.11+.

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.