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(®istered, 0, 1024).await?;
println!("Read {} bytes", result.bytes_read);
Ok(())
}§Architecture Notes
Internally, Uring spawns two background threads:
- Submission thread: Receives requests via a channel, batches them, and submits them to the kernel.
- 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
impl Uring
Sourcepub fn new(cfg: UringCfg) -> Result<Self>
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).
Sourcepub fn register(&self, file: &impl AsRawFd) -> Result<RegisteredFile>
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.
Sourcepub async fn read_into_at<B: IoBufMut>(
&self,
file: &impl UringTarget,
offset: impl TryInto<u64>,
buf: B,
) -> Result<ReadResult<B>>
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).
Sourcepub async fn read_at(
&self,
file: &impl UringTarget,
offset: impl TryInto<u64>,
len: impl TryInto<u32>,
) -> Result<ReadResult<Vec<u8>>>
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.
Sourcepub async fn write_at<B: IoBuf>(
&self,
file: &impl UringTarget,
offset: impl TryInto<u64>,
buf: B,
) -> Result<WriteResult<B>>
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.
Sourcepub async fn read_exact_at(
&self,
file: &impl UringTarget,
offset: impl TryInto<u64>,
len: impl TryInto<u32>,
) -> Result<Vec<u8>>
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.
Sourcepub async fn write_all_at(
&self,
file: &impl UringTarget,
offset: impl TryInto<u64>,
data: &[u8],
) -> Result<()>
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).
Sourcepub async fn sync(&self, file: &impl UringTarget) -> Result<()>
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.
Sourcepub async fn datasync(&self, file: &impl UringTarget) -> Result<()>
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.
Sourcepub async fn statx(&self, file: &impl UringTarget) -> Result<Metadata>
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.
Sourcepub async fn fallocate(
&self,
file: &impl UringTarget,
offset: impl TryInto<u64>,
len: impl TryInto<u64>,
mode: i32,
) -> Result<()>
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+.
Sourcepub async fn fadvise(
&self,
file: &impl UringTarget,
offset: impl TryInto<u64>,
len: impl TryInto<u64>,
advice: i32,
) -> Result<()>
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+.
Sourcepub async fn ftruncate(
&self,
file: &impl UringTarget,
len: impl TryInto<u64>,
) -> Result<()>
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.
Sourcepub async fn open(
&self,
path: impl AsRef<Path>,
flags: i32,
mode: u32,
) -> Result<OwnedFd>
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 (anyCStr-like type:&CStr,CString,c"literal").flags- Open flags fromlibc(e.g.,libc::O_RDONLY,libc::O_RDWR | libc::O_CREAT).mode- File mode for creation (only used withO_CREAT).
§Returns
Returns an OwnedFd on success. The fd is automatically closed when dropped.
Sourcepub async fn open_at(
&self,
dir_fd: RawFd,
path: impl AsRef<Path>,
flags: i32,
mode: u32,
) -> Result<OwnedFd>
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, orlibc::AT_FDCWDfor current directory.path- Path to open relative todir_fd.flags- Open flags.mode- File mode for creation.
Sourcepub async fn statx_path(&self, path: impl AsRef<Path>) -> Result<Metadata>
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.
Sourcepub async fn statx_at(
&self,
dir_fd: RawFd,
path: impl AsRef<Path>,
flags: i32,
) -> Result<Metadata>
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, orlibc::AT_FDCWDfor current directory.path- Path to stat relative todir_fd.flags- Flags fromlibc(e.g.,libc::AT_SYMLINK_NOFOLLOWto not follow symlinks).
Sourcepub async fn close(&self, fd: impl IntoRawFd) -> Result<()>
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
Sourcepub async fn rename(
&self,
old_path: impl AsRef<Path>,
new_path: impl AsRef<Path>,
) -> Result<()>
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+.
Sourcepub 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<()>
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.
Sourcepub async fn unlink(&self, path: impl AsRef<Path>) -> Result<()>
pub async fn unlink(&self, path: impl AsRef<Path>) -> Result<()>
Delete a file or empty directory. This is the io_uring equivalent of unlink(2). Requires Linux 5.11+.
Sourcepub async fn rmdir(&self, path: impl AsRef<Path>) -> Result<()>
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+.
Sourcepub async fn unlink_at(
&self,
dir_fd: RawFd,
path: impl AsRef<Path>,
flags: i32,
) -> Result<()>
pub async fn unlink_at( &self, dir_fd: RawFd, path: impl AsRef<Path>, flags: i32, ) -> Result<()>
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.
Sourcepub async fn mkdir(&self, path: impl AsRef<Path>, mode: u32) -> Result<()>
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+.
Sourcepub async fn mkdir_at(
&self,
dir_fd: RawFd,
path: impl AsRef<Path>,
mode: u32,
) -> Result<()>
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+.
Sourcepub async fn symlink(
&self,
target: impl AsRef<Path>,
link_path: impl AsRef<Path>,
) -> Result<()>
pub async fn symlink( &self, target: impl AsRef<Path>, link_path: impl AsRef<Path>, ) -> Result<()>
Create a symbolic link. This is the io_uring equivalent of symlink(2). Requires Linux 5.11+.
Sourcepub async fn symlink_at(
&self,
target: impl AsRef<Path>,
new_dir_fd: RawFd,
link_path: impl AsRef<Path>,
) -> Result<()>
pub async fn symlink_at( &self, target: impl AsRef<Path>, new_dir_fd: RawFd, link_path: impl AsRef<Path>, ) -> Result<()>
Create a symbolic link relative to a directory fd. This is the io_uring equivalent of symlinkat(2). Requires Linux 5.11+.