compio_driver/sys/extra/mod.rs
1cfg_select! {
2 windows => {
3 mod iocp;
4 use iocp as sys;
5 }
6 fusion => {
7 mod fusion;
8 mod poll;
9 mod iour;
10 use fusion as sys;
11 }
12 io_uring => {
13 mod iour;
14 use iour as sys;
15 }
16 polling => {
17 mod poll;
18 use poll as sys;
19 }
20 stub => {
21 mod stub;
22 use stub as sys;
23 }
24 _ => {}
25}
26
27use std::{fmt::Debug, io};
28
29#[allow(unused_imports)]
30pub use sys::*;
31
32/// Platform-specific extra data associated with a driver instance.
33///
34/// It can be used to set options for or get extra data from I/O operations.
35#[repr(transparent)]
36pub struct Extra(pub(super) sys::Extra);
37
38impl Debug for Extra {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 Debug::fmt(&self.0, f)
41 }
42}
43
44impl<I: Into<sys::Extra>> From<I> for Extra {
45 fn from(inner: I) -> Self {
46 Self(inner.into())
47 }
48}
49
50impl Extra {
51 pub(crate) fn new(driver: &Driver) -> Self {
52 driver.default_extra().into()
53 }
54}
55
56impl Extra {
57 iour_only! {
58 /// Checks whether this completion reports a notification (2nd CQE returned for a zerocopy op).
59 ///
60 /// # Behaviour
61 ///
62 /// This is only supported on `io_uring` drivers, in which the driver will
63 /// check whether the `IORING_CQE_F_NOTIF` flag was set by the kernel for
64 /// the CQE. On other platforms, this will always return the
65 /// [`Unsupported`] error.
66 ///
67 /// [`Unsupported`]: io::ErrorKind::Unsupported
68 get fn is_notification(&self) -> io::Result<bool> = |extra| Ok(extra.is_notification());
69
70 /// Try to get the buffer ID associated with this operation.
71 ///
72 /// # Behavior
73 ///
74 /// This is only supported on `io_uring` drivers, in which the driver will
75 /// try to extract `buffer_id` returned by the kernel as a part of `flags`.
76 /// If the id cannot be extracted from the flag, an [`InvalidInput`]
77 /// [`io::Error`] will be returned. On other platforms, this will always
78 /// return [`Unsupported`] error.
79 ///
80 /// [`InvalidInput`]: io::ErrorKind::InvalidInput
81 /// [`Unsupported`]: io::ErrorKind::Unsupported
82 get fn buffer_id(&self) -> io::Result<u16> =
83 |extra| extra
84 .buffer_id()
85 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Buffer id was not set"));
86
87
88 /// Get the personality for this operation.
89 ///
90 /// # Behavior
91 ///
92 /// - If the driver is not `io_uring`, return [`Unsupported`] error,
93 /// - If the personality was not set with [`set_personality`], return `Ok(None)`
94 /// - Otherwise, return `Ok(Some(personality))`
95 ///
96 /// [`Unsupported`]: io::ErrorKind::Unsupported
97 /// [`set_personality`]: Extra::set_personality
98 get fn get_personality(&self) -> io::Result<Option<u16>> = |extra| Ok(extra.get_personality());
99
100 /// Checks whether the underlying socket has more data to be read.
101 ///
102 /// # Behaviour
103 ///
104 /// This method must be used only on the flags for any of the `receive`
105 /// variants supported by `IO_URING`. The driver will try to check whether
106 /// the `IORING_CQE_F_SOCK_NONEMPTY` flag was set by the kernel for the CQE.
107 /// On other platforms, this will always return the [`Unsupported`] error.
108 ///
109 /// [`Unsupported`]: io::ErrorKind::Unsupported
110 get fn sock_nonempty(&self) -> io::Result<bool> = |extra| Ok(extra.sock_nonempty());
111
112 /// Set the `IOSQE_IO_DRAIN` flag for this operation.
113 ///
114 /// This ensures that this operation won't start until all previously submitted operations complete.
115 ///
116 /// See [`io_uring_sqe_set_flags(3)`] for more details.
117 ///
118 /// [`io_uring_sqe_set_flags(3)`]: https://man7.org/linux/man-pages/man3/io_uring_sqe_set_flags.3.html
119 set fn drain(&mut self) = |extra| extra.set_drain();
120
121 /// Set the `IOSQE_IO_LINK` flag for this operation.
122 ///
123 /// This links this operation with the next one. The next operation will not start until this operation
124 /// completed successfully.
125 ///
126 /// See [`io_uring_sqe_set_flags(3)`] for more details.
127 ///
128 /// [`io_uring_sqe_set_flags(3)`]: https://man7.org/linux/man-pages/man3/io_uring_sqe_set_flags.3.html
129 set fn link(&mut self) = |extra| extra.set_link();
130
131 /// Set the `IOSQE_IO_HARDLINK` flag for this operation.
132 ///
133 /// Like link, but the next operation will execute regardless of this operation's result.
134 ///
135 /// See [`io_uring_sqe_set_flags(3)`] for more details.
136 ///
137 /// [`io_uring_sqe_set_flags(3)`]: https://man7.org/linux/man-pages/man3/io_uring_sqe_set_flags.3.html
138 set fn hardlink(&mut self) = |extra| extra.set_hardlink();
139
140 /// Set the personality for this operation.
141 ///
142 /// A personality represents a set of credentials (uid, gid, etc.) that will be used for this operation.
143 ///
144 /// The personality can be retrieved with [`Proactor::register_personality`].
145 ///
146 /// [`Proactor::register_personality`]: crate::Proactor::register_personality
147 set fn personality(&mut self, personality: u16) = |extra| extra.set_personality(personality);
148 }
149}
150
151macro_rules! iour_only {
152 {} => {};
153 {
154 $(#[$doc:meta])*
155 get fn $fn:ident(&$this:ident) -> io::Result<$ret:ty> = |$extra:ident| $body:expr;
156 $($rest:tt)*
157 } => {
158 $(#[$doc])*
159 pub fn $fn (&$this) -> io::Result<$ret> {
160 const UNSUPPORTED: &str = concat!(stringify!($fn), " is only supported on the io_uring driver");
161 #[cfg(io_uring)]
162 if let Some($extra) = $this.try_as_iour() {
163 $body
164 } else {
165 Err(io::Error::new(io::ErrorKind::Unsupported, UNSUPPORTED))
166 }
167 #[cfg(not(io_uring))]
168 Err(io::Error::new(io::ErrorKind::Unsupported, UNSUPPORTED))
169 }
170 iour_only!($($rest)*);
171 };
172 {
173 $(#[$doc:meta])*
174 set fn $val:ident(&mut $this:ident $(, $arg:ident: $arg_ty:ty)*) = |$extra:ident| $body:expr;
175 $($rest:tt)*
176 } => {
177 paste::paste! {
178 $(#[$doc])*
179 #[doc = " This is a no-op when not using `io_uring` driver."]
180 pub fn [<set_ $val>] (&mut $this $(, $arg: $arg_ty)*) {
181 #[cfg(io_uring)]
182 if let Some($extra) = $this.try_as_iour_mut() {
183 $body
184 }
185 #[cfg(not(io_uring))]
186 {$(let _ = $arg;)*}
187 }
188
189 #[doc = concat!("Call [`set_", stringify!($val), "`] and return the modified `Extra`.")]
190 #[doc = ""]
191 #[doc = concat!("[`set_", stringify!($val), "`]: Self::set_", stringify!($val))]
192 pub fn [<with_ $val>] (mut $this $(, $arg: $arg_ty)*) -> Self {
193 $this.[<set_ $val>]($($arg),*);
194 $this
195 }
196 }
197 iour_only!($($rest)*);
198 };
199}
200
201use iour_only;
202
203use crate::Driver;