1 //! Linux [io_uring].
2 //!
3 //! This API is very low-level. The main adaptations it makes from the raw
4 //! Linux io_uring API are the use of appropriately-sized `bitflags`, `enum`,
5 //! `Result`, `OwnedFd`, `AsFd`, `RawFd`, and `*mut c_void` in place of plain
6 //! integers.
7 //!
8 //! For a higher-level API built on top of this, see the [rustix-uring] crate.
9 //!
10 //! # Safety
11 //!
12 //! io_uring operates on raw pointers and raw file descriptors. Rustix does not
13 //! attempt to provide a safe API for these, because the abstraction level is
14 //! too low for this to be practical. Safety should be introduced in
15 //! higher-level abstraction layers.
16 //!
17 //! # References
18 //!  - [Linux]
19 //!  - [io_uring header]
20 //!
21 //! [Linux]: https://man.archlinux.org/man/io_uring.7.en
22 //! [io_uring]: https://en.wikipedia.org/wiki/Io_uring
23 //! [io_uring header]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/io_uring.h
24 //! [rustix-uring]: https://crates.io/crates/rustix-uring
25 #![allow(unsafe_code)]
26 
27 use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
28 use crate::{backend, io};
29 use core::ffi::c_void;
30 use core::mem::MaybeUninit;
31 use core::ptr::{null_mut, write_bytes};
32 use linux_raw_sys::net;
33 
34 // Export types used in io_uring APIs.
35 pub use crate::event::epoll::{
36     Event as EpollEvent, EventData as EpollEventData, EventFlags as EpollEventFlags,
37 };
38 pub use crate::fs::{Advice, AtFlags, Mode, OFlags, RenameFlags, ResolveFlags, Statx, StatxFlags};
39 pub use crate::io::ReadWriteFlags;
40 pub use crate::net::{RecvFlags, SendFlags, SocketFlags};
41 pub use crate::timespec::Timespec;
42 pub use linux_raw_sys::general::sigset_t;
43 
44 pub use net::{__kernel_sockaddr_storage as sockaddr_storage, msghdr, sockaddr, socklen_t};
45 
46 // Declare the `c_char` type for use with entries that take pointers
47 // to C strings. Define it as unsigned or signed according to the platform
48 // so that we match what Rust's `CStr` uses.
49 //
50 // When we can update to linux-raw-sys 0.5, we can remove this, as its
51 // `c_char` type will declare this.
52 /// The C `char` type.
53 #[cfg(any(
54     target_arch = "aarch64",
55     target_arch = "arm",
56     target_arch = "msp430",
57     target_arch = "powerpc",
58     target_arch = "powerpc64",
59     target_arch = "riscv32",
60     target_arch = "riscv64",
61     target_arch = "s390x",
62 ))]
63 #[allow(non_camel_case_types)]
64 pub type c_char = u8;
65 /// The C `char` type.
66 #[cfg(any(
67     target_arch = "mips",
68     target_arch = "mips64",
69     target_arch = "sparc64",
70     target_arch = "x86",
71     target_arch = "x86_64",
72     target_arch = "xtensa",
73 ))]
74 #[allow(non_camel_case_types)]
75 pub type c_char = i8;
76 
77 mod sys {
78     pub(super) use linux_raw_sys::io_uring::*;
79     #[cfg(test)]
80     pub(super) use {crate::backend::c::iovec, linux_raw_sys::general::open_how};
81 }
82 
83 /// `io_uring_setup(entries, params)`—Setup a context for performing
84 /// asynchronous I/O.
85 ///
86 /// # References
87 ///  - [Linux]
88 ///
89 /// [Linux]: https://man.archlinux.org/man/io_uring_setup.2.en
90 #[inline]
io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd>91 pub fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd> {
92     backend::io_uring::syscalls::io_uring_setup(entries, params)
93 }
94 
95 /// `io_uring_register(fd, opcode, arg, nr_args)`—Register files or user
96 /// buffers for asynchronous I/O.
97 ///
98 /// # Safety
99 ///
100 /// io_uring operates on raw pointers and raw file descriptors. Users are
101 /// responsible for ensuring that memory and resources are only accessed in
102 /// valid ways.
103 ///
104 /// # References
105 ///  - [Linux]
106 ///
107 /// [Linux]: https://man.archlinux.org/man/io_uring_register.2.en
108 #[inline]
io_uring_register<Fd: AsFd>( fd: Fd, opcode: IoringRegisterOp, arg: *const c_void, nr_args: u32, ) -> io::Result<u32>109 pub unsafe fn io_uring_register<Fd: AsFd>(
110     fd: Fd,
111     opcode: IoringRegisterOp,
112     arg: *const c_void,
113     nr_args: u32,
114 ) -> io::Result<u32> {
115     backend::io_uring::syscalls::io_uring_register(fd.as_fd(), opcode, arg, nr_args)
116 }
117 
118 /// `io_uring_enter(fd, to_submit, min_complete, flags, arg, size)`—Initiate
119 /// and/or complete asynchronous I/O.
120 ///
121 /// # Safety
122 ///
123 /// io_uring operates on raw pointers and raw file descriptors. Users are
124 /// responsible for ensuring that memory and resources are only accessed in
125 /// valid ways.
126 ///
127 /// # References
128 ///  - [Linux]
129 ///
130 /// [Linux]: https://man.archlinux.org/man/io_uring_enter.2.en
131 #[inline]
io_uring_enter<Fd: AsFd>( fd: Fd, to_submit: u32, min_complete: u32, flags: IoringEnterFlags, arg: *const c_void, size: usize, ) -> io::Result<u32>132 pub unsafe fn io_uring_enter<Fd: AsFd>(
133     fd: Fd,
134     to_submit: u32,
135     min_complete: u32,
136     flags: IoringEnterFlags,
137     arg: *const c_void,
138     size: usize,
139 ) -> io::Result<u32> {
140     backend::io_uring::syscalls::io_uring_enter(
141         fd.as_fd(),
142         to_submit,
143         min_complete,
144         flags,
145         arg,
146         size,
147     )
148 }
149 
150 bitflags::bitflags! {
151     /// `IORING_ENTER_*` flags for use with [`io_uring_enter`].
152     #[repr(transparent)]
153     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
154     pub struct IoringEnterFlags: u32 {
155         /// `IORING_ENTER_GETEVENTS`
156         const GETEVENTS = sys::IORING_ENTER_GETEVENTS;
157 
158         /// `IORING_ENTER_SQ_WAKEUP`
159         const SQ_WAKEUP = sys::IORING_ENTER_SQ_WAKEUP;
160 
161         /// `IORING_ENTER_SQ_WAIT`
162         const SQ_WAIT = sys::IORING_ENTER_SQ_WAIT;
163 
164         /// `IORING_ENTER_EXT_ARG`
165         const EXT_ARG = sys::IORING_ENTER_EXT_ARG;
166 
167         /// `IORING_ENTER_REGISTERED_RING`
168         const REGISTERED_RING = sys::IORING_ENTER_REGISTERED_RING;
169 
170         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
171         const _ = !0;
172     }
173 }
174 
175 /// `IORING_REGISTER_*` and `IORING_UNREGISTER_*` constants for use with
176 /// [`io_uring_register`].
177 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
178 #[repr(u8)]
179 #[non_exhaustive]
180 pub enum IoringRegisterOp {
181     /// `IORING_REGISTER_BUFFERS`
182     RegisterBuffers = sys::IORING_REGISTER_BUFFERS as _,
183 
184     /// `IORING_UNREGISTER_BUFFERS`
185     UnregisterBuffers = sys::IORING_UNREGISTER_BUFFERS as _,
186 
187     /// `IORING_REGISTER_FILES`
188     RegisterFiles = sys::IORING_REGISTER_FILES as _,
189 
190     /// `IORING_UNREGISTER_FILES`
191     UnregisterFiles = sys::IORING_UNREGISTER_FILES as _,
192 
193     /// `IORING_REGISTER_EVENTFD`
194     RegisterEventfd = sys::IORING_REGISTER_EVENTFD as _,
195 
196     /// `IORING_UNREGISTER_EVENTFD`
197     UnregisterEventfd = sys::IORING_UNREGISTER_EVENTFD as _,
198 
199     /// `IORING_REGISTER_FILES_UPDATE`
200     RegisterFilesUpdate = sys::IORING_REGISTER_FILES_UPDATE as _,
201 
202     /// `IORING_REGISTER_EVENTFD_ASYNC`
203     RegisterEventfdAsync = sys::IORING_REGISTER_EVENTFD_ASYNC as _,
204 
205     /// `IORING_REGISTER_PROBE`
206     RegisterProbe = sys::IORING_REGISTER_PROBE as _,
207 
208     /// `IORING_REGISTER_PERSONALITY`
209     RegisterPersonality = sys::IORING_REGISTER_PERSONALITY as _,
210 
211     /// `IORING_UNREGISTER_PERSONALITY`
212     UnregisterPersonality = sys::IORING_UNREGISTER_PERSONALITY as _,
213 
214     /// `IORING_REGISTER_RESTRICTIONS`
215     RegisterRestrictions = sys::IORING_REGISTER_RESTRICTIONS as _,
216 
217     /// `IORING_REGISTER_ENABLE_RINGS`
218     RegisterEnableRings = sys::IORING_REGISTER_ENABLE_RINGS as _,
219 
220     /// `IORING_REGISTER_BUFFERS2`
221     RegisterBuffers2 = sys::IORING_REGISTER_BUFFERS2 as _,
222 
223     /// `IORING_REGISTER_BUFFERS_UPDATE`
224     RegisterBuffersUpdate = sys::IORING_REGISTER_BUFFERS_UPDATE as _,
225 
226     /// `IORING_REGISTER_FILES2`
227     RegisterFiles2 = sys::IORING_REGISTER_FILES2 as _,
228 
229     /// `IORING_REGISTER_FILES_SKIP`
230     RegisterFilesSkip = sys::IORING_REGISTER_FILES_SKIP as _,
231 
232     /// `IORING_REGISTER_FILES_UPDATE2`
233     RegisterFilesUpdate2 = sys::IORING_REGISTER_FILES_UPDATE2 as _,
234 
235     /// `IORING_REGISTER_IOWQ_AFF`
236     RegisterIowqAff = sys::IORING_REGISTER_IOWQ_AFF as _,
237 
238     /// `IORING_UNREGISTER_IOWQ_AFF`
239     UnregisterIowqAff = sys::IORING_UNREGISTER_IOWQ_AFF as _,
240 
241     /// `IORING_REGISTER_IOWQ_MAX_WORKERS`
242     RegisterIowqMaxWorkers = sys::IORING_REGISTER_IOWQ_MAX_WORKERS as _,
243 
244     /// `IORING_REGISTER_RING_FDS`
245     RegisterRingFds = sys::IORING_REGISTER_RING_FDS as _,
246 
247     /// `IORING_UNREGISTER_RING_FDS`
248     UnregisterRingFds = sys::IORING_UNREGISTER_RING_FDS as _,
249 
250     /// `IORING_REGISTER_PBUF_RING`
251     RegisterPbufRing = sys::IORING_REGISTER_PBUF_RING as _,
252 
253     /// `IORING_UNREGISTER_PBUF_RING`
254     UnregisterPbufRing = sys::IORING_UNREGISTER_PBUF_RING as _,
255 
256     /// `IORING_REGISTER_SYNC_CANCEL`
257     RegisterSyncCancel = sys::IORING_REGISTER_SYNC_CANCEL as _,
258 
259     /// `IORING_REGISTER_FILE_ALLOC_RANGE`
260     RegisterFileAllocRange = sys::IORING_REGISTER_FILE_ALLOC_RANGE as _,
261 }
262 
263 /// `IORING_OP_*` constants for use with [`io_uring_sqe`].
264 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
265 #[repr(u8)]
266 #[non_exhaustive]
267 pub enum IoringOp {
268     /// `IORING_OP_NOP`
269     Nop = sys::io_uring_op::IORING_OP_NOP as _,
270 
271     /// `IORING_OP_ACCEPT`
272     Accept = sys::io_uring_op::IORING_OP_ACCEPT as _,
273 
274     /// `IORING_OP_ASYNC_CANCEL`
275     AsyncCancel = sys::io_uring_op::IORING_OP_ASYNC_CANCEL as _,
276 
277     /// `IORING_OP_CLOSE`
278     Close = sys::io_uring_op::IORING_OP_CLOSE as _,
279 
280     /// `IORING_OP_CONNECT`
281     Connect = sys::io_uring_op::IORING_OP_CONNECT as _,
282 
283     /// `IORING_OP_EPOLL_CTL`
284     EpollCtl = sys::io_uring_op::IORING_OP_EPOLL_CTL as _,
285 
286     /// `IORING_OP_FADVISE`
287     Fadvise = sys::io_uring_op::IORING_OP_FADVISE as _,
288 
289     /// `IORING_OP_FALLOCATE`
290     Fallocate = sys::io_uring_op::IORING_OP_FALLOCATE as _,
291 
292     /// `IORING_OP_FILES_UPDATE`
293     FilesUpdate = sys::io_uring_op::IORING_OP_FILES_UPDATE as _,
294 
295     /// `IORING_OP_FSYNC`
296     Fsync = sys::io_uring_op::IORING_OP_FSYNC as _,
297 
298     /// `IORING_OP_LINKAT`
299     Linkat = sys::io_uring_op::IORING_OP_LINKAT as _,
300 
301     /// `IORING_OP_LINK_TIMEOUT`
302     LinkTimeout = sys::io_uring_op::IORING_OP_LINK_TIMEOUT as _,
303 
304     /// `IORING_OP_MADVISE`
305     Madvise = sys::io_uring_op::IORING_OP_MADVISE as _,
306 
307     /// `IORING_OP_MKDIRAT`
308     Mkdirat = sys::io_uring_op::IORING_OP_MKDIRAT as _,
309 
310     /// `IORING_OP_OPENAT`
311     Openat = sys::io_uring_op::IORING_OP_OPENAT as _,
312 
313     /// `IORING_OP_OPENAT2`
314     Openat2 = sys::io_uring_op::IORING_OP_OPENAT2 as _,
315 
316     /// `IORING_OP_POLL_ADD`
317     PollAdd = sys::io_uring_op::IORING_OP_POLL_ADD as _,
318 
319     /// `IORING_OP_POLL_REMOVE`
320     PollRemove = sys::io_uring_op::IORING_OP_POLL_REMOVE as _,
321 
322     /// `IORING_OP_PROVIDE_BUFFERS`
323     ProvideBuffers = sys::io_uring_op::IORING_OP_PROVIDE_BUFFERS as _,
324 
325     /// `IORING_OP_READ`
326     Read = sys::io_uring_op::IORING_OP_READ as _,
327 
328     /// `IORING_OP_READV`
329     Readv = sys::io_uring_op::IORING_OP_READV as _,
330 
331     /// `IORING_OP_READ_FIXED`
332     ReadFixed = sys::io_uring_op::IORING_OP_READ_FIXED as _,
333 
334     /// `IORING_OP_RECV`
335     Recv = sys::io_uring_op::IORING_OP_RECV as _,
336 
337     /// `IORING_OP_RECVMSG`
338     Recvmsg = sys::io_uring_op::IORING_OP_RECVMSG as _,
339 
340     /// `IORING_OP_REMOVE_BUFFERS`
341     RemoveBuffers = sys::io_uring_op::IORING_OP_REMOVE_BUFFERS as _,
342 
343     /// `IORING_OP_RENAMEAT`
344     Renameat = sys::io_uring_op::IORING_OP_RENAMEAT as _,
345 
346     /// `IORING_OP_SEND`
347     Send = sys::io_uring_op::IORING_OP_SEND as _,
348 
349     /// `IORING_OP_SENDMSG`
350     Sendmsg = sys::io_uring_op::IORING_OP_SENDMSG as _,
351 
352     /// `IORING_OP_SHUTDOWN`
353     Shutdown = sys::io_uring_op::IORING_OP_SHUTDOWN as _,
354 
355     /// `IORING_OP_SPLICE`
356     Splice = sys::io_uring_op::IORING_OP_SPLICE as _,
357 
358     /// `IORING_OP_STATX`
359     Statx = sys::io_uring_op::IORING_OP_STATX as _,
360 
361     /// `IORING_OP_SYMLINKAT`
362     Symlinkat = sys::io_uring_op::IORING_OP_SYMLINKAT as _,
363 
364     /// `IORING_OP_SYNC_FILE_RANGE`
365     SyncFileRange = sys::io_uring_op::IORING_OP_SYNC_FILE_RANGE as _,
366 
367     /// `IORING_OP_TEE`
368     Tee = sys::io_uring_op::IORING_OP_TEE as _,
369 
370     /// `IORING_OP_TIMEOUT`
371     Timeout = sys::io_uring_op::IORING_OP_TIMEOUT as _,
372 
373     /// `IORING_OP_TIMEOUT_REMOVE`
374     TimeoutRemove = sys::io_uring_op::IORING_OP_TIMEOUT_REMOVE as _,
375 
376     /// `IORING_OP_UNLINKAT`
377     Unlinkat = sys::io_uring_op::IORING_OP_UNLINKAT as _,
378 
379     /// `IORING_OP_WRITE`
380     Write = sys::io_uring_op::IORING_OP_WRITE as _,
381 
382     /// `IORING_OP_WRITEV`
383     Writev = sys::io_uring_op::IORING_OP_WRITEV as _,
384 
385     /// `IORING_OP_WRITE_FIXED`
386     WriteFixed = sys::io_uring_op::IORING_OP_WRITE_FIXED as _,
387 
388     /// `IORING_OP_MSG_RING`
389     MsgRing = sys::io_uring_op::IORING_OP_MSG_RING as _,
390 
391     /// `IORING_OP_FSETXATTR`
392     Fsetxattr = sys::io_uring_op::IORING_OP_FSETXATTR as _,
393 
394     /// `IORING_OP_SETXATTR`
395     Setxattr = sys::io_uring_op::IORING_OP_SETXATTR as _,
396 
397     /// `IORING_OP_FGETXATTR`
398     Fgetxattr = sys::io_uring_op::IORING_OP_FGETXATTR as _,
399 
400     /// `IORING_OP_GETXATTR`
401     Getxattr = sys::io_uring_op::IORING_OP_GETXATTR as _,
402 
403     /// `IORING_OP_SOCKET`
404     Socket = sys::io_uring_op::IORING_OP_SOCKET as _,
405 
406     /// `IORING_OP_URING_CMD`
407     UringCmd = sys::io_uring_op::IORING_OP_URING_CMD as _,
408 
409     /// `IORING_OP_SEND_ZC`
410     SendZc = sys::io_uring_op::IORING_OP_SEND_ZC as _,
411 
412     /// `IORING_OP_SENDMSG_ZC`
413     SendmsgZc = sys::io_uring_op::IORING_OP_SENDMSG_ZC as _,
414 }
415 
416 impl Default for IoringOp {
417     #[inline]
default() -> Self418     fn default() -> Self {
419         Self::Nop
420     }
421 }
422 
423 /// `IORING_RESTRICTION_*` constants for use with [`io_uring_restriction`].
424 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
425 #[repr(u16)]
426 #[non_exhaustive]
427 pub enum IoringRestrictionOp {
428     /// `IORING_RESTRICTION_REGISTER_OP`
429     RegisterOp = sys::IORING_RESTRICTION_REGISTER_OP as _,
430 
431     /// `IORING_RESTRICTION_SQE_FLAGS_ALLOWED`
432     SqeFlagsAllowed = sys::IORING_RESTRICTION_SQE_FLAGS_ALLOWED as _,
433 
434     /// `IORING_RESTRICTION_SQE_FLAGS_REQUIRED`
435     SqeFlagsRequired = sys::IORING_RESTRICTION_SQE_FLAGS_REQUIRED as _,
436 
437     /// `IORING_RESTRICTION_SQE_OP`
438     SqeOp = sys::IORING_RESTRICTION_SQE_OP as _,
439 }
440 
441 impl Default for IoringRestrictionOp {
442     #[inline]
default() -> Self443     fn default() -> Self {
444         Self::RegisterOp
445     }
446 }
447 
448 /// `IORING_MSG_*` constants which represent commands for use with
449 /// [`IoringOp::MsgRing`], (`seq.addr`)
450 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
451 #[repr(u64)]
452 #[non_exhaustive]
453 pub enum IoringMsgringCmds {
454     /// `IORING_MSG_DATA`
455     Data = sys::IORING_MSG_DATA as _,
456 
457     /// `IORING_MSG_SEND_FD`
458     SendFd = sys::IORING_MSG_SEND_FD as _,
459 }
460 
461 bitflags::bitflags! {
462     /// `IORING_SETUP_*` flags for use with [`io_uring_params`].
463     #[repr(transparent)]
464     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
465     pub struct IoringSetupFlags: u32 {
466         /// `IORING_SETUP_ATTACH_WQ`
467         const ATTACH_WQ = sys::IORING_SETUP_ATTACH_WQ;
468 
469         /// `IORING_SETUP_CLAMP`
470         const CLAMP = sys::IORING_SETUP_CLAMP;
471 
472         /// `IORING_SETUP_CQSIZE`
473         const CQSIZE = sys::IORING_SETUP_CQSIZE;
474 
475         /// `IORING_SETUP_IOPOLL`
476         const IOPOLL = sys::IORING_SETUP_IOPOLL;
477 
478         /// `IORING_SETUP_R_DISABLED`
479         const R_DISABLED = sys::IORING_SETUP_R_DISABLED;
480 
481         /// `IORING_SETUP_SQPOLL`
482         const SQPOLL = sys::IORING_SETUP_SQPOLL;
483 
484         /// `IORING_SETUP_SQ_AFF`
485         const SQ_AFF = sys::IORING_SETUP_SQ_AFF;
486 
487         /// `IORING_SETUP_SQE128`
488         const SQE128 = sys::IORING_SETUP_SQE128;
489 
490         /// `IORING_SETUP_CQE32`
491         const CQE32 = sys::IORING_SETUP_CQE32;
492 
493         /// `IORING_SETUP_SUBMIT_ALL`
494         const SUBMIT_ALL = sys::IORING_SETUP_SUBMIT_ALL;
495 
496         /// `IORING_SETUP_COOP_TRASKRUN`
497         const COOP_TASKRUN = sys::IORING_SETUP_COOP_TASKRUN;
498 
499         /// `IORING_SETUP_TASKRUN_FLAG`
500         const TASKRUN_FLAG = sys::IORING_SETUP_TASKRUN_FLAG;
501 
502         /// `IORING_SETUP_SINGLE_ISSUER`
503         const SINGLE_ISSUER = sys::IORING_SETUP_SINGLE_ISSUER;
504 
505         /// `IORING_SETUP_DEFER_TASKRUN`
506         const DEFER_TASKRUN = sys::IORING_SETUP_DEFER_TASKRUN;
507 
508         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
509         const _ = !0;
510     }
511 }
512 
513 bitflags::bitflags! {
514     /// `IOSQE_*` flags for use with [`io_uring_sqe`].
515     #[repr(transparent)]
516     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
517     pub struct IoringSqeFlags: u8 {
518         /// `1 << IOSQE_ASYNC_BIT`
519         const ASYNC = 1 << sys::IOSQE_ASYNC_BIT as u8;
520 
521         /// `1 << IOSQE_BUFFER_SELECT_BIT`
522         const BUFFER_SELECT = 1 << sys::IOSQE_BUFFER_SELECT_BIT as u8;
523 
524         /// `1 << IOSQE_FIXED_FILE_BIT`
525         const FIXED_FILE = 1 << sys::IOSQE_FIXED_FILE_BIT as u8;
526 
527         /// 1 << `IOSQE_IO_DRAIN_BIT`
528         const IO_DRAIN = 1 << sys::IOSQE_IO_DRAIN_BIT as u8;
529 
530         /// `1 << IOSQE_IO_HARDLINK_BIT`
531         const IO_HARDLINK = 1 << sys::IOSQE_IO_HARDLINK_BIT as u8;
532 
533         /// `1 << IOSQE_IO_LINK_BIT`
534         const IO_LINK = 1 << sys::IOSQE_IO_LINK_BIT as u8;
535 
536         /// `1 << IOSQE_CQE_SKIP_SUCCESS_BIT`
537         const CQE_SKIP_SUCCESS = 1 << sys::IOSQE_CQE_SKIP_SUCCESS_BIT as u8;
538 
539         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
540         const _ = !0;
541     }
542 }
543 
544 bitflags::bitflags! {
545     /// `IORING_CQE_F_*` flags for use with [`io_uring_cqe`].
546     #[repr(transparent)]
547     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
548     pub struct IoringCqeFlags: u32 {
549         /// `IORING_CQE_F_BUFFER`
550         const BUFFER = bitcast!(sys::IORING_CQE_F_BUFFER);
551 
552         /// `IORING_CQE_F_MORE`
553         const MORE = bitcast!(sys::IORING_CQE_F_MORE);
554 
555         /// `IORING_CQE_F_SOCK_NONEMPTY`
556         const SOCK_NONEMPTY = bitcast!(sys::IORING_CQE_F_SOCK_NONEMPTY);
557 
558         /// `IORING_CQE_F_NOTIF`
559         const NOTIF = bitcast!(sys::IORING_CQE_F_NOTIF);
560 
561         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
562         const _ = !0;
563     }
564 }
565 
566 bitflags::bitflags! {
567     /// `IORING_FSYNC_*` flags for use with [`io_uring_sqe`].
568     #[repr(transparent)]
569     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
570     pub struct IoringFsyncFlags: u32 {
571         /// `IORING_FSYNC_DATASYNC`
572         const DATASYNC = sys::IORING_FSYNC_DATASYNC;
573 
574         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
575         const _ = !0;
576     }
577 }
578 
579 bitflags::bitflags! {
580     /// `IORING_TIMEOUT_*` and `IORING_LINK_TIMEOUT_UPDATE` flags for use with
581     /// [`io_uring_sqe`].
582     #[repr(transparent)]
583     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
584     pub struct IoringTimeoutFlags: u32 {
585         /// `IORING_TIMEOUT_ABS`
586         const ABS = sys::IORING_TIMEOUT_ABS;
587 
588         /// `IORING_TIMEOUT_UPDATE`
589         const UPDATE = sys::IORING_TIMEOUT_UPDATE;
590 
591         /// `IORING_TIMEOUT_BOOTTIME`
592         const BOOTTIME = sys::IORING_TIMEOUT_BOOTTIME;
593 
594         /// `IORING_TIMEOUT_ETIME_SUCCESS`
595         const ETIME_SUCCESS = sys::IORING_TIMEOUT_ETIME_SUCCESS;
596 
597         /// `IORING_TIMEOUT_REALTIME`
598         const REALTIME = sys::IORING_TIMEOUT_REALTIME;
599 
600         /// `IORING_TIMEOUT_CLOCK_MASK`
601         const CLOCK_MASK = sys::IORING_TIMEOUT_CLOCK_MASK;
602 
603         /// `IORING_TIMEOUT_UPDATE_MASK`
604         const UPDATE_MASK = sys::IORING_TIMEOUT_UPDATE_MASK;
605 
606         /// `IORING_LINK_TIMEOUT_UPDATE`
607         const LINK_TIMEOUT_UPDATE = sys::IORING_LINK_TIMEOUT_UPDATE;
608 
609         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
610         const _ = !0;
611     }
612 }
613 
614 bitflags::bitflags! {
615     /// `SPLICE_F_*` flags for use with [`io_uring_sqe`].
616     #[repr(transparent)]
617     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
618     pub struct SpliceFlags: u32 {
619         /// `SPLICE_F_FD_IN_FIXED`
620         const FD_IN_FIXED = sys::SPLICE_F_FD_IN_FIXED;
621 
622         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
623         const _ = !0;
624     }
625 }
626 
627 bitflags::bitflags! {
628     /// `IORING_MSG_RING_*` flags for use with [`io_uring_sqe`].
629     #[repr(transparent)]
630     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
631     pub struct IoringMsgringFlags: u32 {
632         /// `IORING_MSG_RING_CQE_SKIP`
633         const CQE_SKIP = sys::IORING_MSG_RING_CQE_SKIP;
634 
635         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
636         const _ = !0;
637     }
638 }
639 
640 bitflags::bitflags! {
641     /// `IORING_ASYNC_CANCEL_*` flags for use with [`io_uring_sqe`].
642     #[repr(transparent)]
643     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
644     pub struct IoringAsyncCancelFlags: u32 {
645         /// `IORING_ASYNC_CANCEL_ALL`
646         const ALL = sys::IORING_ASYNC_CANCEL_ALL;
647 
648         /// `IORING_ASYNC_CANCEL_FD`
649         const FD = sys::IORING_ASYNC_CANCEL_FD;
650 
651         /// `IORING_ASYNC_CANCEL_FD`
652         const ANY = sys::IORING_ASYNC_CANCEL_ANY;
653 
654         /// `IORING_ASYNC_CANCEL_FD`
655         const FD_FIXED = sys::IORING_ASYNC_CANCEL_FD_FIXED;
656 
657         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
658         const _ = !0;
659     }
660 }
661 
662 bitflags::bitflags! {
663     /// `IORING_FEAT_*` flags for use with [`io_uring_params`].
664     #[repr(transparent)]
665     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
666     pub struct IoringFeatureFlags: u32 {
667         /// `IORING_FEAT_CQE_SKIP`
668         const CQE_SKIP = sys::IORING_FEAT_CQE_SKIP;
669 
670         /// `IORING_FEAT_CUR_PERSONALITY`
671         const CUR_PERSONALITY = sys::IORING_FEAT_CUR_PERSONALITY;
672 
673         /// `IORING_FEAT_EXT_ARG`
674         const EXT_ARG = sys::IORING_FEAT_EXT_ARG;
675 
676         /// `IORING_FEAT_FAST_POLL`
677         const FAST_POLL = sys::IORING_FEAT_FAST_POLL;
678 
679         /// `IORING_FEAT_NATIVE_WORKERS`
680         const NATIVE_WORKERS = sys::IORING_FEAT_NATIVE_WORKERS;
681 
682         /// `IORING_FEAT_NODROP`
683         const NODROP = sys::IORING_FEAT_NODROP;
684 
685         /// `IORING_FEAT_POLL_32BITS`
686         const POLL_32BITS = sys::IORING_FEAT_POLL_32BITS;
687 
688         /// `IORING_FEAT_RSRC_TAGS`
689         const RSRC_TAGS = sys::IORING_FEAT_RSRC_TAGS;
690 
691         /// `IORING_FEAT_RW_CUR_POS`
692         const RW_CUR_POS = sys::IORING_FEAT_RW_CUR_POS;
693 
694         /// `IORING_FEAT_SINGLE_MMAP`
695         const SINGLE_MMAP = sys::IORING_FEAT_SINGLE_MMAP;
696 
697         /// `IORING_FEAT_SQPOLL_NONFIXED`
698         const SQPOLL_NONFIXED = sys::IORING_FEAT_SQPOLL_NONFIXED;
699 
700         /// `IORING_FEAT_SUBMIT_STABLE`
701         const SUBMIT_STABLE = sys::IORING_FEAT_SUBMIT_STABLE;
702 
703         /// `IORING_FEAT_LINKED_FILE`
704         const LINKED_FILE = sys::IORING_FEAT_LINKED_FILE;
705 
706         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
707         const _ = !0;
708     }
709 }
710 
711 bitflags::bitflags! {
712     /// `IO_URING_OP_*` flags for use with [`io_uring_probe_op`].
713     #[repr(transparent)]
714     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
715     pub struct IoringOpFlags: u16 {
716         /// `IO_URING_OP_SUPPORTED`
717         const SUPPORTED = sys::IO_URING_OP_SUPPORTED as _;
718 
719         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
720         const _ = !0;
721     }
722 }
723 
724 bitflags::bitflags! {
725     /// `IORING_RSRC_*` flags for use with [`io_uring_rsrc_register`].
726     #[repr(transparent)]
727     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
728     pub struct IoringRsrcFlags: u32 {
729         /// `IORING_RSRC_REGISTER_SPARSE`
730         const REGISTER_SPARSE = sys::IORING_RSRC_REGISTER_SPARSE as _;
731 
732         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
733         const _ = !0;
734     }
735 }
736 
737 bitflags::bitflags! {
738     /// `IORING_SQ_*` flags.
739     #[repr(transparent)]
740     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
741     pub struct IoringSqFlags: u32 {
742         /// `IORING_SQ_NEED_WAKEUP`
743         const NEED_WAKEUP = sys::IORING_SQ_NEED_WAKEUP;
744 
745         /// `IORING_SQ_CQ_OVERFLOW`
746         const CQ_OVERFLOW = sys::IORING_SQ_CQ_OVERFLOW;
747 
748         /// `IORING_SQ_TASKRUN`
749         const TASKRUN = sys::IORING_SQ_TASKRUN;
750 
751         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
752         const _ = !0;
753     }
754 }
755 
756 bitflags::bitflags! {
757     /// `IORING_CQ_*` flags.
758     #[repr(transparent)]
759     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
760     pub struct IoringCqFlags: u32 {
761         /// `IORING_CQ_EVENTFD_DISABLED`
762         const EVENTFD_DISABLED = sys::IORING_CQ_EVENTFD_DISABLED;
763 
764         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
765         const _ = !0;
766     }
767 }
768 
769 bitflags::bitflags! {
770     /// `IORING_POLL_*` flags.
771     #[repr(transparent)]
772     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
773     pub struct IoringPollFlags: u32 {
774         /// `IORING_POLL_ADD_MULTI`
775         const ADD_MULTI = sys::IORING_POLL_ADD_MULTI;
776 
777         /// `IORING_POLL_UPDATE_EVENTS`
778         const UPDATE_EVENTS = sys::IORING_POLL_UPDATE_EVENTS;
779 
780         /// `IORING_POLL_UPDATE_USER_DATA`
781         const UPDATE_USER_DATA = sys::IORING_POLL_UPDATE_USER_DATA;
782 
783         /// `IORING_POLL_ADD_LEVEL`
784         const ADD_LEVEL = sys::IORING_POLL_ADD_LEVEL;
785 
786         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
787         const _ = !0;
788     }
789 }
790 
791 bitflags::bitflags! {
792     /// send/sendmsg flags (`sqe.ioprio`)
793     #[repr(transparent)]
794     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
795     pub struct IoringSendFlags: u16 {
796         /// `IORING_RECVSEND_POLL_FIRST`.
797         ///
798         /// See also [`IoringRecvFlags::POLL_FIRST`].
799         const POLL_FIRST = sys::IORING_RECVSEND_POLL_FIRST as _;
800 
801         /// `IORING_RECVSEND_FIXED_BUF`
802         ///
803         /// See also [`IoringRecvFlags::FIXED_BUF`].
804         const FIXED_BUF = sys::IORING_RECVSEND_FIXED_BUF as _;
805 
806         /// `IORING_SEND_ZC_REPORT_USAGE` (since Linux 6.2)
807         const ZC_REPORT_USAGE = sys::IORING_SEND_ZC_REPORT_USAGE as _;
808 
809         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
810         const _ = !0;
811     }
812 }
813 
814 bitflags::bitflags! {
815     /// recv/recvmsg flags (`sqe.ioprio`)
816     #[repr(transparent)]
817     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
818     pub struct IoringRecvFlags: u16 {
819         /// `IORING_RECVSEND_POLL_FIRST`
820         ///
821         /// See also [`IoringSendFlags::POLL_FIRST`].
822         const POLL_FIRST = sys::IORING_RECVSEND_POLL_FIRST as _;
823 
824         /// `IORING_RECV_MULTISHOT`
825         const MULTISHOT = sys::IORING_RECV_MULTISHOT as _;
826 
827         /// `IORING_RECVSEND_FIXED_BUF`
828         ///
829         /// See also [`IoringSendFlags::FIXED_BUF`].
830         const FIXED_BUF = sys::IORING_RECVSEND_FIXED_BUF as _;
831 
832         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
833         const _ = !0;
834     }
835 }
836 
837 bitflags::bitflags! {
838     /// accept flags (`sqe.ioprio`)
839     #[repr(transparent)]
840     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
841     pub struct IoringAcceptFlags: u16 {
842         /// `IORING_ACCEPT_MULTISHOT`
843         const MULTISHOT = sys::IORING_ACCEPT_MULTISHOT as _;
844 
845         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
846         const _ = !0;
847     }
848 }
849 
850 bitflags::bitflags! {
851     /// recvmsg out flags
852     #[repr(transparent)]
853     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
854     pub struct RecvmsgOutFlags: u32 {
855         /// `MSG_EOR`
856         const EOR = net::MSG_EOR;
857 
858         /// `MSG_TRUNC`
859         const TRUNC = net::MSG_TRUNC;
860 
861         /// `MSG_CTRUNC`
862         const CTRUNC = net::MSG_CTRUNC;
863 
864         /// `MSG_OOB`
865         const OOB = net::MSG_OOB;
866 
867         /// `MSG_ERRQUEUE`
868         const ERRQUEUE = net::MSG_ERRQUEUE;
869 
870         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
871         const _ = !0;
872     }
873 }
874 
875 #[allow(missing_docs)]
876 pub const IORING_CQE_BUFFER_SHIFT: u32 = sys::IORING_CQE_BUFFER_SHIFT as _;
877 #[allow(missing_docs)]
878 pub const IORING_FILE_INDEX_ALLOC: i32 = sys::IORING_FILE_INDEX_ALLOC as _;
879 
880 // Re-export these as `u64`, which is the `offset` type in `rustix::io::mmap`.
881 #[allow(missing_docs)]
882 pub const IORING_OFF_SQ_RING: u64 = sys::IORING_OFF_SQ_RING as _;
883 #[allow(missing_docs)]
884 pub const IORING_OFF_CQ_RING: u64 = sys::IORING_OFF_CQ_RING as _;
885 #[allow(missing_docs)]
886 pub const IORING_OFF_SQES: u64 = sys::IORING_OFF_SQES as _;
887 
888 /// `IORING_REGISTER_FILES_SKIP`
889 #[inline]
890 #[doc(alias = "IORING_REGISTER_FILES_SKIP")]
io_uring_register_files_skip() -> BorrowedFd<'static>891 pub const fn io_uring_register_files_skip() -> BorrowedFd<'static> {
892     let files_skip = sys::IORING_REGISTER_FILES_SKIP as RawFd;
893 
894     // SAFETY: `IORING_REGISTER_FILES_SKIP` is a reserved value that is never
895     // dynamically allocated, so it'll remain valid for the duration of
896     // `'static`.
897     unsafe { BorrowedFd::<'static>::borrow_raw(files_skip) }
898 }
899 
900 /// `IORING_NOTIF_USAGE_ZC_COPIED` (since Linux 6.2)
901 pub const IORING_NOTIF_USAGE_ZC_COPIED: i32 = sys::IORING_NOTIF_USAGE_ZC_COPIED as _;
902 
903 /// A pointer in the io_uring API.
904 ///
905 /// `io_uring`'s native API represents pointers as `u64` values. In order to
906 /// preserve strict-provenance, use a `*mut c_void`. On platforms where
907 /// pointers are narrower than 64 bits, this requires additional padding.
908 #[repr(C)]
909 #[derive(Copy, Clone)]
910 pub struct io_uring_ptr {
911     #[cfg(all(target_pointer_width = "32", target_endian = "big"))]
912     #[doc(hidden)]
913     pub __pad32: u32,
914     #[cfg(all(target_pointer_width = "16", target_endian = "big"))]
915     #[doc(hidden)]
916     pub __pad16: u16,
917 
918     /// The pointer value.
919     pub ptr: *mut c_void,
920 
921     #[cfg(all(target_pointer_width = "16", target_endian = "little"))]
922     #[doc(hidden)]
923     pub __pad16: u16,
924     #[cfg(all(target_pointer_width = "32", target_endian = "little"))]
925     #[doc(hidden)]
926     pub __pad32: u32,
927 }
928 
929 impl From<*mut c_void> for io_uring_ptr {
930     #[inline]
from(ptr: *mut c_void) -> Self931     fn from(ptr: *mut c_void) -> Self {
932         Self {
933             ptr,
934 
935             #[cfg(target_pointer_width = "16")]
936             __pad16: Default::default(),
937             #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
938             __pad32: Default::default(),
939         }
940     }
941 }
942 
943 impl Default for io_uring_ptr {
944     #[inline]
default() -> Self945     fn default() -> Self {
946         Self::from(null_mut())
947     }
948 }
949 
950 /// User data in the io_uring API.
951 ///
952 /// `io_uring`'s native API represents `user_data` fields as `u64` values. In
953 /// order to preserve strict-provenance, use a union which allows users to
954 /// optionally store pointers.
955 #[repr(C)]
956 #[derive(Copy, Clone)]
957 pub union io_uring_user_data {
958     /// An arbitrary `u64`.
959     pub u64_: u64,
960 
961     /// A pointer.
962     pub ptr: io_uring_ptr,
963 }
964 
965 impl io_uring_user_data {
966     /// Return the `u64` value.
967     #[inline]
u64_(self) -> u64968     pub fn u64_(self) -> u64 {
969         // SAFETY: All the fields have the same underlying representation.
970         unsafe { self.u64_ }
971     }
972 
973     /// Create a `Self` from a `u64` value.
974     #[inline]
from_u64(u64_: u64) -> Self975     pub fn from_u64(u64_: u64) -> Self {
976         Self { u64_ }
977     }
978 
979     /// Return the `ptr` pointer value.
980     #[inline]
ptr(self) -> *mut c_void981     pub fn ptr(self) -> *mut c_void {
982         // SAFETY: All the fields have the same underlying representation.
983         unsafe { self.ptr }.ptr
984     }
985 
986     /// Create a `Self` from a pointer value.
987     #[inline]
from_ptr(ptr: *mut c_void) -> Self988     pub fn from_ptr(ptr: *mut c_void) -> Self {
989         Self {
990             ptr: io_uring_ptr::from(ptr),
991         }
992     }
993 }
994 
995 impl Default for io_uring_user_data {
996     #[inline]
default() -> Self997     fn default() -> Self {
998         let mut s = MaybeUninit::<Self>::uninit();
999         // SAFETY: All of Linux's io_uring structs may be zero-initialized.
1000         unsafe {
1001             write_bytes(s.as_mut_ptr(), 0, 1);
1002             s.assume_init()
1003         }
1004     }
1005 }
1006 
1007 impl core::fmt::Debug for io_uring_user_data {
fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result1008     fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1009         // SAFETY: Just format as a `u64`, since formatting doesn't preserve
1010         // provenance, and we don't have a discriminant.
1011         unsafe { self.u64_.fmt(fmt) }
1012     }
1013 }
1014 
1015 /// An io_uring Submission Queue Entry.
1016 #[allow(missing_docs)]
1017 #[repr(C)]
1018 #[derive(Copy, Clone, Default)]
1019 pub struct io_uring_sqe {
1020     pub opcode: IoringOp,
1021     pub flags: IoringSqeFlags,
1022     pub ioprio: ioprio_union,
1023     pub fd: RawFd,
1024     pub off_or_addr2: off_or_addr2_union,
1025     pub addr_or_splice_off_in: addr_or_splice_off_in_union,
1026     pub len: len_union,
1027     pub op_flags: op_flags_union,
1028     pub user_data: io_uring_user_data,
1029     pub buf: buf_union,
1030     pub personality: u16,
1031     pub splice_fd_in_or_file_index: splice_fd_in_or_file_index_union,
1032     pub addr3_or_cmd: addr3_or_cmd_union,
1033 }
1034 
1035 #[allow(missing_docs)]
1036 #[repr(C)]
1037 #[derive(Copy, Clone)]
1038 pub union ioprio_union {
1039     pub recv_flags: IoringRecvFlags,
1040     pub send_flags: IoringSendFlags,
1041     pub accept_flags: IoringAcceptFlags,
1042     pub ioprio: u16,
1043 }
1044 
1045 #[allow(missing_docs)]
1046 #[repr(C)]
1047 #[derive(Copy, Clone)]
1048 pub union len_union {
1049     pub poll_flags: IoringPollFlags,
1050     pub len: u32,
1051 }
1052 
1053 #[allow(missing_docs)]
1054 #[repr(C)]
1055 #[derive(Copy, Clone)]
1056 pub union addr3_or_cmd_union {
1057     pub addr3: addr3_struct,
1058     pub cmd: [u8; 0],
1059 }
1060 
1061 #[allow(missing_docs)]
1062 #[repr(C)]
1063 #[derive(Copy, Clone, Default)]
1064 pub struct addr3_struct {
1065     pub addr3: u64,
1066     pub __pad2: [u64; 1],
1067 }
1068 
1069 #[allow(missing_docs)]
1070 #[repr(C)]
1071 #[derive(Copy, Clone)]
1072 pub union off_or_addr2_union {
1073     pub off: u64,
1074     pub addr2: io_uring_ptr,
1075     pub cmd_op: cmd_op_struct,
1076     pub user_data: io_uring_user_data,
1077 }
1078 
1079 #[allow(missing_docs)]
1080 #[repr(C)]
1081 #[derive(Copy, Clone)]
1082 pub struct cmd_op_struct {
1083     pub cmd_op: u32,
1084     pub __pad1: u32,
1085 }
1086 
1087 #[allow(missing_docs)]
1088 #[repr(C)]
1089 #[derive(Copy, Clone)]
1090 pub union addr_or_splice_off_in_union {
1091     pub addr: io_uring_ptr,
1092     pub splice_off_in: u64,
1093     pub msgring_cmd: IoringMsgringCmds,
1094     pub user_data: io_uring_user_data,
1095 }
1096 
1097 #[allow(missing_docs)]
1098 #[repr(C)]
1099 #[derive(Copy, Clone)]
1100 pub union op_flags_union {
1101     pub rw_flags: crate::io::ReadWriteFlags,
1102     pub fsync_flags: IoringFsyncFlags,
1103     pub poll_events: u16,
1104     pub poll32_events: u32,
1105     pub sync_range_flags: u32,
1106     /// `msg_flags` is split into `send_flags` and `recv_flags`.
1107     #[doc(alias = "msg_flags")]
1108     pub send_flags: SendFlags,
1109     /// `msg_flags` is split into `send_flags` and `recv_flags`.
1110     #[doc(alias = "msg_flags")]
1111     pub recv_flags: RecvFlags,
1112     pub timeout_flags: IoringTimeoutFlags,
1113     pub accept_flags: SocketFlags,
1114     pub cancel_flags: IoringAsyncCancelFlags,
1115     pub open_flags: OFlags,
1116     pub statx_flags: AtFlags,
1117     pub fadvise_advice: Advice,
1118     pub splice_flags: SpliceFlags,
1119     pub rename_flags: RenameFlags,
1120     pub unlink_flags: AtFlags,
1121     pub hardlink_flags: AtFlags,
1122     pub msg_ring_flags: IoringMsgringFlags,
1123 }
1124 
1125 #[allow(missing_docs)]
1126 #[repr(C, packed)]
1127 #[derive(Copy, Clone)]
1128 pub union buf_union {
1129     pub buf_index: u16,
1130     pub buf_group: u16,
1131 }
1132 
1133 // TODO: Rename this to include `addr_len` when we have a semver bump?
1134 #[allow(missing_docs)]
1135 #[repr(C)]
1136 #[derive(Copy, Clone)]
1137 pub union splice_fd_in_or_file_index_union {
1138     pub splice_fd_in: i32,
1139     pub file_index: u32,
1140     pub addr_len: addr_len_struct,
1141 }
1142 
1143 #[allow(missing_docs)]
1144 #[repr(C)]
1145 #[derive(Copy, Clone)]
1146 pub struct addr_len_struct {
1147     pub addr_len: u16,
1148     pub __pad3: [u16; 1],
1149 }
1150 
1151 #[allow(missing_docs)]
1152 #[repr(C)]
1153 #[derive(Copy, Clone)]
1154 pub struct io_uring_sync_cancel_reg {
1155     pub addr: u64,
1156     pub fd: i32,
1157     pub flags: IoringAsyncCancelFlags,
1158     pub timeout: Timespec,
1159     pub pad: [u64; 4],
1160 }
1161 
1162 /// An io_uring Completion Queue Entry.
1163 ///
1164 /// This does not derive `Copy` or `Clone` because the `big_cqe` field is not
1165 /// automatically copyable.
1166 #[allow(missing_docs)]
1167 #[repr(C)]
1168 #[derive(Debug, Default)]
1169 pub struct io_uring_cqe {
1170     pub user_data: io_uring_user_data,
1171     pub res: i32,
1172     pub flags: IoringCqeFlags,
1173     pub big_cqe: sys::__IncompleteArrayField<u64>,
1174 }
1175 
1176 #[allow(missing_docs)]
1177 #[repr(C)]
1178 #[derive(Copy, Clone, Default)]
1179 pub struct io_uring_restriction {
1180     pub opcode: IoringRestrictionOp,
1181     pub register_or_sqe_op_or_sqe_flags: register_or_sqe_op_or_sqe_flags_union,
1182     pub resv: u8,
1183     pub resv2: [u32; 3],
1184 }
1185 
1186 #[allow(missing_docs)]
1187 #[repr(C)]
1188 #[derive(Copy, Clone)]
1189 pub union register_or_sqe_op_or_sqe_flags_union {
1190     pub register_op: IoringRegisterOp,
1191     pub sqe_op: IoringOp,
1192     pub sqe_flags: IoringSqeFlags,
1193 }
1194 
1195 #[allow(missing_docs)]
1196 #[repr(C)]
1197 #[derive(Debug, Copy, Clone, Default)]
1198 pub struct io_uring_params {
1199     pub sq_entries: u32,
1200     pub cq_entries: u32,
1201     pub flags: IoringSetupFlags,
1202     pub sq_thread_cpu: u32,
1203     pub sq_thread_idle: u32,
1204     pub features: IoringFeatureFlags,
1205     pub wq_fd: u32,
1206     pub resv: [u32; 3],
1207     pub sq_off: io_sqring_offsets,
1208     pub cq_off: io_cqring_offsets,
1209 }
1210 
1211 #[allow(missing_docs)]
1212 #[repr(C)]
1213 #[derive(Debug, Copy, Clone, Default)]
1214 pub struct io_sqring_offsets {
1215     pub head: u32,
1216     pub tail: u32,
1217     pub ring_mask: u32,
1218     pub ring_entries: u32,
1219     pub flags: u32,
1220     pub dropped: u32,
1221     pub array: u32,
1222     pub resv1: u32,
1223     pub resv2: u64,
1224 }
1225 
1226 #[allow(missing_docs)]
1227 #[repr(C)]
1228 #[derive(Debug, Copy, Clone, Default)]
1229 pub struct io_cqring_offsets {
1230     pub head: u32,
1231     pub tail: u32,
1232     pub ring_mask: u32,
1233     pub ring_entries: u32,
1234     pub overflow: u32,
1235     pub cqes: u32,
1236     pub flags: u32,
1237     pub resv1: u32,
1238     pub resv2: u64,
1239 }
1240 
1241 #[allow(missing_docs)]
1242 #[repr(C)]
1243 #[derive(Debug, Default)]
1244 pub struct io_uring_probe {
1245     pub last_op: IoringOp,
1246     pub ops_len: u8,
1247     pub resv: u16,
1248     pub resv2: [u32; 3],
1249     pub ops: sys::__IncompleteArrayField<io_uring_probe_op>,
1250 }
1251 
1252 #[allow(missing_docs)]
1253 #[repr(C)]
1254 #[derive(Debug, Copy, Clone, Default)]
1255 pub struct io_uring_probe_op {
1256     pub op: IoringOp,
1257     pub resv: u8,
1258     pub flags: IoringOpFlags,
1259     pub resv2: u32,
1260 }
1261 
1262 #[allow(missing_docs)]
1263 #[repr(C, align(8))]
1264 #[derive(Debug, Copy, Clone, Default)]
1265 pub struct io_uring_files_update {
1266     pub offset: u32,
1267     pub resv: u32,
1268     pub fds: u64,
1269 }
1270 
1271 #[allow(missing_docs)]
1272 #[repr(C, align(8))]
1273 #[derive(Debug, Copy, Clone, Default)]
1274 pub struct io_uring_rsrc_register {
1275     pub nr: u32,
1276     pub flags: IoringRsrcFlags,
1277     pub resv2: u64,
1278     pub data: u64,
1279     pub tags: u64,
1280 }
1281 
1282 #[allow(missing_docs)]
1283 #[repr(C, align(8))]
1284 #[derive(Debug, Copy, Clone, Default)]
1285 pub struct io_uring_rsrc_update {
1286     pub offset: u32,
1287     pub resv: u32,
1288     pub data: u64,
1289 }
1290 
1291 #[allow(missing_docs)]
1292 #[repr(C, align(8))]
1293 #[derive(Debug, Copy, Clone, Default)]
1294 pub struct io_uring_rsrc_update2 {
1295     pub offset: u32,
1296     pub resv: u32,
1297     pub data: u64,
1298     pub tags: u64,
1299     pub nr: u32,
1300     pub resv2: u32,
1301 }
1302 
1303 #[allow(missing_docs)]
1304 #[repr(C)]
1305 #[derive(Debug, Copy, Clone, Default)]
1306 pub struct io_uring_getevents_arg {
1307     pub sigmask: u64,
1308     pub sigmask_sz: u32,
1309     pub pad: u32,
1310     pub ts: u64,
1311 }
1312 
1313 #[allow(missing_docs)]
1314 #[repr(C)]
1315 #[derive(Debug, Default, Copy, Clone)]
1316 pub struct io_uring_recvmsg_out {
1317     pub namelen: u32,
1318     pub controllen: u32,
1319     pub payloadlen: u32,
1320     pub flags: RecvmsgOutFlags,
1321 }
1322 
1323 #[allow(missing_docs)]
1324 #[repr(C)]
1325 #[derive(Debug, Copy, Clone)]
1326 pub struct iovec {
1327     pub iov_base: *mut c_void,
1328     pub iov_len: usize,
1329 }
1330 
1331 #[allow(missing_docs)]
1332 #[repr(C)]
1333 #[derive(Debug, Copy, Clone, Default)]
1334 pub struct open_how {
1335     /// An [`OFlags`] value represented as a `u64`.
1336     pub flags: u64,
1337 
1338     /// A [`Mode`] value represented as a `u64`.
1339     pub mode: u64,
1340 
1341     pub resolve: ResolveFlags,
1342 }
1343 
1344 #[allow(missing_docs)]
1345 #[repr(C)]
1346 #[derive(Debug, Copy, Clone, Default)]
1347 pub struct io_uring_buf_reg {
1348     pub ring_addr: u64,
1349     pub ring_entries: u32,
1350     pub bgid: u16,
1351     pub pad: u16,
1352     pub resv: [u64; 3_usize],
1353 }
1354 
1355 #[allow(missing_docs)]
1356 #[repr(C)]
1357 #[derive(Debug, Copy, Clone, Default)]
1358 pub struct io_uring_buf {
1359     pub addr: u64,
1360     pub len: u32,
1361     pub bid: u16,
1362     pub resv: u16,
1363 }
1364 
1365 impl Default for ioprio_union {
1366     #[inline]
default() -> Self1367     fn default() -> Self {
1368         default_union!(ioprio_union, ioprio)
1369     }
1370 }
1371 
1372 impl Default for len_union {
1373     #[inline]
default() -> Self1374     fn default() -> Self {
1375         default_union!(len_union, len)
1376     }
1377 }
1378 
1379 impl Default for off_or_addr2_union {
1380     #[inline]
default() -> Self1381     fn default() -> Self {
1382         default_union!(off_or_addr2_union, off)
1383     }
1384 }
1385 
1386 impl Default for addr_or_splice_off_in_union {
1387     #[inline]
default() -> Self1388     fn default() -> Self {
1389         default_union!(addr_or_splice_off_in_union, splice_off_in)
1390     }
1391 }
1392 
1393 impl Default for addr3_or_cmd_union {
1394     #[inline]
default() -> Self1395     fn default() -> Self {
1396         default_union!(addr3_or_cmd_union, addr3)
1397     }
1398 }
1399 
1400 impl Default for op_flags_union {
1401     #[inline]
default() -> Self1402     fn default() -> Self {
1403         default_union!(op_flags_union, sync_range_flags)
1404     }
1405 }
1406 
1407 impl Default for buf_union {
1408     #[inline]
default() -> Self1409     fn default() -> Self {
1410         default_union!(buf_union, buf_index)
1411     }
1412 }
1413 
1414 impl Default for splice_fd_in_or_file_index_union {
1415     #[inline]
default() -> Self1416     fn default() -> Self {
1417         default_union!(splice_fd_in_or_file_index_union, splice_fd_in)
1418     }
1419 }
1420 
1421 impl Default for register_or_sqe_op_or_sqe_flags_union {
1422     #[inline]
default() -> Self1423     fn default() -> Self {
1424         default_union!(register_or_sqe_op_or_sqe_flags_union, sqe_flags)
1425     }
1426 }
1427 
1428 /// Check that our custom structs and unions have the same layout as the
1429 /// kernel's versions.
1430 #[test]
io_uring_layouts()1431 fn io_uring_layouts() {
1432     use sys as c;
1433 
1434     assert_eq_size!(io_uring_ptr, u64);
1435 
1436     check_renamed_type!(off_or_addr2_union, io_uring_sqe__bindgen_ty_1);
1437     check_renamed_type!(addr_or_splice_off_in_union, io_uring_sqe__bindgen_ty_2);
1438     check_renamed_type!(addr3_or_cmd_union, io_uring_sqe__bindgen_ty_6);
1439     check_renamed_type!(op_flags_union, io_uring_sqe__bindgen_ty_3);
1440     check_renamed_type!(buf_union, io_uring_sqe__bindgen_ty_4);
1441     check_renamed_type!(splice_fd_in_or_file_index_union, io_uring_sqe__bindgen_ty_5);
1442     check_renamed_type!(addr_len_struct, io_uring_sqe__bindgen_ty_5__bindgen_ty_1);
1443     check_renamed_type!(
1444         register_or_sqe_op_or_sqe_flags_union,
1445         io_uring_restriction__bindgen_ty_1
1446     );
1447 
1448     check_renamed_type!(addr3_struct, io_uring_sqe__bindgen_ty_6__bindgen_ty_1);
1449     check_renamed_type!(cmd_op_struct, io_uring_sqe__bindgen_ty_1__bindgen_ty_1);
1450 
1451     check_type!(io_uring_sqe);
1452     check_struct_field!(io_uring_sqe, opcode);
1453     check_struct_field!(io_uring_sqe, flags);
1454     check_struct_field!(io_uring_sqe, ioprio);
1455     check_struct_field!(io_uring_sqe, fd);
1456     check_struct_renamed_field!(io_uring_sqe, off_or_addr2, __bindgen_anon_1);
1457     check_struct_renamed_field!(io_uring_sqe, addr_or_splice_off_in, __bindgen_anon_2);
1458     check_struct_field!(io_uring_sqe, len);
1459     check_struct_renamed_field!(io_uring_sqe, op_flags, __bindgen_anon_3);
1460     check_struct_field!(io_uring_sqe, user_data);
1461     check_struct_renamed_field!(io_uring_sqe, buf, __bindgen_anon_4);
1462     check_struct_field!(io_uring_sqe, personality);
1463     check_struct_renamed_field!(io_uring_sqe, splice_fd_in_or_file_index, __bindgen_anon_5);
1464     check_struct_renamed_field!(io_uring_sqe, addr3_or_cmd, __bindgen_anon_6);
1465 
1466     check_type!(io_uring_restriction);
1467     check_struct_field!(io_uring_restriction, opcode);
1468     check_struct_renamed_field!(
1469         io_uring_restriction,
1470         register_or_sqe_op_or_sqe_flags,
1471         __bindgen_anon_1
1472     );
1473     check_struct_field!(io_uring_restriction, resv);
1474     check_struct_field!(io_uring_restriction, resv2);
1475 
1476     check_struct!(io_uring_cqe, user_data, res, flags, big_cqe);
1477     check_struct!(
1478         io_uring_params,
1479         sq_entries,
1480         cq_entries,
1481         flags,
1482         sq_thread_cpu,
1483         sq_thread_idle,
1484         features,
1485         wq_fd,
1486         resv,
1487         sq_off,
1488         cq_off
1489     );
1490     check_struct!(
1491         io_sqring_offsets,
1492         head,
1493         tail,
1494         ring_mask,
1495         ring_entries,
1496         flags,
1497         dropped,
1498         array,
1499         resv1,
1500         resv2
1501     );
1502     check_struct!(
1503         io_cqring_offsets,
1504         head,
1505         tail,
1506         ring_mask,
1507         ring_entries,
1508         overflow,
1509         cqes,
1510         flags,
1511         resv1,
1512         resv2
1513     );
1514     check_struct!(io_uring_recvmsg_out, namelen, controllen, payloadlen, flags);
1515     check_struct!(io_uring_probe, last_op, ops_len, resv, resv2, ops);
1516     check_struct!(io_uring_probe_op, op, resv, flags, resv2);
1517     check_struct!(io_uring_files_update, offset, resv, fds);
1518     check_struct!(io_uring_rsrc_register, nr, flags, resv2, data, tags);
1519     check_struct!(io_uring_rsrc_update, offset, resv, data);
1520     check_struct!(io_uring_rsrc_update2, offset, resv, data, tags, nr, resv2);
1521     check_struct!(io_uring_getevents_arg, sigmask, sigmask_sz, pad, ts);
1522     check_struct!(iovec, iov_base, iov_len);
1523     check_struct!(open_how, flags, mode, resolve);
1524     check_struct!(io_uring_buf_reg, ring_addr, ring_entries, bgid, pad, resv);
1525     check_struct!(io_uring_buf, addr, len, bid, resv);
1526     check_struct!(io_uring_sync_cancel_reg, addr, fd, flags, timeout, pad);
1527 }
1528