diff --git a/src/io_uring/constants.rs b/src/io_uring/constants.rs index 43957cd..b40ae63 100644 --- a/src/io_uring/constants.rs +++ b/src/io_uring/constants.rs @@ -60,3 +60,9 @@ pub const IORING_REGISTER_EVENTFD: u32 = 4; pub const IORING_UNREGISTER_EVENTFD: u32 = 5; pub const IORING_REGISTER_FILES_UPDATE: u32 = 6; pub const IORING_REGISTER_EVENTFD_ASYNC: u32 = 7; +pub const IORING_REGISTER_PROBE: u32 = 8; +pub const IORING_REGISTER_PERSONALITY: u32 = 9; +pub const IORING_UNREGISTER_PERSONALITY: u32 = 10; +pub const IORING_REGISTER_RESTRICTIONS: u32 = 11; +pub const IORING_REGISTER_ENABLE_RINGS: u32 = 12; + diff --git a/src/io_uring/kernel_types.rs b/src/io_uring/kernel_types.rs index f7ed435..e610838 100644 --- a/src/io_uring/kernel_types.rs +++ b/src/io_uring/kernel_types.rs @@ -163,3 +163,38 @@ pub struct io_cqring_offsets { pub cqes: u32, pub resv: [u64; 2_usize], } + +#[repr(C)] +#[derive(Default, Debug, Copy, Clone)] +pub struct io_uring_probe_op { + pub op: u8, + pub resv: u8, + pub flags: u16,/* IO_URING_OP_* flags */ + pub resv2: u32, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct io_uring_probe { + pub last_op: u8, /* last opcode supported */ + pub ops_len: u8, /* length of ops[] array below */ + pub resv: u16, + pub resv2: [u32; 3_usize], + + // This is a variable length field in C, but the usual call + // to get all available ops would always use 256 + pub ops: [io_uring_probe_op; 256] +} + +impl Default for io_uring_probe { + fn default() -> Self { + Self { + last_op: 0, + ops_len: 0, + resv: 0, + resv2: [0; 3], + ops: [io_uring_probe_op::default(); 256] + } + } + +} \ No newline at end of file diff --git a/src/io_uring/uring.rs b/src/io_uring/uring.rs index 3e53a74..f982e1a 100644 --- a/src/io_uring/uring.rs +++ b/src/io_uring/uring.rs @@ -1,4 +1,6 @@ use super::*; +use crate::io_uring::syscall::register; +use crate::io_uring::kernel_types::{io_uring_probe, io_uring_probe_op}; /// Nice bindings for the shiny new linux IO system #[derive(Debug, Clone)] @@ -77,6 +79,30 @@ impl Uring { } } + /// Gets a list of io_uring opcodes supported by the + /// running kernel. + /// + /// # Warning + /// + /// This only becomes usable on linux kernels + /// 5.6 and up. + pub fn probe_ops( + &self + ) -> io::Result> + { + let probe = io_uring_probe::default(); + let probe_ptr: *const io_uring_probe = &probe; + + register( + self.ring_fd.as_raw_fd(), + IORING_REGISTER_PROBE, + probe_ptr as *const libc::c_void, + 256 + )?; + + Ok(probe.ops[0..probe.last_op as usize + 1].into()) + } + pub(crate) fn ensure_submitted( &self, sqe_id: u64,