compio_driver/sys/fusion/
mod.rs1pub(crate) mod op;
2
3#[cfg_attr(all(doc, docsrs), doc(cfg(all())))]
4pub use std::os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
5use std::{
6 io,
7 task::{Poll, Waker},
8 time::Duration,
9};
10
11use compio_log::warn;
12pub use iour::{IourOpCode, OpEntry};
13pub use poll::{Decision, OpType, PollOpCode};
14
15pub(crate) use super::iour::is_op_supported;
16use super::{iour, poll};
17pub use crate::driver_type::DriverType; use crate::{BufferPool, Key, ProactorBuilder, key::ErasedKey};
19
20pub enum Extra {
21 Poll(poll::Extra),
22 IoUring(iour::Extra),
23}
24
25impl From<poll::Extra> for Extra {
26 fn from(inner: poll::Extra) -> Self {
27 Self::Poll(inner)
28 }
29}
30
31impl From<iour::Extra> for Extra {
32 fn from(inner: iour::Extra) -> Self {
33 Self::IoUring(inner)
34 }
35}
36
37#[allow(dead_code)]
38impl super::Extra {
39 pub(crate) fn is_iour(&self) -> bool {
40 matches!(self.0, Extra::IoUring(_))
41 }
42
43 pub(in crate::sys) fn try_as_iour(&self) -> Option<&iour::Extra> {
44 if let Extra::IoUring(extra) = &self.0 {
45 Some(extra)
46 } else {
47 None
48 }
49 }
50
51 pub(in crate::sys) fn try_as_iour_mut(&mut self) -> Option<&mut iour::Extra> {
52 if let Extra::IoUring(extra) = &mut self.0 {
53 Some(extra)
54 } else {
55 None
56 }
57 }
58
59 pub(in crate::sys) fn try_as_poll(&self) -> Option<&poll::Extra> {
60 if let Extra::Poll(extra) = &self.0 {
61 Some(extra)
62 } else {
63 None
64 }
65 }
66
67 pub(in crate::sys) fn try_as_poll_mut(&mut self) -> Option<&mut poll::Extra> {
68 if let Extra::Poll(extra) = &mut self.0 {
69 Some(extra)
70 } else {
71 None
72 }
73 }
74}
75
76pub trait OpCode: PollOpCode + IourOpCode {}
80
81impl<T: PollOpCode + IourOpCode + ?Sized> OpCode for T {}
82
83#[allow(clippy::large_enum_variant)]
84enum FuseDriver {
85 Poll(poll::Driver),
86 IoUring(iour::Driver),
87}
88
89pub(crate) struct Driver {
91 fuse: FuseDriver,
92}
93
94impl Driver {
95 pub fn new(builder: &ProactorBuilder) -> io::Result<Self> {
97 let (ty, fallback) = match &builder.driver_type {
98 Some(t) => (*t, false),
99 None => (DriverType::suggest(), true),
100 };
101 match ty {
102 DriverType::Poll => Ok(Self {
103 fuse: FuseDriver::Poll(poll::Driver::new(builder)?),
104 }),
105 DriverType::IoUring => match iour::Driver::new(builder) {
106 Ok(driver) => Ok(Self {
107 fuse: FuseDriver::IoUring(driver),
108 }),
109 Err(_e) if fallback => {
111 warn!("Fail to create io-uring driver: {_e:?}, fallback to polling driver.");
112 Ok(Self {
113 fuse: FuseDriver::Poll(poll::Driver::new(builder)?),
114 })
115 }
116 Err(e) => Err(e),
117 },
118 _ => unreachable!("Fuse driver will only be enabled on linux"),
119 }
120 }
121
122 #[allow(dead_code)]
123 pub fn as_iour(&self) -> Option<&iour::Driver> {
124 if let FuseDriver::IoUring(driver) = &self.fuse {
125 Some(driver)
126 } else {
127 None
128 }
129 }
130
131 pub fn driver_type(&self) -> DriverType {
132 match &self.fuse {
133 FuseDriver::Poll(driver) => driver.driver_type(),
134 FuseDriver::IoUring(driver) => driver.driver_type(),
135 }
136 }
137
138 pub fn default_extra(&self) -> Extra {
139 match &self.fuse {
140 FuseDriver::Poll(driver) => Extra::Poll(driver.default_extra()),
141 FuseDriver::IoUring(driver) => Extra::IoUring(driver.default_extra()),
142 }
143 }
144
145 pub fn attach(&mut self, fd: RawFd) -> io::Result<()> {
146 match &mut self.fuse {
147 FuseDriver::Poll(driver) => driver.attach(fd),
148 FuseDriver::IoUring(driver) => driver.attach(fd),
149 }
150 }
151
152 pub fn cancel<T>(&mut self, key: Key<T>) {
153 match &mut self.fuse {
154 FuseDriver::Poll(driver) => driver.cancel(key),
155 FuseDriver::IoUring(driver) => driver.cancel(key),
156 }
157 }
158
159 pub fn push(&mut self, op: ErasedKey) -> Poll<io::Result<usize>> {
160 match &mut self.fuse {
161 FuseDriver::Poll(driver) => driver.push(op),
162 FuseDriver::IoUring(driver) => driver.push(op),
163 }
164 }
165
166 pub fn poll(&mut self, timeout: Option<Duration>) -> io::Result<()> {
167 match &mut self.fuse {
168 FuseDriver::Poll(driver) => driver.poll(timeout),
169 FuseDriver::IoUring(driver) => driver.poll(timeout),
170 }
171 }
172
173 pub fn waker(&self) -> Waker {
174 match &self.fuse {
175 FuseDriver::Poll(driver) => driver.waker(),
176 FuseDriver::IoUring(driver) => driver.waker(),
177 }
178 }
179
180 pub fn create_buffer_pool(
181 &mut self,
182 buffer_len: u16,
183 buffer_size: usize,
184 ) -> io::Result<BufferPool> {
185 match &mut self.fuse {
186 FuseDriver::IoUring(driver) => Ok(driver.create_buffer_pool(buffer_len, buffer_size)?),
187 FuseDriver::Poll(driver) => Ok(driver.create_buffer_pool(buffer_len, buffer_size)?),
188 }
189 }
190
191 pub unsafe fn release_buffer_pool(&mut self, buffer_pool: BufferPool) -> io::Result<()> {
195 unsafe {
196 match &mut self.fuse {
197 FuseDriver::Poll(driver) => driver.release_buffer_pool(buffer_pool),
198 FuseDriver::IoUring(driver) => driver.release_buffer_pool(buffer_pool),
199 }
200 }
201 }
202}
203
204impl AsRawFd for Driver {
205 fn as_raw_fd(&self) -> RawFd {
206 match &self.fuse {
207 FuseDriver::Poll(driver) => driver.as_raw_fd(),
208 FuseDriver::IoUring(driver) => driver.as_raw_fd(),
209 }
210 }
211}