use crate::error::{check_ret, Error, Result};
use crate::flags::SetupFlags;
use crate::queue::{CompletionQueue, SubmissionQueue};
use crate::sys;
use std::mem::MaybeUninit;
use std::os::unix::io::{AsRawFd, RawFd};
pub struct IoUring {
ring: sys::io_uring,
}
impl IoUring {
pub fn new(entries: u32) -> Result<Self> {
Self::with_flags(entries, SetupFlags::empty())
}
pub fn with_flags(entries: u32, flags: SetupFlags) -> Result<Self> {
let mut ring = MaybeUninit::<sys::io_uring>::uninit();
let ret = unsafe { sys::io_uring_queue_init(entries, ring.as_mut_ptr(), flags.bits()) };
check_ret(ret).map_err(Error::Setup)?;
Ok(Self {
ring: unsafe { ring.assume_init() },
})
}
pub fn with_params(entries: u32, params: &mut sys::io_uring_params) -> Result<Self> {
let mut ring = MaybeUninit::<sys::io_uring>::uninit();
let ret = unsafe { sys::io_uring_queue_init_params(entries, ring.as_mut_ptr(), params) };
check_ret(ret).map_err(Error::Setup)?;
Ok(Self {
ring: unsafe { ring.assume_init() },
})
}
pub fn submit(&mut self) -> Result<usize> {
let ret = unsafe { sys::io_uring_submit(&mut self.ring) };
check_ret(ret).map(|n| n as usize).map_err(Into::into)
}
pub fn submit_and_wait(&mut self, wait_nr: u32) -> Result<usize> {
let ret = unsafe { sys::io_uring_submit_and_wait(&mut self.ring, wait_nr) };
check_ret(ret).map(|n| n as usize).map_err(Into::into)
}
pub fn submission(&mut self) -> SubmissionQueue<'_> {
SubmissionQueue::new(&mut self.ring)
}
pub fn completion(&mut self) -> CompletionQueue<'_> {
CompletionQueue::new(&mut self.ring)
}
pub unsafe fn as_raw_mut(&mut self) -> *mut sys::io_uring {
&mut self.ring
}
pub fn as_raw_fd(&self) -> RawFd {
self.ring.ring_fd
}
}
impl AsRawFd for IoUring {
fn as_raw_fd(&self) -> RawFd {
self.ring.ring_fd
}
}
impl Drop for IoUring {
fn drop(&mut self) {
unsafe {
sys::io_uring_queue_exit(&mut self.ring);
}
}
}
unsafe impl Send for IoUring {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_ring() {
let ring = IoUring::new(8);
assert!(ring.is_ok(), "Failed to create io_uring");
}
#[test]
fn test_create_with_flags() {
let ring = IoUring::with_flags(8, SetupFlags::CLAMP);
assert!(ring.is_ok(), "Failed to create io_uring with flags");
}
}