1use 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
17pub 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 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 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#[repr(transparent)]
88pub struct Restriction(sys::io_uring_restriction);
89
90#[inline(always)]
92fn res_zeroed() -> sys::io_uring_restriction {
93 unsafe { std::mem::zeroed() }
94}
95
96impl Restriction {
97 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 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 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 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
131pub 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}