Skip to main content

liburing_rs/
lib.rs

1#![no_std]
2#![allow(unsafe_op_in_unsafe_fn, non_snake_case)]
3#![warn(clippy::pedantic)]
4#![allow(clippy::missing_safety_doc,
5         clippy::cast_sign_loss,
6         clippy::similar_names,
7         clippy::cast_possible_truncation,
8         clippy::cast_possible_wrap,
9         clippy::cast_ptr_alignment,
10         clippy::used_underscore_items,
11         clippy::unnecessary_cast,
12         clippy::doc_markdown)]
13#![doc = include_str!("../README.md")]
14#![cfg_attr(docsrs, feature(doc_cfg))]
15
16#[doc(hidden)]
17mod uring;
18
19use core::{
20    ffi::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ushort, c_void},
21    mem::{self, zeroed},
22    ptr,
23    sync::atomic::{
24        AtomicU16, AtomicU32,
25        Ordering::{self, Acquire, Relaxed, Release},
26    },
27    time::Duration,
28};
29
30#[doc(hidden)]
31pub use uring::*;
32
33#[doc(hidden)]
34pub mod docs
35{
36    #[allow(unused_imports)]
37    use super::*;
38
39    #[doc = include_str!("../docs/io_uring.md")]
40    pub mod io_uring
41    {}
42
43    #[doc = include_str!("../docs/io_uring_cancelation.md")]
44    pub mod io_uring_cancelation
45    {}
46
47    #[doc = include_str!("../docs/io_uring_linked_requests.md")]
48    pub mod io_uring_linked_requests
49    {}
50
51    #[doc = include_str!("../docs/io_uring_multishot.md")]
52    pub mod io_uring_multishot
53    {}
54
55    #[doc = include_str!("../docs/io_uring_provided_buffers.md")]
56    pub mod io_uring_provided_buffers
57    {}
58
59    #[doc = include_str!("../docs/io_uring_registered_buffers.md")]
60    pub mod io_uring_registered_buffers
61    {}
62
63    #[doc = include_str!("../docs/io_uring_registered_files.md")]
64    pub mod io_uring_registered_files
65    {}
66
67    #[doc = include_str!("../docs/io_uring_setup_flags.md")]
68    pub mod io_uring_setup_flags
69    {}
70
71    #[doc = include_str!("../docs/io_uring_sqpoll.md")]
72    pub mod io_uring_sqpoll
73    {}
74}
75
76pub use docs::io_uring as io_uring_overview;
77pub use docs::io_uring_cancelation;
78pub use docs::io_uring_linked_requests;
79pub use docs::io_uring_multishot;
80pub use docs::io_uring_provided_buffers;
81pub use docs::io_uring_registered_buffers;
82pub use docs::io_uring_registered_files;
83pub use docs::io_uring_setup_flags;
84pub use docs::io_uring_sqpoll;
85
86pub use uring::{io_uring, io_uring_cq, io_uring_cqe, io_uring_sq, io_uring_sqe};
87
88#[doc = include_str!("../docs/io_uring_enter.md")]
89pub use uring::io_uring_enter;
90
91#[doc = include_str!("../docs/io_uring_enter.md")]
92pub use uring::io_uring_enter2;
93
94#[doc = include_str!("../docs/io_uring_setup.md")]
95pub use uring::io_uring_setup;
96
97#[doc = include_str!("../docs/io_uring_register.md")]
98pub use uring::io_uring_register;
99
100#[doc = include_str!("../docs/io_uring_submit_and_wait.md")]
101pub use uring::io_uring_submit_and_wait;
102
103#[doc = include_str!("../docs/io_uring_check_version.md")]
104pub use uring::io_uring_check_version;
105
106#[doc = include_str!("../docs/io_uring_check_version.md")]
107pub use uring::io_uring_major_version;
108
109#[doc = include_str!("../docs/io_uring_check_version.md")]
110pub use uring::io_uring_minor_version;
111
112#[doc = include_str!("../docs/io_uring_clone_buffers.md")]
113pub use uring::io_uring_clone_buffers;
114
115#[doc = include_str!("../docs/io_uring_clone_buffers_offset.md")]
116pub use uring::io_uring_clone_buffers_offset;
117
118#[doc = include_str!("../docs/io_uring_clone_buffers.md")]
119pub use uring::__io_uring_clone_buffers;
120
121#[doc = include_str!("../docs/io_uring_clone_buffers_offset.md")]
122pub use uring::__io_uring_clone_buffers_offset;
123
124#[doc = include_str!("../docs/io_uring_close_ring_fd.md")]
125pub use uring::io_uring_close_ring_fd;
126
127#[doc = include_str!("../docs/io_uring_enable_rings.md")]
128pub use uring::io_uring_enable_rings;
129
130#[doc = include_str!("../docs/io_uring_free_buf_ring.md")]
131pub use uring::io_uring_free_buf_ring;
132
133#[doc = include_str!("../docs/io_uring_free_probe.md")]
134pub use uring::io_uring_free_probe;
135
136#[doc = include_str!("../docs/io_uring_get_events.md")]
137pub use uring::io_uring_get_events;
138
139#[doc = include_str!("../docs/io_uring_get_probe.md")]
140pub use uring::io_uring_get_probe;
141
142#[doc = include_str!("../docs/io_uring_get_probe_ring.md")]
143pub use uring::io_uring_get_probe_ring;
144
145#[doc = include_str!("../docs/io_uring_peek_batch_cqe.md")]
146pub use uring::io_uring_peek_batch_cqe;
147
148#[doc = include_str!("../docs/io_uring_queue_exit.md")]
149pub use uring::io_uring_queue_exit;
150
151#[doc = include_str!("../docs/io_uring_queue_init.md")]
152pub use uring::io_uring_queue_init;
153
154#[doc = include_str!("../docs/io_uring_queue_init_mem.md")]
155pub use uring::io_uring_queue_init_mem;
156
157#[doc = include_str!("../docs/io_uring_queue_init_params.md")]
158pub use uring::io_uring_queue_init_params;
159
160#[doc = include_str!("../docs/io_uring_queue_mmap.md")]
161pub use uring::io_uring_queue_mmap;
162
163#[doc = include_str!("../docs/io_uring_register_bpf_filter.md")]
164pub use uring::io_uring_register_bpf_filter;
165
166#[doc = include_str!("../docs/io_uring_register_bpf_filter_task.md")]
167pub use uring::io_uring_register_bpf_filter_task;
168
169#[doc = include_str!("../docs/io_uring_register_buf_ring.md")]
170pub use uring::io_uring_register_buf_ring;
171
172#[doc = include_str!("../docs/io_uring_register_buffers.md")]
173pub use uring::io_uring_register_buffers;
174
175#[doc = include_str!("../docs/io_uring_register_buffers_sparse.md")]
176pub use uring::io_uring_register_buffers_sparse;
177
178#[doc = include_str!("../docs/io_uring_register_buffers_tags.md")]
179pub use uring::io_uring_register_buffers_tags;
180
181#[doc = include_str!("../docs/io_uring_register_buffers_update_tag.md")]
182pub use uring::io_uring_register_buffers_update_tag;
183
184#[doc = include_str!("../docs/io_uring_register_clock.md")]
185pub use uring::io_uring_register_clock;
186
187#[doc = include_str!("../docs/io_uring_register_eventfd.md")]
188pub use uring::io_uring_register_eventfd;
189
190#[doc = include_str!("../docs/io_uring_register_eventfd_async.md")]
191pub use uring::io_uring_register_eventfd_async;
192
193#[doc = include_str!("../docs/io_uring_register_file_alloc_range.md")]
194pub use uring::io_uring_register_file_alloc_range;
195
196#[doc = include_str!("../docs/io_uring_register_files.md")]
197pub use uring::io_uring_register_files;
198
199#[doc = include_str!("../docs/io_uring_register_files_sparse.md")]
200pub use uring::io_uring_register_files_sparse;
201
202#[doc = include_str!("../docs/io_uring_register_files_tags.md")]
203pub use uring::io_uring_register_files_tags;
204
205#[doc = include_str!("../docs/io_uring_register_files_update.md")]
206pub use uring::io_uring_register_files_update;
207
208#[doc = include_str!("../docs/io_uring_register_files_update_tag.md")]
209pub use uring::io_uring_register_files_update_tag;
210
211#[doc = include_str!("../docs/io_uring_register_ifq.md")]
212pub use uring::io_uring_register_ifq;
213
214#[doc = include_str!("../docs/io_uring_register_iowq_max_workers.md")]
215pub use uring::io_uring_register_iowq_max_workers;
216
217#[doc = include_str!("../docs/io_uring_register_napi.md")]
218pub use uring::io_uring_register_napi;
219
220#[doc = include_str!("../docs/io_uring_register_personality.md")]
221pub use uring::io_uring_register_personality;
222
223#[doc = include_str!("../docs/io_uring_register_probe.md")]
224pub use uring::io_uring_register_probe;
225
226#[doc = include_str!("../docs/io_uring_register_query.md")]
227pub use uring::io_uring_register_query;
228
229#[doc = include_str!("../docs/io_uring_register_region.md")]
230pub use uring::io_uring_register_region;
231
232#[doc = include_str!("../docs/io_uring_register_restrictions.md")]
233pub use uring::io_uring_register_restrictions;
234
235#[doc = include_str!("../docs/io_uring_register_ring_fd.md")]
236pub use uring::io_uring_register_ring_fd;
237
238#[doc = include_str!("../docs/io_uring_register_sync_cancel.md")]
239pub use uring::io_uring_register_sync_cancel;
240
241#[doc = include_str!("../docs/io_uring_register_sync_msg.md")]
242pub use uring::io_uring_register_sync_msg;
243
244#[doc = include_str!("../docs/io_uring_register_wait_reg.md")]
245pub use uring::io_uring_register_wait_reg;
246
247#[doc = include_str!("../docs/io_uring_register_zcrx_ctrl.md")]
248pub use uring::io_uring_register_zcrx_ctrl;
249
250#[doc = include_str!("../docs/io_uring_resize_rings.md")]
251pub use uring::io_uring_resize_rings;
252
253#[doc = include_str!("../docs/io_uring_ring_dontfork.md")]
254pub use uring::io_uring_ring_dontfork;
255
256#[doc = include_str!("../docs/io_uring_setup_buf_ring.md")]
257pub use uring::io_uring_setup_buf_ring;
258
259#[doc = include_str!("../docs/io_uring_submit.md")]
260pub use uring::io_uring_submit;
261
262#[doc = include_str!("../docs/io_uring_submit_and_get_events.md")]
263pub use uring::io_uring_submit_and_get_events;
264
265#[doc = include_str!("../docs/io_uring_submit_and_wait_min_timeout.md")]
266pub use uring::io_uring_submit_and_wait_min_timeout;
267
268#[doc = include_str!("../docs/io_uring_submit_and_wait_reg.md")]
269pub use uring::io_uring_submit_and_wait_reg;
270
271#[doc = include_str!("../docs/io_uring_submit_and_wait_timeout.md")]
272pub use uring::io_uring_submit_and_wait_timeout;
273
274#[doc = include_str!("../docs/io_uring_unregister_buf_ring.md")]
275pub use uring::io_uring_unregister_buf_ring;
276
277#[doc = include_str!("../docs/io_uring_unregister_buffers.md")]
278pub use uring::io_uring_unregister_buffers;
279
280#[doc = include_str!("../docs/io_uring_unregister_eventfd.md")]
281pub use uring::io_uring_unregister_eventfd;
282
283#[doc = include_str!("../docs/io_uring_unregister_files.md")]
284pub use uring::io_uring_unregister_files;
285
286#[doc = include_str!("../docs/io_uring_unregister_iowq_aff.md")]
287pub use uring::io_uring_unregister_iowq_aff;
288
289#[doc = include_str!("../docs/io_uring_unregister_napi.md")]
290pub use uring::io_uring_unregister_napi;
291
292#[doc = include_str!("../docs/io_uring_unregister_personality.md")]
293pub use uring::io_uring_unregister_personality;
294
295#[doc = include_str!("../docs/io_uring_unregister_ring_fd.md")]
296pub use uring::io_uring_unregister_ring_fd;
297
298#[doc = include_str!("../docs/io_uring_wait_cqe_timeout.md")]
299pub use uring::io_uring_wait_cqe_timeout;
300
301#[doc = include_str!("../docs/io_uring_wait_cqes.md")]
302pub use uring::io_uring_wait_cqes;
303
304#[doc = include_str!("../docs/io_uring_wait_cqes_min_timeout.md")]
305pub use uring::io_uring_wait_cqes_min_timeout;
306
307#[cfg(feature = "gnu")]
308#[cfg_attr(docsrs, doc(cfg(feature = "gnu")))]
309unsafe extern "C" {
310    #[doc = include_str!("../docs/io_uring_register_iowq_aff.md")]
311    pub unsafe fn io_uring_register_iowq_aff(ring: *mut io_uring, cpusz: usize,
312                                             mask: *const cpu_set_t);
313}
314
315pub const IOSQE_FIXED_FILE: u32 = 1 << IOSQE_FIXED_FILE_BIT;
316pub const IOSQE_IO_DRAIN: u32 = 1 << IOSQE_IO_DRAIN_BIT;
317pub const IOSQE_IO_LINK: u32 = 1 << IOSQE_IO_LINK_BIT;
318pub const IOSQE_IO_HARDLINK: u32 = 1 << IOSQE_IO_HARDLINK_BIT;
319pub const IOSQE_ASYNC: u32 = 1 << IOSQE_ASYNC_BIT;
320pub const IOSQE_BUFFER_SELECT: u32 = 1 << IOSQE_BUFFER_SELECT_BIT;
321pub const IOSQE_CQE_SKIP_SUCCESS: u32 = 1 << IOSQE_CQE_SKIP_SUCCESS_BIT;
322
323const LIBURING_UDATA_TIMEOUT: u64 = u64::MAX;
324
325trait Atomic: Copy
326{
327    unsafe fn store(p: *mut Self, val: Self, order: Ordering);
328    unsafe fn load(p: *mut Self, order: Ordering) -> Self;
329}
330
331impl Atomic for u32
332{
333    #[inline]
334    unsafe fn store(p: *mut u32, val: u32, order: Ordering)
335    {
336        AtomicU32::from_ptr(p).store(val, order);
337    }
338
339    #[inline]
340    unsafe fn load(p: *mut u32, order: Ordering) -> u32
341    {
342        AtomicU32::from_ptr(p).load(order)
343    }
344}
345
346impl Atomic for u16
347{
348    #[inline]
349    unsafe fn store(p: *mut u16, val: u16, order: Ordering)
350    {
351        AtomicU16::from_ptr(p).store(val, order);
352    }
353
354    #[inline]
355    unsafe fn load(p: *mut u16, order: Ordering) -> u16
356    {
357        AtomicU16::from_ptr(p).load(order)
358    }
359}
360
361unsafe fn io_uring_smp_store_release<T: Atomic>(p: *mut T, v: T)
362{
363    Atomic::store(p, v, Release);
364}
365
366unsafe fn io_uring_smp_load_acquire<T: Atomic>(p: *const T) -> T
367{
368    Atomic::load(p.cast_mut(), Acquire)
369}
370
371unsafe fn IO_URING_READ_ONCE<T: Atomic>(var: *const T) -> T
372{
373    Atomic::load(var.cast_mut(), Relaxed)
374}
375
376unsafe fn IO_URING_WRITE_ONCE<T: Atomic>(var: *mut T, val: T)
377{
378    Atomic::store(var, val, Relaxed);
379}
380
381/*
382 * Library interface
383 */
384
385#[must_use]
386#[inline]
387unsafe fn uring_ptr_to_u64(ptr: *const c_void) -> u64
388{
389    ptr as u64
390}
391
392#[doc = include_str!("../docs/io_uring_opcode_supported.md")]
393#[inline]
394pub unsafe fn io_uring_opcode_supported(p: *mut io_uring_probe, op: c_int) -> c_int
395{
396    if op < 0 || op > (*p).last_op.into() {
397        return 0;
398    }
399
400    i32::from((*(*p).ops.as_ptr().add(op as _)).flags & IO_URING_OP_SUPPORTED as u16 != 0)
401}
402
403/*
404 * Returns the bit shift needed to index the CQ.
405 * This shift is 1 for rings with big CQEs, and 0 for rings with normal CQEs.
406 * CQE `index` can be computed as &cq.cqes[(index & cq.ring_mask) << cqe_shift].
407 */
408#[doc(hidden)]
409#[must_use]
410#[inline]
411pub fn io_uring_cqe_shift_from_flags(flags: c_uint) -> c_uint
412{
413    u32::from(flags & IORING_SETUP_CQE32 != 0)
414}
415
416#[doc(hidden)]
417#[must_use]
418#[inline]
419pub unsafe fn io_uring_cqe_shift(ring: *const io_uring) -> c_uint
420{
421    io_uring_cqe_shift_from_flags((*ring).flags)
422}
423
424#[doc = include_str!("../docs/io_uring_cqe_nr.md")]
425#[must_use]
426#[inline]
427pub unsafe fn io_uring_cqe_nr(cqe: *const io_uring_cqe) -> c_uint
428{
429    let shift = i32::from((*cqe).flags & IORING_CQE_F_32 != 0);
430    1 << shift
431}
432
433#[doc(hidden)]
434#[must_use]
435#[inline]
436pub unsafe fn io_uring_cqe_iter_init(ring: *const io_uring) -> io_uring_cqe_iter
437{
438    io_uring_cqe_iter { cqes: (*ring).cq.cqes,
439                        mask: (*ring).cq.ring_mask,
440                        shift: io_uring_cqe_shift(ring),
441                        head: *(*ring).cq.khead,
442                        /* Acquire ordering ensures tail is loaded before any CQEs */
443                        tail: io_uring_smp_load_acquire((*ring).cq.ktail) }
444}
445
446#[doc(hidden)]
447#[inline]
448pub unsafe fn io_uring_cqe_iter_next(iter: *mut io_uring_cqe_iter, cqe: *mut *mut io_uring_cqe)
449                                     -> bool
450{
451    if (*iter).head == (*iter).tail {
452        return false;
453    }
454
455    let head = (*iter).head;
456    (*iter).head += 1;
457
458    let offset = (head & (*iter).mask) << (*iter).shift;
459    *cqe = (*iter).cqes.add(offset as usize);
460
461    if (*(*cqe)).flags & IORING_CQE_F_32 > 0 {
462        (*iter).head += 1;
463    }
464
465    true
466}
467
468#[doc = include_str!("../docs/io_uring_for_each_cqe.md")]
469pub unsafe fn io_uring_for_each_cqe<F>(ring: *mut io_uring, mut f: F)
470    where F: FnMut(*mut io_uring_cqe)
471{
472    let mut iter = io_uring_cqe_iter_init(ring);
473    let mut cqe = ptr::null_mut::<io_uring_cqe>();
474    while io_uring_cqe_iter_next(&raw mut iter, &raw mut cqe) {
475        f(cqe);
476    }
477}
478
479/*
480 * Must be called after io_uring_for_each_cqe()
481 */
482#[doc = include_str!("../docs/io_uring_cq_advance.md")]
483#[inline]
484pub unsafe fn io_uring_cq_advance(ring: *mut io_uring, nr: c_uint)
485{
486    if nr > 0 {
487        let cq = &raw mut (*ring).cq;
488
489        /*
490         * Ensure that the kernel only sees the new value of the head
491         * index after the CQEs have been read.
492         */
493        io_uring_smp_store_release((*cq).khead, *(*cq).khead + nr);
494    }
495}
496
497/*
498 * Must be called after io_uring_{peek,wait}_cqe() after the cqe has
499 * been processed by the application.
500 */
501#[doc = include_str!("../docs/io_uring_cqe_seen.md")]
502#[inline]
503pub unsafe fn io_uring_cqe_seen(ring: *mut io_uring, cqe: *mut io_uring_cqe)
504{
505    if !cqe.is_null() {
506        io_uring_cq_advance(ring, io_uring_cqe_nr(cqe));
507    }
508}
509
510/*
511 * Command prep helpers
512 */
513
514/*
515 * Associate pointer @data with the sqe, for later retrieval from the cqe
516 * at command completion time with io_uring_cqe_get_data().
517 */
518#[doc = include_str!("../docs/io_uring_sqe_set_data.md")]
519#[inline]
520pub unsafe fn io_uring_sqe_set_data(sqe: *mut io_uring_sqe, data: *mut c_void)
521{
522    (*sqe).user_data = data as u64;
523}
524
525#[doc = include_str!("../docs/io_uring_cqe_get_data.md")]
526#[must_use]
527#[inline]
528pub unsafe fn io_uring_cqe_get_data(cqe: *const io_uring_cqe) -> *mut c_void
529{
530    (*cqe).user_data as *mut c_void
531}
532
533/*
534 * Assign a 64-bit value to this sqe, which can get retrieved at completion
535 * time with io_uring_cqe_get_data64. Just like the non-64 variants, except
536 * these store a 64-bit type rather than a data pointer.
537 */
538#[doc = include_str!("../docs/io_uring_sqe_set_data64.md")]
539#[inline]
540pub unsafe fn io_uring_sqe_set_data64(sqe: *mut io_uring_sqe, data: u64)
541{
542    (*sqe).user_data = data;
543}
544
545#[doc = include_str!("../docs/io_uring_cqe_get_data.md")]
546#[must_use]
547#[inline]
548pub unsafe fn io_uring_cqe_get_data64(cqe: *const io_uring_cqe) -> u64
549{
550    (*cqe).user_data
551}
552
553#[doc = include_str!("../docs/io_uring_sqe_set_flags.md")]
554#[inline]
555pub unsafe fn io_uring_sqe_set_flags(sqe: *mut io_uring_sqe, flags: c_uint)
556{
557    (*sqe).flags = flags as u8;
558}
559
560#[doc = include_str!("../docs/io_uring_sqe_set_buf_group.md")]
561#[inline]
562pub unsafe fn io_uring_sqe_set_buf_group(sqe: *mut io_uring_sqe, bgid: c_int)
563{
564    (*sqe).__liburing_anon_4.buf_group = bgid as u16;
565}
566
567#[inline]
568unsafe fn __io_uring_set_target_fixed_file(sqe: *mut io_uring_sqe, file_index: c_uint)
569{
570    /* 0 means no fixed files, indexes should be encoded as "index + 1" */
571    (*sqe).__liburing_anon_5.file_index = file_index + 1;
572}
573
574#[doc(hidden)]
575#[inline]
576pub unsafe fn io_uring_initialize_sqe(sqe: *mut io_uring_sqe)
577{
578    (*sqe).flags = 0;
579    (*sqe).ioprio = 0;
580    (*sqe).__liburing_anon_3.rw_flags = 0;
581    (*sqe).__liburing_anon_4.buf_index = 0;
582    (*sqe).personality = 0;
583    (*sqe).__liburing_anon_5.file_index = 0;
584    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = 0;
585    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().__pad2[0] = 0;
586}
587
588#[doc(hidden)]
589#[inline]
590pub unsafe fn io_uring_prep_rw(op: c_uint, sqe: *mut io_uring_sqe, fd: c_int, addr: *const c_void,
591                               len: c_uint, offset: __u64)
592{
593    (*sqe).opcode = op as u8;
594    (*sqe).fd = fd;
595    (*sqe).__liburing_anon_1.off = offset;
596    (*sqe).__liburing_anon_2.addr = addr as u64;
597    (*sqe).len = len;
598}
599
600/*
601 * io_uring_prep_splice() - Either @fd_in or @fd_out must be a pipe.
602 *
603 * - If @fd_in refers to a pipe, @off_in is ignored and must be set to -1.
604 *
605 * - If @fd_in does not refer to a pipe and @off_in is -1, then @nbytes are read
606 *   from @fd_in starting from the file offset, which is incremented by the
607 *   number of bytes read.
608 *
609 * - If @fd_in does not refer to a pipe and @off_in is not -1, then the starting
610 *   offset of @fd_in will be @off_in.
611 *
612 * This splice operation can be used to implement sendfile by splicing to an
613 * intermediate pipe first, then splice to the final destination.
614 * In fact, the implementation of sendfile in kernel uses splice internally.
615 *
616 * NOTE that even if fd_in or fd_out refers to a pipe, the splice operation
617 * can still fail with EINVAL if one of the fd doesn't explicitly support splice
618 * operation, e.g. reading from terminal is unsupported from kernel 5.7 to 5.11.
619 * Check issue #291 for more information.
620 */
621#[doc = include_str!("../docs/io_uring_prep_splice.md")]
622#[inline]
623pub unsafe fn io_uring_prep_splice(sqe: *mut io_uring_sqe, fd_in: c_int, off_in: i64,
624                                   fd_out: c_int, off_out: i64, nbytes: c_uint,
625                                   splice_flags: c_uint)
626{
627    io_uring_prep_rw(IORING_OP_SPLICE, sqe, fd_out, ptr::null_mut(), nbytes, off_out as u64);
628    (*sqe).__liburing_anon_2.splice_off_in = off_in as u64;
629    (*sqe).__liburing_anon_5.splice_fd_in = fd_in;
630    (*sqe).__liburing_anon_3.splice_flags = splice_flags;
631}
632
633#[doc = include_str!("../docs/io_uring_prep_tee.md")]
634#[inline]
635pub unsafe fn io_uring_prep_tee(sqe: *mut io_uring_sqe, fd_in: c_int, fd_out: c_int,
636                                nbytes: c_uint, splice_flags: c_uint)
637{
638    io_uring_prep_rw(IORING_OP_TEE, sqe, fd_out, ptr::null_mut(), nbytes, 0);
639    (*sqe).__liburing_anon_2.splice_off_in = 0;
640    (*sqe).__liburing_anon_5.splice_fd_in = fd_in;
641    (*sqe).__liburing_anon_3.splice_flags = splice_flags;
642}
643
644#[doc = include_str!("../docs/io_uring_prep_readv.md")]
645#[inline]
646pub unsafe fn io_uring_prep_readv(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
647                                  nr_vecs: c_uint, offset: u64)
648{
649    io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs.cast(), nr_vecs, offset);
650}
651
652#[doc = include_str!("../docs/io_uring_prep_readv2.md")]
653#[inline]
654pub unsafe fn io_uring_prep_readv2(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
655                                   nr_vecs: c_uint, offset: u64, flags: c_int)
656{
657    io_uring_prep_readv(sqe, fd, iovecs, nr_vecs, offset);
658    (*sqe).__liburing_anon_3.rw_flags = flags;
659}
660
661#[doc = include_str!("../docs/io_uring_prep_read_fixed.md")]
662#[inline]
663pub unsafe fn io_uring_prep_read_fixed(sqe: *mut io_uring_sqe, fd: c_int, buf: *mut c_void,
664                                       nbytes: c_uint, offset: u64, buf_index: c_int)
665{
666    io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset);
667    (*sqe).__liburing_anon_4.buf_index = buf_index as u16;
668}
669
670#[doc = include_str!("../docs/io_uring_prep_readv_fixed.md")]
671#[inline]
672pub unsafe fn io_uring_prep_readv_fixed(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
673                                        nr_vecs: c_uint, offset: u64, flags: c_int,
674                                        buf_index: c_int)
675{
676    io_uring_prep_readv2(sqe, fd, iovecs, nr_vecs, offset, flags);
677    (*sqe).opcode = IORING_OP_READV_FIXED as _;
678    (*sqe).__liburing_anon_4.buf_index = buf_index as u16;
679}
680
681#[doc = include_str!("../docs/io_uring_prep_writev.md")]
682#[inline]
683pub unsafe fn io_uring_prep_writev(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
684                                   nr_vecs: c_uint, offset: u64)
685{
686    io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs.cast(), nr_vecs, offset);
687}
688
689#[doc = include_str!("../docs/io_uring_prep_writev2.md")]
690#[inline]
691pub unsafe fn io_uring_prep_writev2(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
692                                    nr_vecs: c_uint, offset: u64, flags: c_int)
693{
694    io_uring_prep_writev(sqe, fd, iovecs, nr_vecs, offset);
695    (*sqe).__liburing_anon_3.rw_flags = flags;
696}
697
698#[doc = include_str!("../docs/io_uring_prep_write_fixed.md")]
699#[inline]
700pub unsafe fn io_uring_prep_write_fixed(sqe: *mut io_uring_sqe, fd: c_int, buf: *const c_void,
701                                        nbytes: c_uint, offset: u64, buf_index: c_int)
702{
703    io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset);
704    (*sqe).__liburing_anon_4.buf_index = buf_index as u16;
705}
706
707#[doc = include_str!("../docs/io_uring_prep_writev_fixed.md")]
708#[inline]
709pub unsafe fn io_uring_prep_writev_fixed(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
710                                         nr_vecs: c_uint, offset: u64, flags: c_int,
711                                         buf_index: c_int)
712{
713    io_uring_prep_writev2(sqe, fd, iovecs, nr_vecs, offset, flags);
714    (*sqe).opcode = IORING_OP_WRITEV_FIXED as _;
715    (*sqe).__liburing_anon_4.buf_index = buf_index as u16;
716}
717
718#[doc = include_str!("../docs/io_uring_prep_recvmsg.md")]
719#[inline]
720pub unsafe fn io_uring_prep_recvmsg(sqe: *mut io_uring_sqe, fd: c_int, msg: *mut msghdr,
721                                    flags: c_uint)
722{
723    io_uring_prep_rw(IORING_OP_RECVMSG, sqe, fd, msg.cast(), 1, 0);
724    (*sqe).__liburing_anon_3.msg_flags = flags;
725}
726
727#[doc = include_str!("../docs/io_uring_prep_recvmsg_multishot.md")]
728#[inline]
729pub unsafe fn io_uring_prep_recvmsg_multishot(sqe: *mut io_uring_sqe, fd: c_int, msg: *mut msghdr,
730                                              flags: c_uint)
731{
732    io_uring_prep_recvmsg(sqe, fd, msg, flags);
733    (*sqe).ioprio |= IORING_RECV_MULTISHOT as u16;
734}
735
736#[doc = include_str!("../docs/io_uring_prep_sendmsg.md")]
737#[inline]
738pub unsafe fn io_uring_prep_sendmsg(sqe: *mut io_uring_sqe, fd: c_int, msg: *const msghdr,
739                                    flags: c_uint)
740{
741    io_uring_prep_rw(IORING_OP_SENDMSG, sqe, fd, msg.cast(), 1, 0);
742    (*sqe).__liburing_anon_3.msg_flags = flags;
743}
744
745#[must_use]
746#[inline]
747fn __io_uring_prep_poll_mask(poll_mask: c_uint) -> c_uint
748{
749    poll_mask.to_le()
750}
751
752#[doc = include_str!("../docs/io_uring_prep_poll_add.md")]
753#[inline]
754pub unsafe fn io_uring_prep_poll_add(sqe: *mut io_uring_sqe, fd: c_int, poll_mask: c_uint)
755{
756    io_uring_prep_rw(IORING_OP_POLL_ADD, sqe, fd, ptr::null_mut(), 0, 0);
757    (*sqe).__liburing_anon_3.poll32_events = __io_uring_prep_poll_mask(poll_mask);
758}
759
760#[doc = include_str!("../docs/io_uring_prep_poll_multishot.md")]
761#[inline]
762pub unsafe fn io_uring_prep_poll_multishot(sqe: *mut io_uring_sqe, fd: c_int, poll_mask: c_uint)
763{
764    io_uring_prep_poll_add(sqe, fd, poll_mask);
765    (*sqe).len = IORING_POLL_ADD_MULTI;
766}
767
768#[doc = include_str!("../docs/io_uring_prep_poll_remove.md")]
769#[inline]
770pub unsafe fn io_uring_prep_poll_remove(sqe: *mut io_uring_sqe, user_data: u64)
771{
772    io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, ptr::null_mut(), 0, 0);
773    (*sqe).__liburing_anon_2.addr = user_data;
774}
775
776#[doc = include_str!("../docs/io_uring_prep_poll_update.md")]
777#[inline]
778pub unsafe fn io_uring_prep_poll_update(sqe: *mut io_uring_sqe, old_user_data: u64,
779                                        new_user_data: u64, poll_mask: c_uint, flags: c_uint)
780{
781    io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, ptr::null_mut(), flags, new_user_data);
782    (*sqe).__liburing_anon_2.addr = old_user_data;
783    (*sqe).__liburing_anon_3.poll32_events = __io_uring_prep_poll_mask(poll_mask);
784}
785
786#[doc = include_str!("../docs/io_uring_prep_fsync.md")]
787#[inline]
788pub unsafe fn io_uring_prep_fsync(sqe: *mut io_uring_sqe, fd: c_int, fsync_flags: c_uint)
789{
790    io_uring_prep_rw(IORING_OP_FSYNC, sqe, fd, ptr::null_mut(), 0, 0);
791    (*sqe).__liburing_anon_3.fsync_flags = fsync_flags;
792}
793
794#[doc = include_str!("../docs/io_uring_prep_nop.md")]
795#[inline]
796pub unsafe fn io_uring_prep_nop(sqe: *mut io_uring_sqe)
797{
798    io_uring_prep_rw(IORING_OP_NOP, sqe, -1, ptr::null_mut(), 0, 0);
799}
800
801#[doc = include_str!("../docs/io_uring_prep_nop128.md")]
802#[inline]
803pub unsafe fn io_uring_prep_nop128(sqe: *mut io_uring_sqe)
804{
805    io_uring_prep_rw(IORING_OP_NOP128, sqe, -1, ptr::null_mut(), 0, 0);
806}
807
808#[doc = include_str!("../docs/io_uring_prep_timeout.md")]
809#[inline]
810pub unsafe fn io_uring_prep_timeout(sqe: *mut io_uring_sqe, ts: *const __kernel_timespec,
811                                    count: c_uint, flags: c_uint)
812{
813    io_uring_prep_rw(IORING_OP_TIMEOUT, sqe, -1, ts.cast(), 1, count.into());
814    (*sqe).__liburing_anon_3.timeout_flags = flags;
815}
816
817#[doc = include_str!("../docs/io_uring_prep_timeout_remove.md")]
818#[inline]
819pub unsafe fn io_uring_prep_timeout_remove(sqe: *mut io_uring_sqe, user_data: __u64, flags: c_uint)
820{
821    io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, ptr::null_mut(), 0, 0);
822    (*sqe).__liburing_anon_2.addr = user_data;
823    (*sqe).__liburing_anon_3.timeout_flags = flags;
824}
825
826#[doc = include_str!("../docs/io_uring_prep_timeout_update.md")]
827#[inline]
828pub unsafe fn io_uring_prep_timeout_update(sqe: *mut io_uring_sqe, ts: *const __kernel_timespec,
829                                           user_data: __u64, flags: c_uint)
830{
831    io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, ptr::null_mut(), 0, ts as u64);
832    (*sqe).__liburing_anon_2.addr = user_data;
833    (*sqe).__liburing_anon_3.timeout_flags = flags | IORING_TIMEOUT_UPDATE;
834}
835
836#[doc = include_str!("../docs/io_uring_prep_accept.md")]
837#[inline]
838pub unsafe fn io_uring_prep_accept(sqe: *mut io_uring_sqe, fd: c_int, addr: *mut sockaddr,
839                                   addrlen: *mut socklen_t, flags: c_int)
840{
841    io_uring_prep_rw(IORING_OP_ACCEPT, sqe, fd, addr.cast(), 0, uring_ptr_to_u64(addrlen.cast()));
842    (*sqe).__liburing_anon_3.accept_flags = flags as u32;
843}
844
845/* accept directly into the fixed file table */
846#[doc = include_str!("../docs/io_uring_prep_accept_direct.md")]
847#[inline]
848pub unsafe fn io_uring_prep_accept_direct(sqe: *mut io_uring_sqe, fd: c_int, addr: *mut sockaddr,
849                                          addrlen: *mut socklen_t, flags: c_int,
850                                          mut file_index: c_uint)
851{
852    io_uring_prep_accept(sqe, fd, addr, addrlen, flags);
853    /* offset by 1 for allocation */
854    if file_index == IORING_FILE_INDEX_ALLOC as _ {
855        file_index -= 1;
856    }
857    __io_uring_set_target_fixed_file(sqe, file_index);
858}
859
860#[doc = include_str!("../docs/io_uring_prep_multishot_accept.md")]
861#[inline]
862pub unsafe fn io_uring_prep_multishot_accept(sqe: *mut io_uring_sqe, fd: c_int,
863                                             addr: *mut sockaddr, addrlen: *mut socklen_t,
864                                             flags: c_int)
865{
866    io_uring_prep_accept(sqe, fd, addr, addrlen, flags);
867    (*sqe).ioprio |= IORING_ACCEPT_MULTISHOT as u16;
868}
869
870/* multishot accept directly into the fixed file table */
871#[doc = include_str!("../docs/io_uring_prep_multishot_accept_direct.md")]
872#[inline]
873pub unsafe fn io_uring_prep_multishot_accept_direct(sqe: *mut io_uring_sqe, fd: c_int,
874                                                    addr: *mut sockaddr, addrlen: *mut socklen_t,
875                                                    flags: c_int)
876{
877    io_uring_prep_multishot_accept(sqe, fd, addr, addrlen, flags);
878    __io_uring_set_target_fixed_file(sqe, (IORING_FILE_INDEX_ALLOC - 1) as u32);
879}
880
881#[doc = include_str!("../docs/io_uring_prep_cancel64.md")]
882#[inline]
883pub unsafe fn io_uring_prep_cancel64(sqe: *mut io_uring_sqe, user_data: u64, flags: c_int)
884{
885    io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, -1, ptr::null_mut(), 0, 0);
886    (*sqe).__liburing_anon_2.addr = user_data;
887    (*sqe).__liburing_anon_3.cancel_flags = flags as u32;
888}
889
890#[doc = include_str!("../docs/io_uring_prep_cancel.md")]
891#[inline]
892pub unsafe fn io_uring_prep_cancel(sqe: *mut io_uring_sqe, user_data: *const c_void, flags: c_int)
893{
894    io_uring_prep_cancel64(sqe, user_data as usize as u64, flags);
895}
896
897#[doc = include_str!("../docs/io_uring_prep_cancel_fd.md")]
898#[inline]
899pub unsafe fn io_uring_prep_cancel_fd(sqe: *mut io_uring_sqe, fd: c_int, flags: c_uint)
900{
901    io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, fd, ptr::null_mut(), 0, 0);
902    (*sqe).__liburing_anon_3.cancel_flags = flags | IORING_ASYNC_CANCEL_FD;
903}
904
905#[doc = include_str!("../docs/io_uring_prep_link_timeout.md")]
906#[inline]
907pub unsafe fn io_uring_prep_link_timeout(sqe: *mut io_uring_sqe, ts: *const __kernel_timespec,
908                                         flags: c_uint)
909{
910    io_uring_prep_rw(IORING_OP_LINK_TIMEOUT, sqe, -1, ts.cast(), 1, 0);
911    (*sqe).__liburing_anon_3.timeout_flags = flags;
912}
913
914#[doc = include_str!("../docs/io_uring_prep_connect.md")]
915#[inline]
916pub unsafe fn io_uring_prep_connect(sqe: *mut io_uring_sqe, fd: c_int, addr: *const sockaddr,
917                                    addrlen: socklen_t)
918{
919    io_uring_prep_rw(IORING_OP_CONNECT, sqe, fd, addr.cast(), 0, addrlen.into());
920}
921
922#[doc = include_str!("../docs/io_uring_prep_bind.md")]
923#[inline]
924pub unsafe fn io_uring_prep_bind(sqe: *mut io_uring_sqe, fd: c_int, addr: *const sockaddr,
925                                 addrlen: socklen_t)
926{
927    io_uring_prep_rw(IORING_OP_BIND, sqe, fd, addr.cast(), 0, addrlen.into());
928}
929
930#[doc = include_str!("../docs/io_uring_prep_listen.md")]
931#[inline]
932pub unsafe fn io_uring_prep_listen(sqe: *mut io_uring_sqe, fd: c_int, backlog: c_int)
933{
934    io_uring_prep_rw(IORING_OP_LISTEN, sqe, fd, ptr::null_mut(), backlog as _, 0);
935}
936
937#[doc = include_str!("../docs/io_uring_prep_epoll_wait.md")]
938#[inline]
939pub unsafe fn io_uring_prep_epoll_wait(sqe: *mut io_uring_sqe, fd: c_int,
940                                       events: *mut epoll_event, maxevents: c_int, flags: c_uint)
941{
942    io_uring_prep_rw(IORING_OP_EPOLL_WAIT, sqe, fd, events.cast(), maxevents as _, 0);
943    (*sqe).__liburing_anon_3.rw_flags = flags as _;
944}
945
946#[doc = include_str!("../docs/io_uring_prep_files_update.md")]
947#[inline]
948pub unsafe fn io_uring_prep_files_update(sqe: *mut io_uring_sqe, fds: *mut c_int, nr_fds: c_uint,
949                                         offset: c_int)
950{
951    io_uring_prep_rw(IORING_OP_FILES_UPDATE, sqe, -1, fds.cast(), nr_fds, offset as u64);
952}
953
954#[doc = include_str!("../docs/io_uring_prep_fallocate.md")]
955#[inline]
956pub unsafe fn io_uring_prep_fallocate(sqe: *mut io_uring_sqe, fd: c_int, mode: c_int, offset: u64,
957                                      len: u64)
958{
959    io_uring_prep_rw(IORING_OP_FALLOCATE, sqe, fd, ptr::null_mut(), mode as c_uint, offset);
960    (*sqe).__liburing_anon_2.addr = len;
961}
962
963#[doc = include_str!("../docs/io_uring_prep_openat.md")]
964#[inline]
965pub unsafe fn io_uring_prep_openat(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
966                                   flags: c_int, mode: mode_t)
967{
968    io_uring_prep_rw(IORING_OP_OPENAT, sqe, dfd, path.cast(), mode, 0);
969    (*sqe).__liburing_anon_3.open_flags = flags as u32;
970}
971
972/* open directly into the fixed file table */
973#[doc = include_str!("../docs/io_uring_prep_openat_direct.md")]
974#[inline]
975pub unsafe fn io_uring_prep_openat_direct(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
976                                          flags: c_int, mode: mode_t, mut file_index: c_uint)
977{
978    io_uring_prep_openat(sqe, dfd, path, flags, mode);
979    /* offset by 1 for allocation */
980    if file_index == IORING_FILE_INDEX_ALLOC as _ {
981        file_index -= 1;
982    }
983    __io_uring_set_target_fixed_file(sqe, file_index);
984}
985
986#[doc = include_str!("../docs/io_uring_prep_open.md")]
987#[inline]
988pub unsafe fn io_uring_prep_open(sqe: *mut io_uring_sqe, path: *const c_char, flags: c_int,
989                                 mode: mode_t)
990{
991    io_uring_prep_openat(sqe, AT_FDCWD, path, flags, mode);
992}
993
994/* open directly into the fixed file table */
995#[doc = include_str!("../docs/io_uring_prep_open_direct.md")]
996#[inline]
997pub unsafe fn io_uring_prep_open_direct(sqe: *mut io_uring_sqe, path: *const c_char, flags: c_int,
998                                        mode: mode_t, file_index: c_uint)
999{
1000    io_uring_prep_openat_direct(sqe, AT_FDCWD, path, flags, mode, file_index);
1001}
1002
1003#[doc = include_str!("../docs/io_uring_prep_close.md")]
1004#[inline]
1005pub unsafe fn io_uring_prep_close(sqe: *mut io_uring_sqe, fd: c_int)
1006{
1007    io_uring_prep_rw(IORING_OP_CLOSE, sqe, fd, ptr::null_mut(), 0, 0);
1008}
1009
1010#[doc = include_str!("../docs/io_uring_prep_close_direct.md")]
1011#[inline]
1012pub unsafe fn io_uring_prep_close_direct(sqe: *mut io_uring_sqe, file_index: c_uint)
1013{
1014    io_uring_prep_close(sqe, 0);
1015    __io_uring_set_target_fixed_file(sqe, file_index);
1016}
1017
1018#[doc = include_str!("../docs/io_uring_prep_read.md")]
1019#[inline]
1020pub unsafe fn io_uring_prep_read(sqe: *mut io_uring_sqe, fd: c_int, buf: *mut c_void,
1021                                 nbytes: c_uint, offset: u64)
1022{
1023    io_uring_prep_rw(IORING_OP_READ, sqe, fd, buf, nbytes, offset);
1024}
1025
1026#[doc = include_str!("../docs/io_uring_prep_read_multishot.md")]
1027#[inline]
1028pub unsafe fn io_uring_prep_read_multishot(sqe: *mut io_uring_sqe, fd: c_int, nbytes: c_uint,
1029                                           offset: u64, buf_group: c_int)
1030{
1031    io_uring_prep_rw(IORING_OP_READ_MULTISHOT, sqe, fd, ptr::null_mut(), nbytes, offset);
1032    (*sqe).__liburing_anon_4.buf_group = buf_group as _;
1033    (*sqe).flags = IOSQE_BUFFER_SELECT as _;
1034}
1035
1036#[doc = include_str!("../docs/io_uring_prep_write.md")]
1037#[inline]
1038pub unsafe fn io_uring_prep_write(sqe: *mut io_uring_sqe, fd: c_int, buf: *const c_void,
1039                                  nbytes: c_uint, offset: u64)
1040{
1041    io_uring_prep_rw(IORING_OP_WRITE, sqe, fd, buf, nbytes, offset);
1042}
1043
1044#[doc = include_str!("../docs/io_uring_prep_statx.md")]
1045#[inline]
1046pub unsafe fn io_uring_prep_statx(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
1047                                  flags: c_int, mask: c_uint, statxbuf: *mut statx)
1048{
1049    io_uring_prep_rw(IORING_OP_STATX,
1050                     sqe,
1051                     dfd,
1052                     path.cast(),
1053                     mask,
1054                     uring_ptr_to_u64(statxbuf.cast()));
1055    (*sqe).__liburing_anon_3.statx_flags = flags as u32;
1056}
1057
1058#[doc = include_str!("../docs/io_uring_prep_fadvise.md")]
1059#[inline]
1060pub unsafe fn io_uring_prep_fadvise(sqe: *mut io_uring_sqe, fd: c_int, offset: u64, len: u32,
1061                                    advice: c_int)
1062{
1063    io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, ptr::null_mut(), len, offset);
1064    (*sqe).__liburing_anon_3.fadvise_advice = advice as u32;
1065}
1066
1067#[doc = include_str!("../docs/io_uring_prep_madvise.md")]
1068#[inline]
1069pub unsafe fn io_uring_prep_madvise(sqe: *mut io_uring_sqe, addr: *mut c_void, length: u32,
1070                                    advice: c_int)
1071{
1072    io_uring_prep_rw(IORING_OP_MADVISE, sqe, -1, addr, length, 0);
1073    (*sqe).__liburing_anon_3.fadvise_advice = advice as u32;
1074}
1075
1076#[doc = include_str!("../docs/io_uring_prep_fadvise64.md")]
1077#[inline]
1078pub unsafe fn io_uring_prep_fadvise64(sqe: *mut io_uring_sqe, fd: c_int, offset: u64, len: off_t,
1079                                      advice: c_int)
1080{
1081    io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, ptr::null_mut(), 0, offset);
1082    (*sqe).__liburing_anon_2.addr = len as _;
1083    (*sqe).__liburing_anon_3.fadvise_advice = advice as u32;
1084}
1085
1086#[doc = include_str!("../docs/io_uring_prep_madvise64.md")]
1087#[inline]
1088pub unsafe fn io_uring_prep_madvise64(sqe: *mut io_uring_sqe, addr: *mut c_void, length: off_t,
1089                                      advice: c_int)
1090{
1091    io_uring_prep_rw(IORING_OP_MADVISE, sqe, -1, addr, 0, length as _);
1092    (*sqe).__liburing_anon_3.fadvise_advice = advice as u32;
1093}
1094
1095#[doc = include_str!("../docs/io_uring_prep_send.md")]
1096#[inline]
1097pub unsafe fn io_uring_prep_send(sqe: *mut io_uring_sqe, sockfd: c_int, buf: *const c_void,
1098                                 len: usize, flags: c_int)
1099{
1100    io_uring_prep_rw(IORING_OP_SEND, sqe, sockfd, buf, len as u32, 0);
1101    (*sqe).__liburing_anon_3.msg_flags = flags as u32;
1102}
1103
1104#[doc = include_str!("../docs/io_uring_prep_send_bundle.md")]
1105#[inline]
1106pub unsafe fn io_uring_prep_send_bundle(sqe: *mut io_uring_sqe, sockfd: c_int, len: usize,
1107                                        flags: c_int)
1108{
1109    io_uring_prep_send(sqe, sockfd, ptr::null_mut(), len, flags);
1110    (*sqe).ioprio |= IORING_RECVSEND_BUNDLE as u16;
1111}
1112
1113#[doc = include_str!("../docs/io_uring_prep_send_set_addr.md")]
1114#[inline]
1115pub unsafe fn io_uring_prep_send_set_addr(sqe: *mut io_uring_sqe, dest_addr: *const sockaddr,
1116                                          addr_len: u16)
1117{
1118    (*sqe).__liburing_anon_1.addr2 = dest_addr as usize as u64;
1119    (*sqe).__liburing_anon_5.__liburing_anon_1.addr_len = addr_len;
1120}
1121
1122#[doc = include_str!("../docs/io_uring_prep_sendto.md")]
1123#[inline]
1124pub unsafe fn io_uring_prep_sendto(sqe: *mut io_uring_sqe, sockfd: c_int, buf: *const c_void,
1125                                   len: usize, flags: c_int, addr: *const sockaddr,
1126                                   addrlen: socklen_t)
1127{
1128    io_uring_prep_send(sqe, sockfd, buf, len, flags);
1129    io_uring_prep_send_set_addr(sqe, addr, addrlen as _);
1130}
1131
1132#[doc = include_str!("../docs/io_uring_prep_send_zc.md")]
1133#[inline]
1134pub unsafe fn io_uring_prep_send_zc(sqe: *mut io_uring_sqe, sockfd: c_int, buf: *const c_void,
1135                                    len: usize, flags: c_int, zc_flags: c_uint)
1136{
1137    io_uring_prep_rw(IORING_OP_SEND_ZC, sqe, sockfd, buf, len as u32, 0);
1138    (*sqe).__liburing_anon_3.msg_flags = flags as u32;
1139    (*sqe).ioprio = zc_flags as _;
1140}
1141
1142#[doc = include_str!("../docs/io_uring_prep_send_zc_fixed.md")]
1143#[inline]
1144pub unsafe fn io_uring_prep_send_zc_fixed(sqe: *mut io_uring_sqe, sockfd: c_int,
1145                                          buf: *const c_void, len: usize, flags: c_int,
1146                                          zc_flags: c_uint, buf_index: c_uint)
1147{
1148    io_uring_prep_send_zc(sqe, sockfd, buf, len, flags, zc_flags);
1149    (*sqe).ioprio |= IORING_RECVSEND_FIXED_BUF as u16;
1150    (*sqe).__liburing_anon_4.buf_index = buf_index as _;
1151}
1152
1153#[doc = include_str!("../docs/io_uring_prep_sendmsg_zc.md")]
1154#[inline]
1155pub unsafe fn io_uring_prep_sendmsg_zc(sqe: *mut io_uring_sqe, fd: c_int, msg: *const msghdr,
1156                                       flags: c_uint)
1157{
1158    io_uring_prep_sendmsg(sqe, fd, msg, flags);
1159    (*sqe).opcode = IORING_OP_SENDMSG_ZC as _;
1160}
1161
1162#[doc = include_str!("../docs/io_uring_prep_sendmsg_zc_fixed.md")]
1163#[inline]
1164pub unsafe fn io_uring_prep_sendmsg_zc_fixed(sqe: *mut io_uring_sqe, fd: c_int,
1165                                             msg: *const msghdr, flags: c_uint, buf_index: c_uint)
1166{
1167    io_uring_prep_sendmsg_zc(sqe, fd, msg, flags);
1168    (*sqe).ioprio |= IORING_RECVSEND_FIXED_BUF as u16;
1169    (*sqe).__liburing_anon_4.buf_index = buf_index as _;
1170}
1171
1172#[doc = include_str!("../docs/io_uring_prep_recv.md")]
1173#[inline]
1174pub unsafe fn io_uring_prep_recv(sqe: *mut io_uring_sqe, sockfd: c_int, buf: *mut c_void,
1175                                 len: usize, flags: c_int)
1176{
1177    io_uring_prep_rw(IORING_OP_RECV, sqe, sockfd, buf, len as u32, 0);
1178    (*sqe).__liburing_anon_3.msg_flags = flags as u32;
1179}
1180
1181#[doc = include_str!("../docs/io_uring_prep_recv_multishot.md")]
1182#[inline]
1183pub unsafe fn io_uring_prep_recv_multishot(sqe: *mut io_uring_sqe, sockfd: c_int,
1184                                           buf: *mut c_void, len: usize, flags: c_int)
1185{
1186    io_uring_prep_recv(sqe, sockfd, buf, len, flags);
1187    (*sqe).ioprio |= IORING_RECV_MULTISHOT as u16;
1188}
1189
1190#[doc = include_str!("../docs/io_uring_recvmsg_validate.md")]
1191#[inline]
1192pub unsafe fn io_uring_recvmsg_validate(buf: *mut c_void, buf_len: c_int, msgh: *mut msghdr)
1193                                        -> *mut io_uring_recvmsg_out
1194{
1195    let ulen = c_ulong::from(buf_len as c_uint);
1196    let hdr = size_of::<io_uring_recvmsg_out>() as c_ulong;
1197    let namelen = c_ulong::from((*msgh).msg_namelen);
1198    let controllen = (*msgh).msg_controllen as c_ulong;
1199
1200    if buf_len < 0 || ulen < hdr {
1201        return ptr::null_mut();
1202    }
1203    /* check each addition separately to avoid integer overflow */
1204    if namelen > ulen - hdr {
1205        return ptr::null_mut();
1206    }
1207    if controllen > ulen - hdr - namelen {
1208        return ptr::null_mut();
1209    }
1210
1211    buf.cast()
1212}
1213
1214#[doc = include_str!("../docs/io_uring_recvmsg_name.md")]
1215#[inline]
1216pub unsafe fn io_uring_recvmsg_name(o: *mut io_uring_recvmsg_out) -> *mut c_void
1217{
1218    o.add(1).cast()
1219}
1220
1221#[doc = include_str!("../docs/io_uring_recvmsg_cmsg_firsthdr.md")]
1222#[inline]
1223pub unsafe fn io_uring_recvmsg_cmsg_firsthdr(o: *mut io_uring_recvmsg_out, msgh: *mut msghdr)
1224                                             -> *mut cmsghdr
1225{
1226    if ((*o).controllen as usize) < mem::size_of::<cmsghdr>() {
1227        return ptr::null_mut();
1228    }
1229
1230    io_uring_recvmsg_name(o).cast::<u8>()
1231                            .add((*msgh).msg_namelen as _)
1232                            .cast()
1233}
1234
1235#[doc = include_str!("../docs/io_uring_recvmsg_cmsg_nexthdr.md")]
1236#[inline]
1237pub unsafe fn io_uring_recvmsg_cmsg_nexthdr(o: *mut io_uring_recvmsg_out, msgh: *mut msghdr,
1238                                            cmsg: *mut cmsghdr)
1239                                            -> *mut cmsghdr
1240{
1241    #[allow(non_snake_case)]
1242    fn CMSG_ALIGN(len: usize) -> usize
1243    {
1244        ((len) + mem::size_of::<usize>() - 1) & !(mem::size_of::<usize>() - 1)
1245    }
1246
1247    if ((*cmsg).cmsg_len as usize) < mem::size_of::<cmsghdr>() {
1248        return ptr::null_mut();
1249    }
1250
1251    let end = io_uring_recvmsg_cmsg_firsthdr(o, msgh).cast::<u8>()
1252                                                     .add((*o).controllen as _);
1253
1254    let cmsg = cmsg.cast::<u8>()
1255                   .add(CMSG_ALIGN((*cmsg).cmsg_len as usize))
1256                   .cast::<cmsghdr>();
1257
1258    if cmsg.add(1).cast::<u8>() > end {
1259        return ptr::null_mut();
1260    }
1261
1262    if cmsg.cast::<u8>().add(CMSG_ALIGN((*cmsg).cmsg_len as usize)) > end {
1263        return ptr::null_mut();
1264    }
1265
1266    cmsg
1267}
1268
1269#[doc = include_str!("../docs/io_uring_recvmsg_payload.md")]
1270#[inline]
1271pub unsafe fn io_uring_recvmsg_payload(o: *mut io_uring_recvmsg_out, msgh: *mut msghdr)
1272                                       -> *mut c_void
1273{
1274    io_uring_recvmsg_name(o).cast::<u8>()
1275                            .add((*msgh).msg_namelen as usize + (*msgh).msg_controllen as usize)
1276                            .cast::<c_void>()
1277}
1278
1279#[doc = include_str!("../docs/io_uring_recvmsg_payload_length.md")]
1280#[inline]
1281pub unsafe fn io_uring_recvmsg_payload_length(o: *mut io_uring_recvmsg_out, buf_len: c_int,
1282                                              msgh: *mut msghdr)
1283                                              -> c_uint
1284{
1285    if buf_len < 0 {
1286        return 0;
1287    }
1288
1289    let payload_start = io_uring_recvmsg_payload(o, msgh) as usize;
1290    let payload_end = o as usize + buf_len as usize;
1291    if payload_start >= payload_end {
1292        return 0;
1293    }
1294
1295    (payload_end - payload_start) as _
1296}
1297
1298#[doc = include_str!("../docs/io_uring_prep_openat2.md")]
1299#[inline]
1300pub unsafe fn io_uring_prep_openat2(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
1301                                    how: *const open_how)
1302{
1303    io_uring_prep_rw(IORING_OP_OPENAT2 as _,
1304                     sqe,
1305                     dfd,
1306                     path.cast(),
1307                     mem::size_of::<open_how>() as u32,
1308                     how as usize as u64);
1309}
1310
1311/* open directly into the fixed file table */
1312#[doc = include_str!("../docs/io_uring_prep_openat2_direct.md")]
1313#[inline]
1314pub unsafe fn io_uring_prep_openat2_direct(sqe: *mut io_uring_sqe, dfd: c_int,
1315                                           path: *const c_char, how: *const open_how,
1316                                           mut file_index: c_uint)
1317{
1318    io_uring_prep_openat2(sqe, dfd, path, how);
1319    /* offset by 1 for allocation */
1320    if file_index == IORING_FILE_INDEX_ALLOC as _ {
1321        file_index -= 1;
1322    }
1323    __io_uring_set_target_fixed_file(sqe, file_index);
1324}
1325
1326#[doc = include_str!("../docs/io_uring_prep_epoll_ctl.md")]
1327#[inline]
1328pub unsafe fn io_uring_prep_epoll_ctl(sqe: *mut io_uring_sqe, epfd: c_int, fd: c_int, op: c_int,
1329                                      ev: *const epoll_event)
1330{
1331    io_uring_prep_rw(IORING_OP_EPOLL_CTL, sqe, epfd, ev.cast(), op as u32, u64::from(fd as u32));
1332}
1333
1334#[doc = include_str!("../docs/io_uring_prep_provide_buffers.md")]
1335#[inline]
1336pub unsafe fn io_uring_prep_provide_buffers(sqe: *mut io_uring_sqe, addr: *mut c_void, len: c_int,
1337                                            nr: c_int, bgid: c_int, bid: c_int)
1338{
1339    io_uring_prep_rw(IORING_OP_PROVIDE_BUFFERS, sqe, nr, addr, len as u32, bid as u64);
1340    (*sqe).__liburing_anon_4.buf_group = bgid as u16;
1341}
1342
1343#[doc = include_str!("../docs/io_uring_prep_remove_buffers.md")]
1344#[inline]
1345pub unsafe fn io_uring_prep_remove_buffers(sqe: *mut io_uring_sqe, nr: c_int, bgid: c_int)
1346{
1347    io_uring_prep_rw(IORING_OP_REMOVE_BUFFERS, sqe, nr, ptr::null_mut(), 0, 0);
1348    (*sqe).__liburing_anon_4.buf_group = bgid as u16;
1349}
1350
1351#[doc = include_str!("../docs/io_uring_prep_shutdown.md")]
1352#[inline]
1353pub unsafe fn io_uring_prep_shutdown(sqe: *mut io_uring_sqe, fd: c_int, how: c_int)
1354{
1355    io_uring_prep_rw(IORING_OP_SHUTDOWN, sqe, fd, ptr::null_mut(), how as u32, 0);
1356}
1357
1358#[doc = include_str!("../docs/io_uring_prep_unlinkat.md")]
1359#[inline]
1360pub unsafe fn io_uring_prep_unlinkat(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
1361                                     flags: c_int)
1362{
1363    io_uring_prep_rw(IORING_OP_UNLINKAT, sqe, dfd, path.cast(), 0, 0);
1364    (*sqe).__liburing_anon_3.unlink_flags = flags as u32;
1365}
1366
1367#[doc = include_str!("../docs/io_uring_prep_unlink.md")]
1368#[inline]
1369pub unsafe fn io_uring_prep_unlink(sqe: *mut io_uring_sqe, path: *const c_char, flags: c_int)
1370{
1371    io_uring_prep_unlinkat(sqe, AT_FDCWD, path, flags);
1372}
1373
1374#[doc = include_str!("../docs/io_uring_prep_renameat.md")]
1375#[inline]
1376pub unsafe fn io_uring_prep_renameat(sqe: *mut io_uring_sqe, olddfd: c_int,
1377                                     oldpath: *const c_char, newdfd: c_int,
1378                                     newpath: *const c_char, flags: c_uint)
1379{
1380    io_uring_prep_rw(IORING_OP_RENAMEAT,
1381                     sqe,
1382                     olddfd,
1383                     oldpath.cast(),
1384                     newdfd as u32,
1385                     newpath as usize as u64);
1386    (*sqe).__liburing_anon_3.rename_flags = flags;
1387}
1388
1389#[doc = include_str!("../docs/io_uring_prep_rename.md")]
1390#[inline]
1391pub unsafe fn io_uring_prep_rename(sqe: *mut io_uring_sqe, oldpath: *const c_char,
1392                                   newpath: *const c_char)
1393{
1394    io_uring_prep_renameat(sqe, AT_FDCWD, oldpath, AT_FDCWD, newpath, 0);
1395}
1396
1397#[doc = include_str!("../docs/io_uring_prep_sync_file_range.md")]
1398#[inline]
1399pub unsafe fn io_uring_prep_sync_file_range(sqe: *mut io_uring_sqe, fd: c_int, len: c_uint,
1400                                            offset: u64, flags: c_int)
1401{
1402    io_uring_prep_rw(IORING_OP_SYNC_FILE_RANGE, sqe, fd, ptr::null_mut(), len, offset);
1403    (*sqe).__liburing_anon_3.sync_range_flags = flags as u32;
1404}
1405
1406#[doc = include_str!("../docs/io_uring_prep_mkdirat.md")]
1407#[inline]
1408pub unsafe fn io_uring_prep_mkdirat(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
1409                                    mode: mode_t)
1410{
1411    io_uring_prep_rw(IORING_OP_MKDIRAT, sqe, dfd, path.cast(), mode, 0);
1412}
1413
1414#[doc = include_str!("../docs/io_uring_prep_mkdir.md")]
1415#[inline]
1416pub unsafe fn io_uring_prep_mkdir(sqe: *mut io_uring_sqe, path: *const c_char, mode: mode_t)
1417{
1418    io_uring_prep_mkdirat(sqe, AT_FDCWD, path, mode);
1419}
1420
1421#[doc = include_str!("../docs/io_uring_prep_symlinkat.md")]
1422#[inline]
1423pub unsafe fn io_uring_prep_symlinkat(sqe: *mut io_uring_sqe, target: *const c_char,
1424                                      newdirfd: c_int, linkpath: *const c_char)
1425{
1426    io_uring_prep_rw(IORING_OP_SYMLINKAT,
1427                     sqe,
1428                     newdirfd,
1429                     target.cast(),
1430                     0,
1431                     linkpath as usize as u64);
1432}
1433#[doc = include_str!("../docs/io_uring_prep_symlink.md")]
1434#[inline]
1435pub unsafe fn io_uring_prep_symlink(sqe: *mut io_uring_sqe, target: *const c_char,
1436                                    linkpath: *const c_char)
1437{
1438    io_uring_prep_symlinkat(sqe, target, AT_FDCWD, linkpath);
1439}
1440
1441#[doc = include_str!("../docs/io_uring_prep_linkat.md")]
1442#[inline]
1443pub unsafe fn io_uring_prep_linkat(sqe: *mut io_uring_sqe, olddfd: c_int, oldpath: *const c_char,
1444                                   newdfd: c_int, newpath: *const c_char, flags: c_int)
1445{
1446    io_uring_prep_rw(IORING_OP_LINKAT,
1447                     sqe,
1448                     olddfd,
1449                     oldpath.cast(),
1450                     newdfd as u32,
1451                     newpath as usize as u64);
1452    (*sqe).__liburing_anon_3.hardlink_flags = flags as u32;
1453}
1454
1455#[doc = include_str!("../docs/io_uring_prep_link.md")]
1456#[inline]
1457pub unsafe fn io_uring_prep_link(sqe: *mut io_uring_sqe, oldpath: *const c_char,
1458                                 newpath: *const c_char, flags: c_int)
1459{
1460    io_uring_prep_linkat(sqe, AT_FDCWD, oldpath, AT_FDCWD, newpath, flags);
1461}
1462
1463#[doc = include_str!("../docs/io_uring_prep_msg_ring_cqe_flags.md")]
1464#[inline]
1465pub unsafe fn io_uring_prep_msg_ring_cqe_flags(sqe: *mut io_uring_sqe, fd: c_int, len: c_uint,
1466                                               data: u64, flags: c_uint, cqe_flags: c_uint)
1467{
1468    io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd, ptr::null_mut(), len, data);
1469    (*sqe).__liburing_anon_3.msg_ring_flags = IORING_MSG_RING_FLAGS_PASS | flags;
1470    (*sqe).__liburing_anon_5.file_index = cqe_flags;
1471}
1472
1473#[doc = include_str!("../docs/io_uring_prep_msg_ring.md")]
1474#[inline]
1475pub unsafe fn io_uring_prep_msg_ring(sqe: *mut io_uring_sqe, fd: c_int, len: c_uint, data: u64,
1476                                     flags: c_uint)
1477{
1478    io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd, ptr::null_mut(), len, data);
1479    (*sqe).__liburing_anon_3.msg_ring_flags = IORING_MSG_RING_FLAGS_PASS | flags;
1480}
1481
1482#[doc = include_str!("../docs/io_uring_prep_msg_ring_fd.md")]
1483#[inline]
1484pub unsafe fn io_uring_prep_msg_ring_fd(sqe: *mut io_uring_sqe, fd: c_int, source_fd: c_int,
1485                                        mut target_fd: c_int, data: u64, flags: c_uint)
1486{
1487    io_uring_prep_rw(IORING_OP_MSG_RING,
1488                     sqe,
1489                     fd,
1490                     IORING_MSG_SEND_FD as usize as *const c_void,
1491                     0,
1492                     data);
1493    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = source_fd as _;
1494    /* offset by 1 for allocation */
1495    if target_fd == IORING_FILE_INDEX_ALLOC as _ {
1496        target_fd -= 1;
1497    }
1498    __io_uring_set_target_fixed_file(sqe, target_fd as _);
1499    (*sqe).__liburing_anon_3.msg_ring_flags = flags;
1500}
1501
1502#[doc = include_str!("../docs/io_uring_prep_msg_ring_fd_alloc.md")]
1503#[inline]
1504pub unsafe fn io_uring_prep_msg_ring_fd_alloc(sqe: *mut io_uring_sqe, fd: c_int, source_fd: c_int,
1505                                              data: u64, flags: c_uint)
1506{
1507    io_uring_prep_msg_ring_fd(sqe, fd, source_fd, IORING_FILE_INDEX_ALLOC, data, flags);
1508}
1509
1510#[doc = include_str!("../docs/io_uring_prep_getxattr.md")]
1511#[inline]
1512pub unsafe fn io_uring_prep_getxattr(sqe: *mut io_uring_sqe, name: *const c_char,
1513                                     value: *mut c_char, path: *const c_char, len: c_uint)
1514{
1515    io_uring_prep_rw(IORING_OP_GETXATTR, sqe, 0, name.cast(), len, value as usize as u64);
1516    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = path as usize as u64;
1517
1518    (*sqe).__liburing_anon_3.xattr_flags = 0;
1519}
1520
1521#[doc = include_str!("../docs/io_uring_prep_setxattr.md")]
1522#[inline]
1523pub unsafe fn io_uring_prep_setxattr(sqe: *mut io_uring_sqe, name: *const c_char,
1524                                     value: *const c_char, path: *const c_char, flags: c_int,
1525                                     len: c_uint)
1526{
1527    io_uring_prep_rw(IORING_OP_SETXATTR, sqe, 0, name.cast(), len, value as usize as u64);
1528    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = path as usize as u64;
1529    (*sqe).__liburing_anon_3.xattr_flags = flags as _;
1530}
1531
1532#[doc = include_str!("../docs/io_uring_prep_fgetxattr.md")]
1533#[inline]
1534pub unsafe fn io_uring_prep_fgetxattr(sqe: *mut io_uring_sqe, fd: c_int, name: *const c_char,
1535                                      value: *mut c_char, len: c_uint)
1536{
1537    io_uring_prep_rw(IORING_OP_FGETXATTR, sqe, fd, name.cast(), len, value as usize as u64);
1538    (*sqe).__liburing_anon_3.xattr_flags = 0;
1539}
1540
1541#[doc = include_str!("../docs/io_uring_prep_fsetxattr.md")]
1542#[inline]
1543pub unsafe fn io_uring_prep_fsetxattr(sqe: *mut io_uring_sqe, fd: c_int, name: *const c_char,
1544                                      value: *mut c_char, flags: c_int, len: c_uint)
1545{
1546    io_uring_prep_rw(IORING_OP_FSETXATTR, sqe, fd, name.cast(), len, value as usize as u64);
1547    (*sqe).__liburing_anon_3.xattr_flags = flags as _;
1548}
1549
1550#[doc = include_str!("../docs/io_uring_prep_socket.md")]
1551#[inline]
1552pub unsafe fn io_uring_prep_socket(sqe: *mut io_uring_sqe, domain: c_int, r#type: c_int,
1553                                   protocol: c_int, flags: c_uint)
1554{
1555    io_uring_prep_rw(IORING_OP_SOCKET,
1556                     sqe,
1557                     domain,
1558                     ptr::null_mut(),
1559                     protocol as u32,
1560                     r#type as u64);
1561    (*sqe).__liburing_anon_3.rw_flags = flags as i32;
1562}
1563
1564#[doc = include_str!("../docs/io_uring_prep_socket_direct.md")]
1565#[inline]
1566pub unsafe fn io_uring_prep_socket_direct(sqe: *mut io_uring_sqe, domain: c_int, r#type: c_int,
1567                                          protocol: c_int, mut file_index: c_uint, flags: c_uint)
1568{
1569    io_uring_prep_rw(IORING_OP_SOCKET,
1570                     sqe,
1571                     domain,
1572                     ptr::null_mut(),
1573                     protocol as u32,
1574                     r#type as u64);
1575    (*sqe).__liburing_anon_3.rw_flags = flags as i32;
1576    /* offset by 1 for allocation */
1577    if file_index == IORING_FILE_INDEX_ALLOC as _ {
1578        file_index -= 1;
1579    }
1580    __io_uring_set_target_fixed_file(sqe, file_index);
1581}
1582
1583#[doc = include_str!("../docs/io_uring_prep_socket_direct_alloc.md")]
1584#[inline]
1585pub unsafe fn io_uring_prep_socket_direct_alloc(sqe: *mut io_uring_sqe, domain: c_int,
1586                                                r#type: c_int, protocol: c_int, flags: c_uint)
1587{
1588    io_uring_prep_rw(IORING_OP_SOCKET,
1589                     sqe,
1590                     domain,
1591                     ptr::null_mut(),
1592                     protocol as u32,
1593                     r#type as u64);
1594    (*sqe).__liburing_anon_3.rw_flags = flags as i32;
1595    __io_uring_set_target_fixed_file(sqe, (IORING_FILE_INDEX_ALLOC - 1) as _);
1596}
1597
1598#[inline]
1599unsafe fn __io_uring_prep_uring_cmd(sqe: *mut io_uring_sqe, op: c_int, cmd_op: u32, fd: c_int)
1600{
1601    (*sqe).opcode = op as _;
1602    (*sqe).fd = fd;
1603    (*sqe).__liburing_anon_1.__liburing_anon_1.cmd_op = cmd_op;
1604    (*sqe).__liburing_anon_1.__liburing_anon_1.__pad1 = 0;
1605    (*sqe).__liburing_anon_2.addr = 0;
1606    (*sqe).len = 0;
1607}
1608
1609#[doc = include_str!("../docs/io_uring_prep_uring_cmd.md")]
1610#[inline]
1611pub unsafe fn io_uring_prep_uring_cmd(sqe: *mut io_uring_sqe, cmd_op: c_int, fd: c_int)
1612{
1613    __io_uring_prep_uring_cmd(sqe, IORING_OP_URING_CMD as _, cmd_op as _, fd);
1614}
1615
1616#[doc = include_str!("../docs/io_uring_prep_uring_cmd128.md")]
1617#[inline]
1618pub unsafe fn io_uring_prep_uring_cmd128(sqe: *mut io_uring_sqe, cmd_op: c_int, fd: c_int)
1619{
1620    __io_uring_prep_uring_cmd(sqe, IORING_OP_URING_CMD128 as _, cmd_op as _, fd);
1621}
1622
1623/*
1624 * Prepare commands for sockets
1625 */
1626#[doc = include_str!("../docs/io_uring_prep_cmd_sock.md")]
1627#[inline]
1628pub unsafe fn io_uring_prep_cmd_sock(sqe: *mut io_uring_sqe, cmd_op: c_int, fd: c_int,
1629                                     level: c_int, optname: c_int, optval: *mut c_void,
1630                                     optlen: c_int)
1631{
1632    io_uring_prep_uring_cmd(sqe, cmd_op as _, fd);
1633
1634    *(*sqe).__liburing_anon_6.optval.as_mut() = optval as usize as _;
1635    (*sqe).__liburing_anon_2.__liburing_anon_1.optname = optname as _;
1636    (*sqe).__liburing_anon_5.optlen = optlen as _;
1637    (*sqe).__liburing_anon_1.__liburing_anon_1.cmd_op = cmd_op as _;
1638    (*sqe).__liburing_anon_2.__liburing_anon_1.level = level as _;
1639}
1640
1641#[doc = include_str!("../docs/io_uring_prep_cmd_getsockname.md")]
1642#[inline]
1643pub unsafe fn io_uring_prep_cmd_getsockname(sqe: *mut io_uring_sqe, fd: c_int,
1644                                            sockaddr: *mut sockaddr, sockaddr_len: *mut socklen_t,
1645                                            peer: c_int)
1646{
1647    io_uring_prep_uring_cmd(sqe, SOCKET_URING_OP_GETSOCKNAME as _, fd);
1648
1649    (*sqe).__liburing_anon_2.addr = sockaddr as _;
1650    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = sockaddr_len as _;
1651    (*sqe).__liburing_anon_5.optlen = peer as _;
1652}
1653
1654#[doc = include_str!("../docs/io_uring_prep_waitid.md")]
1655#[inline]
1656pub unsafe fn io_uring_prep_waitid(sqe: *mut io_uring_sqe, idtype: idtype_t, id: id_t,
1657                                   infop: *mut siginfo_t, options: c_int, flags: c_uint)
1658{
1659    io_uring_prep_rw(IORING_OP_WAITID, sqe, id as _, ptr::null_mut(), idtype, 0);
1660    (*sqe).__liburing_anon_3.waitid_flags = flags;
1661    (*sqe).__liburing_anon_5.file_index = options as _;
1662    (*sqe).__liburing_anon_1.addr2 = infop as usize as u64;
1663}
1664
1665#[doc = include_str!("../docs/io_uring_prep_futex_wake.md")]
1666#[inline]
1667pub unsafe fn io_uring_prep_futex_wake(sqe: *mut io_uring_sqe, futex: *const u32, val: u64,
1668                                       mask: u64, futex_flags: u32, flags: c_uint)
1669{
1670    io_uring_prep_rw(IORING_OP_FUTEX_WAKE, sqe, futex_flags as _, futex.cast(), 0, val);
1671    (*sqe).__liburing_anon_3.futex_flags = flags;
1672    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = mask;
1673}
1674
1675#[doc = include_str!("../docs/io_uring_prep_futex_wait.md")]
1676#[inline]
1677pub unsafe fn io_uring_prep_futex_wait(sqe: *mut io_uring_sqe, futex: *const u32, val: u64,
1678                                       mask: u64, futex_flags: u32, flags: c_uint)
1679{
1680    io_uring_prep_rw(IORING_OP_FUTEX_WAIT, sqe, futex_flags as _, futex.cast(), 0, val);
1681    (*sqe).__liburing_anon_3.futex_flags = flags;
1682    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = mask;
1683}
1684
1685#[doc = include_str!("../docs/io_uring_prep_futex_waitv.md")]
1686#[inline]
1687pub unsafe fn io_uring_prep_futex_waitv(sqe: *mut io_uring_sqe, futex: *const futex_waitv,
1688                                        nr_futex: u32, flags: c_uint)
1689{
1690    io_uring_prep_rw(IORING_OP_FUTEX_WAITV, sqe, 0, futex.cast(), nr_futex, 0);
1691    (*sqe).__liburing_anon_3.futex_flags = flags;
1692}
1693
1694#[doc = include_str!("../docs/io_uring_prep_fixed_fd_install.md")]
1695#[inline]
1696pub unsafe fn io_uring_prep_fixed_fd_install(sqe: *mut io_uring_sqe, fd: c_int, flags: c_uint)
1697{
1698    io_uring_prep_rw(IORING_OP_FIXED_FD_INSTALL, sqe, fd, ptr::null_mut(), 0, 0);
1699
1700    (*sqe).flags = IOSQE_FIXED_FILE as _;
1701    (*sqe).__liburing_anon_3.install_fd_flags = flags;
1702}
1703
1704#[doc = include_str!("../docs/io_uring_prep_ftruncate.md")]
1705#[inline]
1706pub unsafe fn io_uring_prep_ftruncate(sqe: *mut io_uring_sqe, fd: c_int, len: c_longlong)
1707{
1708    io_uring_prep_rw(IORING_OP_FTRUNCATE, sqe, fd, ptr::null_mut(), 0, len as _);
1709}
1710
1711#[doc = include_str!("../docs/io_uring_prep_cmd_discard.md")]
1712#[inline]
1713pub unsafe fn io_uring_prep_cmd_discard(sqe: *mut io_uring_sqe, fd: c_int, offset: u64, nbytes: u64)
1714{
1715    // TODO: really someday fix this
1716    // We need bindgen to actually evaluate this macro's value during generation.
1717    // No idea if hard-coding this value like this is viable in practice.
1718    io_uring_prep_uring_cmd(sqe, ((0x12) << 8) as _ /* BLOCK_URING_CMD_DISCARD */, fd);
1719
1720    (*sqe).__liburing_anon_2.addr = offset;
1721    (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = nbytes;
1722}
1723
1724#[doc = include_str!("../docs/io_uring_prep_pipe.md")]
1725#[inline]
1726pub unsafe fn io_uring_prep_pipe(sqe: *mut io_uring_sqe, fds: *mut c_int, pipe_flags: c_int)
1727{
1728    io_uring_prep_rw(IORING_OP_PIPE, sqe, 0, fds as *const _, 0, 0);
1729    (*sqe).__liburing_anon_3.pipe_flags = pipe_flags as u32;
1730}
1731
1732/* setup pipe directly into the fixed file table */
1733#[doc = include_str!("../docs/io_uring_prep_pipe_direct.md")]
1734#[inline]
1735pub unsafe fn io_uring_prep_pipe_direct(sqe: *mut io_uring_sqe, fds: *mut c_int,
1736                                        pipe_flags: c_int, mut file_index: c_uint)
1737{
1738    io_uring_prep_pipe(sqe, fds, pipe_flags);
1739    /* offset by 1 for allocation */
1740    if file_index == IORING_FILE_INDEX_ALLOC as u32 {
1741        file_index -= 1;
1742    }
1743    __io_uring_set_target_fixed_file(sqe, file_index);
1744}
1745
1746/* Read the kernel's SQ head index with appropriate memory ordering */
1747#[doc(hidden)]
1748#[inline]
1749pub unsafe fn io_uring_load_sq_head(ring: *mut io_uring) -> c_uint
1750{
1751    /*
1752     * Without acquire ordering, we could overwrite a SQE before the kernel
1753     * finished reading it. We don't need the acquire ordering for
1754     * non-SQPOLL since then we drive updates.
1755     */
1756    if (*ring).flags & IORING_SETUP_SQPOLL > 0 {
1757        return io_uring_smp_load_acquire((*ring).sq.khead);
1758    }
1759
1760    *(*ring).sq.khead
1761}
1762
1763/*
1764 * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
1765 * the SQ ring
1766 */
1767#[doc = include_str!("../docs/io_uring_sq_ready.md")]
1768#[inline]
1769pub unsafe fn io_uring_sq_ready(ring: *mut io_uring) -> c_uint
1770{
1771    (*ring).sq.sqe_tail - io_uring_load_sq_head(ring)
1772}
1773
1774/*
1775 * Returns how much space is left in the SQ ring.
1776 */
1777#[doc = include_str!("../docs/io_uring_sq_space_left.md")]
1778#[inline]
1779pub unsafe fn io_uring_sq_space_left(ring: *mut io_uring) -> c_uint
1780{
1781    (*ring).sq.ring_entries - io_uring_sq_ready(ring)
1782}
1783
1784/*
1785 * Returns the bit shift needed to index the SQ.
1786 * This shift is 1 for rings with big SQEs, and 0 for rings with normal SQEs.
1787 * SQE `index` can be computed as &sq.sqes[(index & sq.ring_mask) << sqe_shift].
1788 */
1789#[doc(hidden)]
1790#[must_use]
1791#[inline]
1792pub fn io_uring_sqe_shift_from_flags(flags: c_uint) -> c_uint
1793{
1794    u32::from(flags & IORING_SETUP_SQE128 != 0)
1795}
1796
1797#[doc(hidden)]
1798#[inline]
1799pub unsafe fn io_uring_sqe_shift(ring: *mut io_uring) -> c_uint
1800{
1801    io_uring_sqe_shift_from_flags((*ring).flags)
1802}
1803
1804/*
1805 * Only applicable when using SQPOLL - allows the caller to wait for space
1806 * to free up in the SQ ring, which happens when the kernel side thread has
1807 * consumed one or more entries. If the SQ ring is currently non-full, no
1808 * action is taken. Note: may return -EINVAL if the kernel doesn't support
1809 * this feature.
1810 */
1811#[doc = include_str!("../docs/io_uring_sqring_wait.md")]
1812#[inline]
1813pub unsafe fn io_uring_sqring_wait(ring: *mut io_uring) -> c_int
1814{
1815    if (*ring).flags & IORING_SETUP_SQPOLL == 0 {
1816        return 0;
1817    }
1818    if io_uring_sq_space_left(ring) > 0 {
1819        return 0;
1820    }
1821
1822    __io_uring_sqring_wait(ring)
1823}
1824
1825/*
1826 * Returns how many unconsumed entries are ready in the CQ ring
1827 */
1828#[doc = include_str!("../docs/io_uring_cq_ready.md")]
1829#[inline]
1830pub unsafe fn io_uring_cq_ready(ring: *mut io_uring) -> c_uint
1831{
1832    io_uring_smp_load_acquire((*ring).cq.ktail) - *(*ring).cq.khead
1833}
1834
1835/*
1836 * Returns true if there are overflow entries waiting to be flushed onto
1837 * the CQ ring
1838 */
1839#[doc = include_str!("../docs/io_uring_cq_has_overflow.md")]
1840#[inline]
1841pub unsafe fn io_uring_cq_has_overflow(ring: *mut io_uring) -> bool
1842{
1843    IO_URING_READ_ONCE((*ring).sq.kflags) & IORING_SQ_CQ_OVERFLOW > 0
1844}
1845
1846/*
1847 * Returns true if the eventfd notification is currently enabled
1848 */
1849#[doc = include_str!("../docs/io_uring_cq_eventfd_enabled.md")]
1850#[inline]
1851pub unsafe fn io_uring_cq_eventfd_enabled(ring: *mut io_uring) -> bool
1852{
1853    if (*ring).cq.kflags.is_null() {
1854        return true;
1855    }
1856    (*(*ring).cq.kflags & IORING_CQ_EVENTFD_DISABLED) == 0
1857}
1858
1859/*
1860 * Toggle eventfd notification on or off, if an eventfd is registered with
1861 * the ring.
1862 */
1863#[doc = include_str!("../docs/io_uring_cq_eventfd_toggle.md")]
1864#[inline]
1865pub unsafe fn io_uring_cq_eventfd_toggle(ring: *mut io_uring, enabled: bool) -> c_int
1866{
1867    if enabled == io_uring_cq_eventfd_enabled(ring) {
1868        return 0;
1869    }
1870
1871    if (*ring).cq.kflags.is_null() {
1872        return -(EOPNOTSUPP as c_int);
1873    }
1874
1875    let mut flags = *(*ring).cq.kflags;
1876
1877    if enabled {
1878        flags &= !IORING_CQ_EVENTFD_DISABLED;
1879    } else {
1880        flags |= IORING_CQ_EVENTFD_DISABLED;
1881    }
1882
1883    IO_URING_WRITE_ONCE((*ring).cq.kflags, flags);
1884
1885    0
1886}
1887
1888/*
1889 * Return an IO completion, waiting for 'wait_nr' completions if one isn't
1890 * readily available. Returns 0 with cqe_ptr filled in on success, -errno on
1891 * failure.
1892 */
1893#[doc = include_str!("../docs/io_uring_wait_cqe_nr.md")]
1894#[inline]
1895pub unsafe fn io_uring_wait_cqe_nr(ring: *mut io_uring, cqe_ptr: *mut *mut io_uring_cqe,
1896                                   wait_nr: c_uint)
1897                                   -> c_int
1898{
1899    __io_uring_get_cqe(ring, cqe_ptr, 0, wait_nr, ptr::null_mut())
1900}
1901
1902#[inline]
1903unsafe fn io_uring_skip_cqe(ring: *mut io_uring, cqe: *mut io_uring_cqe, err: *mut c_int) -> bool
1904{
1905    'out: {
1906        if (*cqe).flags & IORING_CQE_F_SKIP != 0 {
1907            break 'out;
1908        }
1909
1910        if (*ring).features & IORING_FEAT_EXT_ARG != 0 {
1911            return false;
1912        }
1913
1914        if (*cqe).user_data != LIBURING_UDATA_TIMEOUT {
1915            return false;
1916        }
1917
1918        if (*cqe).res < 0 {
1919            *err = (*cqe).res;
1920        }
1921    }
1922
1923    io_uring_cq_advance(ring, io_uring_cqe_nr(cqe));
1924    *err == 0
1925}
1926
1927/*
1928 * Internal helper, don't use directly in applications. Use one of the
1929 * "official" versions of this, io_uring_peek_cqe(), io_uring_wait_cqe(),
1930 * or io_uring_wait_cqes*().
1931 */
1932#[doc(hidden)]
1933#[inline]
1934pub unsafe fn __io_uring_peek_cqe(ring: *mut io_uring, cqe_ptr: *mut *mut io_uring_cqe,
1935                                  nr_available: *mut c_uint)
1936                                  -> c_int
1937{
1938    let mut cqe;
1939    let mut err = 0;
1940
1941    let mut available;
1942    let mask = (*ring).cq.ring_mask;
1943    let shift = io_uring_cqe_shift(ring);
1944
1945    loop {
1946        let tail = io_uring_smp_load_acquire((*ring).cq.ktail);
1947
1948        /*
1949         * The acquire ordering on the tail load pairs with the kernel
1950         * side publishing CQEs, and guarantees the contents of any
1951         * entry in [head, tail). The CQ head is only ever written by
1952         * the application, so a plain load is sufficient.
1953         */
1954        let head = *((*ring).cq.khead);
1955
1956        cqe = ptr::null_mut();
1957        available = tail - head;
1958        if available == 0 {
1959            break;
1960        }
1961
1962        cqe = &raw mut *(*ring).cq.cqes.add(((head & mask) << shift) as usize);
1963        if !io_uring_skip_cqe(ring, cqe, &raw mut err) {
1964            /*
1965             * If an error was set, the CQE was an internal
1966             * timeout and has already been consumed - don't
1967             * return a pointer to it.
1968             */
1969            if err != 0 {
1970                cqe = ptr::null_mut();
1971            }
1972            break;
1973        }
1974    }
1975
1976    *cqe_ptr = cqe;
1977    if !nr_available.is_null() {
1978        *nr_available = available;
1979    }
1980    err
1981}
1982
1983/*
1984 * Return an IO completion, if one is readily available. Returns 0 with
1985 * cqe_ptr filled in on success, -errno on failure.
1986 */
1987#[doc = include_str!("../docs/io_uring_peek_cqe.md")]
1988#[inline]
1989pub unsafe fn io_uring_peek_cqe(ring: *mut io_uring, cqe_ptr: *mut *mut io_uring_cqe) -> c_int
1990{
1991    if __io_uring_peek_cqe(ring, cqe_ptr, ptr::null_mut()) == 0 {
1992        if !(*cqe_ptr).is_null() {
1993            return 0;
1994        }
1995
1996        /*
1997         * If the CQ is empty and there's nothing the kernel could
1998         * flush to it (no IOPOLL completions to reap, no overflown
1999         * CQEs, no pending task work), avoid the round trip into
2000         * the full get_cqe machinery.
2001         */
2002        if ((*ring).flags & IORING_SETUP_IOPOLL) == 0
2003           && (IO_URING_READ_ONCE((*ring).sq.kflags) & (IORING_SQ_CQ_OVERFLOW | IORING_SQ_TASKRUN))
2004              == 0
2005        {
2006            return -(EAGAIN as c_int);
2007        }
2008    }
2009
2010    io_uring_wait_cqe_nr(ring, cqe_ptr, 0)
2011}
2012
2013/*
2014 * Return an IO completion, waiting for it if necessary. Returns 0 with
2015 * cqe_ptr filled in on success, -errno on failure.
2016 */
2017#[doc = include_str!("../docs/io_uring_wait_cqe.md")]
2018#[inline]
2019pub unsafe fn io_uring_wait_cqe(ring: *mut io_uring, cqe_ptr: *mut *mut io_uring_cqe) -> c_int
2020{
2021    if __io_uring_peek_cqe(ring, cqe_ptr, ptr::null_mut()) == 0 && !(*cqe_ptr).is_null() {
2022        return 0;
2023    }
2024
2025    io_uring_wait_cqe_nr(ring, cqe_ptr, 1)
2026}
2027
2028/*
2029 * Return an sqe to fill. Application must later call io_uring_submit()
2030 * when it's ready to tell the kernel about it. The caller may call this
2031 * function multiple times before calling io_uring_submit().
2032 *
2033 * Returns a vacant sqe, or NULL if we're full.
2034 */
2035#[doc(hidden)]
2036#[inline]
2037pub unsafe fn _io_uring_get_sqe(ring: *mut io_uring) -> *mut io_uring_sqe
2038{
2039    let sq = &raw mut (*ring).sq;
2040
2041    let head = io_uring_load_sq_head(ring);
2042    let tail = (*sq).sqe_tail;
2043
2044    if tail - head >= (*sq).ring_entries {
2045        return ptr::null_mut();
2046    }
2047
2048    let offset = (tail & (*sq).ring_mask) << io_uring_sqe_shift(ring);
2049    let sqe = (*sq).sqes.add(offset as usize);
2050    (*sq).sqe_tail = tail + 1;
2051    io_uring_initialize_sqe(sqe);
2052    sqe
2053}
2054
2055/*
2056 * Return the appropriate mask for a buffer ring of size 'ring_entries'
2057 */
2058#[doc = include_str!("../docs/io_uring_buf_ring_mask.md")]
2059#[must_use]
2060#[inline]
2061pub fn io_uring_buf_ring_mask(ring_entries: u32) -> c_int
2062{
2063    (ring_entries - 1) as _
2064}
2065
2066#[doc = include_str!("../docs/io_uring_buf_ring_init.md")]
2067#[inline]
2068pub unsafe fn io_uring_buf_ring_init(br: *mut io_uring_buf_ring)
2069{
2070    (*br).__liburing_anon_1.__liburing_anon_1.as_mut().tail = 0;
2071}
2072
2073/*
2074 * Assign 'buf' with the addr/len/buffer ID supplied
2075 */
2076#[doc = include_str!("../docs/io_uring_buf_ring_add.md")]
2077#[inline]
2078pub unsafe fn io_uring_buf_ring_add(br: *mut io_uring_buf_ring, addr: *mut c_void, len: c_uint,
2079                                    bid: c_ushort, mask: c_int, buf_offset: c_int)
2080{
2081    let tail = (*br).__liburing_anon_1.__liburing_anon_1.as_ref().tail;
2082    let buf = (*br).__liburing_anon_1
2083                   .bufs
2084                   .as_mut()
2085                   .as_mut_ptr()
2086                   .add(((i32::from(tail) + buf_offset) & mask) as usize);
2087
2088    (*buf).addr = addr as usize as u64;
2089    (*buf).len = len;
2090    (*buf).bid = bid;
2091}
2092
2093/*
2094 * Make 'count' new buffers visible to the kernel. Called after
2095 * io_uring_buf_ring_add() has been called 'count' times to fill in new
2096 * buffers.
2097 */
2098#[doc = include_str!("../docs/io_uring_buf_ring_advance.md")]
2099#[inline]
2100pub unsafe fn io_uring_buf_ring_advance(br: *mut io_uring_buf_ring, count: c_int)
2101{
2102    let tail = (*br).__liburing_anon_1.__liburing_anon_1.as_ref().tail;
2103    let new_tail = tail.wrapping_add(count as u16);
2104
2105    io_uring_smp_store_release(&raw mut (*br).__liburing_anon_1.__liburing_anon_1.as_mut().tail,
2106                               new_tail);
2107}
2108
2109#[doc = include_str!("../docs/io_uring_buf_ring_cq_advance.md")]
2110#[inline]
2111pub unsafe fn __io_uring_buf_ring_cq_advance(ring: *mut io_uring, br: *mut io_uring_buf_ring,
2112                                             cq_count: i32, buf_count: c_int)
2113{
2114    io_uring_buf_ring_advance(br, buf_count);
2115    io_uring_cq_advance(ring, cq_count as _);
2116}
2117
2118/*
2119 * Make 'count' new buffers visible to the kernel while at the same time
2120 * advancing the CQ ring seen entries. This can be used when the application
2121 * is using ring provided buffers and returns buffers while processing CQEs,
2122 * avoiding an extra atomic when needing to increment both the CQ ring and
2123 * the ring buffer index at the same time.
2124 */
2125#[doc = include_str!("../docs/io_uring_buf_ring_cq_advance.md")]
2126#[inline]
2127pub unsafe fn io_uring_buf_ring_cq_advance(ring: *mut io_uring, br: *mut io_uring_buf_ring,
2128                                           count: c_int)
2129{
2130    __io_uring_buf_ring_cq_advance(ring, br, count, count);
2131}
2132
2133#[doc = include_str!("../docs/io_uring_buf_ring_available.md")]
2134#[inline]
2135pub unsafe fn io_uring_buf_ring_available(ring: *mut io_uring, br: *mut io_uring_buf_ring,
2136                                          bgid: c_ushort)
2137                                          -> c_int
2138{
2139    let mut head = 0;
2140    let ret = io_uring_buf_ring_head(ring, bgid.into(), &raw mut head);
2141    if ret > 0 {
2142        return ret;
2143    }
2144    c_int::from((*br).__liburing_anon_1.__liburing_anon_1.as_mut().tail - head)
2145}
2146
2147#[doc = include_str!("../docs/io_uring_get_sqe.md")]
2148#[inline]
2149pub unsafe fn io_uring_get_sqe(ring: *mut io_uring) -> *mut io_uring_sqe
2150{
2151    _io_uring_get_sqe(ring)
2152}
2153
2154/*
2155 * Return a 128B sqe to fill. Applications must later call io_uring_submit()
2156 * when it's ready to tell the kernel about it. The caller may call this
2157 * function multiple times before calling io_uring_submit().
2158 *
2159 * Returns a vacant 128B sqe, or NULL if we're full. If the current tail is the
2160 * last entry in the ring, this function will insert a nop + skip complete such
2161 * that the 128b entry wraps back to the beginning of the queue for a
2162 * contiguous big sq entry. It's up to the caller to use a 128b opcode in order
2163 * for the kernel to know how to advance its sq head pointer.
2164 */
2165#[doc = include_str!("../docs/io_uring_get_sqe128.md")]
2166#[inline]
2167pub unsafe fn io_uring_get_sqe128(ring: *mut io_uring) -> *mut io_uring_sqe
2168{
2169    let sq = &raw mut (*ring).sq;
2170
2171    let head = io_uring_load_sq_head(ring);
2172    let mut tail = (*sq).sqe_tail;
2173
2174    if (*ring).flags & IORING_SETUP_SQE128 != 0 {
2175        return io_uring_get_sqe(ring);
2176    }
2177
2178    if (*ring).flags & IORING_SETUP_SQE_MIXED == 0 {
2179        return ptr::null_mut();
2180    }
2181
2182    let mut sqe: *mut io_uring_sqe;
2183    if (tail + 1) & (*sq).ring_mask == 0 {
2184        if (tail + 2) - head >= (*sq).ring_entries {
2185            return ptr::null_mut();
2186        }
2187
2188        sqe = _io_uring_get_sqe(ring);
2189        io_uring_prep_nop(sqe);
2190        (*sqe).flags |= IOSQE_CQE_SKIP_SUCCESS as u8;
2191        tail = (*sq).sqe_tail;
2192    } else if (tail + 1) - head >= (*sq).ring_entries {
2193        return ptr::null_mut();
2194    }
2195
2196    sqe = &raw mut *(*sq).sqes.add((tail & (*sq).ring_mask) as usize);
2197    (*sq).sqe_tail = tail + 2;
2198    io_uring_initialize_sqe(sqe);
2199    sqe
2200}
2201
2202//-----------------------------------------------------------------------------
2203
2204impl From<Duration> for timespec
2205{
2206    #[cfg(not(any(target_arch = "powerpc", target_arch = "arm")))]
2207    #[inline]
2208    fn from(duration: Duration) -> Self
2209    {
2210        let mut ts = unsafe { zeroed::<timespec>() };
2211        ts.tv_sec = duration.as_secs() as _;
2212        ts.tv_nsec = duration.subsec_nanos().into();
2213        ts
2214    }
2215
2216    #[cfg(any(target_arch = "powerpc", target_arch = "arm"))]
2217    #[inline]
2218    fn from(duration: Duration) -> Self
2219    {
2220        let mut ts = unsafe { zeroed::<timespec>() };
2221        ts.tv_sec = duration.as_secs() as _;
2222        ts.tv_nsec = duration.subsec_nanos().try_into().unwrap();
2223        ts
2224    }
2225}
2226
2227impl From<Duration> for __kernel_timespec
2228{
2229    #[inline]
2230    fn from(duration: Duration) -> Self
2231    {
2232        let mut ts = unsafe { zeroed::<__kernel_timespec>() };
2233        ts.tv_sec = duration.as_secs() as _;
2234        ts.tv_nsec = duration.subsec_nanos().into();
2235        ts
2236    }
2237}