]> git.proxmox.com Git - rustc.git/blame - vendor/rustix/src/io_uring.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / vendor / rustix / src / io_uring.rs
CommitLineData
064997fb
FG
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//! # Safety
9//!
10//! io_uring operates on raw pointers and raw file descriptors. Rustix does not
11//! attempt to provide a safe API for these, because the abstraction level is
12//! too low for this to be practical. Safety should be introduced in
13//! higher-level abstraction layers.
14//!
15//! # References
16//! - [Linux]
17//!
18//! [Linux]: https://man.archlinux.org/man/io_uring.7.en
19//! [io_uring]: https://en.wikipedia.org/wiki/Io_uring
20#![allow(unsafe_code)]
21
6522a427
EL
22use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
23use crate::{backend, io};
064997fb
FG
24use core::ffi::c_void;
25use core::ptr::null_mut;
26use linux_raw_sys::general as sys;
27
28/// `io_uring_setup(entries, params)`—Setup a context for performing
29/// asynchronous I/O.
30///
31/// # References
32/// - [Linux]
33///
34/// [Linux]: https://man.archlinux.org/man/io_uring_setup.2.en
35#[inline]
36pub fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd> {
6522a427 37 backend::io_uring::syscalls::io_uring_setup(entries, params)
064997fb
FG
38}
39
40/// `io_uring_register(fd, opcode, arg, nr_args)`—Register files or user
41/// buffers for asynchronous I/O.
42///
43/// # Safety
44///
45/// io_uring operates on raw pointers and raw file descriptors. Users are
46/// responsible for ensuring that memory and resources are only accessed in
47/// valid ways.
48///
49/// # References
50/// - [Linux]
51///
52/// [Linux]: https://man.archlinux.org/man/io_uring_register.2.en
53#[inline]
54pub unsafe fn io_uring_register<Fd: AsFd>(
55 fd: Fd,
56 opcode: IoringRegisterOp,
57 arg: *const c_void,
58 nr_args: u32,
59) -> io::Result<()> {
6522a427 60 backend::io_uring::syscalls::io_uring_register(fd.as_fd(), opcode, arg, nr_args)
064997fb
FG
61}
62
63/// `io_uring_enter(fd, to_submit, min_complete, flags, arg, size)`—Initiate
64/// and/or complete asynchronous I/O.
65///
66/// # Safety
67///
68/// io_uring operates on raw pointers and raw file descriptors. Users are
69/// responsible for ensuring that memory and resources are only accessed in
70/// valid ways.
71///
72/// # References
73/// - [Linux]
74///
75/// [Linux]: https://man.archlinux.org/man/io_uring_enter.2.en
76#[inline]
77pub unsafe fn io_uring_enter<Fd: AsFd>(
78 fd: Fd,
79 to_submit: u32,
80 min_complete: u32,
81 flags: IoringEnterFlags,
82 arg: *const c_void,
83 size: usize,
84) -> io::Result<u32> {
6522a427
EL
85 backend::io_uring::syscalls::io_uring_enter(
86 fd.as_fd(),
87 to_submit,
88 min_complete,
89 flags,
90 arg,
91 size,
92 )
064997fb
FG
93}
94
95bitflags::bitflags! {
96 /// `IORING_ENTER_*` flags for use with [`io_uring_enter`].
97 #[derive(Default)]
98 pub struct IoringEnterFlags: u32 {
99 /// `IORING_ENTER_GETEVENTS`
100 const GETEVENTS = sys::IORING_ENTER_GETEVENTS;
101
102 /// `IORING_ENTER_SQ_WAKEUP`
103 const SQ_WAKEUP = sys::IORING_ENTER_SQ_WAKEUP;
104
105 /// `IORING_ENTER_SQ_WAIT`
106 const SQ_WAIT = sys::IORING_ENTER_SQ_WAIT;
107
108 /// `IORING_ENTER_EXT_ARG`
109 const EXT_ARG = sys::IORING_ENTER_EXT_ARG;
110 }
111}
112
113/// `IORING_REGISTER_*` and `IORING_UNREGISTER_*` constants for use with
114/// [`io_uring_register`].
115#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
116#[repr(u8)]
117#[non_exhaustive]
118pub enum IoringRegisterOp {
119 /// `IORING_REGISTER_BUFFERS`
120 RegisterBuffers = sys::IORING_REGISTER_BUFFERS as _,
121
122 /// `IORING_UNREGISTER_BUFFERS`
123 UnregisterBuffers = sys::IORING_UNREGISTER_BUFFERS as _,
124
125 /// `IORING_REGISTER_FILES`
126 RegisterFiles = sys::IORING_REGISTER_FILES as _,
127
128 /// `IORING_UNREGISTER_FILES`
129 UnregisterFiles = sys::IORING_UNREGISTER_FILES as _,
130
131 /// `IORING_REGISTER_EVENTFD`
132 RegisterEventfd = sys::IORING_REGISTER_EVENTFD as _,
133
134 /// `IORING_UNREGISTER_EVENTFD`
135 UnregisterEventfd = sys::IORING_UNREGISTER_EVENTFD as _,
136
137 /// `IORING_REGISTER_FILES_UPDATE`
138 RegisterFilesUpdate = sys::IORING_REGISTER_FILES_UPDATE as _,
139
140 /// `IORING_REGISTER_EVENTFD_ASYNC`
141 RegisterEventfdAsync = sys::IORING_REGISTER_EVENTFD_ASYNC as _,
142
143 /// `IORING_REGISTER_PROBE`
144 RegisterProbe = sys::IORING_REGISTER_PROBE as _,
145
146 /// `IORING_REGISTER_PERSONALITY`
147 RegisterPersonality = sys::IORING_REGISTER_PERSONALITY as _,
148
149 /// `IORING_UNREGISTER_PERSONALITY`
150 UnregisterPersonality = sys::IORING_UNREGISTER_PERSONALITY as _,
151
152 /// `IORING_REGISTER_RESTRICTIONS`
153 RegisterRestrictions = sys::IORING_REGISTER_RESTRICTIONS as _,
154
155 /// `IORING_REGISTER_ENABLE_RINGS`
156 RegisterEnableRings = sys::IORING_REGISTER_ENABLE_RINGS as _,
157
158 /// `IORING_REGISTER_BUFFERS2`
159 RegisterBuffers2 = sys::IORING_REGISTER_BUFFERS2 as _,
160
161 /// `IORING_REGISTER_BUFFERS_UPDATE`
162 RegisterBuffersUpdate = sys::IORING_REGISTER_BUFFERS_UPDATE as _,
163
164 /// `IORING_REGISTER_FILES2`
165 RegisterFiles2 = sys::IORING_REGISTER_FILES2 as _,
166
167 /// `IORING_REGISTER_FILES_SKIP`
168 RegisterFilesSkip = sys::IORING_REGISTER_FILES_SKIP as _,
169
170 /// `IORING_REGISTER_FILES_UPDATE2`
171 RegisterFilesUpdate2 = sys::IORING_REGISTER_FILES_UPDATE2 as _,
172
173 /// `IORING_REGISTER_IOWQ_AFF`
174 RegisterIowqAff = sys::IORING_REGISTER_IOWQ_AFF as _,
175
176 /// `IORING_UNREGISTER_IOWQ_AFF`
177 UnregisterIowqAff = sys::IORING_UNREGISTER_IOWQ_AFF as _,
178
179 /// `IORING_REGISTER_IOWQ_MAX_WORKERS`
180 RegisterIowqMaxWorkers = sys::IORING_REGISTER_IOWQ_MAX_WORKERS as _,
181}
182
183/// `IORING_OP_*` constants for use with [`io_uring_sqe`].
184#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
185#[repr(u8)]
186#[non_exhaustive]
187pub enum IoringOp {
188 /// `IORING_OP_NOP`
189 Nop = sys::IORING_OP_NOP as _,
190
191 /// `IORING_OP_ACCEPT`
192 Accept = sys::IORING_OP_ACCEPT as _,
193
194 /// `IORING_OP_ASYNC_CANCEL`
195 AsyncCancel = sys::IORING_OP_ASYNC_CANCEL as _,
196
197 /// `IORING_OP_CLOSE`
198 Close = sys::IORING_OP_CLOSE as _,
199
200 /// `IORING_OP_CONNECT`
201 Connect = sys::IORING_OP_CONNECT as _,
202
203 /// `IORING_OP_EPOLL_CTL`
204 EpollCtl = sys::IORING_OP_EPOLL_CTL as _,
205
206 /// `IORING_OP_FADVISE`
207 Fadvise = sys::IORING_OP_FADVISE as _,
208
209 /// `IORING_OP_FALLOCATE`
210 Fallocate = sys::IORING_OP_FALLOCATE as _,
211
212 /// `IORING_OP_FILES_UPDATE`
213 FilesUpdate = sys::IORING_OP_FILES_UPDATE as _,
214
215 /// `IORING_OP_FSYNC`
216 Fsync = sys::IORING_OP_FSYNC as _,
217
218 /// `IORING_OP_LINKAT`
219 Linkat = sys::IORING_OP_LINKAT as _,
220
221 /// `IORING_OP_LINK_TIMEOUT`
222 LinkTimeout = sys::IORING_OP_LINK_TIMEOUT as _,
223
224 /// `IORING_OP_MADVISE`
225 Madvise = sys::IORING_OP_MADVISE as _,
226
227 /// `IORING_OP_MKDIRAT`
228 Mkdirat = sys::IORING_OP_MKDIRAT as _,
229
230 /// `IORING_OP_OPENAT`
231 Openat = sys::IORING_OP_OPENAT as _,
232
233 /// `IORING_OP_OPENAT2`
234 Openat2 = sys::IORING_OP_OPENAT2 as _,
235
236 /// `IORING_OP_POLL_ADD`
237 PollAdd = sys::IORING_OP_POLL_ADD as _,
238
239 /// `IORING_OP_POLL_REMOVE`
240 PollRemove = sys::IORING_OP_POLL_REMOVE as _,
241
242 /// `IORING_OP_PROVIDE_BUFFERS`
243 ProvideBuffers = sys::IORING_OP_PROVIDE_BUFFERS as _,
244
245 /// `IORING_OP_READ`
246 Read = sys::IORING_OP_READ as _,
247
248 /// `IORING_OP_READV`
249 Readv = sys::IORING_OP_READV as _,
250
251 /// `IORING_OP_READ_FIXED`
252 ReadFixed = sys::IORING_OP_READ_FIXED as _,
253
254 /// `IORING_OP_RECV`
255 Recv = sys::IORING_OP_RECV as _,
256
257 /// `IORING_OP_RECVMSG`
258 Recvmsg = sys::IORING_OP_RECVMSG as _,
259
260 /// `IORING_OP_REMOVE_BUFFERS`
261 RemoveBuffers = sys::IORING_OP_REMOVE_BUFFERS as _,
262
263 /// `IORING_OP_RENAMEAT`
264 Renameat = sys::IORING_OP_RENAMEAT as _,
265
266 /// `IORING_OP_SEND`
267 Send = sys::IORING_OP_SEND as _,
268
269 /// `IORING_OP_SENDMSG`
270 Sendmsg = sys::IORING_OP_SENDMSG as _,
271
272 /// `IORING_OP_SHUTDOWN`
273 Shutdown = sys::IORING_OP_SHUTDOWN as _,
274
275 /// `IORING_OP_SPLICE`
276 Splice = sys::IORING_OP_SPLICE as _,
277
278 /// `IORING_OP_STATX`
279 Statx = sys::IORING_OP_STATX as _,
280
281 /// `IORING_OP_SYMLINKAT`
282 Symlinkat = sys::IORING_OP_SYMLINKAT as _,
283
284 /// `IORING_OP_SYNC_FILE_RANGE`
285 SyncFileRange = sys::IORING_OP_SYNC_FILE_RANGE as _,
286
287 /// `IORING_OP_TEE`
288 Tee = sys::IORING_OP_TEE as _,
289
290 /// `IORING_OP_TIMEOUT`
291 Timeout = sys::IORING_OP_TIMEOUT as _,
292
293 /// `IORING_OP_TIMEOUT_REMOVE`
294 TimeoutRemove = sys::IORING_OP_TIMEOUT_REMOVE as _,
295
296 /// `IORING_OP_UNLINKAT`
297 Unlinkat = sys::IORING_OP_UNLINKAT as _,
298
299 /// `IORING_OP_WRITE`
300 Write = sys::IORING_OP_WRITE as _,
301
302 /// `IORING_OP_WRITEV`
303 Writev = sys::IORING_OP_WRITEV as _,
304
305 /// `IORING_OP_WRITE_FIXED`
306 WriteFixed = sys::IORING_OP_WRITE_FIXED as _,
307}
308
309impl Default for IoringOp {
310 #[inline]
311 fn default() -> Self {
312 Self::Nop
313 }
314}
315
316/// `IORING_RESTRICTION_*` constants for use with [`io_uring_restriction`].
317#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
318#[repr(u16)]
319#[non_exhaustive]
320pub enum IoringRestrictionOp {
321 /// `IORING_RESTRICTION_REGISTER_OP`
322 RegisterOp = sys::IORING_RESTRICTION_REGISTER_OP as _,
323
324 /// `IORING_RESTRICTION_SQE_FLAGS_ALLOWED`
325 SqeFlagsAllowed = sys::IORING_RESTRICTION_SQE_FLAGS_ALLOWED as _,
326
327 /// `IORING_RESTRICTION_SQE_FLAGS_REQUIRED`
328 SqeFlagsRequired = sys::IORING_RESTRICTION_SQE_FLAGS_REQUIRED as _,
329
330 /// `IORING_RESTRICTION_SQE_OP`
331 SqeOp = sys::IORING_RESTRICTION_SQE_OP as _,
332}
333
334impl Default for IoringRestrictionOp {
335 #[inline]
336 fn default() -> Self {
337 Self::RegisterOp
338 }
339}
340
341bitflags::bitflags! {
342 /// `IORING_SETUP_*` flags for use with [`io_uring_params`].
343 #[derive(Default)]
344 pub struct IoringSetupFlags: u32 {
345 /// `IORING_SETUP_ATTACH_WQ`
346 const ATTACH_WQ = sys::IORING_SETUP_ATTACH_WQ;
347
348 /// `IORING_SETUP_CLAMP`
349 const CLAMP = sys::IORING_SETUP_CLAMP;
350
351 /// `IORING_SETUP_CQSIZE`
352 const CQSIZE = sys::IORING_SETUP_CQSIZE;
353
354 /// `IORING_SETUP_IOPOLL`
355 const IOPOLL = sys::IORING_SETUP_IOPOLL;
356
357 /// `IORING_SETUP_R_DISABLED`
358 const R_DISABLED = sys::IORING_SETUP_R_DISABLED;
359
360 /// `IORING_SETUP_SQPOLL`
361 const SQPOLL = sys::IORING_SETUP_SQPOLL;
362
363 /// `IORING_SETUP_SQ_AFF`
364 const SQ_AFF = sys::IORING_SETUP_SQ_AFF;
365 }
366}
367
368bitflags::bitflags! {
369 /// `IOSQE_*` flags for use with [`io_uring_sqe`].
370 #[derive(Default)]
371 pub struct IoringSqeFlags: u8 {
372 /// `1 << IOSQE_ASYNC_BIT`
373 const ASYNC = 1 << sys::IOSQE_ASYNC_BIT as u8;
374
375 /// `1 << IOSQE_BUFFER_SELECT_BIT`
376 const BUFFER_SELECT = 1 << sys::IOSQE_BUFFER_SELECT_BIT as u8;
377
378 /// `1 << IOSQE_FIXED_FILE_BIT`
379 const FIXED_FILE = 1 << sys::IOSQE_FIXED_FILE_BIT as u8;
380
381 /// 1 << `IOSQE_IO_DRAIN_BIT`
382 const IO_DRAIN = 1 << sys::IOSQE_IO_DRAIN_BIT as u8;
383
384 /// `1 << IOSQE_IO_HARDLINK_BIT`
385 const IO_HARDLINK = 1 << sys::IOSQE_IO_HARDLINK_BIT as u8;
386
387 /// `1 << IOSQE_IO_LINK_BIT`
388 const IO_LINK = 1 << sys::IOSQE_IO_LINK_BIT as u8;
389 }
390}
391
392bitflags::bitflags! {
393 /// `IORING_CQE_F_*` flags for use with [`io_uring_cqe`].
394 #[derive(Default)]
395 pub struct IoringCqeFlags: u32 {
396 /// `IORING_CQE_F_BUFFER`
397 const BUFFER = sys::IORING_CQE_F_BUFFER as _;
398
399 /// `IORING_CQE_F_MORE`
400 const MORE = sys::IORING_CQE_F_MORE as _;
401 }
402}
403
404bitflags::bitflags! {
405 /// `IORING_FSYNC_*` flags for use with [`io_uring_sqe`].
406 #[derive(Default)]
407 pub struct IoringFsyncFlags: u32 {
408 /// `IORING_FSYNC_DATASYNC`
409 const DATASYNC = sys::IORING_FSYNC_DATASYNC;
410 }
411}
412
413bitflags::bitflags! {
414 /// `IORING_TIMEOUT_*` and `IORING_LINK_TIMEOUT_UPDATE` flags for use with
415 /// [`io_uring_sqe`].
416 #[derive(Default)]
417 pub struct IoringTimeoutFlags: u32 {
418 /// `IORING_TIMEOUT_ABS`
419 const ABS = sys::IORING_TIMEOUT_ABS;
420
421 /// `IORING_TIMEOUT_UPDATE`
422 const UPDATE = sys::IORING_TIMEOUT_UPDATE;
423
424 /// `IORING_TIMEOUT_BOOTTIME`
425 const BOOTTIME = sys::IORING_TIMEOUT_BOOTTIME;
426
427 /// `IORING_TIMEOUT_ETIME_SUCCESS`
428 const ETIME_SUCCESS = sys::IORING_TIMEOUT_ETIME_SUCCESS;
429
430 /// `IORING_TIMEOUT_REALTIME`
431 const REALTIME = sys::IORING_TIMEOUT_REALTIME;
432
433 /// `IORING_TIMEOUT_CLOCK_MASK`
434 const CLOCK_MASK = sys::IORING_TIMEOUT_CLOCK_MASK;
435
436 /// `IORING_TIMEOUT_UPDATE_MASK`
437 const UPDATE_MASK = sys::IORING_TIMEOUT_UPDATE_MASK;
438
439 /// `IORING_LINK_TIMEOUT_UPDATE`
440 const LINK_TIMEOUT_UPDATE = sys::IORING_LINK_TIMEOUT_UPDATE;
441 }
442}
443
444bitflags::bitflags! {
445 /// `SPLICE_F_*` flags for use with [`io_uring_sqe`].
446 #[derive(Default)]
447 pub struct SpliceFlags: u32 {
448 /// `SPLICE_F_FD_IN_FIXED`
449 const FD_IN_FIXED = sys::SPLICE_F_FD_IN_FIXED;
450 }
451}
452
453bitflags::bitflags! {
454 /// `IORING_FEAT_*` flags for use with [`io_uring_params`].
455 #[derive(Default)]
456 pub struct IoringFeatureFlags: u32 {
457 /// `IORING_FEAT_CQE_SKIP`
458 const CQE_SKIP = sys::IORING_FEAT_CQE_SKIP;
459
460 /// `IORING_FEAT_CUR_PERSONALITY`
461 const CUR_PERSONALITY = sys::IORING_FEAT_CUR_PERSONALITY;
462
463 /// `IORING_FEAT_EXT_ARG`
464 const EXT_ARG = sys::IORING_FEAT_EXT_ARG;
465
466 /// `IORING_FEAT_FAST_POLL`
467 const FAST_POLL = sys::IORING_FEAT_FAST_POLL;
468
469 /// `IORING_FEAT_NATIVE_WORKERS`
470 const NATIVE_WORKERS = sys::IORING_FEAT_NATIVE_WORKERS;
471
472 /// `IORING_FEAT_NODROP`
473 const NODROP = sys::IORING_FEAT_NODROP;
474
475 /// `IORING_FEAT_POLL_32BITS`
476 const POLL_32BITS = sys::IORING_FEAT_POLL_32BITS;
477
478 /// `IORING_FEAT_RSRC_TAGS`
479 const RSRC_TAGS = sys::IORING_FEAT_RSRC_TAGS;
480
481 /// `IORING_FEAT_RW_CUR_POS`
482 const RW_CUR_POS = sys::IORING_FEAT_RW_CUR_POS;
483
484 /// `IORING_FEAT_SINGLE_MMAP`
485 const SINGLE_MMAP = sys::IORING_FEAT_SINGLE_MMAP;
486
487 /// `IORING_FEAT_SQPOLL_NONFIXED`
488 const SQPOLL_NONFIXED = sys::IORING_FEAT_SQPOLL_NONFIXED;
489
490 /// `IORING_FEAT_SUBMIT_STABLE`
491 const SUBMIT_STABLE = sys::IORING_FEAT_SUBMIT_STABLE;
492 }
493}
494
495bitflags::bitflags! {
496 /// `IO_URING_OP_*` flags for use with [`io_uring_probe_op`].
497 #[derive(Default)]
498 pub struct IoringOpFlags: u16 {
499 /// `IO_URING_OP_SUPPORTED`
500 const SUPPORTED = sys::IO_URING_OP_SUPPORTED as _;
501 }
502}
503
504bitflags::bitflags! {
505 /// `IORING_SQ_*` flags.
506 #[derive(Default)]
507 pub struct IoringSqFlags: u32 {
508 /// `IORING_SQ_NEED_WAKEUP`
509 const NEED_WAKEUP = sys::IORING_SQ_NEED_WAKEUP;
510
511 /// `IORING_SQ_CQ_OVERFLOW`
512 const CQ_OVERFLOW = sys::IORING_SQ_CQ_OVERFLOW;
513 }
514}
515
516bitflags::bitflags! {
517 /// `IORING_CQ_*` flags.
518 #[derive(Default)]
519 pub struct IoringCqFlags: u32 {
520 /// `IORING_CQ_EVENTFD_DISABLED`
521 const EVENTFD_DISABLED = sys::IORING_CQ_EVENTFD_DISABLED;
522 }
523}
524
525bitflags::bitflags! {
526 /// `IORING_POLL_*` flags.
527 #[derive(Default)]
528 pub struct IoringPollFlags: u32 {
529 /// `IORING_POLL_ADD_MULTI`
530 const ADD_MULTI = sys::IORING_POLL_ADD_MULTI;
531
532 /// `IORING_POLL_UPDATE_EVENTS`
533 const UPDATE_EVENTS = sys::IORING_POLL_UPDATE_EVENTS;
534
535 /// `IORING_POLL_UPDATE_USER_DATA`
536 const UPDATE_USER_DATA = sys::IORING_POLL_UPDATE_USER_DATA;
537 }
538}
539
540#[allow(missing_docs)]
541pub const IORING_CQE_BUFFER_SHIFT: u32 = sys::IORING_CQE_BUFFER_SHIFT as _;
542
543// Re-export these as `u64`, which is the `offset` type in `rustix::io::mmap`.
544#[allow(missing_docs)]
545pub const IORING_OFF_SQ_RING: u64 = sys::IORING_OFF_SQ_RING as _;
546#[allow(missing_docs)]
547pub const IORING_OFF_CQ_RING: u64 = sys::IORING_OFF_CQ_RING as _;
548#[allow(missing_docs)]
549pub const IORING_OFF_SQES: u64 = sys::IORING_OFF_SQES as _;
550
551/// `IORING_REGISTER_FILES_SKIP`
552#[inline]
553#[doc(alias = "IORING_REGISTER_FILES_SKIP")]
064997fb
FG
554pub const fn io_uring_register_files_skip() -> BorrowedFd<'static> {
555 let files_skip = sys::IORING_REGISTER_FILES_SKIP as RawFd;
556
557 // Safety: `IORING_REGISTER_FILES_SKIP` is a reserved value that is never
558 // dynamically allocated, so it'll remain valid for the duration of
559 // `'static`.
560 unsafe { BorrowedFd::<'static>::borrow_raw(files_skip) }
561}
562
563/// A pointer in the io_uring API.
564///
565/// `io_uring`'s native API represents pointers as `u64` values. In order to
566/// preserve strict-provenance, use a `*mut c_void`. On platforms where
567/// pointers are narrower than 64 bits, this requires additional padding.
568#[repr(C)]
569#[derive(Copy, Clone)]
570pub struct io_uring_ptr {
571 #[cfg(all(target_pointer_width = "32", target_endian = "big"))]
572 #[doc(hidden)]
573 pub __pad32: u32,
574 #[cfg(all(target_pointer_width = "16", target_endian = "big"))]
575 #[doc(hidden)]
576 pub __pad16: u16,
577
578 /// The pointer value.
579 pub ptr: *mut c_void,
580
581 #[cfg(all(target_pointer_width = "16", target_endian = "little"))]
582 #[doc(hidden)]
583 pub __pad16: u16,
584 #[cfg(all(target_pointer_width = "32", target_endian = "little"))]
585 #[doc(hidden)]
586 pub __pad32: u32,
587}
588
589impl From<*mut c_void> for io_uring_ptr {
590 #[inline]
591 fn from(ptr: *mut c_void) -> Self {
592 Self {
593 ptr,
594
595 #[cfg(target_pointer_width = "16")]
596 __pad16: Default::default(),
597 #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
598 __pad32: Default::default(),
599 }
600 }
601}
602
603impl Default for io_uring_ptr {
604 #[inline]
605 fn default() -> Self {
606 Self::from(null_mut())
607 }
608}
609
610/// User data in the io_uring API.
611///
612/// `io_uring`'s native API represents `user_data` fields as `u64` values. In
613/// order to preserve strict-provenance, use a union which allows users to
614/// optionally store pointers.
615#[repr(C)]
616#[derive(Copy, Clone)]
617pub union io_uring_user_data {
618 /// An arbitrary `u64`.
619 pub u64_: u64,
620
621 /// A pointer.
622 pub ptr: io_uring_ptr,
623}
624
625impl io_uring_user_data {
626 /// Return the `u64` value.
627 #[inline]
628 pub fn u64_(self) -> u64 {
629 // Safety: All the fields have the same underlying representation.
630 unsafe { self.u64_ }
631 }
632
633 /// Create a `Self` from a `u64` value.
634 #[inline]
635 pub fn from_u64(u64_: u64) -> Self {
636 Self { u64_ }
637 }
638
639 /// Return the `ptr` pointer value.
640 #[inline]
641 pub fn ptr(self) -> *mut c_void {
642 // Safety: All the fields have the same underlying representation.
643 unsafe { self.ptr }.ptr
644 }
645
646 /// Create a `Self` from a pointer value.
647 #[inline]
648 pub fn from_ptr(ptr: *mut c_void) -> Self {
649 Self {
650 ptr: io_uring_ptr::from(ptr),
651 }
652 }
653}
654
655impl Default for io_uring_user_data {
656 #[inline]
657 fn default() -> Self {
658 let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
659 // Safety: All of Linux's io_uring structs may be zero-initialized.
660 unsafe {
661 ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
662 s.assume_init()
663 }
664 }
665}
666
667impl core::fmt::Debug for io_uring_user_data {
668 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
669 // Safety: Just format as a `u64`, since formatting doesn't preserve
670 // provenance, and we don't have a discriminant.
671 unsafe { self.u64_.fmt(fmt) }
672 }
673}
674
675/// An io_uring Submission Queue Entry.
676#[allow(missing_docs)]
677#[repr(C)]
678#[derive(Copy, Clone, Default)]
679pub struct io_uring_sqe {
680 pub opcode: IoringOp,
681 pub flags: IoringSqeFlags,
682 pub ioprio: u16,
683 pub fd: RawFd,
684 pub off_or_addr2: off_or_addr2_union,
685 pub addr_or_splice_off_in: addr_or_splice_off_in_union,
686 pub len: u32,
687 pub op_flags: op_flags_union,
688 pub user_data: io_uring_user_data,
689 pub buf: buf_union,
690 pub personality: u16,
691 pub splice_fd_in_or_file_index: splice_fd_in_or_file_index_union,
692 pub __pad2: [u64; 2],
693}
694
695#[allow(missing_docs)]
696#[repr(C)]
697#[derive(Copy, Clone)]
698pub union off_or_addr2_union {
699 pub off: u64,
700 pub addr2: io_uring_ptr,
701}
702
703#[allow(missing_docs)]
704#[repr(C)]
705#[derive(Copy, Clone)]
706pub union addr_or_splice_off_in_union {
707 pub addr: io_uring_ptr,
708 pub splice_off_in: u64,
709}
710
711#[allow(missing_docs)]
712#[repr(C)]
713#[derive(Copy, Clone)]
714pub union op_flags_union {
715 pub rw_flags: crate::io::ReadWriteFlags,
716 pub fsync_flags: IoringFsyncFlags,
717 pub poll_events: u16,
718 pub poll32_events: u32,
719 pub sync_range_flags: u32,
720 /// `msg_flags` is split into `send_flags` and `recv_flags`.
721 #[doc(alias = "msg_flags")]
722 pub send_flags: crate::net::SendFlags,
723 /// `msg_flags` is split into `send_flags` and `recv_flags`.
724 #[doc(alias = "msg_flags")]
725 pub recv_flags: crate::net::RecvFlags,
726 pub timeout_flags: IoringTimeoutFlags,
727 pub accept_flags: crate::net::AcceptFlags,
728 pub cancel_flags: u32,
729 pub open_flags: crate::fs::AtFlags,
730 pub statx_flags: crate::fs::AtFlags,
731 pub fadvise_advice: crate::fs::Advice,
732 pub splice_flags: SpliceFlags,
733 pub rename_flags: crate::fs::RenameFlags,
734 pub unlink_flags: crate::fs::AtFlags,
735 pub hardlink_flags: crate::fs::AtFlags,
736}
737
738#[allow(missing_docs)]
739#[repr(C, packed)]
740#[derive(Copy, Clone)]
741pub union buf_union {
742 pub buf_index: u16,
743 pub buf_group: u16,
744}
745
746#[allow(missing_docs)]
747#[repr(C)]
748#[derive(Copy, Clone)]
749pub union splice_fd_in_or_file_index_union {
750 pub splice_fd_in: i32,
751 pub file_index: u32,
752}
753
754/// An io_uring Completion Queue Entry.
755#[allow(missing_docs)]
756#[repr(C)]
757#[derive(Debug, Copy, Clone, Default)]
758pub struct io_uring_cqe {
759 pub user_data: io_uring_user_data,
760 pub res: i32,
761 pub flags: IoringCqeFlags,
762}
763
764#[allow(missing_docs)]
765#[repr(C)]
766#[derive(Copy, Clone, Default)]
767pub struct io_uring_restriction {
768 pub opcode: IoringRestrictionOp,
769 pub register_or_sqe_op_or_sqe_flags: register_or_sqe_op_or_sqe_flags_union,
770 pub resv: u8,
771 pub resv2: [u32; 3],
772}
773
774#[allow(missing_docs)]
775#[repr(C)]
776#[derive(Copy, Clone)]
777pub union register_or_sqe_op_or_sqe_flags_union {
778 pub register_op: IoringRegisterOp,
779 pub sqe_op: IoringOp,
780 pub sqe_flags: IoringSqeFlags,
781}
782
783#[allow(missing_docs)]
784#[repr(C)]
785#[derive(Debug, Copy, Clone, Default)]
786pub struct io_uring_params {
787 pub sq_entries: u32,
788 pub cq_entries: u32,
789 pub flags: IoringSetupFlags,
790 pub sq_thread_cpu: u32,
791 pub sq_thread_idle: u32,
792 pub features: IoringFeatureFlags,
793 pub wq_fd: u32,
794 pub resv: [u32; 3],
795 pub sq_off: io_sqring_offsets,
796 pub cq_off: io_cqring_offsets,
797}
798
799#[allow(missing_docs)]
800#[repr(C)]
801#[derive(Debug, Copy, Clone, Default)]
802pub struct io_sqring_offsets {
803 pub head: u32,
804 pub tail: u32,
805 pub ring_mask: u32,
806 pub ring_entries: u32,
807 pub flags: u32,
808 pub dropped: u32,
809 pub array: u32,
810 pub resv1: u32,
811 pub resv2: u64,
812}
813
814#[allow(missing_docs)]
815#[repr(C)]
816#[derive(Debug, Copy, Clone, Default)]
817pub struct io_cqring_offsets {
818 pub head: u32,
819 pub tail: u32,
820 pub ring_mask: u32,
821 pub ring_entries: u32,
822 pub overflow: u32,
823 pub cqes: u32,
824 pub flags: u32,
825 pub resv1: u32,
826 pub resv2: u64,
827}
828
829#[allow(missing_docs)]
830#[repr(C)]
831#[derive(Debug, Default)]
832pub struct io_uring_probe {
833 pub last_op: IoringOp,
834 pub ops_len: u8,
835 pub resv: u16,
836 pub resv2: [u32; 3],
837 pub ops: sys::__IncompleteArrayField<io_uring_probe_op>,
838}
839
840#[allow(missing_docs)]
841#[repr(C)]
842#[derive(Debug, Copy, Clone, Default)]
843pub struct io_uring_probe_op {
844 pub op: IoringOp,
845 pub resv: u8,
846 pub flags: IoringOpFlags,
847 pub resv2: u32,
848}
849
850#[allow(missing_docs)]
851#[repr(C, align(8))]
852#[derive(Debug, Copy, Clone, Default)]
853pub struct io_uring_files_update {
854 pub offset: u32,
855 pub resv: u32,
856 pub fds: u64,
857}
858
859#[allow(missing_docs)]
860#[repr(C, align(8))]
861#[derive(Debug, Copy, Clone, Default)]
862pub struct io_uring_rsrc_register {
863 pub nr: u32,
864 pub resv: u32,
865 pub resv2: u64,
866 pub data: u64,
867 pub tags: u64,
868}
869
870#[allow(missing_docs)]
871#[repr(C, align(8))]
872#[derive(Debug, Copy, Clone, Default)]
873pub struct io_uring_rsrc_update {
874 pub offset: u32,
875 pub resv: u32,
876 pub data: u64,
877}
878
879#[allow(missing_docs)]
880#[repr(C, align(8))]
881#[derive(Debug, Copy, Clone, Default)]
882pub struct io_uring_rsrc_update2 {
883 pub offset: u32,
884 pub resv: u32,
885 pub data: u64,
886 pub tags: u64,
887 pub nr: u32,
888 pub resv2: u32,
889}
890
891#[allow(missing_docs)]
892#[repr(C)]
893#[derive(Debug, Copy, Clone, Default)]
894pub struct io_uring_getevents_arg {
895 pub sigmask: u64,
896 pub sigmask_sz: u32,
897 pub pad: u32,
898 pub ts: u64,
899}
900
901#[allow(missing_docs)]
902#[repr(C)]
903#[derive(Debug, Copy, Clone)]
904pub struct iovec {
905 pub iov_base: *mut c_void,
906 pub iov_len: usize,
907}
908
909#[allow(missing_docs)]
910#[repr(C)]
911#[derive(Debug, Copy, Clone, Default)]
912pub struct open_how {
913 /// An [`OFlags`] value represented as a `u64`.
914 ///
915 /// [`OFlags`]: crate::fs::OFlags
916 pub flags: u64,
917
918 /// A [`Mode`] value represented as a `u64`.
919 ///
920 /// [`Mode`]: crate::fs::Mode
921 pub mode: u64,
922
923 pub resolve: crate::fs::ResolveFlags,
924}
925
926impl Default for off_or_addr2_union {
927 #[inline]
928 fn default() -> Self {
929 let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
930 // Safety: All of Linux's io_uring structs may be zero-initialized.
931 unsafe {
932 ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
933 s.assume_init()
934 }
935 }
936}
937
938impl Default for addr_or_splice_off_in_union {
939 #[inline]
940 fn default() -> Self {
941 let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
942 // Safety: All of Linux's io_uring structs may be zero-initialized.
943 unsafe {
944 ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
945 s.assume_init()
946 }
947 }
948}
949
950impl Default for op_flags_union {
951 #[inline]
952 fn default() -> Self {
953 let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
954 // Safety: All of Linux's io_uring structs may be zero-initialized.
955 unsafe {
956 ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
957 s.assume_init()
958 }
959 }
960}
961
962impl Default for buf_union {
963 #[inline]
964 fn default() -> Self {
965 let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
966 // Safety: All of Linux's io_uring structs may be zero-initialized.
967 unsafe {
968 ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
969 s.assume_init()
970 }
971 }
972}
973
974impl Default for splice_fd_in_or_file_index_union {
975 #[inline]
976 fn default() -> Self {
977 let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
978 // Safety: All of Linux's io_uring structs may be zero-initialized.
979 unsafe {
980 ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
981 s.assume_init()
982 }
983 }
984}
985
986impl Default for register_or_sqe_op_or_sqe_flags_union {
987 #[inline]
988 fn default() -> Self {
989 let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
990 // Safety: All of Linux's io_uring structs may be zero-initialized.
991 unsafe {
992 ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
993 s.assume_init()
994 }
995 }
996}
997
998/// Check that our custom structs and unions have the same layout as the
999/// kernel's versions.
1000#[test]
1001fn io_uring_layouts() {
1002 use core::mem::{align_of, size_of};
1003 use memoffset::{offset_of, span_of};
1004
1005 // Check that the size and alignment of a type match the `sys` bindings.
1006 macro_rules! check_type {
1007 ($struct:ident) => {
1008 assert_eq!(
1009 (size_of::<$struct>(), align_of::<$struct>()),
1010 (size_of::<sys::$struct>(), align_of::<sys::$struct>())
1011 );
1012 };
1013 }
1014
1015 // The same as `check_type`, but for unions we've renamed to avoid having
1016 // types like "bindgen_ty_1" in the API.
1017 macro_rules! check_renamed_union {
1018 ($to:ident, $from:ident) => {
1019 assert_eq!(
1020 (size_of::<$to>(), align_of::<$to>()),
1021 (size_of::<sys::$from>(), align_of::<sys::$from>())
1022 );
1023 };
1024 }
1025
1026 // Check that the field of a struct has the same offset as the
1027 // corresponding field in the `sys` bindings.
1028 macro_rules! check_struct_field {
1029 ($struct:ident, $field:ident) => {
1030 assert_eq!(
1031 offset_of!($struct, $field),
1032 offset_of!(sys::$struct, $field)
1033 );
1034 assert_eq!(span_of!($struct, $field), span_of!(sys::$struct, $field));
1035 };
1036 }
1037
1038 // The same as `check_struct_field`, but for unions we've renamed to avoid
1039 // having types like "bindgen_ty_1" in the API.
1040 macro_rules! check_struct_renamed_union_field {
1041 ($struct:ident, $to:ident, $from:ident) => {
1042 assert_eq!(offset_of!($struct, $to), offset_of!(sys::$struct, $from));
1043 assert_eq!(span_of!($struct, $to), span_of!(sys::$struct, $from));
1044 };
1045 }
1046
1047 // For the common case of no renaming, check all fields of a struct.
1048 macro_rules! check_struct {
1049 ($name:ident, $($field:ident),*) => {
1050 // Check the size and alignment.
1051 check_type!($name);
1052
1053 // Check that we have all the fields.
1054 let _test = $name {
1055 // Safety: All of io_uring's types can be zero-initialized.
1056 $($field: unsafe { core::mem::zeroed() }),*
1057 };
1058
1059 // Check that the fields have the right sizes and offsets.
1060 $(check_struct_field!($name, $field));*
1061 };
1062 }
1063
1064 check_renamed_union!(off_or_addr2_union, io_uring_sqe__bindgen_ty_1);
1065 check_renamed_union!(addr_or_splice_off_in_union, io_uring_sqe__bindgen_ty_2);
1066 check_renamed_union!(op_flags_union, io_uring_sqe__bindgen_ty_3);
1067 check_renamed_union!(buf_union, io_uring_sqe__bindgen_ty_4);
1068 check_renamed_union!(splice_fd_in_or_file_index_union, io_uring_sqe__bindgen_ty_5);
1069 check_renamed_union!(
1070 register_or_sqe_op_or_sqe_flags_union,
1071 io_uring_restriction__bindgen_ty_1
1072 );
1073
1074 check_type!(io_uring_sqe);
1075 check_struct_field!(io_uring_sqe, opcode);
1076 check_struct_field!(io_uring_sqe, flags);
1077 check_struct_field!(io_uring_sqe, ioprio);
1078 check_struct_field!(io_uring_sqe, fd);
1079 check_struct_renamed_union_field!(io_uring_sqe, off_or_addr2, __bindgen_anon_1);
1080 check_struct_renamed_union_field!(io_uring_sqe, addr_or_splice_off_in, __bindgen_anon_2);
1081 check_struct_field!(io_uring_sqe, len);
1082 check_struct_renamed_union_field!(io_uring_sqe, op_flags, __bindgen_anon_3);
1083 check_struct_field!(io_uring_sqe, user_data);
1084 check_struct_renamed_union_field!(io_uring_sqe, buf, __bindgen_anon_4);
1085 check_struct_field!(io_uring_sqe, personality);
1086 check_struct_renamed_union_field!(io_uring_sqe, splice_fd_in_or_file_index, __bindgen_anon_5);
1087 check_struct_field!(io_uring_sqe, __pad2);
1088
1089 check_type!(io_uring_restriction);
1090 check_struct_field!(io_uring_restriction, opcode);
1091 check_struct_renamed_union_field!(
1092 io_uring_restriction,
1093 register_or_sqe_op_or_sqe_flags,
1094 __bindgen_anon_1
1095 );
1096 check_struct_field!(io_uring_restriction, resv);
1097 check_struct_field!(io_uring_restriction, resv2);
1098
1099 check_struct!(io_uring_cqe, user_data, res, flags);
1100 check_struct!(
1101 io_uring_params,
1102 sq_entries,
1103 cq_entries,
1104 flags,
1105 sq_thread_cpu,
1106 sq_thread_idle,
1107 features,
1108 wq_fd,
1109 resv,
1110 sq_off,
1111 cq_off
1112 );
1113 check_struct!(
1114 io_sqring_offsets,
1115 head,
1116 tail,
1117 ring_mask,
1118 ring_entries,
1119 flags,
1120 dropped,
1121 array,
1122 resv1,
1123 resv2
1124 );
1125 check_struct!(
1126 io_cqring_offsets,
1127 head,
1128 tail,
1129 ring_mask,
1130 ring_entries,
1131 overflow,
1132 cqes,
1133 flags,
1134 resv1,
1135 resv2
1136 );
1137 check_struct!(io_uring_probe, last_op, ops_len, resv, resv2, ops);
1138 check_struct!(io_uring_probe_op, op, resv, flags, resv2);
1139 check_struct!(io_uring_files_update, offset, resv, fds);
1140 check_struct!(io_uring_rsrc_register, nr, resv, resv2, data, tags);
1141 check_struct!(io_uring_rsrc_update, offset, resv, data);
1142 check_struct!(io_uring_rsrc_update2, offset, resv, data, tags, nr, resv2);
1143 check_struct!(io_uring_getevents_arg, sigmask, sigmask_sz, pad, ts);
1144 check_struct!(iovec, iov_base, iov_len);
1145 check_struct!(open_how, flags, mode, resolve);
1146}