Skip to main content

rustix/io_uring/
mod.rs

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://www.man7.org/linux/man-pages/man7/io_uring.7.html
22//! [io_uring]: https://en.wikipedia.org/wiki/Io_uring
23//! [io_uring header]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/io_uring.h?h=v6.13
24//! [rustix-uring]: https://crates.io/crates/rustix-uring
25#![allow(unsafe_code)]
26
27mod bindgen_types;
28
29use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
30use crate::utils::option_as_ptr;
31use crate::{backend, io};
32use bindgen_types::*;
33use core::cmp::Ordering;
34use core::ffi::c_void;
35use core::hash::{Hash, Hasher};
36use core::mem::size_of;
37use core::ptr::null_mut;
38use linux_raw_sys::net;
39
40// Export types used in io_uring APIs.
41pub use crate::clockid::ClockId;
42pub use crate::event::epoll::{
43    Event as EpollEvent, EventData as EpollEventData, EventFlags as EpollEventFlags,
44};
45pub use crate::ffi::c_char;
46pub use crate::fs::{
47    Advice, AtFlags, Mode, OFlags, RenameFlags, ResolveFlags, Statx, StatxFlags, XattrFlags,
48};
49pub use crate::io::ReadWriteFlags;
50pub use crate::kernel_sigset::KernelSigSet;
51pub use crate::net::addr::{SocketAddrLen, SocketAddrOpaque, SocketAddrStorage};
52pub use crate::net::{RecvFlags, SendFlags, SocketFlags};
53pub use crate::signal::Signal;
54pub use crate::thread::futex::{
55    Wait as FutexWait, WaitFlags as FutexWaitFlags, WaitPtr as FutexWaitPtr,
56    WaitvFlags as FutexWaitvFlags,
57};
58pub use crate::timespec::{Nsecs, Secs, Timespec};
59
60mod sys {
61    pub(super) use linux_raw_sys::io_uring::*;
62    #[cfg(test)]
63    pub(super) use {
64        crate::backend::c::iovec, linux_raw_sys::general::open_how, linux_raw_sys::net::msghdr,
65    };
66}
67
68/// `msghdr`
69#[allow(missing_docs)]
70#[repr(C)]
71pub struct MsgHdr {
72    pub msg_name: *mut c_void,
73    pub msg_namelen: SocketAddrLen,
74    pub msg_iov: *mut iovec,
75    pub msg_iovlen: usize,
76    pub msg_control: *mut c_void,
77    pub msg_controllen: usize,
78    pub msg_flags: RecvFlags,
79}
80
81/// `io_uring_setup(entries, params)`—Setup a context for performing
82/// asynchronous I/O.
83///
84/// # Safety
85///
86/// If [`IoringSetupFlags::ATTACH_WQ`] is set, the `wq_fd` field of
87/// `io_uring_params` must be an open file descriptor.
88///
89/// # References
90///  - [Linux]
91///
92/// [Linux]: https://www.man7.org/linux/man-pages/man2/io_uring_setup.2.html
93#[inline]
94pub unsafe fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd> {
95    backend::io_uring::syscalls::io_uring_setup(entries, params)
96}
97
98/// `io_uring_register(fd, opcode, arg, nr_args)`—Register files or user
99/// buffers for asynchronous I/O.
100///
101/// To pass flags, use [`io_uring_register_with`].
102///
103/// # Safety
104///
105/// io_uring operates on raw pointers and raw file descriptors. Users are
106/// responsible for ensuring that memory and resources are only accessed in
107/// valid ways.
108///
109/// If `opcode` is `IoringRegisterOp::RegisterRingFds`, `arg` must point to
110/// mutable memory, despite being `*const`.
111///
112/// # References
113///  - [Linux]
114///
115/// [Linux]: https://www.man7.org/linux/man-pages/man2/io_uring_register.2.html
116#[inline]
117pub unsafe fn io_uring_register<Fd: AsFd>(
118    fd: Fd,
119    opcode: IoringRegisterOp,
120    arg: *const c_void,
121    nr_args: u32,
122) -> io::Result<u32> {
123    backend::io_uring::syscalls::io_uring_register(fd.as_fd(), opcode, arg, nr_args)
124}
125
126/// `io_uring_register_with(fd, opcode, flags, arg, nr_args)`—Register files or
127/// user buffers for asynchronous I/O.
128///
129/// # Safety
130///
131/// io_uring operates on raw pointers and raw file descriptors. Users are
132/// responsible for ensuring that memory and resources are only accessed in
133/// valid ways.
134///
135/// If `opcode` is `IoringRegisterOp::RegisterRingFds`, `arg` must point to
136/// mutable memory, despite being `*const`.
137///
138/// # References
139///  - [Linux]
140///
141/// [Linux]: https://www.man7.org/linux/man-pages/man2/io_uring_register.2.html
142#[inline]
143pub unsafe fn io_uring_register_with<Fd: AsFd>(
144    fd: Fd,
145    opcode: IoringRegisterOp,
146    flags: IoringRegisterFlags,
147    arg: *const c_void,
148    nr_args: u32,
149) -> io::Result<u32> {
150    backend::io_uring::syscalls::io_uring_register_with(fd.as_fd(), opcode, flags, arg, nr_args)
151}
152
153/// `io_uring_enter(fd, to_submit, min_complete, flags, 0, 0)`—Initiate
154/// and/or complete asynchronous I/O.
155///
156/// This version has no `arg` argument. To pass:
157///  - a signal mask, use [`io_uring_enter_sigmask`].
158///  - an [`io_uring_getevents_arg`], use [`io_uring_enter_arg`] (aka
159///    `io_uring_enter2`).
160///
161/// # Safety
162///
163/// io_uring operates on raw pointers and raw file descriptors. Users are
164/// responsible for ensuring that memory and resources are only accessed in
165/// valid ways.
166///
167/// And, `flags` must not have [`IoringEnterFlags::EXT_ARG`] or
168/// [`IoringEnterFlags::EXT_ARG_REG`] set.
169///
170/// # References
171///  - [Linux]
172///
173/// [Linux]: https://www.man7.org/linux/man-pages/man2/io_uring_enter.2.html
174#[doc(alias = "io_uring_enter2")]
175#[inline]
176pub unsafe fn io_uring_enter<Fd: AsFd>(
177    fd: Fd,
178    to_submit: u32,
179    min_complete: u32,
180    flags: IoringEnterFlags,
181) -> io::Result<u32> {
182    debug_assert!(!flags.contains(IoringEnterFlags::EXT_ARG));
183    debug_assert!(!flags.contains(IoringEnterFlags::EXT_ARG_REG));
184
185    backend::io_uring::syscalls::io_uring_enter(
186        fd.as_fd(),
187        to_submit,
188        min_complete,
189        flags,
190        null_mut(),
191        0,
192    )
193}
194
195/// `io_uring_enter(fd, to_submit, min_complete, flags, sigmask,
196/// sizeof(*sigmask))`— Initiate and/or complete asynchronous I/O, with a
197/// signal mask.
198///
199/// # Safety
200///
201/// io_uring operates on raw pointers and raw file descriptors. Users are
202/// responsible for ensuring that memory and resources are only accessed in
203/// valid ways.
204///
205/// And, `flags` must not have [`IoringEnterFlags::EXT_ARG`] or
206/// [`IoringEnterFlags::EXT_ARG_REG`] set.
207///
208/// And, the `KernelSigSet` referred to by `arg` must not contain any signal
209/// numbers reserved by libc.
210///
211/// # References
212///  - [Linux]
213///
214/// [Linux]: https://www.man7.org/linux/man-pages/man2/io_uring_enter.2.html
215#[doc(alias = "io_uring_enter")]
216#[inline]
217pub unsafe fn io_uring_enter_sigmask<Fd: AsFd>(
218    fd: Fd,
219    to_submit: u32,
220    min_complete: u32,
221    flags: IoringEnterFlags,
222    sigmask: Option<&KernelSigSet>,
223) -> io::Result<u32> {
224    debug_assert!(!flags.contains(IoringEnterFlags::EXT_ARG));
225    debug_assert!(!flags.contains(IoringEnterFlags::EXT_ARG_REG));
226
227    backend::io_uring::syscalls::io_uring_enter(
228        fd.as_fd(),
229        to_submit,
230        min_complete,
231        flags,
232        option_as_ptr(sigmask).cast::<c_void>(),
233        size_of::<KernelSigSet>(),
234    )
235}
236
237/// `io_uring_enter2(fd, to_submit, min_complete, flags, arg, sizeof(*arg))`—
238/// Initiate and/or complete asynchronous I/O, with a signal mask and a
239/// timeout.
240///
241/// # Safety
242///
243/// io_uring operates on raw pointers and raw file descriptors. Users are
244/// responsible for ensuring that memory and resources are only accessed in
245/// valid ways.
246///
247/// And, `flags` must have [`IoringEnterFlags::EXT_ARG`] set, and must not have
248/// [`IoringEnterFlags::EXT_ARG_REG`] set.
249///
250/// And, the `KernelSigSet` pointed to by the `io_uring_getenvets_arg` referred
251/// to by `arg` must not contain any signal numbers reserved by libc.
252///
253/// # References
254///  - [Linux]
255///
256/// [Linux]: https://www.man7.org/linux/man-pages/man2/io_uring_enter.2.html
257#[doc(alias = "io_uring_enter")]
258#[doc(alias = "io_uring_enter2")]
259#[inline]
260pub unsafe fn io_uring_enter_arg<Fd: AsFd>(
261    fd: Fd,
262    to_submit: u32,
263    min_complete: u32,
264    flags: IoringEnterFlags,
265    arg: Option<&io_uring_getevents_arg>,
266) -> io::Result<u32> {
267    debug_assert!(flags.contains(IoringEnterFlags::EXT_ARG));
268    debug_assert!(!flags.contains(IoringEnterFlags::EXT_ARG_REG));
269
270    backend::io_uring::syscalls::io_uring_enter(
271        fd.as_fd(),
272        to_submit,
273        min_complete,
274        flags,
275        option_as_ptr(arg).cast::<c_void>(),
276        size_of::<io_uring_getevents_arg>(),
277    )
278}
279
280// TODO: Uncomment this when we support `IoringRegisterOp::CQWAIT_REG`.
281/*
282/// `io_uring_enter2(fd, to_submit, min_complete, flags, offset,
283/// sizeof(io_uring_reg_wait))`— Initiate and/or complete asynchronous I/O,
284/// using a previously registered `io_uring_reg_wait`.
285///
286/// `offset` is an offset into an area of wait regions previously registered
287/// with [`io_uring_register`] using the [`IoringRegisterOp::CQWAIT_REG`]
288/// operation.
289///
290/// # Safety
291///
292/// io_uring operates on raw pointers and raw file descriptors. Users are
293/// responsible for ensuring that memory and resources are only accessed in
294/// valid ways.
295///
296/// And, `flags` must have [`IoringEnterFlags::EXT_ARG_REG`] set, and must not
297/// have [`IoringEnterFlags::EXT_ARG`] set.
298///
299/// # References
300///  - [Linux]
301///
302/// [Linux]: https://www.man7.org/linux/man-pages/man2/io_uring_enter.2.html
303#[doc(alias = "io_uring_enter")]
304#[doc(alias = "io_uring_enter2")]
305#[inline]
306pub unsafe fn io_uring_enter_reg_wait<Fd: AsFd>(
307    fd: Fd,
308    to_submit: u32,
309    min_complete: u32,
310    flags: IoringEnterFlags,
311    reg_wait: usize,
312) -> io::Result<u32> {
313    debug_assert!(!flags.contains(IoringEnterFlags::EXT_ARG));
314    debug_assert!(flags.contains(IoringEnterFlags::EXT_ARG_REG));
315
316    backend::io_uring::syscalls::io_uring_enter(
317        fd.as_fd(),
318        to_submit,
319        min_complete,
320        flags,
321        reg_wait as *mut c_void,
322        size_of::<io_uring_reg_wait>(),
323    )
324}
325*/
326
327bitflags::bitflags! {
328    /// `IORING_ENTER_*` flags for use with [`io_uring_enter`].
329    #[repr(transparent)]
330    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
331    pub struct IoringEnterFlags: u32 {
332        /// `IORING_ENTER_GETEVENTS`
333        const GETEVENTS = sys::IORING_ENTER_GETEVENTS;
334
335        /// `IORING_ENTER_SQ_WAKEUP`
336        const SQ_WAKEUP = sys::IORING_ENTER_SQ_WAKEUP;
337
338        /// `IORING_ENTER_SQ_WAIT`
339        const SQ_WAIT = sys::IORING_ENTER_SQ_WAIT;
340
341        /// `IORING_ENTER_EXT_ARG` (since Linux 5.11)
342        const EXT_ARG = sys::IORING_ENTER_EXT_ARG;
343
344        /// `IORING_ENTER_REGISTERED_RING`
345        const REGISTERED_RING = sys::IORING_ENTER_REGISTERED_RING;
346
347        /// `IORING_ENTER_ABS_TIMER` (since Linux 6.12)
348        const ABS_TIMER = sys::IORING_ENTER_ABS_TIMER;
349
350        /// `IORING_ENTER_EXT_ARG_REG` (since Linux 6.12)
351        const EXT_ARG_REG = sys::IORING_ENTER_EXT_ARG_REG;
352
353        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
354        const _ = !0;
355    }
356}
357
358/// `IORING_REGISTER_*` and `IORING_UNREGISTER_*` constants for use with
359/// [`io_uring_register`].
360#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
361#[repr(u8)]
362#[non_exhaustive]
363pub enum IoringRegisterOp {
364    /// `IORING_REGISTER_BUFFERS`
365    RegisterBuffers = sys::io_uring_register_op::IORING_REGISTER_BUFFERS as _,
366
367    /// `IORING_UNREGISTER_BUFFERS`
368    UnregisterBuffers = sys::io_uring_register_op::IORING_UNREGISTER_BUFFERS as _,
369
370    /// `IORING_REGISTER_FILES`
371    RegisterFiles = sys::io_uring_register_op::IORING_REGISTER_FILES as _,
372
373    /// `IORING_UNREGISTER_FILES`
374    UnregisterFiles = sys::io_uring_register_op::IORING_UNREGISTER_FILES as _,
375
376    /// `IORING_REGISTER_EVENTFD`
377    RegisterEventfd = sys::io_uring_register_op::IORING_REGISTER_EVENTFD as _,
378
379    /// `IORING_UNREGISTER_EVENTFD`
380    UnregisterEventfd = sys::io_uring_register_op::IORING_UNREGISTER_EVENTFD as _,
381
382    /// `IORING_REGISTER_FILES_UPDATE`
383    RegisterFilesUpdate = sys::io_uring_register_op::IORING_REGISTER_FILES_UPDATE as _,
384
385    /// `IORING_REGISTER_EVENTFD_ASYNC`
386    RegisterEventfdAsync = sys::io_uring_register_op::IORING_REGISTER_EVENTFD_ASYNC as _,
387
388    /// `IORING_REGISTER_PROBE`
389    RegisterProbe = sys::io_uring_register_op::IORING_REGISTER_PROBE as _,
390
391    /// `IORING_REGISTER_PERSONALITY`
392    RegisterPersonality = sys::io_uring_register_op::IORING_REGISTER_PERSONALITY as _,
393
394    /// `IORING_UNREGISTER_PERSONALITY`
395    UnregisterPersonality = sys::io_uring_register_op::IORING_UNREGISTER_PERSONALITY as _,
396
397    /// `IORING_REGISTER_RESTRICTIONS`
398    RegisterRestrictions = sys::io_uring_register_op::IORING_REGISTER_RESTRICTIONS as _,
399
400    /// `IORING_REGISTER_ENABLE_RINGS`
401    RegisterEnableRings = sys::io_uring_register_op::IORING_REGISTER_ENABLE_RINGS as _,
402
403    /// `IORING_REGISTER_BUFFERS2`
404    RegisterBuffers2 = sys::io_uring_register_op::IORING_REGISTER_BUFFERS2 as _,
405
406    /// `IORING_REGISTER_BUFFERS_UPDATE`
407    RegisterBuffersUpdate = sys::io_uring_register_op::IORING_REGISTER_BUFFERS_UPDATE as _,
408
409    /// `IORING_REGISTER_FILES2`
410    RegisterFiles2 = sys::io_uring_register_op::IORING_REGISTER_FILES2 as _,
411
412    /// `IORING_REGISTER_FILES_UPDATE2`
413    RegisterFilesUpdate2 = sys::io_uring_register_op::IORING_REGISTER_FILES_UPDATE2 as _,
414
415    /// `IORING_REGISTER_IOWQ_AFF`
416    RegisterIowqAff = sys::io_uring_register_op::IORING_REGISTER_IOWQ_AFF as _,
417
418    /// `IORING_UNREGISTER_IOWQ_AFF`
419    UnregisterIowqAff = sys::io_uring_register_op::IORING_UNREGISTER_IOWQ_AFF as _,
420
421    /// `IORING_REGISTER_IOWQ_MAX_WORKERS`
422    RegisterIowqMaxWorkers = sys::io_uring_register_op::IORING_REGISTER_IOWQ_MAX_WORKERS as _,
423
424    /// `IORING_REGISTER_RING_FDS`
425    RegisterRingFds = sys::io_uring_register_op::IORING_REGISTER_RING_FDS as _,
426
427    /// `IORING_UNREGISTER_RING_FDS`
428    UnregisterRingFds = sys::io_uring_register_op::IORING_UNREGISTER_RING_FDS as _,
429
430    /// `IORING_REGISTER_PBUF_RING`
431    RegisterPbufRing = sys::io_uring_register_op::IORING_REGISTER_PBUF_RING as _,
432
433    /// `IORING_UNREGISTER_PBUF_RING`
434    UnregisterPbufRing = sys::io_uring_register_op::IORING_UNREGISTER_PBUF_RING as _,
435
436    /// `IORING_REGISTER_SYNC_CANCEL`
437    RegisterSyncCancel = sys::io_uring_register_op::IORING_REGISTER_SYNC_CANCEL as _,
438
439    /// `IORING_REGISTER_FILE_ALLOC_RANGE`
440    RegisterFileAllocRange = sys::io_uring_register_op::IORING_REGISTER_FILE_ALLOC_RANGE as _,
441
442    /// `IORING_REGISTER_PBUF_STATUS` (since Linux 6.8)
443    RegisterPbufStatus = sys::io_uring_register_op::IORING_REGISTER_PBUF_STATUS as _,
444
445    /// `IORING_REGISTER_NAPI` (since Linux 6.9)
446    RegisterNapi = sys::io_uring_register_op::IORING_REGISTER_NAPI as _,
447
448    /// `IORING_UNREGISTER_NAPI` (since Linux 6.9)
449    UnregisterNapi = sys::io_uring_register_op::IORING_UNREGISTER_NAPI as _,
450
451    /// `IORING_REGISTER_CLOCK` (since Linux 6.12)
452    RegisterClock = sys::io_uring_register_op::IORING_REGISTER_CLOCK as _,
453
454    /// `IORING_REGISTER_CLONE_BUFFERS ` (since Linux 6.12)
455    RegisterCloneBuffers = sys::io_uring_register_op::IORING_REGISTER_CLONE_BUFFERS as _,
456
457    /// `IORING_REGISTER_SEND_MSG_RING` (since Linux 6.12)
458    RegisterSendMsgRing = sys::io_uring_register_op::IORING_REGISTER_SEND_MSG_RING as _,
459
460    /// `IORING_REGISTER_RESIZE_RINGS`(since Linux 6.13)
461    RegisterResizeRings = sys::io_uring_register_op::IORING_REGISTER_RESIZE_RINGS as _,
462}
463
464bitflags::bitflags! {
465    /// `IORING_REGISTER_*` flags for use with [`io_uring_register_with`].
466    #[repr(transparent)]
467    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
468    pub struct IoringRegisterFlags: u32 {
469        /// `IORING_REGISTER_USE_REGISTERED_RING`
470        const USE_REGISTERED_RING = sys::io_uring_register_op::IORING_REGISTER_USE_REGISTERED_RING as u32;
471
472        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
473        const _ = !0;
474    }
475}
476
477/// `IORING_OP_*` constants for use with [`io_uring_sqe`].
478#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
479#[repr(u8)]
480#[non_exhaustive]
481pub enum IoringOp {
482    /// `IORING_OP_NOP`
483    Nop = sys::io_uring_op::IORING_OP_NOP as _,
484
485    /// `IORING_OP_ACCEPT`
486    Accept = sys::io_uring_op::IORING_OP_ACCEPT as _,
487
488    /// `IORING_OP_ASYNC_CANCEL`
489    AsyncCancel = sys::io_uring_op::IORING_OP_ASYNC_CANCEL as _,
490
491    /// `IORING_OP_CLOSE`
492    Close = sys::io_uring_op::IORING_OP_CLOSE as _,
493
494    /// `IORING_OP_CONNECT`
495    Connect = sys::io_uring_op::IORING_OP_CONNECT as _,
496
497    /// `IORING_OP_EPOLL_CTL`
498    EpollCtl = sys::io_uring_op::IORING_OP_EPOLL_CTL as _,
499
500    /// `IORING_OP_FADVISE`
501    Fadvise = sys::io_uring_op::IORING_OP_FADVISE as _,
502
503    /// `IORING_OP_FALLOCATE`
504    Fallocate = sys::io_uring_op::IORING_OP_FALLOCATE as _,
505
506    /// `IORING_OP_FILES_UPDATE`
507    FilesUpdate = sys::io_uring_op::IORING_OP_FILES_UPDATE as _,
508
509    /// `IORING_OP_FSYNC`
510    Fsync = sys::io_uring_op::IORING_OP_FSYNC as _,
511
512    /// `IORING_OP_LINKAT`
513    Linkat = sys::io_uring_op::IORING_OP_LINKAT as _,
514
515    /// `IORING_OP_LINK_TIMEOUT`
516    LinkTimeout = sys::io_uring_op::IORING_OP_LINK_TIMEOUT as _,
517
518    /// `IORING_OP_MADVISE`
519    Madvise = sys::io_uring_op::IORING_OP_MADVISE as _,
520
521    /// `IORING_OP_MKDIRAT`
522    Mkdirat = sys::io_uring_op::IORING_OP_MKDIRAT as _,
523
524    /// `IORING_OP_OPENAT`
525    Openat = sys::io_uring_op::IORING_OP_OPENAT as _,
526
527    /// `IORING_OP_OPENAT2`
528    Openat2 = sys::io_uring_op::IORING_OP_OPENAT2 as _,
529
530    /// `IORING_OP_POLL_ADD`
531    PollAdd = sys::io_uring_op::IORING_OP_POLL_ADD as _,
532
533    /// `IORING_OP_POLL_REMOVE`
534    PollRemove = sys::io_uring_op::IORING_OP_POLL_REMOVE as _,
535
536    /// `IORING_OP_PROVIDE_BUFFERS`
537    ProvideBuffers = sys::io_uring_op::IORING_OP_PROVIDE_BUFFERS as _,
538
539    /// `IORING_OP_READ`
540    Read = sys::io_uring_op::IORING_OP_READ as _,
541
542    /// `IORING_OP_READV`
543    Readv = sys::io_uring_op::IORING_OP_READV as _,
544
545    /// `IORING_OP_READ_FIXED`
546    ReadFixed = sys::io_uring_op::IORING_OP_READ_FIXED as _,
547
548    /// `IORING_OP_RECV`
549    Recv = sys::io_uring_op::IORING_OP_RECV as _,
550
551    /// `IORING_OP_RECVMSG`
552    Recvmsg = sys::io_uring_op::IORING_OP_RECVMSG as _,
553
554    /// `IORING_OP_REMOVE_BUFFERS`
555    RemoveBuffers = sys::io_uring_op::IORING_OP_REMOVE_BUFFERS as _,
556
557    /// `IORING_OP_RENAMEAT`
558    Renameat = sys::io_uring_op::IORING_OP_RENAMEAT as _,
559
560    /// `IORING_OP_SEND`
561    Send = sys::io_uring_op::IORING_OP_SEND as _,
562
563    /// `IORING_OP_SENDMSG`
564    Sendmsg = sys::io_uring_op::IORING_OP_SENDMSG as _,
565
566    /// `IORING_OP_SHUTDOWN`
567    Shutdown = sys::io_uring_op::IORING_OP_SHUTDOWN as _,
568
569    /// `IORING_OP_SPLICE`
570    Splice = sys::io_uring_op::IORING_OP_SPLICE as _,
571
572    /// `IORING_OP_STATX`
573    Statx = sys::io_uring_op::IORING_OP_STATX as _,
574
575    /// `IORING_OP_SYMLINKAT`
576    Symlinkat = sys::io_uring_op::IORING_OP_SYMLINKAT as _,
577
578    /// `IORING_OP_SYNC_FILE_RANGE`
579    SyncFileRange = sys::io_uring_op::IORING_OP_SYNC_FILE_RANGE as _,
580
581    /// `IORING_OP_TEE`
582    Tee = sys::io_uring_op::IORING_OP_TEE as _,
583
584    /// `IORING_OP_TIMEOUT`
585    Timeout = sys::io_uring_op::IORING_OP_TIMEOUT as _,
586
587    /// `IORING_OP_TIMEOUT_REMOVE`
588    TimeoutRemove = sys::io_uring_op::IORING_OP_TIMEOUT_REMOVE as _,
589
590    /// `IORING_OP_UNLINKAT`
591    Unlinkat = sys::io_uring_op::IORING_OP_UNLINKAT as _,
592
593    /// `IORING_OP_WRITE`
594    Write = sys::io_uring_op::IORING_OP_WRITE as _,
595
596    /// `IORING_OP_WRITEV`
597    Writev = sys::io_uring_op::IORING_OP_WRITEV as _,
598
599    /// `IORING_OP_WRITE_FIXED`
600    WriteFixed = sys::io_uring_op::IORING_OP_WRITE_FIXED as _,
601
602    /// `IORING_OP_MSG_RING`
603    MsgRing = sys::io_uring_op::IORING_OP_MSG_RING as _,
604
605    /// `IORING_OP_FSETXATTR`
606    Fsetxattr = sys::io_uring_op::IORING_OP_FSETXATTR as _,
607
608    /// `IORING_OP_SETXATTR`
609    Setxattr = sys::io_uring_op::IORING_OP_SETXATTR as _,
610
611    /// `IORING_OP_FGETXATTR`
612    Fgetxattr = sys::io_uring_op::IORING_OP_FGETXATTR as _,
613
614    /// `IORING_OP_GETXATTR`
615    Getxattr = sys::io_uring_op::IORING_OP_GETXATTR as _,
616
617    /// `IORING_OP_SOCKET`
618    Socket = sys::io_uring_op::IORING_OP_SOCKET as _,
619
620    /// `IORING_OP_URING_CMD`
621    UringCmd = sys::io_uring_op::IORING_OP_URING_CMD as _,
622
623    /// `IORING_OP_SEND_ZC`
624    SendZc = sys::io_uring_op::IORING_OP_SEND_ZC as _,
625
626    /// `IORING_OP_SENDMSG_ZC`
627    SendmsgZc = sys::io_uring_op::IORING_OP_SENDMSG_ZC as _,
628
629    /// `IORING_OP_READ_MULTISHOT` (since Linux 6.7)
630    ReadMultishot = sys::io_uring_op::IORING_OP_READ_MULTISHOT as _,
631
632    /// `IORING_OP_WAITID` (since Linux 6.5)
633    Waitid = sys::io_uring_op::IORING_OP_WAITID as _,
634
635    /// `IORING_OP_FUTEX_WAIT` (since Linux 6.7)
636    FutexWait = sys::io_uring_op::IORING_OP_FUTEX_WAIT as _,
637
638    /// `IORING_OP_FUTEX_WAKE` (since Linux 6.7)
639    FutexWake = sys::io_uring_op::IORING_OP_FUTEX_WAKE as _,
640
641    /// `IORING_OP_FUTEX_WAITV` (since Linux 6.7)
642    FutexWaitv = sys::io_uring_op::IORING_OP_FUTEX_WAITV as _,
643
644    /// `IORING_OP_FIXED_FD_INSTALL` (since Linux 6.8)
645    FixedFdInstall = sys::io_uring_op::IORING_OP_FIXED_FD_INSTALL as _,
646
647    /// `IORING_OP_FTRUNCATE` (since Linux 6.9)
648    Ftruncate = sys::io_uring_op::IORING_OP_FTRUNCATE as _,
649
650    /// `IORING_OP_BIND` (since Linux 6.11)
651    Bind = sys::io_uring_op::IORING_OP_BIND as _,
652
653    /// `IORING_OP_LISTEN` (since Linux 6.11)
654    Listen = sys::io_uring_op::IORING_OP_LISTEN as _,
655}
656
657impl Default for IoringOp {
658    #[inline]
659    fn default() -> Self {
660        Self::Nop
661    }
662}
663
664/// `IORING_RESTRICTION_*` constants for use with [`io_uring_restriction`].
665#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
666#[repr(u16)]
667#[non_exhaustive]
668pub enum IoringRestrictionOp {
669    /// `IORING_RESTRICTION_REGISTER_OP`
670    RegisterOp = sys::io_uring_register_restriction_op::IORING_RESTRICTION_REGISTER_OP as _,
671
672    /// `IORING_RESTRICTION_SQE_FLAGS_ALLOWED`
673    SqeFlagsAllowed =
674        sys::io_uring_register_restriction_op::IORING_RESTRICTION_SQE_FLAGS_ALLOWED as _,
675
676    /// `IORING_RESTRICTION_SQE_FLAGS_REQUIRED`
677    SqeFlagsRequired =
678        sys::io_uring_register_restriction_op::IORING_RESTRICTION_SQE_FLAGS_REQUIRED as _,
679
680    /// `IORING_RESTRICTION_SQE_OP`
681    SqeOp = sys::io_uring_register_restriction_op::IORING_RESTRICTION_SQE_OP as _,
682}
683
684impl Default for IoringRestrictionOp {
685    #[inline]
686    fn default() -> Self {
687        Self::RegisterOp
688    }
689}
690
691/// `IORING_MSG_*` constants which represent commands for use with
692/// [`IoringOp::MsgRing`], (`seq.addr`)
693#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
694#[repr(u64)]
695#[non_exhaustive]
696pub enum IoringMsgringCmds {
697    /// `IORING_MSG_DATA`
698    Data = sys::io_uring_msg_ring_flags::IORING_MSG_DATA as _,
699
700    /// `IORING_MSG_SEND_FD`
701    SendFd = sys::io_uring_msg_ring_flags::IORING_MSG_SEND_FD as _,
702}
703
704bitflags::bitflags! {
705    /// `IORING_SETUP_*` flags for use with [`io_uring_params`].
706    #[repr(transparent)]
707    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
708    pub struct IoringSetupFlags: u32 {
709        /// `IORING_SETUP_ATTACH_WQ`
710        const ATTACH_WQ = sys::IORING_SETUP_ATTACH_WQ;
711
712        /// `IORING_SETUP_CLAMP`
713        const CLAMP = sys::IORING_SETUP_CLAMP;
714
715        /// `IORING_SETUP_CQSIZE`
716        const CQSIZE = sys::IORING_SETUP_CQSIZE;
717
718        /// `IORING_SETUP_IOPOLL`
719        const IOPOLL = sys::IORING_SETUP_IOPOLL;
720
721        /// `IORING_SETUP_R_DISABLED`
722        const R_DISABLED = sys::IORING_SETUP_R_DISABLED;
723
724        /// `IORING_SETUP_SQPOLL`
725        const SQPOLL = sys::IORING_SETUP_SQPOLL;
726
727        /// `IORING_SETUP_SQ_AFF`
728        const SQ_AFF = sys::IORING_SETUP_SQ_AFF;
729
730        /// `IORING_SETUP_SQE128`
731        const SQE128 = sys::IORING_SETUP_SQE128;
732
733        /// `IORING_SETUP_CQE32`
734        const CQE32 = sys::IORING_SETUP_CQE32;
735
736        /// `IORING_SETUP_SUBMIT_ALL`
737        const SUBMIT_ALL = sys::IORING_SETUP_SUBMIT_ALL;
738
739        /// `IORING_SETUP_COOP_TRASKRUN`
740        const COOP_TASKRUN = sys::IORING_SETUP_COOP_TASKRUN;
741
742        /// `IORING_SETUP_TASKRUN_FLAG`
743        const TASKRUN_FLAG = sys::IORING_SETUP_TASKRUN_FLAG;
744
745        /// `IORING_SETUP_SINGLE_ISSUER`
746        const SINGLE_ISSUER = sys::IORING_SETUP_SINGLE_ISSUER;
747
748        /// `IORING_SETUP_DEFER_TASKRUN`
749        const DEFER_TASKRUN = sys::IORING_SETUP_DEFER_TASKRUN;
750
751        /// `IORING_SETUP_NO_MMAP`
752        const NO_MMAP = sys::IORING_SETUP_NO_MMAP;
753
754        /// `IORING_SETUP_REGISTERED_FD_ONLY`
755        const REGISTERED_FD_ONLY = sys::IORING_SETUP_REGISTERED_FD_ONLY;
756
757        /// `IORING_SETUP_NO_SQARRAY`
758        const NO_SQARRAY = sys::IORING_SETUP_NO_SQARRAY;
759
760        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
761        const _ = !0;
762    }
763}
764
765bitflags::bitflags! {
766    /// `IOSQE_*` flags for use with [`io_uring_sqe`].
767    #[repr(transparent)]
768    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
769    pub struct IoringSqeFlags: u8 {
770        /// `1 << IOSQE_ASYNC_BIT`
771        const ASYNC = 1 << sys::io_uring_sqe_flags_bit::IOSQE_ASYNC_BIT as u8;
772
773        /// `1 << IOSQE_BUFFER_SELECT_BIT`
774        const BUFFER_SELECT = 1 << sys::io_uring_sqe_flags_bit::IOSQE_BUFFER_SELECT_BIT as u8;
775
776        /// `1 << IOSQE_FIXED_FILE_BIT`
777        const FIXED_FILE = 1 << sys::io_uring_sqe_flags_bit::IOSQE_FIXED_FILE_BIT as u8;
778
779        /// 1 << `IOSQE_IO_DRAIN_BIT`
780        const IO_DRAIN = 1 << sys::io_uring_sqe_flags_bit::IOSQE_IO_DRAIN_BIT as u8;
781
782        /// `1 << IOSQE_IO_HARDLINK_BIT`
783        const IO_HARDLINK = 1 << sys::io_uring_sqe_flags_bit::IOSQE_IO_HARDLINK_BIT as u8;
784
785        /// `1 << IOSQE_IO_LINK_BIT`
786        const IO_LINK = 1 << sys::io_uring_sqe_flags_bit::IOSQE_IO_LINK_BIT as u8;
787
788        /// `1 << IOSQE_CQE_SKIP_SUCCESS_BIT`
789        const CQE_SKIP_SUCCESS = 1 << sys::io_uring_sqe_flags_bit::IOSQE_CQE_SKIP_SUCCESS_BIT as u8;
790
791        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
792        const _ = !0;
793    }
794}
795
796bitflags::bitflags! {
797    /// `IORING_CQE_F_*` flags for use with [`io_uring_cqe`].
798    #[repr(transparent)]
799    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
800    pub struct IoringCqeFlags: u32 {
801        /// `IORING_CQE_F_BUFFER`
802        const BUFFER = bitcast!(sys::IORING_CQE_F_BUFFER);
803
804        /// `IORING_CQE_F_MORE`
805        const MORE = bitcast!(sys::IORING_CQE_F_MORE);
806
807        /// `IORING_CQE_F_SOCK_NONEMPTY`
808        const SOCK_NONEMPTY = bitcast!(sys::IORING_CQE_F_SOCK_NONEMPTY);
809
810        /// `IORING_CQE_F_NOTIF`
811        const NOTIF = bitcast!(sys::IORING_CQE_F_NOTIF);
812
813        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
814        const _ = !0;
815    }
816}
817
818bitflags::bitflags! {
819    /// `IORING_FSYNC_*` flags for use with [`io_uring_sqe`].
820    #[repr(transparent)]
821    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
822    pub struct IoringFsyncFlags: u32 {
823        /// `IORING_FSYNC_DATASYNC`
824        const DATASYNC = sys::IORING_FSYNC_DATASYNC;
825
826        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
827        const _ = !0;
828    }
829}
830
831bitflags::bitflags! {
832    /// `IORING_TIMEOUT_*` and `IORING_LINK_TIMEOUT_UPDATE` flags for use with
833    /// [`io_uring_sqe`].
834    #[repr(transparent)]
835    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
836    pub struct IoringTimeoutFlags: u32 {
837        /// `IORING_TIMEOUT_ABS`
838        const ABS = sys::IORING_TIMEOUT_ABS;
839
840        /// `IORING_TIMEOUT_UPDATE`
841        const UPDATE = sys::IORING_TIMEOUT_UPDATE;
842
843        /// `IORING_TIMEOUT_BOOTTIME`
844        const BOOTTIME = sys::IORING_TIMEOUT_BOOTTIME;
845
846        /// `IORING_TIMEOUT_ETIME_SUCCESS`
847        const ETIME_SUCCESS = sys::IORING_TIMEOUT_ETIME_SUCCESS;
848
849        /// `IORING_TIMEOUT_REALTIME`
850        const REALTIME = sys::IORING_TIMEOUT_REALTIME;
851
852        /// `IORING_TIMEOUT_CLOCK_MASK`
853        const CLOCK_MASK = sys::IORING_TIMEOUT_CLOCK_MASK;
854
855        /// `IORING_TIMEOUT_UPDATE_MASK`
856        const UPDATE_MASK = sys::IORING_TIMEOUT_UPDATE_MASK;
857
858        /// `IORING_LINK_TIMEOUT_UPDATE`
859        const LINK_TIMEOUT_UPDATE = sys::IORING_LINK_TIMEOUT_UPDATE;
860
861        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
862        const _ = !0;
863    }
864}
865
866bitflags::bitflags! {
867    /// `SPLICE_F_*` flags for use with [`io_uring_sqe`].
868    #[repr(transparent)]
869    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
870    pub struct SpliceFlags: u32 {
871        /// `SPLICE_F_FD_IN_FIXED`
872        const FD_IN_FIXED = sys::SPLICE_F_FD_IN_FIXED;
873
874        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
875        const _ = !0;
876    }
877}
878
879bitflags::bitflags! {
880    /// `IORING_MSG_RING_*` flags for use with [`io_uring_sqe`].
881    #[repr(transparent)]
882    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
883    pub struct IoringMsgringFlags: u32 {
884        /// `IORING_MSG_RING_CQE_SKIP`
885        const CQE_SKIP = sys::IORING_MSG_RING_CQE_SKIP;
886
887        /// `IORING_MSG_RING_FLAGS_PASS`
888        const FLAGS_PASS = sys::IORING_MSG_RING_FLAGS_PASS;
889
890        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
891        const _ = !0;
892    }
893}
894
895bitflags::bitflags! {
896    /// `IORING_URING_CMD_*` flags for use with [`io_uring_sqe`].
897    #[repr(transparent)]
898    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
899    pub struct IoringUringCmdFlags: u32 {
900        /// `IORING_URING_CMD_FIXED`
901        const FIXED = sys::IORING_URING_CMD_FIXED;
902
903        /// `IORING_URING_CMD_MASK`
904        const MASK = sys::IORING_URING_CMD_MASK;
905
906        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
907        const _ = !0;
908    }
909}
910
911bitflags::bitflags! {
912    /// `IORING_ASYNC_CANCEL_*` flags for use with [`io_uring_sqe`].
913    #[repr(transparent)]
914    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
915    pub struct IoringAsyncCancelFlags: u32 {
916        /// `IORING_ASYNC_CANCEL_ALL`
917        const ALL = sys::IORING_ASYNC_CANCEL_ALL;
918
919        /// `IORING_ASYNC_CANCEL_FD`
920        const FD = sys::IORING_ASYNC_CANCEL_FD;
921
922        /// `IORING_ASYNC_CANCEL_FD`
923        const ANY = sys::IORING_ASYNC_CANCEL_ANY;
924
925        /// `IORING_ASYNC_CANCEL_FD`
926        const FD_FIXED = sys::IORING_ASYNC_CANCEL_FD_FIXED;
927
928        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
929        const _ = !0;
930    }
931}
932
933bitflags::bitflags! {
934    /// `IORING_FIXED_FD_*` flags for use with [`io_uring_sqe`].
935    #[repr(transparent)]
936    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
937    pub struct IoringFixedFdFlags: u32 {
938        /// `IORING_FIXED_FD_NO_CLOEXEC`
939        const NO_CLOEXEC = sys::IORING_FIXED_FD_NO_CLOEXEC;
940
941        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
942        const _ = !0;
943    }
944}
945
946bitflags::bitflags! {
947    /// `IORING_FEAT_*` flags for use with [`io_uring_params`].
948    #[repr(transparent)]
949    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
950    pub struct IoringFeatureFlags: u32 {
951        /// `IORING_FEAT_CQE_SKIP`
952        const CQE_SKIP = sys::IORING_FEAT_CQE_SKIP;
953
954        /// `IORING_FEAT_CUR_PERSONALITY`
955        const CUR_PERSONALITY = sys::IORING_FEAT_CUR_PERSONALITY;
956
957        /// `IORING_FEAT_EXT_ARG`
958        const EXT_ARG = sys::IORING_FEAT_EXT_ARG;
959
960        /// `IORING_FEAT_FAST_POLL`
961        const FAST_POLL = sys::IORING_FEAT_FAST_POLL;
962
963        /// `IORING_FEAT_NATIVE_WORKERS`
964        const NATIVE_WORKERS = sys::IORING_FEAT_NATIVE_WORKERS;
965
966        /// `IORING_FEAT_NODROP`
967        const NODROP = sys::IORING_FEAT_NODROP;
968
969        /// `IORING_FEAT_POLL_32BITS`
970        const POLL_32BITS = sys::IORING_FEAT_POLL_32BITS;
971
972        /// `IORING_FEAT_RSRC_TAGS`
973        const RSRC_TAGS = sys::IORING_FEAT_RSRC_TAGS;
974
975        /// `IORING_FEAT_RW_CUR_POS`
976        const RW_CUR_POS = sys::IORING_FEAT_RW_CUR_POS;
977
978        /// `IORING_FEAT_SINGLE_MMAP`
979        const SINGLE_MMAP = sys::IORING_FEAT_SINGLE_MMAP;
980
981        /// `IORING_FEAT_SQPOLL_NONFIXED`
982        const SQPOLL_NONFIXED = sys::IORING_FEAT_SQPOLL_NONFIXED;
983
984        /// `IORING_FEAT_SUBMIT_STABLE`
985        const SUBMIT_STABLE = sys::IORING_FEAT_SUBMIT_STABLE;
986
987        /// `IORING_FEAT_LINKED_FILE`
988        const LINKED_FILE = sys::IORING_FEAT_LINKED_FILE;
989
990        /// `IORING_FEAT_REG_REG_RING`
991        const REG_REG_RING = sys::IORING_FEAT_REG_REG_RING;
992
993        /// `IORING_FEAT_RECVSEND_BUNDLE`
994        const RECVSEND_BUNDLE = sys::IORING_FEAT_RECVSEND_BUNDLE;
995
996        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
997        const _ = !0;
998    }
999}
1000
1001bitflags::bitflags! {
1002    /// `IO_URING_OP_*` flags for use with [`io_uring_probe_op`].
1003    #[repr(transparent)]
1004    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1005    pub struct IoringOpFlags: u16 {
1006        /// `IO_URING_OP_SUPPORTED`
1007        const SUPPORTED = sys::IO_URING_OP_SUPPORTED as _;
1008
1009        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1010        const _ = !0;
1011    }
1012}
1013
1014bitflags::bitflags! {
1015    /// `IORING_RSRC_*` flags for use with [`io_uring_rsrc_register`].
1016    #[repr(transparent)]
1017    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1018    pub struct IoringRsrcFlags: u32 {
1019        /// `IORING_RSRC_REGISTER_SPARSE`
1020        const REGISTER_SPARSE = sys::IORING_RSRC_REGISTER_SPARSE as _;
1021
1022        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1023        const _ = !0;
1024    }
1025}
1026
1027bitflags::bitflags! {
1028    /// `IORING_SQ_*` flags.
1029    #[repr(transparent)]
1030    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1031    pub struct IoringSqFlags: u32 {
1032        /// `IORING_SQ_NEED_WAKEUP`
1033        const NEED_WAKEUP = sys::IORING_SQ_NEED_WAKEUP;
1034
1035        /// `IORING_SQ_CQ_OVERFLOW`
1036        const CQ_OVERFLOW = sys::IORING_SQ_CQ_OVERFLOW;
1037
1038        /// `IORING_SQ_TASKRUN`
1039        const TASKRUN = sys::IORING_SQ_TASKRUN;
1040
1041        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1042        const _ = !0;
1043    }
1044}
1045
1046bitflags::bitflags! {
1047    /// `IORING_CQ_*` flags.
1048    #[repr(transparent)]
1049    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1050    pub struct IoringCqFlags: u32 {
1051        /// `IORING_CQ_EVENTFD_DISABLED`
1052        const EVENTFD_DISABLED = sys::IORING_CQ_EVENTFD_DISABLED;
1053
1054        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1055        const _ = !0;
1056    }
1057}
1058
1059bitflags::bitflags! {
1060    /// `IORING_POLL_*` flags.
1061    #[repr(transparent)]
1062    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1063    pub struct IoringPollFlags: u32 {
1064        /// `IORING_POLL_ADD_MULTI`
1065        const ADD_MULTI = sys::IORING_POLL_ADD_MULTI;
1066
1067        /// `IORING_POLL_UPDATE_EVENTS`
1068        const UPDATE_EVENTS = sys::IORING_POLL_UPDATE_EVENTS;
1069
1070        /// `IORING_POLL_UPDATE_USER_DATA`
1071        const UPDATE_USER_DATA = sys::IORING_POLL_UPDATE_USER_DATA;
1072
1073        /// `IORING_POLL_ADD_LEVEL`
1074        const ADD_LEVEL = sys::IORING_POLL_ADD_LEVEL;
1075
1076        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1077        const _ = !0;
1078    }
1079}
1080
1081bitflags::bitflags! {
1082    /// send/sendmsg flags (`sqe.ioprio`)
1083    #[repr(transparent)]
1084    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1085    pub struct IoringSendFlags: u16 {
1086        /// `IORING_RECVSEND_POLL_FIRST`.
1087        ///
1088        /// See also [`IoringRecvFlags::POLL_FIRST`].
1089        const POLL_FIRST = sys::IORING_RECVSEND_POLL_FIRST as _;
1090
1091        /// `IORING_RECVSEND_FIXED_BUF`
1092        ///
1093        /// See also [`IoringRecvFlags::FIXED_BUF`].
1094        const FIXED_BUF = sys::IORING_RECVSEND_FIXED_BUF as _;
1095
1096        /// `IORING_SEND_ZC_REPORT_USAGE` (since Linux 6.2)
1097        const ZC_REPORT_USAGE = sys::IORING_SEND_ZC_REPORT_USAGE as _;
1098
1099        /// `IORING_RECVSEND_BUNDLE`
1100        ///
1101        /// See also [`IoringRecvFlags::BUNDLE`].
1102        const BUNDLE = sys::IORING_RECVSEND_BUNDLE as _;
1103
1104        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1105        const _ = !0;
1106    }
1107}
1108
1109bitflags::bitflags! {
1110    /// recv/recvmsg flags (`sqe.ioprio`)
1111    #[repr(transparent)]
1112    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1113    pub struct IoringRecvFlags: u16 {
1114        /// `IORING_RECVSEND_POLL_FIRST`
1115        ///
1116        /// See also [`IoringSendFlags::POLL_FIRST`].
1117        const POLL_FIRST = sys::IORING_RECVSEND_POLL_FIRST as _;
1118
1119        /// `IORING_RECV_MULTISHOT`
1120        const MULTISHOT = sys::IORING_RECV_MULTISHOT as _;
1121
1122        /// `IORING_RECVSEND_FIXED_BUF`
1123        ///
1124        /// See also [`IoringSendFlags::FIXED_BUF`].
1125        const FIXED_BUF = sys::IORING_RECVSEND_FIXED_BUF as _;
1126
1127        /// `IORING_RECVSEND_BUNDLE`
1128        ///
1129        /// See also [`IoringSendFlags::BUNDLE`].
1130        const BUNDLE = sys::IORING_RECVSEND_BUNDLE as _;
1131
1132        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1133        const _ = !0;
1134    }
1135}
1136
1137bitflags::bitflags! {
1138    /// accept flags (`sqe.ioprio`)
1139    #[repr(transparent)]
1140    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1141    pub struct IoringAcceptFlags: u16 {
1142        /// `IORING_ACCEPT_MULTISHOT`
1143        const MULTISHOT = sys::IORING_ACCEPT_MULTISHOT as _;
1144
1145        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1146        const _ = !0;
1147    }
1148}
1149
1150bitflags::bitflags! {
1151    /// recvmsg out flags
1152    #[repr(transparent)]
1153    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
1154    pub struct RecvmsgOutFlags: u32 {
1155        /// `MSG_EOR`
1156        const EOR = net::MSG_EOR;
1157
1158        /// `MSG_TRUNC`
1159        const TRUNC = net::MSG_TRUNC;
1160
1161        /// `MSG_CTRUNC`
1162        const CTRUNC = net::MSG_CTRUNC;
1163
1164        /// `MSG_OOB`
1165        const OOB = net::MSG_OOB;
1166
1167        /// `MSG_ERRQUEUE`
1168        const ERRQUEUE = net::MSG_ERRQUEUE;
1169
1170        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
1171        const _ = !0;
1172    }
1173}
1174
1175#[allow(missing_docs)]
1176pub const IORING_CQE_BUFFER_SHIFT: u32 = sys::IORING_CQE_BUFFER_SHIFT as _;
1177#[allow(missing_docs)]
1178pub const IORING_FILE_INDEX_ALLOC: i32 = sys::IORING_FILE_INDEX_ALLOC as _;
1179
1180// Re-export these as `u64`, which is the `offset` type in `rustix::io::mmap`.
1181#[allow(missing_docs)]
1182pub const IORING_OFF_SQ_RING: u64 = sys::IORING_OFF_SQ_RING as _;
1183#[allow(missing_docs)]
1184pub const IORING_OFF_CQ_RING: u64 = sys::IORING_OFF_CQ_RING as _;
1185#[allow(missing_docs)]
1186pub const IORING_OFF_SQES: u64 = sys::IORING_OFF_SQES as _;
1187
1188/// `IORING_REGISTER_FILES_SKIP`
1189// SAFETY: `IORING_REGISTER_FILES_SKIP` is a reserved value that is never
1190// dynamically allocated, so it'll remain valid for the duration of
1191// `'static`.
1192pub const IORING_REGISTER_FILES_SKIP: BorrowedFd<'static> =
1193    unsafe { BorrowedFd::<'static>::borrow_raw(sys::IORING_REGISTER_FILES_SKIP as RawFd) };
1194
1195/// `IORING_NOTIF_USAGE_ZC_COPIED` (since Linux 6.2)
1196pub const IORING_NOTIF_USAGE_ZC_COPIED: i32 = sys::IORING_NOTIF_USAGE_ZC_COPIED as _;
1197
1198/// A pointer in the io_uring API.
1199///
1200/// `io_uring`'s native API represents pointers as `u64` values. In order to
1201/// preserve strict-provenance, use a `*mut c_void`. On platforms where
1202/// pointers are narrower than 64 bits, this requires additional padding.
1203#[repr(C)]
1204#[cfg_attr(any(target_arch = "arm", target_arch = "powerpc"), repr(align(8)))]
1205#[derive(Copy, Clone)]
1206#[non_exhaustive]
1207pub struct io_uring_ptr {
1208    #[cfg(all(target_pointer_width = "32", target_endian = "big"))]
1209    #[doc(hidden)]
1210    pub __pad32: u32,
1211    #[cfg(all(target_pointer_width = "16", target_endian = "big"))]
1212    #[doc(hidden)]
1213    pub __pad16: u16,
1214
1215    /// The pointer value.
1216    pub ptr: *mut c_void,
1217
1218    #[cfg(all(target_pointer_width = "16", target_endian = "little"))]
1219    #[doc(hidden)]
1220    pub __pad16: u16,
1221    #[cfg(all(target_pointer_width = "32", target_endian = "little"))]
1222    #[doc(hidden)]
1223    pub __pad32: u32,
1224}
1225
1226impl io_uring_ptr {
1227    /// Construct a null `io_uring_ptr`.
1228    #[inline]
1229    pub const fn null() -> Self {
1230        Self::new(null_mut())
1231    }
1232
1233    /// Construct a new `io_uring_ptr`.
1234    #[inline]
1235    pub const fn new(ptr: *mut c_void) -> Self {
1236        Self {
1237            ptr,
1238
1239            #[cfg(target_pointer_width = "16")]
1240            __pad16: 0,
1241            #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
1242            __pad32: 0,
1243        }
1244    }
1245}
1246
1247impl From<*mut c_void> for io_uring_ptr {
1248    #[inline]
1249    fn from(ptr: *mut c_void) -> Self {
1250        Self::new(ptr)
1251    }
1252}
1253
1254impl PartialEq for io_uring_ptr {
1255    #[inline]
1256    fn eq(&self, other: &Self) -> bool {
1257        self.ptr.eq(&other.ptr)
1258    }
1259}
1260
1261impl Eq for io_uring_ptr {}
1262
1263#[allow(clippy::non_canonical_partial_ord_impl)]
1264impl PartialOrd for io_uring_ptr {
1265    #[inline]
1266    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1267        self.ptr.partial_cmp(&other.ptr)
1268    }
1269}
1270
1271impl Ord for io_uring_ptr {
1272    #[inline]
1273    fn cmp(&self, other: &Self) -> Ordering {
1274        self.ptr.cmp(&other.ptr)
1275    }
1276}
1277
1278impl Hash for io_uring_ptr {
1279    #[inline]
1280    fn hash<H: Hasher>(&self, state: &mut H) {
1281        self.ptr.hash(state)
1282    }
1283}
1284
1285impl Default for io_uring_ptr {
1286    #[inline]
1287    fn default() -> Self {
1288        Self::null()
1289    }
1290}
1291
1292impl core::fmt::Pointer for io_uring_ptr {
1293    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1294        self.ptr.fmt(f)
1295    }
1296}
1297
1298impl core::fmt::Debug for io_uring_ptr {
1299    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1300        self.ptr.fmt(f)
1301    }
1302}
1303
1304/// User data in the io_uring API.
1305///
1306/// `io_uring`'s native API represents `user_data` fields as `u64` values. In
1307/// order to preserve strict-provenance, use a union which allows users to
1308/// optionally store pointers.
1309#[repr(C)]
1310#[derive(Copy, Clone)]
1311pub union io_uring_user_data {
1312    /// An arbitrary `u64`.
1313    pub u64_: u64,
1314
1315    /// A pointer.
1316    pub ptr: io_uring_ptr,
1317}
1318
1319impl io_uring_user_data {
1320    /// Create a zero-initialized `Self`.
1321    pub const fn zeroed() -> Self {
1322        // Initialize the `u64_` field, which is the size of the full union.
1323        // This can use `core::mem::zeroed` in Rust 1.75.
1324        Self { u64_: 0 }
1325    }
1326
1327    /// Return the `u64` value.
1328    #[inline]
1329    pub const fn u64_(self) -> u64 {
1330        // SAFETY: All the fields have the same underlying representation.
1331        unsafe { self.u64_ }
1332    }
1333
1334    /// Create a `Self` from a `u64` value.
1335    #[inline]
1336    pub const fn from_u64(u64_: u64) -> Self {
1337        Self { u64_ }
1338    }
1339
1340    /// Return the `ptr` pointer value.
1341    #[inline]
1342    pub const fn ptr(self) -> *mut c_void {
1343        // SAFETY: All the fields have the same underlying representation.
1344        unsafe { self.ptr }.ptr
1345    }
1346
1347    /// Create a `Self` from a pointer value.
1348    #[inline]
1349    pub const fn from_ptr(ptr: *mut c_void) -> Self {
1350        Self {
1351            ptr: io_uring_ptr::new(ptr),
1352        }
1353    }
1354}
1355
1356impl From<u64> for io_uring_user_data {
1357    #[inline]
1358    fn from(u64_: u64) -> Self {
1359        Self::from_u64(u64_)
1360    }
1361}
1362
1363impl From<*mut c_void> for io_uring_user_data {
1364    #[inline]
1365    fn from(ptr: *mut c_void) -> Self {
1366        Self::from_ptr(ptr)
1367    }
1368}
1369
1370impl PartialEq for io_uring_user_data {
1371    #[inline]
1372    fn eq(&self, other: &Self) -> bool {
1373        // SAFETY: `io_uring_ptr` and `u64` have the same layout.
1374        unsafe { self.u64_.eq(&other.u64_) }
1375    }
1376}
1377
1378impl Eq for io_uring_user_data {}
1379
1380#[allow(clippy::non_canonical_partial_ord_impl)]
1381impl PartialOrd for io_uring_user_data {
1382    #[inline]
1383    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1384        // SAFETY: `io_uring_ptr` and `u64` have the same layout.
1385        unsafe { self.u64_.partial_cmp(&other.u64_) }
1386    }
1387}
1388
1389impl Ord for io_uring_user_data {
1390    #[inline]
1391    fn cmp(&self, other: &Self) -> Ordering {
1392        // SAFETY: `io_uring_ptr` and `u64` have the same layout.
1393        unsafe { self.u64_.cmp(&other.u64_) }
1394    }
1395}
1396
1397impl Hash for io_uring_user_data {
1398    #[inline]
1399    fn hash<H: Hasher>(&self, state: &mut H) {
1400        // SAFETY: `io_uring_ptr` and `u64` have the same layout.
1401        unsafe { self.u64_.hash(state) }
1402    }
1403}
1404
1405impl Default for io_uring_user_data {
1406    #[inline]
1407    fn default() -> Self {
1408        Self::zeroed()
1409    }
1410}
1411
1412impl core::fmt::Debug for io_uring_user_data {
1413    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1414        // SAFETY: Just format as a `u64`, since formatting doesn't preserve
1415        // provenance, and we don't have a discriminant.
1416        unsafe { self.u64_.fmt(f) }
1417    }
1418}
1419
1420/// An io_uring Submission Queue Entry.
1421#[allow(missing_docs)]
1422#[repr(C)]
1423#[derive(Copy, Clone, Default)]
1424pub struct io_uring_sqe {
1425    pub opcode: IoringOp,
1426    pub flags: IoringSqeFlags,
1427    pub ioprio: ioprio_union,
1428    pub fd: RawFd,
1429    pub off_or_addr2: off_or_addr2_union,
1430    pub addr_or_splice_off_in: addr_or_splice_off_in_union,
1431    pub len: len_union,
1432    pub op_flags: op_flags_union,
1433    pub user_data: io_uring_user_data,
1434    pub buf: buf_union,
1435    pub personality: u16,
1436    pub splice_fd_in_or_file_index_or_addr_len: splice_fd_in_or_file_index_or_addr_len_union,
1437    pub addr3_or_cmd: addr3_or_cmd_union,
1438}
1439
1440#[allow(missing_docs)]
1441#[repr(C)]
1442#[derive(Copy, Clone)]
1443pub union ioprio_union {
1444    pub recv_flags: IoringRecvFlags,
1445    pub send_flags: IoringSendFlags,
1446    pub accept_flags: IoringAcceptFlags,
1447    pub ioprio: u16,
1448}
1449
1450#[allow(missing_docs)]
1451#[repr(C)]
1452#[derive(Copy, Clone)]
1453pub union len_union {
1454    pub poll_flags: IoringPollFlags,
1455    pub len: u32,
1456}
1457
1458#[allow(missing_docs)]
1459#[repr(C)]
1460#[derive(Copy, Clone)]
1461pub union addr3_or_cmd_union {
1462    pub addr3: addr3_struct,
1463    pub cmd: [u8; 0],
1464}
1465
1466#[allow(missing_docs)]
1467#[repr(C)]
1468#[derive(Copy, Clone, Default)]
1469#[non_exhaustive]
1470pub struct addr3_struct {
1471    pub addr3: u64,
1472    #[doc(hidden)]
1473    pub __pad2: [u64; 1],
1474}
1475
1476#[allow(missing_docs)]
1477#[repr(C)]
1478#[derive(Copy, Clone)]
1479pub union off_or_addr2_union {
1480    pub off: u64,
1481    pub addr2: io_uring_ptr,
1482    pub cmd_op: cmd_op_struct,
1483    pub user_data: io_uring_user_data,
1484}
1485
1486#[allow(missing_docs)]
1487#[repr(C)]
1488#[derive(Copy, Clone)]
1489#[non_exhaustive]
1490pub struct cmd_op_struct {
1491    pub cmd_op: u32,
1492    #[doc(hidden)]
1493    pub __pad1: u32,
1494}
1495
1496#[allow(missing_docs)]
1497#[repr(C)]
1498#[derive(Copy, Clone)]
1499pub union addr_or_splice_off_in_union {
1500    pub addr: io_uring_ptr,
1501    pub splice_off_in: u64,
1502    pub msgring_cmd: IoringMsgringCmds,
1503    pub user_data: io_uring_user_data,
1504}
1505
1506#[allow(missing_docs)]
1507#[repr(C)]
1508#[derive(Copy, Clone)]
1509pub union op_flags_union {
1510    pub rw_flags: crate::io::ReadWriteFlags,
1511    pub fsync_flags: IoringFsyncFlags,
1512    pub poll_events: u16,
1513    pub poll32_events: u32,
1514    pub sync_range_flags: u32,
1515    /// `msg_flags` is split into `send_flags` and `recv_flags`.
1516    #[doc(alias = "msg_flags")]
1517    pub send_flags: SendFlags,
1518    /// `msg_flags` is split into `send_flags` and `recv_flags`.
1519    #[doc(alias = "msg_flags")]
1520    pub recv_flags: RecvFlags,
1521    pub timeout_flags: IoringTimeoutFlags,
1522    pub accept_flags: SocketFlags,
1523    pub cancel_flags: IoringAsyncCancelFlags,
1524    pub open_flags: OFlags,
1525    pub statx_flags: AtFlags,
1526    pub fadvise_advice: Advice,
1527    pub splice_flags: SpliceFlags,
1528    pub rename_flags: RenameFlags,
1529    pub unlink_flags: AtFlags,
1530    pub hardlink_flags: AtFlags,
1531    pub xattr_flags: XattrFlags,
1532    pub msg_ring_flags: IoringMsgringFlags,
1533    pub uring_cmd_flags: IoringUringCmdFlags,
1534    pub futex_flags: FutexWaitvFlags,
1535    pub install_fd_flags: IoringFixedFdFlags,
1536}
1537
1538#[allow(missing_docs)]
1539#[repr(C, packed)]
1540#[derive(Copy, Clone)]
1541pub union buf_union {
1542    pub buf_index: u16,
1543    pub buf_group: u16,
1544}
1545
1546#[allow(missing_docs)]
1547#[repr(C)]
1548#[derive(Copy, Clone)]
1549pub union splice_fd_in_or_file_index_or_addr_len_union {
1550    pub splice_fd_in: i32,
1551    pub file_index: u32,
1552    pub addr_len: addr_len_struct,
1553}
1554
1555#[allow(missing_docs)]
1556#[repr(C)]
1557#[derive(Copy, Clone)]
1558#[non_exhaustive]
1559pub struct addr_len_struct {
1560    pub addr_len: u16,
1561    #[doc(hidden)]
1562    pub __pad3: [u16; 1],
1563}
1564
1565#[allow(missing_docs)]
1566#[repr(C)]
1567#[derive(Copy, Clone)]
1568#[non_exhaustive]
1569pub struct io_uring_sync_cancel_reg {
1570    pub addr: io_uring_user_data,
1571    pub fd: i32,
1572    pub flags: IoringAsyncCancelFlags,
1573    pub timeout: Timespec,
1574    pub opcode: u8,
1575    #[doc(hidden)]
1576    pub pad: [u8; 7],
1577    #[doc(hidden)]
1578    pub pad2: [u64; 3],
1579}
1580
1581impl Default for io_uring_sync_cancel_reg {
1582    #[inline]
1583    fn default() -> Self {
1584        Self {
1585            addr: Default::default(),
1586            fd: Default::default(),
1587            flags: Default::default(),
1588            timeout: Timespec {
1589                tv_sec: 0,
1590                tv_nsec: 0,
1591            },
1592            opcode: Default::default(),
1593            pad: Default::default(),
1594            pad2: Default::default(),
1595        }
1596    }
1597}
1598
1599/// An io_uring Completion Queue Entry.
1600///
1601/// This does not derive `Copy` or `Clone` because the `big_cqe` field is not
1602/// automatically copyable.
1603#[allow(missing_docs)]
1604#[repr(C)]
1605#[derive(Debug, Default)]
1606pub struct io_uring_cqe {
1607    pub user_data: io_uring_user_data,
1608    pub res: i32,
1609    pub flags: IoringCqeFlags,
1610    pub big_cqe: IncompleteArrayField<u64>,
1611}
1612
1613#[allow(missing_docs)]
1614#[repr(C)]
1615#[derive(Copy, Clone, Default)]
1616#[non_exhaustive]
1617pub struct io_uring_restriction {
1618    pub opcode: IoringRestrictionOp,
1619    pub register_or_sqe_op_or_sqe_flags: register_or_sqe_op_or_sqe_flags_union,
1620    #[doc(hidden)]
1621    pub resv: u8,
1622    #[doc(hidden)]
1623    pub resv2: [u32; 3],
1624}
1625
1626#[allow(missing_docs)]
1627#[repr(C)]
1628#[derive(Copy, Clone)]
1629pub union register_or_sqe_op_or_sqe_flags_union {
1630    pub register_op: IoringRegisterOp,
1631    pub sqe_op: IoringOp,
1632    pub sqe_flags: IoringSqeFlags,
1633}
1634
1635#[allow(missing_docs)]
1636#[repr(C)]
1637#[derive(Debug, Copy, Clone, Default)]
1638#[non_exhaustive]
1639pub struct io_uring_params {
1640    pub sq_entries: u32,
1641    pub cq_entries: u32,
1642    pub flags: IoringSetupFlags,
1643    pub sq_thread_cpu: u32,
1644    pub sq_thread_idle: u32,
1645    pub features: IoringFeatureFlags,
1646    pub wq_fd: RawFd,
1647    #[doc(hidden)]
1648    pub resv: [u32; 3],
1649    pub sq_off: io_sqring_offsets,
1650    pub cq_off: io_cqring_offsets,
1651}
1652
1653#[allow(missing_docs)]
1654#[repr(C)]
1655#[derive(Debug, Copy, Clone, Default)]
1656#[non_exhaustive]
1657pub struct io_sqring_offsets {
1658    pub head: u32,
1659    pub tail: u32,
1660    pub ring_mask: u32,
1661    pub ring_entries: u32,
1662    pub flags: u32,
1663    pub dropped: u32,
1664    pub array: u32,
1665    #[doc(hidden)]
1666    pub resv1: u32,
1667    pub user_addr: io_uring_ptr,
1668}
1669
1670#[allow(missing_docs)]
1671#[repr(C)]
1672#[derive(Debug, Copy, Clone, Default)]
1673#[non_exhaustive]
1674pub struct io_cqring_offsets {
1675    pub head: u32,
1676    pub tail: u32,
1677    pub ring_mask: u32,
1678    pub ring_entries: u32,
1679    pub overflow: u32,
1680    pub cqes: u32,
1681    pub flags: u32,
1682    #[doc(hidden)]
1683    pub resv1: u32,
1684    pub user_addr: io_uring_ptr,
1685}
1686
1687#[allow(missing_docs)]
1688#[repr(C)]
1689#[derive(Debug, Default)]
1690#[non_exhaustive]
1691pub struct io_uring_probe {
1692    pub last_op: IoringOp,
1693    pub ops_len: u8,
1694    #[doc(hidden)]
1695    pub resv: u16,
1696    #[doc(hidden)]
1697    pub resv2: [u32; 3],
1698    pub ops: IncompleteArrayField<io_uring_probe_op>,
1699}
1700
1701#[allow(missing_docs)]
1702#[repr(C)]
1703#[derive(Debug, Copy, Clone, Default)]
1704#[non_exhaustive]
1705pub struct io_uring_probe_op {
1706    pub op: IoringOp,
1707    #[doc(hidden)]
1708    pub resv: u8,
1709    pub flags: IoringOpFlags,
1710    #[doc(hidden)]
1711    pub resv2: u32,
1712}
1713
1714#[allow(missing_docs)]
1715#[repr(C, align(8))]
1716#[derive(Debug, Copy, Clone, Default)]
1717#[non_exhaustive]
1718pub struct io_uring_files_update {
1719    pub offset: u32,
1720    #[doc(hidden)]
1721    pub resv: u32,
1722    pub fds: io_uring_ptr,
1723}
1724
1725#[allow(missing_docs)]
1726#[repr(C, align(8))]
1727#[derive(Debug, Copy, Clone, Default)]
1728#[non_exhaustive]
1729pub struct io_uring_rsrc_register {
1730    pub nr: u32,
1731    pub flags: IoringRsrcFlags,
1732    #[doc(hidden)]
1733    pub resv2: u64,
1734    pub data: io_uring_ptr,
1735    pub tags: io_uring_ptr,
1736}
1737
1738#[allow(missing_docs)]
1739#[repr(C, align(8))]
1740#[derive(Debug, Copy, Clone, Default)]
1741#[non_exhaustive]
1742pub struct io_uring_rsrc_update {
1743    pub offset: u32,
1744    #[doc(hidden)]
1745    pub resv: u32,
1746    pub data: io_uring_ptr,
1747}
1748
1749#[allow(missing_docs)]
1750#[repr(C, align(8))]
1751#[derive(Debug, Copy, Clone, Default)]
1752#[non_exhaustive]
1753pub struct io_uring_rsrc_update2 {
1754    pub offset: u32,
1755    #[doc(hidden)]
1756    pub resv: u32,
1757    pub data: io_uring_ptr,
1758    pub tags: io_uring_ptr,
1759    pub nr: u32,
1760    #[doc(hidden)]
1761    pub resv2: u32,
1762}
1763
1764#[allow(missing_docs)]
1765#[repr(C)]
1766#[derive(Debug, Copy, Clone, Default)]
1767pub struct io_uring_getevents_arg {
1768    pub sigmask: io_uring_ptr,
1769    pub sigmask_sz: u32,
1770    pub min_wait_usec: u32,
1771    pub ts: io_uring_ptr,
1772}
1773
1774#[allow(missing_docs)]
1775#[repr(C)]
1776#[derive(Debug, Default, Copy, Clone)]
1777pub struct io_uring_recvmsg_out {
1778    pub namelen: SocketAddrLen,
1779    pub controllen: u32,
1780    pub payloadlen: u32,
1781    pub flags: RecvmsgOutFlags,
1782}
1783
1784#[allow(missing_docs)]
1785#[repr(C)]
1786#[derive(Debug, Copy, Clone)]
1787pub struct iovec {
1788    pub iov_base: *mut c_void,
1789    pub iov_len: usize,
1790}
1791
1792#[allow(missing_docs)]
1793#[repr(C)]
1794#[derive(Debug, Copy, Clone, Default)]
1795#[non_exhaustive]
1796pub struct open_how {
1797    /// An [`OFlags`] value represented as a `u64`.
1798    pub flags: u64,
1799
1800    /// A [`Mode`] value represented as a `u64`.
1801    pub mode: u64,
1802
1803    pub resolve: ResolveFlags,
1804}
1805
1806impl open_how {
1807    /// Create a zero-initialized `Self`.
1808    pub const fn zeroed() -> Self {
1809        Self {
1810            flags: 0,
1811            mode: 0,
1812            resolve: ResolveFlags::empty(),
1813        }
1814    }
1815}
1816
1817#[allow(missing_docs)]
1818#[repr(C)]
1819#[derive(Debug, Copy, Clone, Default)]
1820#[non_exhaustive]
1821pub struct io_uring_buf_reg {
1822    pub ring_addr: io_uring_ptr,
1823    pub ring_entries: u32,
1824    pub bgid: u16,
1825    pub flags: u16,
1826    #[doc(hidden)]
1827    pub resv: [u64; 3_usize],
1828}
1829
1830#[allow(missing_docs)]
1831#[repr(C)]
1832#[derive(Debug, Copy, Clone, Default)]
1833#[non_exhaustive]
1834pub struct io_uring_buf {
1835    pub addr: io_uring_ptr,
1836    pub len: u32,
1837    pub bid: u16,
1838    #[doc(hidden)]
1839    pub resv: u16,
1840}
1841
1842#[allow(missing_docs)]
1843#[repr(C)]
1844#[derive(Debug, Copy, Clone, Default)]
1845#[non_exhaustive]
1846pub struct buf_ring_tail_struct {
1847    #[doc(hidden)]
1848    pub resv1: u64,
1849    #[doc(hidden)]
1850    pub resv2: u32,
1851    #[doc(hidden)]
1852    pub resv3: u16,
1853    pub tail: u16,
1854}
1855
1856#[allow(missing_docs)]
1857#[repr(C)]
1858#[derive(Debug, Default)]
1859pub struct buf_ring_bufs_struct {
1860    pub bufs: IncompleteArrayField<io_uring_buf>,
1861}
1862
1863#[allow(missing_docs)]
1864#[repr(C)]
1865#[derive(Debug, Default)]
1866pub struct tail_or_bufs_struct {
1867    pub tail: UnionField<buf_ring_tail_struct>,
1868    pub bufs: UnionField<buf_ring_bufs_struct>,
1869    pub union_field: [u64; 2],
1870}
1871
1872#[allow(missing_docs)]
1873#[repr(C)]
1874#[derive(Debug, Default)]
1875pub struct io_uring_buf_ring {
1876    pub tail_or_bufs: tail_or_bufs_struct,
1877}
1878
1879#[allow(missing_docs)]
1880#[repr(C)]
1881#[derive(Debug, Default)]
1882#[non_exhaustive]
1883pub struct io_uring_napi {
1884    pub busy_poll_to: u32,
1885    pub prefer_busy_poll: u8,
1886    pub opcode: u8,
1887    #[doc(hidden)]
1888    pub pad: [u8; 2],
1889    pub op_param: u32,
1890    #[doc(hidden)]
1891    pub resv: u32,
1892}
1893
1894#[allow(missing_docs)]
1895#[repr(C)]
1896#[derive(Debug, Default)]
1897#[non_exhaustive]
1898pub struct io_uring_clone_buffers {
1899    pub src_fd: u32,
1900    pub flags: u32,
1901    pub src_off: u32,
1902    pub dst_off: u32,
1903    pub nr: u32,
1904    #[doc(hidden)]
1905    pub pad: [u32; 3],
1906}
1907
1908#[allow(missing_docs)]
1909#[repr(C)]
1910#[derive(Debug, Default)]
1911#[non_exhaustive]
1912pub struct io_uring_reg_wait {
1913    pub ts: Timespec,
1914    pub min_wait_usec: u32,
1915    pub flags: u32,
1916    pub sigmask: io_uring_ptr,
1917    pub sigmask_sz: u32,
1918    #[doc(hidden)]
1919    pub pad: [u32; 3],
1920    #[doc(hidden)]
1921    pub pad2: [u64; 2],
1922}
1923
1924impl Default for ioprio_union {
1925    #[inline]
1926    fn default() -> Self {
1927        default_union!(ioprio_union, ioprio)
1928    }
1929}
1930
1931impl Default for len_union {
1932    #[inline]
1933    fn default() -> Self {
1934        default_union!(len_union, len)
1935    }
1936}
1937
1938impl Default for off_or_addr2_union {
1939    #[inline]
1940    fn default() -> Self {
1941        default_union!(off_or_addr2_union, off)
1942    }
1943}
1944
1945impl Default for addr_or_splice_off_in_union {
1946    #[inline]
1947    fn default() -> Self {
1948        default_union!(addr_or_splice_off_in_union, splice_off_in)
1949    }
1950}
1951
1952impl Default for addr3_or_cmd_union {
1953    #[inline]
1954    fn default() -> Self {
1955        default_union!(addr3_or_cmd_union, addr3)
1956    }
1957}
1958
1959impl Default for op_flags_union {
1960    #[inline]
1961    fn default() -> Self {
1962        default_union!(op_flags_union, sync_range_flags)
1963    }
1964}
1965
1966impl Default for buf_union {
1967    #[inline]
1968    fn default() -> Self {
1969        default_union!(buf_union, buf_index)
1970    }
1971}
1972
1973impl Default for splice_fd_in_or_file_index_or_addr_len_union {
1974    #[inline]
1975    fn default() -> Self {
1976        default_union!(splice_fd_in_or_file_index_or_addr_len_union, splice_fd_in)
1977    }
1978}
1979
1980impl Default for register_or_sqe_op_or_sqe_flags_union {
1981    #[inline]
1982    fn default() -> Self {
1983        default_union!(register_or_sqe_op_or_sqe_flags_union, sqe_flags)
1984    }
1985}
1986
1987#[cfg(test)]
1988mod tests {
1989    use super::*;
1990    use crate::fd::AsRawFd as _;
1991
1992    /// Check that our custom structs and unions have the same layout as the
1993    /// kernel's versions.
1994    #[test]
1995    fn io_uring_layouts() {
1996        use sys as c;
1997
1998        // `io_uring_ptr` is a replacement for `u64`.
1999        static_assertions::assert_eq_size!(io_uring_ptr, u64);
2000        static_assertions::assert_eq_align!(io_uring_ptr, u64);
2001
2002        // Test that pointers are stored in `io_uring_ptr` in the way that
2003        // io_uring stores them in a `u64`.
2004        unsafe {
2005            const MAGIC: u64 = !0x0123_4567_89ab_cdef;
2006            let ptr = io_uring_ptr::new(MAGIC as usize as *mut c_void);
2007            assert_eq!(ptr.ptr, MAGIC as usize as *mut c_void);
2008            #[cfg(target_pointer_width = "16")]
2009            assert_eq!(ptr.__pad16, 0);
2010            #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
2011            assert_eq!(ptr.__pad32, 0);
2012            let int = core::mem::transmute::<io_uring_ptr, u64>(ptr);
2013            assert_eq!(int, MAGIC as usize as u64);
2014        }
2015
2016        // `io_uring_user_data` is a replacement for `u64`.
2017        static_assertions::assert_eq_size!(io_uring_user_data, u64);
2018        static_assertions::assert_eq_align!(io_uring_user_data, u64);
2019
2020        // Test that `u64`s and pointers are properly stored in
2021        // `io_uring_user_data`.
2022        unsafe {
2023            const MAGIC: u64 = !0x0123_4567_89ab_cdef;
2024            let user_data = io_uring_user_data::from_u64(MAGIC);
2025            assert_eq!(user_data.u64_(), MAGIC);
2026            assert_eq!(
2027                core::mem::transmute::<io_uring_user_data, u64>(user_data),
2028                MAGIC
2029            );
2030            let user_data = io_uring_user_data::from_ptr(MAGIC as usize as *mut c_void);
2031            assert_eq!(user_data.ptr(), MAGIC as usize as *mut c_void);
2032            assert_eq!(
2033                core::mem::transmute::<io_uring_user_data, u64>(user_data),
2034                MAGIC as usize as u64
2035            );
2036        }
2037
2038        check_renamed_type!(off_or_addr2_union, io_uring_sqe__bindgen_ty_1);
2039        check_renamed_type!(addr_or_splice_off_in_union, io_uring_sqe__bindgen_ty_2);
2040        check_renamed_type!(addr3_or_cmd_union, io_uring_sqe__bindgen_ty_6);
2041        check_renamed_type!(op_flags_union, io_uring_sqe__bindgen_ty_3);
2042        check_renamed_type!(buf_union, io_uring_sqe__bindgen_ty_4);
2043        check_renamed_type!(
2044            splice_fd_in_or_file_index_or_addr_len_union,
2045            io_uring_sqe__bindgen_ty_5
2046        );
2047        check_renamed_type!(addr_len_struct, io_uring_sqe__bindgen_ty_5__bindgen_ty_1);
2048        check_renamed_type!(
2049            register_or_sqe_op_or_sqe_flags_union,
2050            io_uring_restriction__bindgen_ty_1
2051        );
2052
2053        check_renamed_type!(addr3_struct, io_uring_sqe__bindgen_ty_6__bindgen_ty_1);
2054        check_renamed_type!(cmd_op_struct, io_uring_sqe__bindgen_ty_1__bindgen_ty_1);
2055
2056        check_type!(io_uring_sqe);
2057        check_struct_field!(io_uring_sqe, opcode);
2058        check_struct_field!(io_uring_sqe, flags);
2059        check_struct_field!(io_uring_sqe, ioprio);
2060        check_struct_field!(io_uring_sqe, fd);
2061        check_struct_renamed_field!(io_uring_sqe, off_or_addr2, __bindgen_anon_1);
2062        check_struct_renamed_field!(io_uring_sqe, addr_or_splice_off_in, __bindgen_anon_2);
2063        check_struct_field!(io_uring_sqe, len);
2064        check_struct_renamed_field!(io_uring_sqe, op_flags, __bindgen_anon_3);
2065        check_struct_field!(io_uring_sqe, user_data);
2066        check_struct_renamed_field!(io_uring_sqe, buf, __bindgen_anon_4);
2067        check_struct_field!(io_uring_sqe, personality);
2068        check_struct_renamed_field!(
2069            io_uring_sqe,
2070            splice_fd_in_or_file_index_or_addr_len,
2071            __bindgen_anon_5
2072        );
2073        check_struct_renamed_field!(io_uring_sqe, addr3_or_cmd, __bindgen_anon_6);
2074
2075        check_type!(io_uring_restriction);
2076        check_struct_field!(io_uring_restriction, opcode);
2077        check_struct_renamed_field!(
2078            io_uring_restriction,
2079            register_or_sqe_op_or_sqe_flags,
2080            __bindgen_anon_1
2081        );
2082        check_struct_field!(io_uring_restriction, resv);
2083        check_struct_field!(io_uring_restriction, resv2);
2084
2085        check_struct!(io_uring_cqe, user_data, res, flags, big_cqe);
2086        check_struct!(
2087            io_uring_params,
2088            sq_entries,
2089            cq_entries,
2090            flags,
2091            sq_thread_cpu,
2092            sq_thread_idle,
2093            features,
2094            wq_fd,
2095            resv,
2096            sq_off,
2097            cq_off
2098        );
2099        check_struct!(
2100            io_sqring_offsets,
2101            head,
2102            tail,
2103            ring_mask,
2104            ring_entries,
2105            flags,
2106            dropped,
2107            array,
2108            resv1,
2109            user_addr
2110        );
2111        check_struct!(
2112            io_cqring_offsets,
2113            head,
2114            tail,
2115            ring_mask,
2116            ring_entries,
2117            overflow,
2118            cqes,
2119            flags,
2120            resv1,
2121            user_addr
2122        );
2123        check_struct!(io_uring_recvmsg_out, namelen, controllen, payloadlen, flags);
2124        check_struct!(io_uring_probe, last_op, ops_len, resv, resv2, ops);
2125        check_struct!(io_uring_probe_op, op, resv, flags, resv2);
2126        check_struct!(io_uring_files_update, offset, resv, fds);
2127        check_struct!(io_uring_rsrc_register, nr, flags, resv2, data, tags);
2128        check_struct!(io_uring_rsrc_update, offset, resv, data);
2129        check_struct!(io_uring_rsrc_update2, offset, resv, data, tags, nr, resv2);
2130        check_struct!(
2131            io_uring_getevents_arg,
2132            sigmask,
2133            sigmask_sz,
2134            min_wait_usec,
2135            ts
2136        );
2137        check_struct!(iovec, iov_base, iov_len);
2138        check_struct!(open_how, flags, mode, resolve);
2139        check_struct!(io_uring_buf_reg, ring_addr, ring_entries, bgid, flags, resv);
2140        check_struct!(io_uring_buf, addr, len, bid, resv);
2141        check_struct!(
2142            io_uring_sync_cancel_reg,
2143            addr,
2144            fd,
2145            flags,
2146            timeout,
2147            opcode,
2148            pad,
2149            pad2
2150        );
2151
2152        check_renamed_type!(tail_or_bufs_struct, io_uring_buf_ring__bindgen_ty_1);
2153        check_renamed_type!(
2154            buf_ring_tail_struct,
2155            io_uring_buf_ring__bindgen_ty_1__bindgen_ty_1
2156        );
2157        check_renamed_type!(
2158            buf_ring_bufs_struct,
2159            io_uring_buf_ring__bindgen_ty_1__bindgen_ty_2
2160        );
2161        check_struct_renamed_field!(io_uring_buf_ring, tail_or_bufs, __bindgen_anon_1);
2162
2163        check_struct!(
2164            io_uring_napi,
2165            busy_poll_to,
2166            prefer_busy_poll,
2167            opcode,
2168            pad,
2169            op_param,
2170            resv
2171        );
2172        check_struct!(
2173            io_uring_clone_buffers,
2174            src_fd,
2175            flags,
2176            src_off,
2177            dst_off,
2178            nr,
2179            pad
2180        );
2181        check_struct!(
2182            io_uring_reg_wait,
2183            ts,
2184            min_wait_usec,
2185            flags,
2186            sigmask,
2187            sigmask_sz,
2188            pad,
2189            pad2
2190        );
2191
2192        check_renamed_struct!(
2193            MsgHdr,
2194            msghdr,
2195            msg_name,
2196            msg_namelen,
2197            msg_iov,
2198            msg_iovlen,
2199            msg_control,
2200            msg_controllen,
2201            msg_flags
2202        );
2203    }
2204
2205    #[test]
2206    fn test_io_uring_register_files_skip() {
2207        use crate::backend::c;
2208        assert!(IORING_REGISTER_FILES_SKIP.as_raw_fd() != -1);
2209        assert!(IORING_REGISTER_FILES_SKIP.as_raw_fd() != c::STDIN_FILENO);
2210        assert!(IORING_REGISTER_FILES_SKIP.as_raw_fd() != c::STDOUT_FILENO);
2211        assert!(IORING_REGISTER_FILES_SKIP.as_raw_fd() != c::STDERR_FILENO);
2212    }
2213}