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
13mod uring;
14
15use core::{
16 ffi::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ushort, c_void},
17 mem::{self, zeroed},
18 ptr,
19 sync::atomic::{
20 AtomicU16, AtomicU32,
21 Ordering::{self, Acquire, Relaxed, Release},
22 },
23 time::Duration,
24};
25
26pub use uring::*;
27
28const LIBURING_UDATA_TIMEOUT: u64 = u64::MAX;
29
30trait Atomic: Copy
31{
32 unsafe fn store(p: *mut Self, val: Self, order: Ordering);
33 unsafe fn load(p: *mut Self, order: Ordering) -> Self;
34}
35
36impl Atomic for u32
37{
38 #[inline]
39 unsafe fn store(p: *mut u32, val: u32, order: Ordering)
40 {
41 AtomicU32::from_ptr(p).store(val, order);
42 }
43
44 #[inline]
45 unsafe fn load(p: *mut u32, order: Ordering) -> u32
46 {
47 AtomicU32::from_ptr(p).load(order)
48 }
49}
50
51impl Atomic for u16
52{
53 #[inline]
54 unsafe fn store(p: *mut u16, val: u16, order: Ordering)
55 {
56 AtomicU16::from_ptr(p).store(val, order);
57 }
58
59 #[inline]
60 unsafe fn load(p: *mut u16, order: Ordering) -> u16
61 {
62 AtomicU16::from_ptr(p).load(order)
63 }
64}
65
66unsafe fn io_uring_smp_store_release<T: Atomic>(p: *mut T, v: T)
67{
68 Atomic::store(p, v, Release);
69}
70
71unsafe fn io_uring_smp_load_acquire<T: Atomic>(p: *const T) -> T
72{
73 Atomic::load(p.cast_mut(), Acquire)
74}
75
76unsafe fn IO_URING_READ_ONCE<T: Atomic>(var: *const T) -> T
77{
78 Atomic::load(var.cast_mut(), Relaxed)
79}
80
81unsafe fn IO_URING_WRITE_ONCE<T: Atomic>(var: *mut T, val: T)
82{
83 Atomic::store(var, val, Relaxed);
84}
85
86#[must_use]
91#[inline]
92unsafe fn uring_ptr_to_u64(ptr: *const c_void) -> u64
93{
94 ptr as u64
95}
96
97#[inline]
98pub unsafe fn io_uring_opcode_supported(p: *mut io_uring_probe, op: c_int) -> c_int
99{
100 if op < 0 || op > (*p).last_op.into() {
101 return 0;
102 }
103
104 i32::from((*(*p).ops.as_ptr().add(op as _)).flags & IO_URING_OP_SUPPORTED as u16 != 0)
105}
106
107#[must_use]
113#[inline]
114pub fn io_uring_cqe_shift_from_flags(flags: c_uint) -> c_uint
115{
116 u32::from(flags & IORING_SETUP_CQE32 != 0)
117}
118
119#[must_use]
120#[inline]
121pub unsafe fn io_uring_cqe_shift(ring: *const io_uring) -> c_uint
122{
123 io_uring_cqe_shift_from_flags((*ring).flags)
124}
125
126#[must_use]
127#[inline]
128pub unsafe fn io_uring_cqe_nr(cqe: *const io_uring_cqe) -> c_uint
129{
130 let shift = i32::from((*cqe).flags & IORING_CQE_F_32 != 0);
131 1 << shift
132}
133
134#[must_use]
135#[inline]
136pub unsafe fn io_uring_cqe_iter_init(ring: *const io_uring) -> io_uring_cqe_iter
137{
138 io_uring_cqe_iter { cqes: (*ring).cq.cqes,
139 mask: (*ring).cq.ring_mask,
140 shift: io_uring_cqe_shift(ring),
141 head: *(*ring).cq.khead,
142 tail: io_uring_smp_load_acquire((*ring).cq.ktail) }
144}
145
146#[inline]
147pub unsafe fn io_uring_cqe_iter_next(iter: *mut io_uring_cqe_iter, cqe: *mut *mut io_uring_cqe)
148 -> bool
149{
150 if (*iter).head == (*iter).tail {
151 return false;
152 }
153
154 let head = (*iter).head;
155 (*iter).head += 1;
156
157 let offset = (head & (*iter).mask) << (*iter).shift;
158 *cqe = (*iter).cqes.add(offset as usize);
159
160 if (*(*cqe)).flags & IORING_CQE_F_32 > 0 {
161 (*iter).head += 1;
162 }
163
164 true
165}
166
167pub unsafe fn io_uring_for_each_cqe<F>(ring: *mut io_uring, mut f: F)
168 where F: FnMut(*mut io_uring_cqe)
169{
170 let mut iter = io_uring_cqe_iter_init(ring);
171 let mut cqe = ptr::null_mut::<io_uring_cqe>();
172 while io_uring_cqe_iter_next(&raw mut iter, &raw mut cqe) {
173 f(cqe);
174 }
175}
176
177#[inline]
181pub unsafe fn io_uring_cq_advance(ring: *mut io_uring, nr: c_uint)
182{
183 if nr > 0 {
184 let cq = &raw mut (*ring).cq;
185
186 io_uring_smp_store_release((*cq).khead, *(*cq).khead + nr);
191 }
192}
193
194#[inline]
199pub unsafe fn io_uring_cqe_seen(ring: *mut io_uring, cqe: *mut io_uring_cqe)
200{
201 if !cqe.is_null() {
202 io_uring_cq_advance(ring, io_uring_cqe_nr(cqe));
203 }
204}
205
206#[inline]
215pub unsafe fn io_uring_sqe_set_data(sqe: *mut io_uring_sqe, data: *mut c_void)
216{
217 (*sqe).user_data = data as u64;
218}
219
220#[must_use]
221#[inline]
222pub unsafe fn io_uring_cqe_get_data(cqe: *const io_uring_cqe) -> *mut c_void
223{
224 (*cqe).user_data as *mut c_void
225}
226
227#[inline]
233pub unsafe fn io_uring_sqe_set_data64(sqe: *mut io_uring_sqe, data: u64)
234{
235 (*sqe).user_data = data;
236}
237
238#[must_use]
239#[inline]
240pub unsafe fn io_uring_cqe_get_data64(cqe: *const io_uring_cqe) -> u64
241{
242 (*cqe).user_data
243}
244
245#[inline]
246pub unsafe fn io_uring_sqe_set_flags(sqe: *mut io_uring_sqe, flags: c_uint)
247{
248 (*sqe).flags = flags as u8;
249}
250
251#[inline]
252pub unsafe fn io_uring_sqe_set_buf_group(sqe: *mut io_uring_sqe, bgid: c_int)
253{
254 (*sqe).__liburing_anon_4.buf_group = bgid as u16;
255}
256
257#[inline]
258unsafe fn __io_uring_set_target_fixed_file(sqe: *mut io_uring_sqe, file_index: c_uint)
259{
260 (*sqe).__liburing_anon_5.file_index = file_index + 1;
262}
263
264#[inline]
265pub unsafe fn io_uring_initialize_sqe(sqe: *mut io_uring_sqe)
266{
267 (*sqe).flags = 0;
268 (*sqe).ioprio = 0;
269 (*sqe).__liburing_anon_3.rw_flags = 0;
270 (*sqe).__liburing_anon_4.buf_index = 0;
271 (*sqe).personality = 0;
272 (*sqe).__liburing_anon_5.file_index = 0;
273 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = 0;
274 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().__pad2[0] = 0;
275}
276
277#[inline]
278pub unsafe fn io_uring_prep_rw(op: c_uint, sqe: *mut io_uring_sqe, fd: c_int, addr: *const c_void,
279 len: c_uint, offset: __u64)
280{
281 (*sqe).opcode = op as u8;
282 (*sqe).fd = fd;
283 (*sqe).__liburing_anon_1.off = offset;
284 (*sqe).__liburing_anon_2.addr = addr as u64;
285 (*sqe).len = len;
286}
287
288#[inline]
310pub unsafe fn io_uring_prep_splice(sqe: *mut io_uring_sqe, fd_in: c_int, off_in: i64,
311 fd_out: c_int, off_out: i64, nbytes: c_uint,
312 splice_flags: c_uint)
313{
314 io_uring_prep_rw(IORING_OP_SPLICE, sqe, fd_out, ptr::null_mut(), nbytes, off_out as u64);
315 (*sqe).__liburing_anon_2.splice_off_in = off_in as u64;
316 (*sqe).__liburing_anon_5.splice_fd_in = fd_in;
317 (*sqe).__liburing_anon_3.splice_flags = splice_flags;
318}
319
320#[inline]
321pub unsafe fn io_uring_prep_tee(sqe: *mut io_uring_sqe, fd_in: c_int, fd_out: c_int,
322 nbytes: c_uint, splice_flags: c_uint)
323{
324 io_uring_prep_rw(IORING_OP_TEE, sqe, fd_out, ptr::null_mut(), nbytes, 0);
325 (*sqe).__liburing_anon_2.splice_off_in = 0;
326 (*sqe).__liburing_anon_5.splice_fd_in = fd_in;
327 (*sqe).__liburing_anon_3.splice_flags = splice_flags;
328}
329
330#[inline]
331pub unsafe fn io_uring_prep_readv(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
332 nr_vecs: c_uint, offset: u64)
333{
334 io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs.cast(), nr_vecs, offset);
335}
336
337#[inline]
338pub unsafe fn io_uring_prep_readv2(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
339 nr_vecs: c_uint, offset: u64, flags: c_int)
340{
341 io_uring_prep_readv(sqe, fd, iovecs, nr_vecs, offset);
342 (*sqe).__liburing_anon_3.rw_flags = flags;
343}
344
345#[inline]
346pub unsafe fn io_uring_prep_read_fixed(sqe: *mut io_uring_sqe, fd: c_int, buf: *mut c_void,
347 nbytes: c_uint, offset: u64, buf_index: c_int)
348{
349 io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset);
350 (*sqe).__liburing_anon_4.buf_index = buf_index as u16;
351}
352
353#[inline]
354pub unsafe fn io_uring_prep_readv_fixed(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
355 nr_vecs: c_uint, offset: u64, flags: c_int,
356 buf_index: c_int)
357{
358 io_uring_prep_readv2(sqe, fd, iovecs, nr_vecs, offset, flags);
359 (*sqe).opcode = IORING_OP_READV_FIXED as _;
360 (*sqe).__liburing_anon_4.buf_index = buf_index as u16;
361}
362
363#[inline]
364pub unsafe fn io_uring_prep_writev(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
365 nr_vecs: c_uint, offset: u64)
366{
367 io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs.cast(), nr_vecs, offset);
368}
369
370#[inline]
371pub unsafe fn io_uring_prep_writev2(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
372 nr_vecs: c_uint, offset: u64, flags: c_int)
373{
374 io_uring_prep_writev(sqe, fd, iovecs, nr_vecs, offset);
375 (*sqe).__liburing_anon_3.rw_flags = flags;
376}
377
378#[inline]
379pub unsafe fn io_uring_prep_write_fixed(sqe: *mut io_uring_sqe, fd: c_int, buf: *const c_void,
380 nbytes: c_uint, offset: u64, buf_index: c_int)
381{
382 io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset);
383 (*sqe).__liburing_anon_4.buf_index = buf_index as u16;
384}
385
386#[inline]
387pub unsafe fn io_uring_prep_writev_fixed(sqe: *mut io_uring_sqe, fd: c_int, iovecs: *const iovec,
388 nr_vecs: c_uint, offset: u64, flags: c_int,
389 buf_index: c_int)
390{
391 io_uring_prep_writev2(sqe, fd, iovecs, nr_vecs, offset, flags);
392 (*sqe).opcode = IORING_OP_WRITEV_FIXED as _;
393 (*sqe).__liburing_anon_4.buf_index = buf_index as u16;
394}
395
396#[inline]
397pub unsafe fn io_uring_prep_recvmsg(sqe: *mut io_uring_sqe, fd: c_int, msg: *mut msghdr,
398 flags: c_uint)
399{
400 io_uring_prep_rw(IORING_OP_RECVMSG, sqe, fd, msg.cast(), 1, 0);
401 (*sqe).__liburing_anon_3.msg_flags = flags;
402}
403
404#[inline]
405pub unsafe fn io_uring_prep_recvmsg_multishot(sqe: *mut io_uring_sqe, fd: c_int, msg: *mut msghdr,
406 flags: c_uint)
407{
408 io_uring_prep_recvmsg(sqe, fd, msg, flags);
409 (*sqe).ioprio |= IORING_RECV_MULTISHOT as u16;
410}
411
412#[inline]
413pub unsafe fn io_uring_prep_sendmsg(sqe: *mut io_uring_sqe, fd: c_int, msg: *const msghdr,
414 flags: c_uint)
415{
416 io_uring_prep_rw(IORING_OP_SENDMSG, sqe, fd, msg.cast(), 1, 0);
417 (*sqe).__liburing_anon_3.msg_flags = flags;
418}
419
420#[must_use]
421#[inline]
422pub fn __io_uring_prep_poll_mask(poll_mask: c_uint) -> c_uint
423{
424 poll_mask.to_le()
425}
426
427#[inline]
428pub unsafe fn io_uring_prep_poll_add(sqe: *mut io_uring_sqe, fd: c_int, poll_mask: c_uint)
429{
430 io_uring_prep_rw(IORING_OP_POLL_ADD, sqe, fd, ptr::null_mut(), 0, 0);
431 (*sqe).__liburing_anon_3.poll32_events = __io_uring_prep_poll_mask(poll_mask);
432}
433
434#[inline]
435pub unsafe fn io_uring_prep_poll_multishot(sqe: *mut io_uring_sqe, fd: c_int, poll_mask: c_uint)
436{
437 io_uring_prep_poll_add(sqe, fd, poll_mask);
438 (*sqe).len = IORING_POLL_ADD_MULTI;
439}
440
441#[inline]
442pub unsafe fn io_uring_prep_poll_remove(sqe: *mut io_uring_sqe, user_data: u64)
443{
444 io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, ptr::null_mut(), 0, 0);
445 (*sqe).__liburing_anon_2.addr = user_data;
446}
447
448#[inline]
449pub unsafe fn io_uring_prep_poll_update(sqe: *mut io_uring_sqe, old_user_data: u64,
450 new_user_data: u64, poll_mask: c_uint, flags: c_uint)
451{
452 io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, ptr::null_mut(), flags, new_user_data);
453 (*sqe).__liburing_anon_2.addr = old_user_data;
454 (*sqe).__liburing_anon_3.poll32_events = __io_uring_prep_poll_mask(poll_mask);
455}
456
457#[inline]
458pub unsafe fn io_uring_prep_fsync(sqe: *mut io_uring_sqe, fd: c_int, fsync_flags: c_uint)
459{
460 io_uring_prep_rw(IORING_OP_FSYNC, sqe, fd, ptr::null_mut(), 0, 0);
461 (*sqe).__liburing_anon_3.fsync_flags = fsync_flags;
462}
463
464#[inline]
465pub unsafe fn io_uring_prep_nop(sqe: *mut io_uring_sqe)
466{
467 io_uring_prep_rw(IORING_OP_NOP, sqe, -1, ptr::null_mut(), 0, 0);
468}
469
470#[inline]
471pub unsafe fn io_uring_prep_nop128(sqe: *mut io_uring_sqe)
472{
473 io_uring_prep_rw(IORING_OP_NOP128, sqe, -1, ptr::null_mut(), 0, 0);
474}
475
476#[inline]
477pub unsafe fn io_uring_prep_timeout(sqe: *mut io_uring_sqe, ts: *const __kernel_timespec,
478 count: c_uint, flags: c_uint)
479{
480 io_uring_prep_rw(IORING_OP_TIMEOUT, sqe, -1, ts.cast(), 1, count.into());
481 (*sqe).__liburing_anon_3.timeout_flags = flags;
482}
483
484#[inline]
485pub unsafe fn io_uring_prep_timeout_remove(sqe: *mut io_uring_sqe, user_data: __u64, flags: c_uint)
486{
487 io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, ptr::null_mut(), 0, 0);
488 (*sqe).__liburing_anon_2.addr = user_data;
489 (*sqe).__liburing_anon_3.timeout_flags = flags;
490}
491
492#[inline]
493pub unsafe fn io_uring_prep_timeout_update(sqe: *mut io_uring_sqe, ts: *const __kernel_timespec,
494 user_data: __u64, flags: c_uint)
495{
496 io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, ptr::null_mut(), 0, ts as u64);
497 (*sqe).__liburing_anon_2.addr = user_data;
498 (*sqe).__liburing_anon_3.timeout_flags = flags | IORING_TIMEOUT_UPDATE;
499}
500
501#[inline]
502pub unsafe fn io_uring_prep_accept(sqe: *mut io_uring_sqe, fd: c_int, addr: *mut sockaddr,
503 addrlen: *mut socklen_t, flags: c_int)
504{
505 io_uring_prep_rw(IORING_OP_ACCEPT, sqe, fd, addr.cast(), 0, uring_ptr_to_u64(addrlen.cast()));
506 (*sqe).__liburing_anon_3.accept_flags = flags as u32;
507}
508
509#[inline]
511pub unsafe fn io_uring_prep_accept_direct(sqe: *mut io_uring_sqe, fd: c_int, addr: *mut sockaddr,
512 addrlen: *mut socklen_t, flags: c_int,
513 mut file_index: c_uint)
514{
515 io_uring_prep_accept(sqe, fd, addr, addrlen, flags);
516 if file_index == IORING_FILE_INDEX_ALLOC as _ {
518 file_index -= 1;
519 }
520 __io_uring_set_target_fixed_file(sqe, file_index);
521}
522
523#[inline]
524pub unsafe fn io_uring_prep_multishot_accept(sqe: *mut io_uring_sqe, fd: c_int,
525 addr: *mut sockaddr, addrlen: *mut socklen_t,
526 flags: c_int)
527{
528 io_uring_prep_accept(sqe, fd, addr, addrlen, flags);
529 (*sqe).ioprio |= IORING_ACCEPT_MULTISHOT as u16;
530}
531
532#[inline]
534pub unsafe fn io_uring_prep_multishot_accept_direct(sqe: *mut io_uring_sqe, fd: c_int,
535 addr: *mut sockaddr, addrlen: *mut socklen_t,
536 flags: c_int)
537{
538 io_uring_prep_multishot_accept(sqe, fd, addr, addrlen, flags);
539 __io_uring_set_target_fixed_file(sqe, (IORING_FILE_INDEX_ALLOC - 1) as u32);
540}
541
542#[inline]
543pub unsafe fn io_uring_prep_cancel64(sqe: *mut io_uring_sqe, user_data: u64, flags: c_int)
544{
545 io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, -1, ptr::null_mut(), 0, 0);
546 (*sqe).__liburing_anon_2.addr = user_data;
547 (*sqe).__liburing_anon_3.cancel_flags = flags as u32;
548}
549
550#[inline]
551pub unsafe fn io_uring_prep_cancel(sqe: *mut io_uring_sqe, user_data: *const c_void, flags: c_int)
552{
553 io_uring_prep_cancel64(sqe, user_data as usize as u64, flags);
554}
555
556#[inline]
557pub unsafe fn io_uring_prep_cancel_fd(sqe: *mut io_uring_sqe, fd: c_int, flags: c_uint)
558{
559 io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, fd, ptr::null_mut(), 0, 0);
560 (*sqe).__liburing_anon_3.cancel_flags = flags | IORING_ASYNC_CANCEL_FD;
561}
562
563#[inline]
564pub unsafe fn io_uring_prep_link_timeout(sqe: *mut io_uring_sqe, ts: *const __kernel_timespec,
565 flags: c_uint)
566{
567 io_uring_prep_rw(IORING_OP_LINK_TIMEOUT, sqe, -1, ts.cast(), 1, 0);
568 (*sqe).__liburing_anon_3.timeout_flags = flags;
569}
570
571#[inline]
572pub unsafe fn io_uring_prep_connect(sqe: *mut io_uring_sqe, fd: c_int, addr: *const sockaddr,
573 addrlen: socklen_t)
574{
575 io_uring_prep_rw(IORING_OP_CONNECT, sqe, fd, addr.cast(), 0, addrlen.into());
576}
577
578#[inline]
579pub unsafe fn io_uring_prep_bind(sqe: *mut io_uring_sqe, fd: c_int, addr: *const sockaddr,
580 addrlen: socklen_t)
581{
582 io_uring_prep_rw(IORING_OP_BIND, sqe, fd, addr.cast(), 0, addrlen.into());
583}
584
585#[inline]
586pub unsafe fn io_uring_prep_listen(sqe: *mut io_uring_sqe, fd: c_int, backlog: c_int)
587{
588 io_uring_prep_rw(IORING_OP_LISTEN, sqe, fd, ptr::null_mut(), backlog as _, 0);
589}
590
591#[inline]
592pub unsafe fn io_uring_prep_epoll_wait(sqe: *mut io_uring_sqe, fd: c_int,
593 events: *mut epoll_event, maxevents: c_int, flags: c_uint)
594{
595 io_uring_prep_rw(IORING_OP_EPOLL_WAIT, sqe, fd, events.cast(), maxevents as _, 0);
596 (*sqe).__liburing_anon_3.rw_flags = flags as _;
597}
598
599#[inline]
600pub unsafe fn io_uring_prep_files_update(sqe: *mut io_uring_sqe, fds: *mut c_int, nr_fds: c_uint,
601 offset: c_int)
602{
603 io_uring_prep_rw(IORING_OP_FILES_UPDATE, sqe, -1, fds.cast(), nr_fds, offset as u64);
604}
605
606#[inline]
607pub unsafe fn io_uring_prep_fallocate(sqe: *mut io_uring_sqe, fd: c_int, mode: c_int, offset: u64,
608 len: u64)
609{
610 io_uring_prep_rw(IORING_OP_FALLOCATE, sqe, fd, ptr::null_mut(), mode as c_uint, offset);
611 (*sqe).__liburing_anon_2.addr = len;
612}
613
614#[inline]
615pub unsafe fn io_uring_prep_openat(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
616 flags: c_int, mode: mode_t)
617{
618 io_uring_prep_rw(IORING_OP_OPENAT, sqe, dfd, path.cast(), mode, 0);
619 (*sqe).__liburing_anon_3.open_flags = flags as u32;
620}
621
622#[inline]
624pub unsafe fn io_uring_prep_openat_direct(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
625 flags: c_int, mode: mode_t, mut file_index: c_uint)
626{
627 io_uring_prep_openat(sqe, dfd, path, flags, mode);
628 if file_index == IORING_FILE_INDEX_ALLOC as _ {
630 file_index -= 1;
631 }
632 __io_uring_set_target_fixed_file(sqe, file_index);
633}
634
635#[inline]
636pub unsafe fn io_uring_prep_open(sqe: *mut io_uring_sqe, path: *const c_char, flags: c_int,
637 mode: mode_t)
638{
639 io_uring_prep_openat(sqe, AT_FDCWD, path, flags, mode);
640}
641
642#[inline]
644pub unsafe fn io_uring_prep_open_direct(sqe: *mut io_uring_sqe, path: *const c_char, flags: c_int,
645 mode: mode_t, file_index: c_uint)
646{
647 io_uring_prep_openat_direct(sqe, AT_FDCWD, path, flags, mode, file_index);
648}
649
650#[inline]
651pub unsafe fn io_uring_prep_close(sqe: *mut io_uring_sqe, fd: c_int)
652{
653 io_uring_prep_rw(IORING_OP_CLOSE, sqe, fd, ptr::null_mut(), 0, 0);
654}
655
656#[inline]
657pub unsafe fn io_uring_prep_close_direct(sqe: *mut io_uring_sqe, file_index: c_uint)
658{
659 io_uring_prep_close(sqe, 0);
660 __io_uring_set_target_fixed_file(sqe, file_index);
661}
662
663#[inline]
664pub unsafe fn io_uring_prep_read(sqe: *mut io_uring_sqe, fd: c_int, buf: *mut c_void,
665 nbytes: c_uint, offset: u64)
666{
667 io_uring_prep_rw(IORING_OP_READ, sqe, fd, buf, nbytes, offset);
668}
669
670#[inline]
671pub unsafe fn io_uring_prep_read_multishot(sqe: *mut io_uring_sqe, fd: c_int, nbytes: c_uint,
672 offset: u64, buf_group: c_int)
673{
674 io_uring_prep_rw(IORING_OP_READ_MULTISHOT, sqe, fd, ptr::null_mut(), nbytes, offset);
675 (*sqe).__liburing_anon_4.buf_group = buf_group as _;
676 (*sqe).flags = IOSQE_BUFFER_SELECT as _;
677}
678
679#[inline]
680pub unsafe fn io_uring_prep_write(sqe: *mut io_uring_sqe, fd: c_int, buf: *const c_void,
681 nbytes: c_uint, offset: u64)
682{
683 io_uring_prep_rw(IORING_OP_WRITE, sqe, fd, buf, nbytes, offset);
684}
685
686#[inline]
687pub unsafe fn io_uring_prep_statx(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
688 flags: c_int, mask: c_uint, statxbuf: *mut statx)
689{
690 io_uring_prep_rw(IORING_OP_STATX,
691 sqe,
692 dfd,
693 path.cast(),
694 mask,
695 uring_ptr_to_u64(statxbuf.cast()));
696 (*sqe).__liburing_anon_3.statx_flags = flags as u32;
697}
698
699#[inline]
700pub unsafe fn io_uring_prep_fadvise(sqe: *mut io_uring_sqe, fd: c_int, offset: u64, len: u32,
701 advice: c_int)
702{
703 io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, ptr::null_mut(), len, offset);
704 (*sqe).__liburing_anon_3.fadvise_advice = advice as u32;
705}
706
707#[inline]
708pub unsafe fn io_uring_prep_madvise(sqe: *mut io_uring_sqe, addr: *mut c_void, length: u32,
709 advice: c_int)
710{
711 io_uring_prep_rw(IORING_OP_MADVISE, sqe, -1, addr, length, 0);
712 (*sqe).__liburing_anon_3.fadvise_advice = advice as u32;
713}
714
715#[inline]
716pub unsafe fn io_uring_prep_fadvise64(sqe: *mut io_uring_sqe, fd: c_int, offset: u64, len: off_t,
717 advice: c_int)
718{
719 io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, ptr::null_mut(), 0, offset);
720 (*sqe).__liburing_anon_2.addr = len as _;
721 (*sqe).__liburing_anon_3.fadvise_advice = advice as u32;
722}
723
724#[inline]
725pub unsafe fn io_uring_prep_madvise64(sqe: *mut io_uring_sqe, addr: *mut c_void, length: off_t,
726 advice: c_int)
727{
728 io_uring_prep_rw(IORING_OP_MADVISE, sqe, -1, addr, 0, length as _);
729 (*sqe).__liburing_anon_3.fadvise_advice = advice as u32;
730}
731
732#[inline]
733pub unsafe fn io_uring_prep_send(sqe: *mut io_uring_sqe, sockfd: c_int, buf: *const c_void,
734 len: usize, flags: c_int)
735{
736 io_uring_prep_rw(IORING_OP_SEND, sqe, sockfd, buf, len as u32, 0);
737 (*sqe).__liburing_anon_3.msg_flags = flags as u32;
738}
739
740#[inline]
741pub unsafe fn io_uring_prep_send_bundle(sqe: *mut io_uring_sqe, sockfd: c_int, len: usize,
742 flags: c_int)
743{
744 io_uring_prep_send(sqe, sockfd, ptr::null_mut(), len, flags);
745 (*sqe).ioprio |= IORING_RECVSEND_BUNDLE as u16;
746}
747
748#[inline]
749pub unsafe fn io_uring_prep_send_set_addr(sqe: *mut io_uring_sqe, dest_addr: *const sockaddr,
750 addr_len: u16)
751{
752 (*sqe).__liburing_anon_1.addr2 = dest_addr as usize as u64;
753 (*sqe).__liburing_anon_5.__liburing_anon_1.addr_len = addr_len;
754}
755
756#[inline]
757pub unsafe fn io_uring_prep_sendto(sqe: *mut io_uring_sqe, sockfd: c_int, buf: *const c_void,
758 len: usize, flags: c_int, addr: *const sockaddr,
759 addrlen: socklen_t)
760{
761 io_uring_prep_send(sqe, sockfd, buf, len, flags);
762 io_uring_prep_send_set_addr(sqe, addr, addrlen as _);
763}
764
765#[inline]
766pub unsafe fn io_uring_prep_send_zc(sqe: *mut io_uring_sqe, sockfd: c_int, buf: *const c_void,
767 len: usize, flags: c_int, zc_flags: c_uint)
768{
769 io_uring_prep_rw(IORING_OP_SEND_ZC, sqe, sockfd, buf, len as u32, 0);
770 (*sqe).__liburing_anon_3.msg_flags = flags as u32;
771 (*sqe).ioprio = zc_flags as _;
772}
773
774#[inline]
775pub unsafe fn io_uring_prep_send_zc_fixed(sqe: *mut io_uring_sqe, sockfd: c_int,
776 buf: *const c_void, len: usize, flags: c_int,
777 zc_flags: c_uint, buf_index: c_uint)
778{
779 io_uring_prep_send_zc(sqe, sockfd, buf, len, flags, zc_flags);
780 (*sqe).ioprio |= IORING_RECVSEND_FIXED_BUF as u16;
781 (*sqe).__liburing_anon_4.buf_index = buf_index as _;
782}
783
784#[inline]
785pub unsafe fn io_uring_prep_sendmsg_zc(sqe: *mut io_uring_sqe, fd: c_int, msg: *const msghdr,
786 flags: c_uint)
787{
788 io_uring_prep_sendmsg(sqe, fd, msg, flags);
789 (*sqe).opcode = IORING_OP_SENDMSG_ZC as _;
790}
791
792#[inline]
793pub unsafe fn io_uring_prep_sendmsg_zc_fixed(sqe: *mut io_uring_sqe, fd: c_int,
794 msg: *const msghdr, flags: c_uint, buf_index: c_uint)
795{
796 io_uring_prep_sendmsg_zc(sqe, fd, msg, flags);
797 (*sqe).ioprio |= IORING_RECVSEND_FIXED_BUF as u16;
798 (*sqe).__liburing_anon_4.buf_index = buf_index as _;
799}
800
801#[inline]
802pub unsafe fn io_uring_prep_recv(sqe: *mut io_uring_sqe, sockfd: c_int, buf: *mut c_void,
803 len: usize, flags: c_int)
804{
805 io_uring_prep_rw(IORING_OP_RECV, sqe, sockfd, buf, len as u32, 0);
806 (*sqe).__liburing_anon_3.msg_flags = flags as u32;
807}
808
809#[inline]
810pub unsafe fn io_uring_prep_recv_multishot(sqe: *mut io_uring_sqe, sockfd: c_int,
811 buf: *mut c_void, len: usize, flags: c_int)
812{
813 io_uring_prep_recv(sqe, sockfd, buf, len, flags);
814 (*sqe).ioprio |= IORING_RECV_MULTISHOT as u16;
815}
816
817#[inline]
818pub unsafe fn io_uring_recvmsg_validate(buf: *mut c_void, buf_len: c_int, msgh: *mut msghdr)
819 -> *mut io_uring_recvmsg_out
820{
821 let ulen = c_ulong::from(buf_len as c_uint);
822 let hdr = size_of::<io_uring_recvmsg_out>() as c_ulong;
823 let namelen = c_ulong::from((*msgh).msg_namelen);
824 let controllen = (*msgh).msg_controllen as c_ulong;
825
826 if buf_len < 0 || ulen < hdr {
827 return ptr::null_mut();
828 }
829 if namelen > ulen - hdr {
831 return ptr::null_mut();
832 }
833 if controllen > ulen - hdr - namelen {
834 return ptr::null_mut();
835 }
836
837 buf.cast()
838}
839
840#[inline]
841pub unsafe fn io_uring_recvmsg_name(o: *mut io_uring_recvmsg_out) -> *mut c_void
842{
843 o.add(1).cast()
844}
845
846#[inline]
847pub unsafe fn io_uring_recvmsg_cmsg_firsthdr(o: *mut io_uring_recvmsg_out, msgh: *mut msghdr)
848 -> *mut cmsghdr
849{
850 if ((*o).controllen as usize) < mem::size_of::<cmsghdr>() {
851 return ptr::null_mut();
852 }
853
854 io_uring_recvmsg_name(o).cast::<u8>()
855 .add((*msgh).msg_namelen as _)
856 .cast()
857}
858
859#[inline]
860pub unsafe fn io_uring_recvmsg_cmsg_nexthdr(o: *mut io_uring_recvmsg_out, msgh: *mut msghdr,
861 cmsg: *mut cmsghdr)
862 -> *mut cmsghdr
863{
864 #[allow(non_snake_case)]
865 fn CMSG_ALIGN(len: usize) -> usize
866 {
867 ((len) + mem::size_of::<usize>() - 1) & !(mem::size_of::<usize>() - 1)
868 }
869
870 if ((*cmsg).cmsg_len as usize) < mem::size_of::<cmsghdr>() {
871 return ptr::null_mut();
872 }
873
874 let end = io_uring_recvmsg_cmsg_firsthdr(o, msgh).cast::<u8>()
875 .add((*o).controllen as _);
876
877 let cmsg = cmsg.cast::<u8>()
878 .add(CMSG_ALIGN((*cmsg).cmsg_len as usize))
879 .cast::<cmsghdr>();
880
881 if cmsg.add(1).cast::<u8>() > end {
882 return ptr::null_mut();
883 }
884
885 if cmsg.cast::<u8>().add(CMSG_ALIGN((*cmsg).cmsg_len as usize)) > end {
886 return ptr::null_mut();
887 }
888
889 cmsg
890}
891
892#[inline]
893pub unsafe fn io_uring_recvmsg_payload(o: *mut io_uring_recvmsg_out, msgh: *mut msghdr)
894 -> *mut c_void
895{
896 io_uring_recvmsg_name(o).cast::<u8>()
897 .add((*msgh).msg_namelen as usize + (*msgh).msg_controllen as usize)
898 .cast::<c_void>()
899}
900
901#[inline]
902pub unsafe fn io_uring_recvmsg_payload_length(o: *mut io_uring_recvmsg_out, buf_len: c_int,
903 msgh: *mut msghdr)
904 -> c_uint
905{
906 if buf_len < 0 {
907 return 0;
908 }
909
910 let payload_start = io_uring_recvmsg_payload(o, msgh) as usize;
911 let payload_end = o as usize + buf_len as usize;
912 if payload_start >= payload_end {
913 return 0;
914 }
915
916 (payload_end - payload_start) as _
917}
918
919#[inline]
920pub unsafe fn io_uring_prep_openat2(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
921 how: *const open_how)
922{
923 io_uring_prep_rw(IORING_OP_OPENAT2 as _,
924 sqe,
925 dfd,
926 path.cast(),
927 mem::size_of::<open_how>() as u32,
928 how as usize as u64);
929}
930
931#[inline]
933pub unsafe fn io_uring_prep_openat2_direct(sqe: *mut io_uring_sqe, dfd: c_int,
934 path: *const c_char, how: *const open_how,
935 mut file_index: c_uint)
936{
937 io_uring_prep_openat2(sqe, dfd, path, how);
938 if file_index == IORING_FILE_INDEX_ALLOC as _ {
940 file_index -= 1;
941 }
942 __io_uring_set_target_fixed_file(sqe, file_index);
943}
944
945#[inline]
946pub unsafe fn io_uring_prep_epoll_ctl(sqe: *mut io_uring_sqe, epfd: c_int, fd: c_int, op: c_int,
947 ev: *const epoll_event)
948{
949 io_uring_prep_rw(IORING_OP_EPOLL_CTL, sqe, epfd, ev.cast(), op as u32, u64::from(fd as u32));
950}
951
952#[inline]
953pub unsafe fn io_uring_prep_provide_buffers(sqe: *mut io_uring_sqe, addr: *mut c_void, len: c_int,
954 nr: c_int, bgid: c_int, bid: c_int)
955{
956 io_uring_prep_rw(IORING_OP_PROVIDE_BUFFERS, sqe, nr, addr, len as u32, bid as u64);
957 (*sqe).__liburing_anon_4.buf_group = bgid as u16;
958}
959
960#[inline]
961pub unsafe fn io_uring_prep_remove_buffers(sqe: *mut io_uring_sqe, nr: c_int, bgid: c_int)
962{
963 io_uring_prep_rw(IORING_OP_REMOVE_BUFFERS, sqe, nr, ptr::null_mut(), 0, 0);
964 (*sqe).__liburing_anon_4.buf_group = bgid as u16;
965}
966
967#[inline]
968pub unsafe fn io_uring_prep_shutdown(sqe: *mut io_uring_sqe, fd: c_int, how: c_int)
969{
970 io_uring_prep_rw(IORING_OP_SHUTDOWN, sqe, fd, ptr::null_mut(), how as u32, 0);
971}
972
973#[inline]
974pub unsafe fn io_uring_prep_unlinkat(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
975 flags: c_int)
976{
977 io_uring_prep_rw(IORING_OP_UNLINKAT, sqe, dfd, path.cast(), 0, 0);
978 (*sqe).__liburing_anon_3.unlink_flags = flags as u32;
979}
980
981#[inline]
982pub unsafe fn io_uring_prep_unlink(sqe: *mut io_uring_sqe, path: *const c_char, flags: c_int)
983{
984 io_uring_prep_unlinkat(sqe, AT_FDCWD, path, flags);
985}
986
987#[inline]
988pub unsafe fn io_uring_prep_renameat(sqe: *mut io_uring_sqe, olddfd: c_int,
989 oldpath: *const c_char, newdfd: c_int,
990 newpath: *const c_char, flags: c_uint)
991{
992 io_uring_prep_rw(IORING_OP_RENAMEAT,
993 sqe,
994 olddfd,
995 oldpath.cast(),
996 newdfd as u32,
997 newpath as usize as u64);
998 (*sqe).__liburing_anon_3.rename_flags = flags;
999}
1000
1001#[inline]
1002pub unsafe fn io_uring_prep_rename(sqe: *mut io_uring_sqe, oldpath: *const c_char,
1003 newpath: *const c_char)
1004{
1005 io_uring_prep_renameat(sqe, AT_FDCWD, oldpath, AT_FDCWD, newpath, 0);
1006}
1007
1008#[inline]
1009pub unsafe fn io_uring_prep_sync_file_range(sqe: *mut io_uring_sqe, fd: c_int, len: c_uint,
1010 offset: u64, flags: c_int)
1011{
1012 io_uring_prep_rw(IORING_OP_SYNC_FILE_RANGE, sqe, fd, ptr::null_mut(), len, offset);
1013 (*sqe).__liburing_anon_3.sync_range_flags = flags as u32;
1014}
1015
1016#[inline]
1017pub unsafe fn io_uring_prep_mkdirat(sqe: *mut io_uring_sqe, dfd: c_int, path: *const c_char,
1018 mode: mode_t)
1019{
1020 io_uring_prep_rw(IORING_OP_MKDIRAT, sqe, dfd, path.cast(), mode, 0);
1021}
1022
1023#[inline]
1024pub unsafe fn io_uring_prep_mkdir(sqe: *mut io_uring_sqe, path: *const c_char, mode: mode_t)
1025{
1026 io_uring_prep_mkdirat(sqe, AT_FDCWD, path, mode);
1027}
1028
1029#[inline]
1030pub unsafe fn io_uring_prep_symlinkat(sqe: *mut io_uring_sqe, target: *const c_char,
1031 newdirfd: c_int, linkpath: *const c_char)
1032{
1033 io_uring_prep_rw(IORING_OP_SYMLINKAT,
1034 sqe,
1035 newdirfd,
1036 target.cast(),
1037 0,
1038 linkpath as usize as u64);
1039}
1040#[inline]
1041pub unsafe fn io_uring_prep_symlink(sqe: *mut io_uring_sqe, target: *const c_char,
1042 linkpath: *const c_char)
1043{
1044 io_uring_prep_symlinkat(sqe, target, AT_FDCWD, linkpath);
1045}
1046
1047#[inline]
1048pub unsafe fn io_uring_prep_linkat(sqe: *mut io_uring_sqe, olddfd: c_int, oldpath: *const c_char,
1049 newdfd: c_int, newpath: *const c_char, flags: c_int)
1050{
1051 io_uring_prep_rw(IORING_OP_LINKAT,
1052 sqe,
1053 olddfd,
1054 oldpath.cast(),
1055 newdfd as u32,
1056 newpath as usize as u64);
1057 (*sqe).__liburing_anon_3.hardlink_flags = flags as u32;
1058}
1059
1060#[inline]
1061pub unsafe fn io_uring_prep_link(sqe: *mut io_uring_sqe, oldpath: *const c_char,
1062 newpath: *const c_char, flags: c_int)
1063{
1064 io_uring_prep_linkat(sqe, AT_FDCWD, oldpath, AT_FDCWD, newpath, flags);
1065}
1066
1067#[inline]
1068pub unsafe fn io_uring_prep_msg_ring_cqe_flags(sqe: *mut io_uring_sqe, fd: c_int, len: c_uint,
1069 data: u64, flags: c_uint, cqe_flags: c_uint)
1070{
1071 io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd, ptr::null_mut(), len, data);
1072 (*sqe).__liburing_anon_3.msg_ring_flags = IORING_MSG_RING_FLAGS_PASS | flags;
1073 (*sqe).__liburing_anon_5.file_index = cqe_flags;
1074}
1075
1076#[inline]
1077pub unsafe fn io_uring_prep_msg_ring(sqe: *mut io_uring_sqe, fd: c_int, len: c_uint, data: u64,
1078 flags: c_uint)
1079{
1080 io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd, ptr::null_mut(), len, data);
1081 (*sqe).__liburing_anon_3.msg_ring_flags = IORING_MSG_RING_FLAGS_PASS | flags;
1082}
1083
1084#[inline]
1085pub unsafe fn io_uring_prep_msg_ring_fd(sqe: *mut io_uring_sqe, fd: c_int, source_fd: c_int,
1086 mut target_fd: c_int, data: u64, flags: c_uint)
1087{
1088 io_uring_prep_rw(IORING_OP_MSG_RING,
1089 sqe,
1090 fd,
1091 IORING_MSG_SEND_FD as usize as *const c_void,
1092 0,
1093 data);
1094 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = source_fd as _;
1095 if target_fd == IORING_FILE_INDEX_ALLOC as _ {
1097 target_fd -= 1;
1098 }
1099 __io_uring_set_target_fixed_file(sqe, target_fd as _);
1100 (*sqe).__liburing_anon_3.msg_ring_flags = flags;
1101}
1102
1103#[inline]
1104pub unsafe fn io_uring_prep_msg_ring_fd_alloc(sqe: *mut io_uring_sqe, fd: c_int, source_fd: c_int,
1105 data: u64, flags: c_uint)
1106{
1107 io_uring_prep_msg_ring_fd(sqe, fd, source_fd, IORING_FILE_INDEX_ALLOC, data, flags);
1108}
1109
1110#[inline]
1111pub unsafe fn io_uring_prep_getxattr(sqe: *mut io_uring_sqe, name: *const c_char,
1112 value: *mut c_char, path: *const c_char, len: c_uint)
1113{
1114 io_uring_prep_rw(IORING_OP_GETXATTR, sqe, 0, name.cast(), len, value as usize as u64);
1115 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = path as usize as u64;
1116
1117 (*sqe).__liburing_anon_3.xattr_flags = 0;
1118}
1119
1120#[inline]
1121pub unsafe fn io_uring_prep_setxattr(sqe: *mut io_uring_sqe, name: *const c_char,
1122 value: *const c_char, path: *const c_char, flags: c_int,
1123 len: c_uint)
1124{
1125 io_uring_prep_rw(IORING_OP_SETXATTR, sqe, 0, name.cast(), len, value as usize as u64);
1126 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = path as usize as u64;
1127 (*sqe).__liburing_anon_3.xattr_flags = flags as _;
1128}
1129
1130#[inline]
1131pub unsafe fn io_uring_prep_fgetxattr(sqe: *mut io_uring_sqe, fd: c_int, name: *const c_char,
1132 value: *mut c_char, len: c_uint)
1133{
1134 io_uring_prep_rw(IORING_OP_FGETXATTR, sqe, fd, name.cast(), len, value as usize as u64);
1135 (*sqe).__liburing_anon_3.xattr_flags = 0;
1136}
1137
1138#[inline]
1139pub unsafe fn io_uring_prep_fsetxattr(sqe: *mut io_uring_sqe, fd: c_int, name: *const c_char,
1140 value: *mut c_char, flags: c_int, len: c_uint)
1141{
1142 io_uring_prep_rw(IORING_OP_FSETXATTR, sqe, fd, name.cast(), len, value as usize as u64);
1143 (*sqe).__liburing_anon_3.xattr_flags = flags as _;
1144}
1145
1146#[inline]
1147pub unsafe fn io_uring_prep_socket(sqe: *mut io_uring_sqe, domain: c_int, r#type: c_int,
1148 protocol: c_int, flags: c_uint)
1149{
1150 io_uring_prep_rw(IORING_OP_SOCKET,
1151 sqe,
1152 domain,
1153 ptr::null_mut(),
1154 protocol as u32,
1155 r#type as u64);
1156 (*sqe).__liburing_anon_3.rw_flags = flags as i32;
1157}
1158
1159#[inline]
1160pub unsafe fn io_uring_prep_socket_direct(sqe: *mut io_uring_sqe, domain: c_int, r#type: c_int,
1161 protocol: c_int, mut file_index: c_uint, flags: c_uint)
1162{
1163 io_uring_prep_rw(IORING_OP_SOCKET,
1164 sqe,
1165 domain,
1166 ptr::null_mut(),
1167 protocol as u32,
1168 r#type as u64);
1169 (*sqe).__liburing_anon_3.rw_flags = flags as i32;
1170 if file_index == IORING_FILE_INDEX_ALLOC as _ {
1172 file_index -= 1;
1173 }
1174 __io_uring_set_target_fixed_file(sqe, file_index);
1175}
1176
1177#[inline]
1178pub unsafe fn io_uring_prep_socket_direct_alloc(sqe: *mut io_uring_sqe, domain: c_int,
1179 r#type: c_int, protocol: c_int, flags: c_uint)
1180{
1181 io_uring_prep_rw(IORING_OP_SOCKET,
1182 sqe,
1183 domain,
1184 ptr::null_mut(),
1185 protocol as u32,
1186 r#type as u64);
1187 (*sqe).__liburing_anon_3.rw_flags = flags as i32;
1188 __io_uring_set_target_fixed_file(sqe, (IORING_FILE_INDEX_ALLOC - 1) as _);
1189}
1190
1191#[inline]
1192pub unsafe fn __io_uring_prep_uring_cmd(sqe: *mut io_uring_sqe, op: c_int, cmd_op: u32, fd: c_int)
1193{
1194 (*sqe).opcode = op as _;
1195 (*sqe).fd = fd;
1196 (*sqe).__liburing_anon_1.__liburing_anon_1.cmd_op = cmd_op;
1197 (*sqe).__liburing_anon_1.__liburing_anon_1.__pad1 = 0;
1198 (*sqe).__liburing_anon_2.addr = 0;
1199 (*sqe).len = 0;
1200}
1201
1202#[inline]
1203pub unsafe fn io_uring_prep_uring_cmd(sqe: *mut io_uring_sqe, cmd_op: c_int, fd: c_int)
1204{
1205 __io_uring_prep_uring_cmd(sqe, IORING_OP_URING_CMD as _, cmd_op as _, fd);
1206}
1207
1208#[inline]
1209pub unsafe fn io_uring_prep_uring_cmd128(sqe: *mut io_uring_sqe, cmd_op: c_int, fd: c_int)
1210{
1211 __io_uring_prep_uring_cmd(sqe, IORING_OP_URING_CMD128 as _, cmd_op as _, fd);
1212}
1213
1214#[inline]
1218pub unsafe fn io_uring_prep_cmd_sock(sqe: *mut io_uring_sqe, cmd_op: c_int, fd: c_int,
1219 level: c_int, optname: c_int, optval: *mut c_void,
1220 optlen: c_int)
1221{
1222 io_uring_prep_uring_cmd(sqe, cmd_op as _, fd);
1223
1224 *(*sqe).__liburing_anon_6.optval.as_mut() = optval as usize as _;
1225 (*sqe).__liburing_anon_2.__liburing_anon_1.optname = optname as _;
1226 (*sqe).__liburing_anon_5.optlen = optlen as _;
1227 (*sqe).__liburing_anon_1.__liburing_anon_1.cmd_op = cmd_op as _;
1228 (*sqe).__liburing_anon_2.__liburing_anon_1.level = level as _;
1229}
1230
1231#[inline]
1232pub unsafe fn io_uring_prep_cmd_getsockname(sqe: *mut io_uring_sqe, fd: c_int,
1233 sockaddr: *mut sockaddr, sockaddr_len: *mut socklen_t,
1234 peer: c_int)
1235{
1236 io_uring_prep_uring_cmd(sqe, SOCKET_URING_OP_GETSOCKNAME as _, fd);
1237
1238 (*sqe).__liburing_anon_2.addr = sockaddr as _;
1239 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = sockaddr_len as _;
1240 (*sqe).__liburing_anon_5.optlen = peer as _;
1241}
1242
1243#[inline]
1244pub unsafe fn io_uring_prep_waitid(sqe: *mut io_uring_sqe, idtype: idtype_t, id: id_t,
1245 infop: *mut siginfo_t, options: c_int, flags: c_uint)
1246{
1247 io_uring_prep_rw(IORING_OP_WAITID, sqe, id as _, ptr::null_mut(), idtype, 0);
1248 (*sqe).__liburing_anon_3.waitid_flags = flags;
1249 (*sqe).__liburing_anon_5.file_index = options as _;
1250 (*sqe).__liburing_anon_1.addr2 = infop as usize as u64;
1251}
1252
1253#[inline]
1254pub unsafe fn io_uring_prep_futex_wake(sqe: *mut io_uring_sqe, futex: *const u32, val: u64,
1255 mask: u64, futex_flags: u32, flags: c_uint)
1256{
1257 io_uring_prep_rw(IORING_OP_FUTEX_WAKE, sqe, futex_flags as _, futex.cast(), 0, val);
1258 (*sqe).__liburing_anon_3.futex_flags = flags;
1259 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = mask;
1260}
1261
1262#[inline]
1263pub unsafe fn io_uring_prep_futex_wait(sqe: *mut io_uring_sqe, futex: *const u32, val: u64,
1264 mask: u64, futex_flags: u32, flags: c_uint)
1265{
1266 io_uring_prep_rw(IORING_OP_FUTEX_WAIT, sqe, futex_flags as _, futex.cast(), 0, val);
1267 (*sqe).__liburing_anon_3.futex_flags = flags;
1268 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = mask;
1269}
1270
1271#[inline]
1272pub unsafe fn io_uring_prep_futex_waitv(sqe: *mut io_uring_sqe, futex: *const futex_waitv,
1273 nr_futex: u32, flags: c_uint)
1274{
1275 io_uring_prep_rw(IORING_OP_FUTEX_WAITV, sqe, 0, futex.cast(), nr_futex, 0);
1276 (*sqe).__liburing_anon_3.futex_flags = flags;
1277}
1278
1279#[inline]
1280pub unsafe fn io_uring_prep_fixed_fd_install(sqe: *mut io_uring_sqe, fd: c_int, flags: c_uint)
1281{
1282 io_uring_prep_rw(IORING_OP_FIXED_FD_INSTALL, sqe, fd, ptr::null_mut(), 0, 0);
1283
1284 (*sqe).flags = IOSQE_FIXED_FILE as _;
1285 (*sqe).__liburing_anon_3.install_fd_flags = flags;
1286}
1287
1288#[inline]
1289pub unsafe fn io_uring_prep_ftruncate(sqe: *mut io_uring_sqe, fd: c_int, len: c_longlong)
1290{
1291 io_uring_prep_rw(IORING_OP_FTRUNCATE, sqe, fd, ptr::null_mut(), 0, len as _);
1292}
1293
1294#[inline]
1295pub unsafe fn io_uring_prep_cmd_discard(sqe: *mut io_uring_sqe, fd: c_int, offset: u64, nbytes: u64)
1296{
1297 io_uring_prep_uring_cmd(sqe, ((0x12) << 8) as _ , fd);
1301
1302 (*sqe).__liburing_anon_2.addr = offset;
1303 (*sqe).__liburing_anon_6.__liburing_anon_1.as_mut().addr3 = nbytes;
1304}
1305
1306#[inline]
1307pub unsafe fn io_uring_prep_pipe(sqe: *mut io_uring_sqe, fds: *mut c_int, pipe_flags: c_int)
1308{
1309 io_uring_prep_rw(IORING_OP_PIPE, sqe, 0, fds as *const _, 0, 0);
1310 (*sqe).__liburing_anon_3.pipe_flags = pipe_flags as u32;
1311}
1312
1313#[inline]
1315pub unsafe fn io_uring_prep_pipe_direct(sqe: *mut io_uring_sqe, fds: *mut c_int,
1316 pipe_flags: c_int, mut file_index: c_uint)
1317{
1318 io_uring_prep_pipe(sqe, fds, pipe_flags);
1319 if file_index == IORING_FILE_INDEX_ALLOC as u32 {
1321 file_index -= 1;
1322 }
1323 __io_uring_set_target_fixed_file(sqe, file_index);
1324}
1325
1326#[inline]
1328pub unsafe fn io_uring_load_sq_head(ring: *mut io_uring) -> c_uint
1329{
1330 if (*ring).flags & IORING_SETUP_SQPOLL > 0 {
1336 return io_uring_smp_load_acquire((*ring).sq.khead);
1337 }
1338
1339 *(*ring).sq.khead
1340}
1341
1342#[inline]
1347pub unsafe fn io_uring_sq_ready(ring: *mut io_uring) -> c_uint
1348{
1349 (*ring).sq.sqe_tail - io_uring_load_sq_head(ring)
1350}
1351
1352#[inline]
1356pub unsafe fn io_uring_sq_space_left(ring: *mut io_uring) -> c_uint
1357{
1358 (*ring).sq.ring_entries - io_uring_sq_ready(ring)
1359}
1360
1361#[must_use]
1367#[inline]
1368pub fn io_uring_sqe_shift_from_flags(flags: c_uint) -> c_uint
1369{
1370 u32::from(flags & IORING_SETUP_SQE128 != 0)
1371}
1372
1373#[inline]
1374pub unsafe fn io_uring_sqe_shift(ring: *mut io_uring) -> c_uint
1375{
1376 io_uring_sqe_shift_from_flags((*ring).flags)
1377}
1378
1379#[inline]
1387pub unsafe fn io_uring_sqring_wait(ring: *mut io_uring) -> c_int
1388{
1389 if (*ring).flags & IORING_SETUP_SQPOLL == 0 {
1390 return 0;
1391 }
1392 if io_uring_sq_space_left(ring) > 0 {
1393 return 0;
1394 }
1395
1396 __io_uring_sqring_wait(ring)
1397}
1398
1399#[inline]
1403pub unsafe fn io_uring_cq_ready(ring: *mut io_uring) -> c_uint
1404{
1405 io_uring_smp_load_acquire((*ring).cq.ktail) - *(*ring).cq.khead
1406}
1407
1408#[inline]
1413pub unsafe fn io_uring_cq_has_overflow(ring: *mut io_uring) -> bool
1414{
1415 IO_URING_READ_ONCE((*ring).sq.kflags) & IORING_SQ_CQ_OVERFLOW > 0
1416}
1417
1418#[inline]
1422pub unsafe fn io_uring_cq_eventfd_enabled(ring: *mut io_uring) -> bool
1423{
1424 if (*ring).cq.kflags.is_null() {
1425 return true;
1426 }
1427 (*(*ring).cq.kflags & IORING_CQ_EVENTFD_DISABLED) == 0
1428}
1429
1430#[inline]
1435pub unsafe fn io_uring_cq_eventfd_toggle(ring: *mut io_uring, enabled: bool) -> c_int
1436{
1437 if enabled == io_uring_cq_eventfd_enabled(ring) {
1438 return 0;
1439 }
1440
1441 if (*ring).cq.kflags.is_null() {
1442 return -(EOPNOTSUPP as c_int);
1443 }
1444
1445 let mut flags = *(*ring).cq.kflags;
1446
1447 if enabled {
1448 flags &= !IORING_CQ_EVENTFD_DISABLED;
1449 } else {
1450 flags |= IORING_CQ_EVENTFD_DISABLED;
1451 }
1452
1453 IO_URING_WRITE_ONCE((*ring).cq.kflags, flags);
1454
1455 0
1456}
1457
1458#[inline]
1464pub unsafe fn io_uring_wait_cqe_nr(ring: *mut io_uring, cqe_ptr: *mut *mut io_uring_cqe,
1465 wait_nr: c_uint)
1466 -> c_int
1467{
1468 __io_uring_get_cqe(ring, cqe_ptr, 0, wait_nr, ptr::null_mut())
1469}
1470
1471#[inline]
1472unsafe fn io_uring_skip_cqe(ring: *mut io_uring, cqe: *mut io_uring_cqe, err: *mut c_int) -> bool
1473{
1474 'out: {
1475 if (*cqe).flags & IORING_CQE_F_SKIP != 0 {
1476 break 'out;
1477 }
1478
1479 if (*ring).features & IORING_FEAT_EXT_ARG != 0 {
1480 return false;
1481 }
1482
1483 if (*cqe).user_data != LIBURING_UDATA_TIMEOUT {
1484 return false;
1485 }
1486
1487 if (*cqe).res < 0 {
1488 *err = (*cqe).res;
1489 }
1490 }
1491
1492 io_uring_cq_advance(ring, io_uring_cqe_nr(cqe));
1493 *err == 0
1494}
1495
1496#[inline]
1502unsafe fn __io_uring_peek_cqe(ring: *mut io_uring, cqe_ptr: *mut *mut io_uring_cqe,
1503 nr_available: *mut c_uint)
1504 -> c_int
1505{
1506 let mut cqe;
1507 let mut err = 0;
1508
1509 let mut available;
1510 let mask = (*ring).cq.ring_mask;
1511 let shift = io_uring_cqe_shift(ring);
1512
1513 loop {
1514 let tail = io_uring_smp_load_acquire((*ring).cq.ktail);
1515
1516 let head = *((*ring).cq.khead);
1523
1524 cqe = ptr::null_mut();
1525 available = tail - head;
1526 if available == 0 {
1527 break;
1528 }
1529
1530 cqe = &raw mut *(*ring).cq.cqes.add(((head & mask) << shift) as usize);
1531 if !io_uring_skip_cqe(ring, cqe, &raw mut err) {
1532 if err != 0 {
1538 cqe = ptr::null_mut();
1539 }
1540 break;
1541 }
1542 }
1543
1544 *cqe_ptr = cqe;
1545 if !nr_available.is_null() {
1546 *nr_available = available;
1547 }
1548 err
1549}
1550
1551#[inline]
1556pub unsafe fn io_uring_peek_cqe(ring: *mut io_uring, cqe_ptr: *mut *mut io_uring_cqe) -> c_int
1557{
1558 if __io_uring_peek_cqe(ring, cqe_ptr, ptr::null_mut()) == 0 {
1559 if !(*cqe_ptr).is_null() {
1560 return 0;
1561 }
1562
1563 if ((*ring).flags & IORING_SETUP_IOPOLL) == 0
1570 && (IO_URING_READ_ONCE((*ring).sq.kflags) & (IORING_SQ_CQ_OVERFLOW | IORING_SQ_TASKRUN))
1571 == 0
1572 {
1573 return -(EAGAIN as c_int);
1574 }
1575 }
1576
1577 io_uring_wait_cqe_nr(ring, cqe_ptr, 0)
1578}
1579
1580#[inline]
1585pub unsafe fn io_uring_wait_cqe(ring: *mut io_uring, cqe_ptr: *mut *mut io_uring_cqe) -> c_int
1586{
1587 if __io_uring_peek_cqe(ring, cqe_ptr, ptr::null_mut()) == 0 && !(*cqe_ptr).is_null() {
1588 return 0;
1589 }
1590
1591 io_uring_wait_cqe_nr(ring, cqe_ptr, 1)
1592}
1593
1594#[inline]
1602unsafe fn _io_uring_get_sqe(ring: *mut io_uring) -> *mut io_uring_sqe
1603{
1604 let sq = &raw mut (*ring).sq;
1605
1606 let head = io_uring_load_sq_head(ring);
1607 let tail = (*sq).sqe_tail;
1608
1609 if tail - head >= (*sq).ring_entries {
1610 return ptr::null_mut();
1611 }
1612
1613 let offset = (tail & (*sq).ring_mask) << io_uring_sqe_shift(ring);
1614 let sqe = (*sq).sqes.add(offset as usize);
1615 (*sq).sqe_tail = tail + 1;
1616 io_uring_initialize_sqe(sqe);
1617 sqe
1618}
1619
1620#[must_use]
1624#[inline]
1625pub fn io_uring_buf_ring_mask(ring_entries: u32) -> c_int
1626{
1627 (ring_entries - 1) as _
1628}
1629
1630#[inline]
1631pub unsafe fn io_uring_buf_ring_init(br: *mut io_uring_buf_ring)
1632{
1633 (*br).__liburing_anon_1.__liburing_anon_1.as_mut().tail = 0;
1634}
1635
1636#[inline]
1640pub unsafe fn io_uring_buf_ring_add(br: *mut io_uring_buf_ring, addr: *mut c_void, len: c_uint,
1641 bid: c_ushort, mask: c_int, buf_offset: c_int)
1642{
1643 let tail = (*br).__liburing_anon_1.__liburing_anon_1.as_ref().tail;
1644 let buf = (*br).__liburing_anon_1
1645 .bufs
1646 .as_mut()
1647 .as_mut_ptr()
1648 .add(((i32::from(tail) + buf_offset) & mask) as usize);
1649
1650 (*buf).addr = addr as usize as u64;
1651 (*buf).len = len;
1652 (*buf).bid = bid;
1653}
1654
1655#[inline]
1661pub unsafe fn io_uring_buf_ring_advance(br: *mut io_uring_buf_ring, count: c_int)
1662{
1663 let tail = (*br).__liburing_anon_1.__liburing_anon_1.as_ref().tail;
1664 let new_tail = tail.wrapping_add(count as u16);
1665
1666 io_uring_smp_store_release(&raw mut (*br).__liburing_anon_1.__liburing_anon_1.as_mut().tail,
1667 new_tail);
1668}
1669
1670#[inline]
1671unsafe fn __io_uring_buf_ring_cq_advance(ring: *mut io_uring, br: *mut io_uring_buf_ring,
1672 cq_count: i32, buf_count: c_int)
1673{
1674 io_uring_buf_ring_advance(br, buf_count);
1675 io_uring_cq_advance(ring, cq_count as _);
1676}
1677
1678#[inline]
1686pub unsafe fn io_uring_buf_ring_cq_advance(ring: *mut io_uring, br: *mut io_uring_buf_ring,
1687 count: c_int)
1688{
1689 __io_uring_buf_ring_cq_advance(ring, br, count, count);
1690}
1691
1692#[inline]
1693pub unsafe fn io_uring_buf_ring_available(ring: *mut io_uring, br: *mut io_uring_buf_ring,
1694 bgid: c_ushort)
1695 -> c_int
1696{
1697 let mut head = 0;
1698 let ret = io_uring_buf_ring_head(ring, bgid.into(), &raw mut head);
1699 if ret > 0 {
1700 return ret;
1701 }
1702 c_int::from((*br).__liburing_anon_1.__liburing_anon_1.as_mut().tail - head)
1703}
1704
1705#[inline]
1706pub unsafe fn io_uring_get_sqe(ring: *mut io_uring) -> *mut io_uring_sqe
1707{
1708 _io_uring_get_sqe(ring)
1709}
1710
1711#[inline]
1723pub unsafe fn io_uring_get_sqe128(ring: *mut io_uring) -> *mut io_uring_sqe
1724{
1725 let sq = &raw mut (*ring).sq;
1726
1727 let head = io_uring_load_sq_head(ring);
1728 let mut tail = (*sq).sqe_tail;
1729
1730 if (*ring).flags & IORING_SETUP_SQE128 != 0 {
1731 return io_uring_get_sqe(ring);
1732 }
1733
1734 if (*ring).flags & IORING_SETUP_SQE_MIXED == 0 {
1735 return ptr::null_mut();
1736 }
1737
1738 let mut sqe: *mut io_uring_sqe;
1739 if (tail + 1) & (*sq).ring_mask == 0 {
1740 if (tail + 2) - head >= (*sq).ring_entries {
1741 return ptr::null_mut();
1742 }
1743
1744 sqe = _io_uring_get_sqe(ring);
1745 io_uring_prep_nop(sqe);
1746 (*sqe).flags |= IOSQE_CQE_SKIP_SUCCESS as u8;
1747 tail = (*sq).sqe_tail;
1748 } else if (tail + 1) - head >= (*sq).ring_entries {
1749 return ptr::null_mut();
1750 }
1751
1752 sqe = &raw mut *(*sq).sqes.add((tail & (*sq).ring_mask) as usize);
1753 (*sq).sqe_tail = tail + 2;
1754 io_uring_initialize_sqe(sqe);
1755 sqe
1756}
1757
1758impl From<Duration> for timespec
1761{
1762 #[cfg(not(any(target_arch = "powerpc", target_arch = "arm")))]
1763 #[inline]
1764 fn from(duration: Duration) -> Self
1765 {
1766 let mut ts = unsafe { zeroed::<timespec>() };
1767 ts.tv_sec = duration.as_secs() as _;
1768 ts.tv_nsec = duration.subsec_nanos().into();
1769 ts
1770 }
1771
1772 #[cfg(any(target_arch = "powerpc", target_arch = "arm"))]
1773 #[inline]
1774 fn from(duration: Duration) -> Self
1775 {
1776 let mut ts = unsafe { zeroed::<timespec>() };
1777 ts.tv_sec = duration.as_secs() as _;
1778 ts.tv_nsec = duration.subsec_nanos().try_into().unwrap();
1779 ts
1780 }
1781}
1782
1783impl From<Duration> for __kernel_timespec
1784{
1785 #[inline]
1786 fn from(duration: Duration) -> Self
1787 {
1788 let mut ts = unsafe { zeroed::<__kernel_timespec>() };
1789 ts.tv_sec = duration.as_secs() as _;
1790 ts.tv_nsec = duration.subsec_nanos().into();
1791 ts
1792 }
1793}