compio_driver/fusion/
mod.rs1#[path = "../poll/mod.rs"]
2mod poll;
3
4#[path = "../iour/mod.rs"]
5mod iour;
6
7pub(crate) mod op;
8
9#[cfg_attr(all(doc, docsrs), doc(cfg(all())))]
10pub use std::os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
11use std::{io, task::Poll, time::Duration};
12
13use compio_log::warn;
14pub(crate) use iour::is_op_supported;
15pub use iour::{OpCode as IourOpCode, OpEntry};
16pub use poll::{Decision, OpCode as PollOpCode, OpType};
17
18pub use crate::driver_type::DriverType; use crate::{BufferPool, Key, ProactorBuilder};
20
21pub trait OpCode: PollOpCode + IourOpCode {}
25
26impl<T: PollOpCode + IourOpCode + ?Sized> OpCode for T {}
27
28#[allow(clippy::large_enum_variant)]
29enum FuseDriver {
30 Poll(poll::Driver),
31 IoUring(iour::Driver),
32}
33
34pub(crate) struct Driver {
36 fuse: FuseDriver,
37}
38
39impl Driver {
40 pub fn new(builder: &ProactorBuilder) -> io::Result<Self> {
42 let (ty, fallback) = match &builder.driver_type {
43 Some(t) => (*t, false),
44 None => (DriverType::suggest(), true),
45 };
46 match ty {
47 DriverType::Poll => Ok(Self {
48 fuse: FuseDriver::Poll(poll::Driver::new(builder)?),
49 }),
50 DriverType::IoUring => match iour::Driver::new(builder) {
51 Ok(driver) => Ok(Self {
52 fuse: FuseDriver::IoUring(driver),
53 }),
54 Err(_e) if fallback => {
55 warn!("Fail to create io-uring driver: {_e:?}, fallback to polling driver.");
56 Ok(Self {
57 fuse: FuseDriver::Poll(poll::Driver::new(builder)?),
58 })
59 }
60 Err(e) => Err(e),
61 },
62 _ => unreachable!("Fuse driver will only be enabled on linux"),
63 }
64 }
65
66 pub fn driver_type(&self) -> DriverType {
67 match &self.fuse {
68 FuseDriver::Poll(driver) => driver.driver_type(),
69 FuseDriver::IoUring(driver) => driver.driver_type(),
70 }
71 }
72
73 pub fn create_op<T: OpCode + 'static>(&self, op: T) -> Key<T> {
74 match &self.fuse {
75 FuseDriver::Poll(driver) => driver.create_op(op),
76 FuseDriver::IoUring(driver) => driver.create_op(op),
77 }
78 }
79
80 pub fn attach(&mut self, fd: RawFd) -> io::Result<()> {
81 match &mut self.fuse {
82 FuseDriver::Poll(driver) => driver.attach(fd),
83 FuseDriver::IoUring(driver) => driver.attach(fd),
84 }
85 }
86
87 pub fn cancel(&mut self, op: &mut Key<dyn OpCode>) {
88 match &mut self.fuse {
89 FuseDriver::Poll(driver) => driver.cancel(op),
90 FuseDriver::IoUring(driver) => driver.cancel(op),
91 }
92 }
93
94 pub fn push(&mut self, op: &mut Key<dyn OpCode>) -> Poll<io::Result<usize>> {
95 match &mut self.fuse {
96 FuseDriver::Poll(driver) => driver.push(op),
97 FuseDriver::IoUring(driver) => driver.push(op),
98 }
99 }
100
101 pub unsafe fn poll(&mut self, timeout: Option<Duration>) -> io::Result<()> {
102 match &mut self.fuse {
103 FuseDriver::Poll(driver) => driver.poll(timeout),
104 FuseDriver::IoUring(driver) => driver.poll(timeout),
105 }
106 }
107
108 pub fn handle(&self) -> NotifyHandle {
109 let fuse = match &self.fuse {
110 FuseDriver::Poll(driver) => FuseNotifyHandle::Poll(driver.handle()),
111 FuseDriver::IoUring(driver) => FuseNotifyHandle::IoUring(driver.handle()),
112 };
113 NotifyHandle::from_fuse(fuse)
114 }
115
116 pub fn create_buffer_pool(
117 &mut self,
118 buffer_len: u16,
119 buffer_size: usize,
120 ) -> io::Result<BufferPool> {
121 match &mut self.fuse {
122 FuseDriver::IoUring(driver) => Ok(driver.create_buffer_pool(buffer_len, buffer_size)?),
123 FuseDriver::Poll(driver) => Ok(driver.create_buffer_pool(buffer_len, buffer_size)?),
124 }
125 }
126
127 pub unsafe fn release_buffer_pool(&mut self, buffer_pool: BufferPool) -> io::Result<()> {
131 match &mut self.fuse {
132 FuseDriver::Poll(driver) => driver.release_buffer_pool(buffer_pool),
133 FuseDriver::IoUring(driver) => driver.release_buffer_pool(buffer_pool),
134 }
135 }
136}
137
138impl AsRawFd for Driver {
139 fn as_raw_fd(&self) -> RawFd {
140 match &self.fuse {
141 FuseDriver::Poll(driver) => driver.as_raw_fd(),
142 FuseDriver::IoUring(driver) => driver.as_raw_fd(),
143 }
144 }
145}
146
147enum FuseNotifyHandle {
148 Poll(poll::NotifyHandle),
149 IoUring(iour::NotifyHandle),
150}
151
152pub struct NotifyHandle {
154 fuse: FuseNotifyHandle,
155}
156
157impl NotifyHandle {
158 fn from_fuse(fuse: FuseNotifyHandle) -> Self {
159 Self { fuse }
160 }
161
162 pub fn notify(&self) -> io::Result<()> {
164 match &self.fuse {
165 FuseNotifyHandle::Poll(handle) => handle.notify(),
166 FuseNotifyHandle::IoUring(handle) => handle.notify(),
167 }
168 }
169}