1#![allow(clippy::new_without_default)]
4
5use linux_io_uring_sys as sys;
6use crate::squeue::Entry;
7use crate::util::sqe_zeroed;
8
9pub mod types {
10 use std::os::unix::io::RawFd;
11 use bitflags::bitflags;
12 use linux_io_uring_sys as sys;
13
14 pub use sys::__kernel_timespec as Timespec;
15 pub use sys::__kernel_rwf_t as RwFlags;
16
17 #[derive(Debug, Clone, Copy)]
18 pub enum Target {
19 Fd(RawFd),
20
21 Fixed(u32)
23 }
24
25 bitflags!{
26 pub struct TimeoutFlags: u32 {
27 #[cfg(feature = "unstable")]
28 const ABS = sys::IORING_TIMEOUT_ABS;
29 }
30 }
31
32 bitflags!{
33 pub struct FsyncFlags: u32 {
34 const DATASYNC = sys::IORING_FSYNC_DATASYNC;
35 }
36 }
37}
38
39
40macro_rules! assign_fd {
41 ( $sqe:ident . fd = $opfd:expr ) => {
42 match $opfd {
43 types::Target::Fd(fd) => $sqe.fd = fd,
44 types::Target::Fixed(i) => {
45 $sqe.fd = i as _;
46 $sqe.flags |= crate::squeue::Flags::FIXED_FILE.bits();
47 }
48 }
49 }
50}
51
52macro_rules! opcode {
53 (
54 $( #[$outer:meta] )*
55 pub struct $name:ident {
56 $( #[$new_meta:meta] )*
57 $( $field:ident : $tname:ty ),* $(,)?
58 ;;
59 $(
60 $( #[$opt_meta:meta] )*
61 $opt_field:ident : $opt_tname:ty = $default:expr
62 ),* $(,)?
63 }
64
65 pub fn build($self:ident) -> Entry $build_block:block
66 ) => {
67 $( #[$outer] )*
68 pub struct $name {
69 $( $field : $tname, )*
70 $( $opt_field : $opt_tname, )*
71 }
72
73 impl $name {
74 $( #[$new_meta] )*
75 pub const fn new( $( $field : $tname ),* ) -> Self {
76 $name {
77 $( $field , )*
78 $( $opt_field: $default, )*
79 }
80 }
81
82 $(
83 $( #[$opt_meta] )*
84 pub const fn $opt_field(mut self, $opt_field: $opt_tname) -> Self {
85 self.$opt_field = $opt_field;
86 self
87 }
88 )*
89
90 pub fn build($self) -> Entry $build_block
91 }
92 }
93}
94
95opcode!(
96 #[derive(Debug)]
100 pub struct Nop { ;; }
101
102 pub fn build(self) -> Entry {
103 let Nop {} = self;
104
105 let mut sqe = sqe_zeroed();
106 sqe.opcode = sys::IORING_OP_NOP as _;
107 sqe.fd = -1;
108 Entry(sqe)
109 }
110);
111
112opcode!(
113 #[derive(Debug)]
117 pub struct Readv {
118 fd: types::Target,
119 iovec: *mut libc::iovec,
120 len: u32,
121 ;;
122 ioprio: u16 = 0,
123 offset: libc::off_t = 0,
124 rw_flags: types::RwFlags = 0
127 }
128
129 pub fn build(self) -> Entry {
130 let Readv {
131 fd,
132 iovec, len, offset,
133 ioprio, rw_flags
134 } = self;
135
136 let mut sqe = sqe_zeroed();
137 sqe.opcode = sys::IORING_OP_READV as _;
138 assign_fd!(sqe.fd = fd);
139 sqe.ioprio = ioprio;
140 sqe.addr = iovec as _;
141 sqe.len = len;
142 sqe.__bindgen_anon_1.off = offset as _;
143 sqe.__bindgen_anon_2.rw_flags = rw_flags;
144 Entry(sqe)
145 }
146);
147
148opcode!(
149 #[derive(Debug)]
153 pub struct Writev {
154 fd: types::Target,
155 iovec: *const libc::iovec,
156 len: u32,
157 ;;
158 ioprio: u16 = 0,
159 offset: libc::off_t = 0,
160 rw_flags: types::RwFlags = 0
163 }
164
165 pub fn build(self) -> Entry {
166 let Writev {
167 fd,
168 iovec, len, offset,
169 ioprio, rw_flags
170 } = self;
171
172 let mut sqe = sqe_zeroed();
173 sqe.opcode = sys::IORING_OP_WRITEV as _;
174 assign_fd!(sqe.fd = fd);
175 sqe.ioprio = ioprio;
176 sqe.addr = iovec as _;
177 sqe.len = len;
178 sqe.__bindgen_anon_1.off = offset as _;
179 sqe.__bindgen_anon_2.rw_flags = rw_flags;
180 Entry(sqe)
181 }
182);
183
184opcode!(
185 #[derive(Debug)]
190 pub struct Fsync {
191 fd: types::Target,
192 ;;
193 flags: types::FsyncFlags = types::FsyncFlags::empty()
197 }
198
199 pub fn build(self) -> Entry {
200 let Fsync { fd, flags } = self;
201
202 let mut sqe = sqe_zeroed();
203 sqe.opcode = sys::IORING_OP_FSYNC as _;
204 assign_fd!(sqe.fd = fd);
205 sqe.__bindgen_anon_2.fsync_flags = flags.bits();
206 Entry(sqe)
207 }
208);
209
210opcode!(
211 #[derive(Debug)]
215 pub struct ReadFixed {
216 fd: types::Target,
219 buf: *mut u8,
220 len: u32,
221 buf_index: u16,
222 ;;
223 ioprio: u16 = 0,
224 offset: libc::off_t = 0,
225 rw_flags: types::RwFlags = 0
228 }
229
230 pub fn build(self) -> Entry {
231 let ReadFixed {
232 fd,
233 buf, len, offset,
234 buf_index,
235 ioprio, rw_flags
236 } = self;
237
238 let mut sqe = sqe_zeroed();
239 sqe.opcode = sys::IORING_OP_READ_FIXED as _;
240 assign_fd!(sqe.fd = fd);
241 sqe.ioprio = ioprio;
242 sqe.addr = buf as _;
243 sqe.len = len;
244 sqe.__bindgen_anon_1.off = offset as _;
245 sqe.__bindgen_anon_2.rw_flags = rw_flags;
246 sqe.__bindgen_anon_3.buf_index = buf_index;
247 Entry(sqe)
248 }
249);
250
251opcode!(
252 #[derive(Debug)]
256 pub struct WriteFixed {
257 fd: types::Target,
260 buf: *const u8,
261 len: u32,
262 buf_index: u16,
263 ;;
264 ioprio: u16 = 0,
265 offset: libc::off_t = 0,
266 rw_flags: types::RwFlags = 0
269 }
270
271 pub fn build(self) -> Entry {
272 let WriteFixed {
273 fd,
274 buf, len, offset,
275 buf_index,
276 ioprio, rw_flags
277 } = self;
278
279 let mut sqe = sqe_zeroed();
280 sqe.opcode = sys::IORING_OP_WRITE_FIXED as _;
281 assign_fd!(sqe.fd = fd);
282 sqe.ioprio = ioprio;
283 sqe.addr = buf as _;
284 sqe.len = len;
285 sqe.__bindgen_anon_1.off = offset as _;
286 sqe.__bindgen_anon_2.rw_flags = rw_flags;
287 sqe.__bindgen_anon_3.buf_index = buf_index;
288 Entry(sqe)
289 }
290);
291
292opcode!(
293 #[derive(Debug)]
298 pub struct PollAdd {
299 fd: types::Target,
302 flags: libc::c_short,
303 ;;
304 }
305
306 pub fn build(self) -> Entry {
307 let PollAdd { fd, flags } = self;
308
309 let mut sqe = sqe_zeroed();
310 sqe.opcode = sys::IORING_OP_POLL_ADD as _;
311 assign_fd!(sqe.fd = fd);
312 sqe.__bindgen_anon_2.poll_events = flags as _;
313 Entry(sqe)
314 }
315);
316
317opcode!(
318 #[derive(Debug)]
323 pub struct PollRemove {
324 user_data: u64
325 ;;
326 }
327
328 pub fn build(self) -> Entry {
329 let PollRemove { user_data } = self;
330
331 let mut sqe = sqe_zeroed();
332 sqe.opcode = sys::IORING_OP_POLL_REMOVE as _;
333 sqe.fd = -1;
334 sqe.addr = user_data as _;
335 Entry(sqe)
336 }
337);
338
339opcode!(
340 #[derive(Debug)]
344 pub struct SyncFileRange {
345 fd: types::Target,
346 len: u32,
347 ;;
348 offset: libc::off_t = 0,
350 flags: u32 = 0
352 }
353
354 pub fn build(self) -> Entry {
355 let SyncFileRange {
356 fd,
357 len, offset,
358 flags
359 } = self;
360
361 let mut sqe = sqe_zeroed();
362 sqe.opcode = sys::IORING_OP_SYNC_FILE_RANGE as _;
363 assign_fd!(sqe.fd = fd);
364 sqe.len = len;
365 sqe.__bindgen_anon_1.off = offset as _;
366 sqe.__bindgen_anon_2.sync_range_flags = flags;
367 Entry(sqe)
368 }
369);
370
371opcode!(
372 #[derive(Debug)]
378 pub struct SendMsg {
379 fd: types::Target,
380 msg: *const libc::msghdr,
381 ;;
382 ioprio: u16 = 0,
383 flags: u32 = 0
384 }
385
386 pub fn build(self) -> Entry {
387 let SendMsg { fd, msg, ioprio, flags } = self;
388
389 let mut sqe = sqe_zeroed();
390 sqe.opcode = sys::IORING_OP_SENDMSG as _;
391 assign_fd!(sqe.fd = fd);
392 sqe.ioprio = ioprio;
393 sqe.addr = msg as _;
394 sqe.len = 1;
395 sqe.__bindgen_anon_2.msg_flags = flags;
396 Entry(sqe)
397 }
398);
399
400opcode!(
401 #[derive(Debug)]
405 pub struct RecvMsg {
406 fd: types::Target,
407 msg: *mut libc::msghdr,
408 ;;
409 ioprio: u16 = 0,
410 flags: u32 = 0
411 }
412
413 pub fn build(self) -> Entry {
414 let RecvMsg { fd, msg, ioprio, flags } = self;
415
416 let mut sqe = sqe_zeroed();
417 sqe.opcode = sys::IORING_OP_RECVMSG as _;
418 assign_fd!(sqe.fd = fd);
419 sqe.ioprio = ioprio;
420 sqe.addr = msg as _;
421 sqe.len = 1;
422 sqe.__bindgen_anon_2.msg_flags = flags;
423 Entry(sqe)
424 }
425);
426
427opcode!(
428 #[derive(Debug)]
437 pub struct Timeout {
438 timespec: *const types::Timespec,
439 ;;
440 count: u32 = 0,
442
443 #[cfg_attr(not(feature = "unstable"), allow(intra_doc_link_resolution_failure))]
444 flags: types::TimeoutFlags = types::TimeoutFlags::empty()
446 }
447
448 pub fn build(self) -> Entry {
449 let Timeout { timespec, count, flags } = self;
450
451 let mut sqe = sqe_zeroed();
452 sqe.opcode = sys::IORING_OP_TIMEOUT as _;
453 sqe.fd = -1;
454 sqe.addr = timespec as _;
455 sqe.len = 1;
456 sqe.__bindgen_anon_1.off = count as _;
457 sqe.__bindgen_anon_2.timeout_flags = flags.bits();
458 Entry(sqe)
459 }
460);
461
462#[cfg(feature = "unstable")]
463opcode!(
464 pub struct TimeoutRemove {
465 user_data: u64,
466 ;;
467 flags: types::TimeoutFlags = types::TimeoutFlags::empty()
468 }
469
470 pub fn build(self) -> Entry {
471 let TimeoutRemove { user_data, flags } = self;
472
473 let mut sqe = sqe_zeroed();
474 sqe.opcode = sys::IORING_OP_TIMEOUT_REMOVE as _;
475 sqe.fd = -1;
476 sqe.addr = user_data as _;
477 sqe.__bindgen_anon_2.timeout_flags = flags.bits();
478 Entry(sqe)
479 }
480);
481
482#[cfg(feature = "unstable")]
483opcode!(
484 pub struct Accept {
485 fd: types::Target,
486 addr: *const libc::sockaddr,
487 addrlen: libc::socklen_t
488 ;;
489 flags: u32 = 0
490 }
491
492 pub fn build(self) -> Entry {
493 let Accept { fd, addr, addrlen, flags } = self;
494
495 let mut sqe = sqe_zeroed();
496 sqe.opcode = sys::IORING_OP_ACCEPT as _;
497 assign_fd!(sqe.fd = fd);
498 sqe.addr = addr as _;
499 sqe.__bindgen_anon_1.off = addrlen as _;
500 sqe.__bindgen_anon_2.accept_flags = flags;
501 Entry(sqe)
502 }
503);
504
505#[cfg(feature = "unstable")]
506opcode!(
507 pub struct AsyncCancel {
508 user_data: u64,
509 ;;
510 flags: u32 = 0
511 }
512
513 pub fn build(self) -> Entry {
514 let AsyncCancel { user_data, flags } = self;
515
516 let mut sqe = sqe_zeroed();
517 sqe.opcode = sys::IORING_OP_ASYNC_CANCEL as _;
518 sqe.fd = -1;
519 sqe.addr = user_data as _;
520 sqe.__bindgen_anon_2.timeout_flags = flags;
521 Entry(sqe)
522 }
523);
524
525#[cfg(feature = "unstable")]
526opcode!(
527 pub struct LinkTimeout {
528 timespec: *const types::Timespec,
529 ;;
530 flags: types::TimeoutFlags = types::TimeoutFlags::empty()
531 }
532
533 pub fn build(self) -> Entry {
534 let LinkTimeout { timespec, flags } = self;
535
536 let mut sqe = sqe_zeroed();
537 sqe.opcode = sys::IORING_OP_TIMEOUT as _;
538 sqe.fd = -1;
539 sqe.addr = timespec as _;
540 sqe.len = 1;
541 sqe.__bindgen_anon_2.timeout_flags = flags.bits();
542 Entry(sqe)
543 }
544);
545
546#[cfg(feature = "unstable")]
547opcode!(
548 pub struct Connect {
549 fd: types::Target,
550 addr: *const libc::sockaddr,
551 addrlen: libc::socklen_t
552 ;;
553 }
554
555 pub fn build(self) -> Entry {
556 let Connect { fd, addr, addrlen } = self;
557
558 let mut sqe = sqe_zeroed();
559 sqe.opcode = sys::IORING_OP_CONNECT as _;
560 assign_fd!(sqe.fd = fd);
561 sqe.addr = addr as _;
562 sqe.__bindgen_anon_1.off = addrlen as _;
563 Entry(sqe)
564 }
565);