io_uring/
register.rs

1//! Some register syscall related types or parameters.
2
3use std::os::unix::io::RawFd;
4use std::{fmt, io};
5
6use crate::sys;
7
8pub(crate) fn execute(
9    fd: RawFd,
10    opcode: libc::c_uint,
11    arg: *const libc::c_void,
12    len: libc::c_uint,
13) -> io::Result<i32> {
14    unsafe { sys::io_uring_register(fd, opcode, arg, len) }
15}
16
17/// Information about what `io_uring` features the kernel supports.
18///
19/// You can fill this in with [`register_probe`](crate::Submitter::register_probe).
20pub struct Probe(ProbeAndOps);
21
22#[repr(C)]
23struct ProbeAndOps(sys::io_uring_probe, [sys::io_uring_probe_op; Probe::COUNT]);
24
25impl Probe {
26    pub(crate) const COUNT: usize = 256;
27
28    /// Create a new probe with no features enabled.
29    pub fn new() -> Probe {
30        Probe(ProbeAndOps(
31            sys::io_uring_probe::default(),
32            [sys::io_uring_probe_op::default(); Probe::COUNT],
33        ))
34    }
35
36    #[inline]
37    pub(crate) fn as_mut_ptr(&mut self) -> *mut sys::io_uring_probe {
38        &mut (self.0).0
39    }
40
41    /// Get whether a specific opcode is supported.
42    pub fn is_supported(&self, opcode: u8) -> bool {
43        unsafe {
44            let probe = &(self.0).0;
45
46            if opcode <= probe.last_op {
47                let ops = probe.ops.as_slice(Self::COUNT);
48                ops[opcode as usize].flags & (sys::IO_URING_OP_SUPPORTED as u16) != 0
49            } else {
50                false
51            }
52        }
53    }
54}
55
56impl Default for Probe {
57    #[inline]
58    fn default() -> Probe {
59        Probe::new()
60    }
61}
62
63impl fmt::Debug for Probe {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        struct Op<'a>(&'a sys::io_uring_probe_op);
66
67        impl fmt::Debug for Op<'_> {
68            #[inline]
69            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70                f.debug_struct("Op").field("code", &self.0.op).finish()
71            }
72        }
73
74        let probe = &(self.0).0;
75        let list = unsafe { probe.ops.as_slice(probe.last_op as usize + 1) };
76        let list = list
77            .iter()
78            .filter(|op| op.flags & (sys::IO_URING_OP_SUPPORTED as u16) != 0)
79            .map(Op);
80
81        f.debug_set().entries(list).finish()
82    }
83}
84
85/// An allowed feature of io_uring. You can set the allowed features with
86/// [`register_restrictions`](crate::Submitter::register_restrictions).
87#[repr(transparent)]
88pub struct Restriction(sys::io_uring_restriction);
89
90/// inline zeroed to improve codegen
91#[inline(always)]
92fn res_zeroed() -> sys::io_uring_restriction {
93    unsafe { std::mem::zeroed() }
94}
95
96impl Restriction {
97    /// Allow an `io_uring_register` opcode.
98    pub fn register_op(op: u8) -> Restriction {
99        let mut res = res_zeroed();
100        res.opcode = sys::IORING_RESTRICTION_REGISTER_OP as _;
101        res.__bindgen_anon_1.register_op = op;
102        Restriction(res)
103    }
104
105    /// Allow a submission queue event opcode.
106    pub fn sqe_op(op: u8) -> Restriction {
107        let mut res = res_zeroed();
108        res.opcode = sys::IORING_RESTRICTION_SQE_OP as _;
109        res.__bindgen_anon_1.sqe_op = op;
110        Restriction(res)
111    }
112
113    /// Allow the given [submission queue event flags](crate::squeue::Flags).
114    pub fn sqe_flags_allowed(flags: u8) -> Restriction {
115        let mut res = res_zeroed();
116        res.opcode = sys::IORING_RESTRICTION_SQE_FLAGS_ALLOWED as _;
117        res.__bindgen_anon_1.sqe_flags = flags;
118        Restriction(res)
119    }
120
121    /// Require the given [submission queue event flags](crate::squeue::Flags). These flags must be
122    /// set on every submission.
123    pub fn sqe_flags_required(flags: u8) -> Restriction {
124        let mut res = res_zeroed();
125        res.opcode = sys::IORING_RESTRICTION_SQE_FLAGS_REQUIRED as _;
126        res.__bindgen_anon_1.sqe_flags = flags;
127        Restriction(res)
128    }
129}
130
131/// A RawFd, which can be used for
132/// [register_files_update](crate::Submitter::register_files_update).
133///
134/// File descriptors can be skipped if they are set to `SKIP_FILE`.
135/// Skipping an fd will not touch the file associated with the previous fd at that index.
136pub const SKIP_FILE: RawFd = sys::IORING_REGISTER_FILES_SKIP;
137
138#[test]
139fn test_probe_layout() {
140    use std::alloc::Layout;
141    use std::mem;
142
143    let probe = Probe::new();
144    assert_eq!(
145        Layout::new::<sys::io_uring_probe>().size()
146            + mem::size_of::<sys::io_uring_probe_op>() * 256,
147        Layout::for_value(&probe.0).size()
148    );
149    assert_eq!(
150        Layout::new::<sys::io_uring_probe>().align(),
151        Layout::for_value(&probe.0).align()
152    );
153}