1use std::io;
2#[cfg(target_os = "linux")]
3use {
4 crate::io_uring::sqpoll::SharedSqPoll,
5 std::os::fd::{AsFd as _, BorrowedFd},
6};
7
8#[derive(Default)]
21pub struct IoSetupState {
22 #[cfg(target_os = "linux")]
23 shared_sqpoll: Option<SharedSqPoll>,
24 pub use_direct_io: bool,
25 pub use_registered_io_uring_buffers: bool,
26}
27
28impl IoSetupState {
29 pub fn with_shared_sqpoll(self) -> io::Result<Self> {
35 Ok(Self {
36 #[cfg(target_os = "linux")]
37 shared_sqpoll: Some(SharedSqPoll::new()?),
38 ..self
39 })
40 }
41
42 pub fn with_buffers_registered(mut self, fixed: bool) -> Self {
46 self.use_registered_io_uring_buffers = fixed;
47 self
48 }
49
50 pub fn with_direct_io(mut self, use_direct_io: bool) -> Self {
57 self.use_direct_io = use_direct_io;
58 self
59 }
60
61 #[cfg(target_os = "linux")]
62 pub fn shared_sqpoll_fd(&self) -> Option<BorrowedFd<'_>> {
63 self.shared_sqpoll.as_ref().map(|s| s.as_fd())
64 }
65}
66
67#[cfg(all(test, target_os = "linux"))]
68mod tests {
69 use {
70 super::*,
71 crate::{
72 file_io::FileCreator,
73 io_uring::{
74 file_creator::IoUringFileCreatorBuilder,
75 sequential_file_reader::SequentialFileReaderBuilder,
76 },
77 },
78 rand::RngCore,
79 std::{
80 fs::File,
81 io::{Cursor, Read},
82 sync::{Arc, RwLock},
83 },
84 };
85
86 #[test]
87 fn test_shared_sqpoll_read_and_create() {
88 let io_setup = &IoSetupState::default().with_shared_sqpoll().unwrap();
89
90 let read_bytes = RwLock::new(vec![]);
91 let read_bytes_ref = &read_bytes;
92 let mut file_creator = IoUringFileCreatorBuilder::new()
93 .shared_sqpoll(io_setup.shared_sqpoll_fd())
94 .build(1 << 20, move |file_info| {
95 let mut reader = SequentialFileReaderBuilder::new()
96 .shared_sqpoll(io_setup.shared_sqpoll_fd())
97 .build(1 << 20)
98 .unwrap();
99 reader.set_path(file_info.path).unwrap();
100 reader
101 .read_to_end(read_bytes_ref.write().unwrap().as_mut())
102 .unwrap();
103 None
104 })
105 .unwrap();
106
107 let temp_dir = tempfile::tempdir().unwrap();
108 let dir_handle = Arc::new(File::open(temp_dir.path()).unwrap());
109 let mut write_bytes = vec![0; 2 << 20];
110 rand::rng().fill_bytes(&mut write_bytes);
111
112 let file_path1 = temp_dir.path().join("test-1.txt");
113 let file_path2 = temp_dir.path().join("test-2.txt");
114 for path in [file_path1, file_path2] {
115 let dir_handle = dir_handle.clone();
116 file_creator
117 .schedule_create_at_dir(path, 0o644, dir_handle, &mut Cursor::new(&write_bytes))
118 .unwrap();
119 }
120 file_creator.drain().unwrap();
121 drop(file_creator);
122
123 let read_bytes = read_bytes.into_inner().unwrap();
125 assert_eq!(&read_bytes[..write_bytes.len()], &write_bytes);
127 assert_eq!(&read_bytes[write_bytes.len()..], &write_bytes);
128 }
129}