1#![allow(clippy::new_without_default)]
4
5use core::convert::TryInto;
6use core::mem;
7
8use rustix::fd::RawFd;
9
10use crate::squeue::Entry;
11use crate::squeue::Entry128;
12use crate::sys;
13use crate::types::{self, sealed};
14
15macro_rules! assign_fd {
16 ( $sqe:ident . fd = $opfd:expr ) => {
17 match $opfd {
18 sealed::Target::Fd(fd) => $sqe.fd = fd,
19 sealed::Target::Fixed(idx) => {
20 $sqe.fd = idx as _;
21 $sqe.flags |= sys::IoringSqeFlags::FIXED_FILE;
22 }
23 }
24 };
25}
26
27macro_rules! opcode {
28 (@type impl sealed::UseFixed ) => {
29 sealed::Target
30 };
31 (@type impl sealed::UseFd ) => {
32 RawFd
33 };
34 (@type $name:ty ) => {
35 $name
36 };
37 (
38 $( #[$outer:meta] )*
39 pub struct $name:ident {
40 $( #[$new_meta:meta] )*
41
42 $( $field:ident : { $( $tnt:tt )+ } ),*
43
44 $(,)?
45
46 ;;
47
48 $(
49 $( #[$opt_meta:meta] )*
50 $opt_field:ident : $opt_tname:ty = $default:expr
51 ),*
52
53 $(,)?
54 }
55
56 pub const CODE = $opcode:expr;
57
58 $( #[$build_meta:meta] )*
59 pub fn build($self:ident) -> $entry:ty $build_block:block
60 ) => {
61 $( #[$outer] )*
62 pub struct $name {
63 $( $field : opcode!(@type $( $tnt )*), )*
64 $( $opt_field : $opt_tname, )*
65 }
66
67 impl $name {
68 $( #[$new_meta] )*
69 #[inline]
70 pub fn new($( $field : $( $tnt )* ),*) -> Self {
71 $name {
72 $( $field: $field.into(), )*
73 $( $opt_field: $default, )*
74 }
75 }
76
77 pub const CODE: sys::IoringOp = $opcode as _;
81
82 $(
83 $( #[$opt_meta] )*
84 #[inline]
85 pub const fn $opt_field(mut self, $opt_field: $opt_tname) -> Self {
86 self.$opt_field = $opt_field;
87 self
88 }
89 )*
90
91 $( #[$build_meta] )*
92 #[inline]
93 pub fn build($self) -> $entry $build_block
94 }
95 }
96}
97
98#[inline(always)]
100fn sqe_zeroed() -> sys::io_uring_sqe {
101 Default::default()
102}
103
104opcode! {
105 #[derive(Debug)]
109 pub struct Nop { ;; }
110
111 pub const CODE = sys::IoringOp::Nop;
112
113 pub fn build(self) -> Entry {
114 let Nop {} = self;
115
116 let mut sqe = sqe_zeroed();
117 sqe.opcode = Self::CODE;
118 sqe.fd = -1;
119 Entry(sqe)
120 }
121}
122
123opcode! {
124 #[derive(Debug)]
126 pub struct Readv {
127 fd: { impl sealed::UseFixed },
128 iovec: { *const sys::iovec },
129 len: { u32 },
130 ;;
131 ioprio: u16 = 0,
132 offset: u64 = 0,
133 rw_flags: types::RwFlags = types::RwFlags::empty(),
136 buf_group: u16 = 0
137 }
138
139 pub const CODE = sys::IoringOp::Readv;
140
141 pub fn build(self) -> Entry {
142 let Readv {
143 fd,
144 iovec, len, offset,
145 ioprio, rw_flags,
146 buf_group
147 } = self;
148
149 let mut sqe = sqe_zeroed();
150 sqe.opcode = Self::CODE;
151 assign_fd!(sqe.fd = fd);
152 sqe.ioprio.ioprio = ioprio;
153 sqe.addr_or_splice_off_in.addr.ptr = iovec as _;
154 sqe.len.len = len;
155 sqe.off_or_addr2.off = offset as _;
156 sqe.op_flags.rw_flags = rw_flags;
157 sqe.buf.buf_group = buf_group;
158 Entry(sqe)
159 }
160}
161
162opcode! {
163 #[derive(Debug)]
165 pub struct Writev {
166 fd: { impl sealed::UseFixed },
167 iovec: { *const sys::iovec },
168 len: { u32 },
169 ;;
170 ioprio: u16 = 0,
171 offset: u64 = 0,
172 rw_flags: types::RwFlags = types::RwFlags::empty()
175 }
176
177 pub const CODE = sys::IoringOp::Writev;
178
179 pub fn build(self) -> Entry {
180 let Writev {
181 fd,
182 iovec, len, offset,
183 ioprio, rw_flags
184 } = self;
185
186 let mut sqe = sqe_zeroed();
187 sqe.opcode = Self::CODE;
188 assign_fd!(sqe.fd = fd);
189 sqe.ioprio.ioprio = ioprio;
190 sqe.addr_or_splice_off_in.addr.ptr = iovec as _;
191 sqe.len.len = len;
192 sqe.off_or_addr2.off = offset as _;
193 sqe.op_flags.rw_flags = rw_flags;
194 Entry(sqe)
195 }
196}
197
198opcode! {
199 #[derive(Debug)]
208 pub struct Fsync {
209 fd: { impl sealed::UseFixed },
210 ;;
211 flags: types::FsyncFlags = types::FsyncFlags::empty()
215 }
216
217 pub const CODE = sys::IoringOp::Fsync;
218
219 pub fn build(self) -> Entry {
220 let Fsync { fd, flags } = self;
221
222 let mut sqe = sqe_zeroed();
223 sqe.opcode = Self::CODE;
224 assign_fd!(sqe.fd = fd);
225 sqe.op_flags.fsync_flags = sys::IoringFsyncFlags::from_bits_retain(flags.bits());
226 Entry(sqe)
227 }
228}
229
230opcode! {
231 #[derive(Debug)]
236 pub struct ReadFixed {
237 fd: { impl sealed::UseFixed },
238 buf: { *mut u8 },
239 len: { u32 },
240 buf_index: { u16 },
241 ;;
242 ioprio: u16 = 0,
243 offset: u64 = 0,
245 rw_flags: types::RwFlags = types::RwFlags::empty()
248 }
249
250 pub const CODE = sys::IoringOp::ReadFixed;
251
252 pub fn build(self) -> Entry {
253 let ReadFixed {
254 fd,
255 buf, len, offset,
256 buf_index,
257 ioprio, rw_flags
258 } = self;
259
260 let mut sqe = sqe_zeroed();
261 sqe.opcode = Self::CODE;
262 assign_fd!(sqe.fd = fd);
263 sqe.ioprio.ioprio = ioprio;
264 sqe.addr_or_splice_off_in.addr.ptr = buf as _;
265 sqe.len.len = len;
266 sqe.off_or_addr2.off = offset as _;
267 sqe.op_flags.rw_flags = rw_flags;
268 sqe.buf.buf_index = buf_index;
269 Entry(sqe)
270 }
271}
272
273opcode! {
274 #[derive(Debug)]
279 pub struct WriteFixed {
280 fd: { impl sealed::UseFixed },
281 buf: { *const u8 },
282 len: { u32 },
283 buf_index: { u16 },
284 ;;
285 ioprio: u16 = 0,
286 offset: u64 = 0,
288 rw_flags: types::RwFlags = types::RwFlags::empty()
291 }
292
293 pub const CODE = sys::IoringOp::WriteFixed;
294
295 pub fn build(self) -> Entry {
296 let WriteFixed {
297 fd,
298 buf, len, offset,
299 buf_index,
300 ioprio, rw_flags
301 } = self;
302
303 let mut sqe = sqe_zeroed();
304 sqe.opcode = Self::CODE;
305 assign_fd!(sqe.fd = fd);
306 sqe.ioprio.ioprio = ioprio;
307 sqe.addr_or_splice_off_in.addr.ptr = buf as _;
308 sqe.len.len = len;
309 sqe.off_or_addr2.off = offset as _;
310 sqe.op_flags.rw_flags = rw_flags;
311 sqe.buf.buf_index = buf_index;
312 Entry(sqe)
313 }
314}
315
316opcode! {
317 #[derive(Debug)]
329 pub struct PollAdd {
330 fd: { impl sealed::UseFixed },
333 flags: { u32 },
334 ;;
335 multi: bool = false
336 }
337
338 pub const CODE = sys::IoringOp::PollAdd;
339
340 pub fn build(self) -> Entry {
341 let PollAdd { fd, flags, multi } = self;
342
343 let mut sqe = sqe_zeroed();
344 sqe.opcode = Self::CODE;
345 assign_fd!(sqe.fd = fd);
346 if multi {
347 sqe.len.poll_flags = sys::IoringPollFlags::ADD_MULTI;
348 }
349
350 #[cfg(target_endian = "little")] {
351 sqe.op_flags.poll32_events = flags;
352 }
353
354 #[cfg(target_endian = "big")] {
355 let x = flags << 16;
356 let y = flags >> 16;
357 let flags = x | y;
358 sqe.op_flags.poll32_events = flags;
359 }
360
361 Entry(sqe)
362 }
363}
364
365opcode! {
366 #[derive(Debug)]
371 pub struct PollRemove {
372 user_data: { sys::io_uring_user_data }
373 ;;
374 }
375
376 pub const CODE = sys::IoringOp::PollRemove;
377
378 pub fn build(self) -> Entry {
379 let PollRemove { user_data } = self;
380
381 let mut sqe = sqe_zeroed();
382 sqe.opcode = Self::CODE;
383 sqe.fd = -1;
384 sqe.addr_or_splice_off_in.user_data = user_data;
385 Entry(sqe)
386 }
387}
388
389opcode! {
390 #[derive(Debug)]
392 pub struct SyncFileRange {
393 fd: { impl sealed::UseFixed },
394 len: { u32 },
395 ;;
396 offset: u64 = 0,
398 flags: u32 = 0
400 }
401
402 pub const CODE = sys::IoringOp::SyncFileRange;
403
404 pub fn build(self) -> Entry {
405 let SyncFileRange {
406 fd,
407 len, offset,
408 flags
409 } = self;
410
411 let mut sqe = sqe_zeroed();
412 sqe.opcode = Self::CODE;
413 assign_fd!(sqe.fd = fd);
414 sqe.len.len = len as _;
415 sqe.off_or_addr2.off = offset as _;
416 sqe.op_flags.sync_range_flags = flags;
417 Entry(sqe)
418 }
419}
420
421opcode! {
422 #[derive(Debug)]
427 pub struct SendMsg {
428 fd: { impl sealed::UseFixed },
429 msg: { *const sys::MsgHdr },
430 ;;
431 ioprio: u16 = 0,
432 flags: sys::SendFlags = sys::SendFlags::empty()
433 }
434
435 pub const CODE = sys::IoringOp::Sendmsg;
436
437 pub fn build(self) -> Entry {
438 let SendMsg { fd, msg, ioprio, flags } = self;
439
440 let mut sqe = sqe_zeroed();
441 sqe.opcode = Self::CODE;
442 assign_fd!(sqe.fd = fd);
443 sqe.ioprio.ioprio = ioprio;
444 sqe.addr_or_splice_off_in.addr.ptr = msg as _;
445 sqe.len.len = 1;
446 sqe.op_flags.send_flags = flags;
447 Entry(sqe)
448 }
449}
450
451opcode! {
452 #[derive(Debug)]
456 pub struct RecvMsg {
457 fd: { impl sealed::UseFixed },
458 msg: { *mut sys::MsgHdr },
459 ;;
460 ioprio: u16 = 0,
461 flags: sys::RecvFlags = sys::RecvFlags::empty(),
462 buf_group: u16 = 0
463 }
464
465 pub const CODE = sys::IoringOp::Recvmsg;
466
467 pub fn build(self) -> Entry {
468 let RecvMsg { fd, msg, ioprio, flags, buf_group } = self;
469
470 let mut sqe = sqe_zeroed();
471 sqe.opcode = Self::CODE;
472 assign_fd!(sqe.fd = fd);
473 sqe.ioprio.ioprio = ioprio;
474 sqe.addr_or_splice_off_in.addr.ptr = msg as _;
475 sqe.len.len = 1;
476 sqe.op_flags.recv_flags = flags;
477 sqe.buf.buf_group = buf_group;
478 Entry(sqe)
479 }
480}
481
482opcode! {
483 #[derive(Debug)]
506 pub struct RecvMsgMulti {
507 fd: { impl sealed::UseFixed },
508 msg: { *const sys::MsgHdr },
509 buf_group: { u16 },
510 ;;
511 ioprio: sys::IoringRecvFlags = sys::IoringRecvFlags::empty(),
512 flags: sys::RecvFlags = sys::RecvFlags::empty()
513 }
514
515 pub const CODE = sys::IoringOp::Recvmsg;
516
517 pub fn build(self) -> Entry {
518 let RecvMsgMulti { fd, msg, buf_group, ioprio, flags } = self;
519
520 let mut sqe = sqe_zeroed();
521 sqe.opcode = Self::CODE;
522 assign_fd!(sqe.fd = fd);
523 sqe.addr_or_splice_off_in.addr.ptr = msg as _;
524 sqe.len.len = 1;
525 sqe.op_flags.recv_flags = flags;
526 sqe.buf.buf_group = buf_group;
527 sqe.flags |= sys::IoringSqeFlags::BUFFER_SELECT;
528 sqe.ioprio.recv_flags = ioprio | sys::IoringRecvFlags::MULTISHOT;
529 Entry(sqe)
530 }
531}
532
533opcode! {
534 #[derive(Debug)]
543 pub struct Timeout {
544 timespec: { *const types::Timespec },
545 ;;
546 count: u32 = 0,
548
549 flags: types::TimeoutFlags = types::TimeoutFlags::empty()
551 }
552
553 pub const CODE = sys::IoringOp::Timeout;
554
555 pub fn build(self) -> Entry {
556 let Timeout { timespec, count, flags } = self;
557
558 let mut sqe = sqe_zeroed();
559 sqe.opcode = Self::CODE;
560 sqe.fd = -1;
561 sqe.addr_or_splice_off_in.addr.ptr = timespec as _;
562 sqe.len.len = 1;
563 sqe.off_or_addr2.off = count as _;
564 sqe.op_flags.timeout_flags = sys::IoringTimeoutFlags::from_bits_retain(flags.bits());
565 Entry(sqe)
566 }
567}
568
569opcode! {
572 pub struct TimeoutRemove {
574 user_data: { sys::io_uring_user_data }
575 ;;
576 }
577
578 pub const CODE = sys::IoringOp::TimeoutRemove;
579
580 pub fn build(self) -> Entry {
581 let TimeoutRemove { user_data } = self;
582
583 let mut sqe = sqe_zeroed();
584 sqe.opcode = Self::CODE;
585 sqe.fd = -1;
586 sqe.addr_or_splice_off_in.user_data = user_data;
587 Entry(sqe)
588 }
589}
590
591opcode! {
592 pub struct TimeoutUpdate {
595 user_data: { sys::io_uring_user_data },
596 timespec: { *const types::Timespec },
597 ;;
598 flags: types::TimeoutFlags = types::TimeoutFlags::empty()
599 }
600
601 pub const CODE = sys::IoringOp::TimeoutRemove;
602
603 pub fn build(self) -> Entry {
604 let TimeoutUpdate { user_data, timespec, flags } = self;
605
606 let mut sqe = sqe_zeroed();
607 sqe.opcode = Self::CODE;
608 sqe.fd = -1;
609 sqe.off_or_addr2.addr2.ptr = timespec as _;
610 sqe.addr_or_splice_off_in.user_data = user_data;
611 sqe.op_flags.timeout_flags = sys::IoringTimeoutFlags::from_bits_retain(flags.bits()) | sys::IoringTimeoutFlags::UPDATE;
612 Entry(sqe)
613 }
614}
615
616opcode! {
617 pub struct Accept {
619 fd: { impl sealed::UseFixed },
620 addr: { *mut sys::SocketAddrOpaque },
621 addrlen: { *mut sys::SocketAddrLen },
622 ;;
623 file_index: Option<types::DestinationSlot> = None,
624 flags: sys::SocketFlags = sys::SocketFlags::empty()
625 }
626
627 pub const CODE = sys::IoringOp::Accept;
628
629 pub fn build(self) -> Entry {
630 let Accept { fd, addr, addrlen, file_index, flags } = self;
631
632 let mut sqe = sqe_zeroed();
633 sqe.opcode = Self::CODE;
634 assign_fd!(sqe.fd = fd);
635 sqe.addr_or_splice_off_in.addr.ptr = addr as _;
636 sqe.off_or_addr2.addr2.ptr = addrlen as _;
637 sqe.op_flags.accept_flags = flags;
638 if let Some(dest) = file_index {
639 sqe.splice_fd_in_or_file_index_or_addr_len.file_index = dest.kernel_index_arg();
640 }
641 Entry(sqe)
642 }
643}
644
645opcode! {
646 pub struct AsyncCancel {
648 user_data: { sys::io_uring_user_data }
649 ;;
650
651 }
653
654 pub const CODE = sys::IoringOp::AsyncCancel;
655
656 pub fn build(self) -> Entry {
657 let AsyncCancel { user_data } = self;
658
659 let mut sqe = sqe_zeroed();
660 sqe.opcode = Self::CODE;
661 sqe.fd = -1;
662 sqe.addr_or_splice_off_in.user_data = user_data;
663 Entry(sqe)
664 }
665}
666
667opcode! {
668 pub struct LinkTimeout {
672 timespec: { *const types::Timespec },
673 ;;
674 flags: types::TimeoutFlags = types::TimeoutFlags::empty()
675 }
676
677 pub const CODE = sys::IoringOp::LinkTimeout;
678
679 pub fn build(self) -> Entry {
680 let LinkTimeout { timespec, flags } = self;
681
682 let mut sqe = sqe_zeroed();
683 sqe.opcode = Self::CODE;
684 sqe.fd = -1;
685 sqe.addr_or_splice_off_in.addr.ptr = timespec as _;
686 sqe.len.len = 1;
687 sqe.op_flags.timeout_flags = sys::IoringTimeoutFlags::from_bits_retain(flags.bits());
688 Entry(sqe)
689 }
690}
691
692opcode! {
693 pub struct Connect {
695 fd: { impl sealed::UseFixed },
696 addr: { *const sys::SocketAddrOpaque },
697 addrlen: { sys::SocketAddrLen }
698 ;;
699 }
700
701 pub const CODE = sys::IoringOp::Connect;
702
703 pub fn build(self) -> Entry {
704 let Connect { fd, addr, addrlen } = self;
705
706 let mut sqe = sqe_zeroed();
707 sqe.opcode = Self::CODE;
708 assign_fd!(sqe.fd = fd);
709 sqe.addr_or_splice_off_in.addr.ptr = addr as _;
710 sqe.off_or_addr2.off = addrlen as _;
711 Entry(sqe)
712 }
713}
714
715opcode! {
718 pub struct Fallocate {
720 fd: { impl sealed::UseFixed },
721 len: { u64 },
722 ;;
723 offset: u64 = 0,
724 mode: i32 = 0
725 }
726
727 pub const CODE = sys::IoringOp::Fallocate;
728
729 pub fn build(self) -> Entry {
730 let Fallocate { fd, len, offset, mode } = self;
731
732 let mut sqe = sqe_zeroed();
733 sqe.opcode = Self::CODE;
734 assign_fd!(sqe.fd = fd);
735 sqe.addr_or_splice_off_in.addr.ptr = len as _;
736 sqe.len.len = mode as _;
737 sqe.off_or_addr2.off = offset as _;
738 Entry(sqe)
739 }
740}
741
742opcode! {
743 pub struct OpenAt {
745 dirfd: { impl sealed::UseFd },
746 pathname: { *const sys::c_char },
747 ;;
748 file_index: Option<types::DestinationSlot> = None,
749 flags: sys::OFlags = sys::OFlags::empty(),
750 mode: sys::Mode = sys::Mode::empty()
751 }
752
753 pub const CODE = sys::IoringOp::Openat;
754
755 pub fn build(self) -> Entry {
756 let OpenAt { dirfd, pathname, file_index, flags, mode } = self;
757
758 let mut sqe = sqe_zeroed();
759 sqe.opcode = Self::CODE;
760 sqe.fd = dirfd;
761 sqe.addr_or_splice_off_in.addr.ptr = pathname as _;
762 sqe.len.len = mode.bits();
763 sqe.op_flags.open_flags = flags;
764 if let Some(dest) = file_index {
765 sqe.splice_fd_in_or_file_index_or_addr_len.file_index = dest.kernel_index_arg();
766 }
767 Entry(sqe)
768 }
769}
770
771opcode! {
772 pub struct Close {
776 fd: { impl sealed::UseFixed },
777 ;;
778 }
779
780 pub const CODE = sys::IoringOp::Close;
781
782 pub fn build(self) -> Entry {
783 let Close { fd } = self;
784
785 let mut sqe = sqe_zeroed();
786 sqe.opcode = Self::CODE;
787 match fd {
788 sealed::Target::Fd(fd) => sqe.fd = fd,
789 sealed::Target::Fixed(idx) => {
790 sqe.fd = 0;
791 sqe.splice_fd_in_or_file_index_or_addr_len.file_index = idx + 1;
792 }
793 }
794 Entry(sqe)
795 }
796}
797
798opcode! {
799 pub struct FilesUpdate {
803 fds: { *const RawFd },
804 len: { u32 },
805 ;;
806 offset: i32 = 0
807 }
808
809 pub const CODE = sys::IoringOp::FilesUpdate;
810
811 pub fn build(self) -> Entry {
812 let FilesUpdate { fds, len, offset } = self;
813
814 let mut sqe = sqe_zeroed();
815 sqe.opcode = Self::CODE;
816 sqe.fd = -1;
817 sqe.addr_or_splice_off_in.addr.ptr = fds as _;
818 sqe.len.len = len;
819 sqe.off_or_addr2.off = offset as _;
820 Entry(sqe)
821 }
822}
823
824opcode! {
825 pub struct Statx {
827 dirfd: { impl sealed::UseFd },
828 pathname: { *const sys::c_char },
829 statxbuf: { *mut types::Statx },
830 ;;
831 flags: sys::AtFlags = sys::AtFlags::empty(),
832 mask: sys::StatxFlags = sys::StatxFlags::empty()
833 }
834
835 pub const CODE = sys::IoringOp::Statx;
836
837 pub fn build(self) -> Entry {
838 let Statx {
839 dirfd, pathname, statxbuf,
840 flags, mask
841 } = self;
842
843 let mut sqe = sqe_zeroed();
844 sqe.opcode = Self::CODE;
845 sqe.fd = dirfd;
846 sqe.addr_or_splice_off_in.addr.ptr = pathname as _;
847 sqe.len.len = mask.bits();
848 sqe.off_or_addr2.addr2.ptr = statxbuf as _;
849 sqe.op_flags.statx_flags = flags;
850 Entry(sqe)
851 }
852}
853
854opcode! {
855 pub struct Read {
866 fd: { impl sealed::UseFixed },
867 buf: { *mut u8 },
868 len: { u32 },
869 ;;
870 offset: u64 = 0,
876 ioprio: u16 = 0,
877 rw_flags: types::RwFlags = types::RwFlags::empty(),
878 buf_group: u16 = 0
879 }
880
881 pub const CODE = sys::IoringOp::Read;
882
883 pub fn build(self) -> Entry {
884 let Read {
885 fd,
886 buf, len, offset,
887 ioprio, rw_flags,
888 buf_group
889 } = self;
890
891 let mut sqe = sqe_zeroed();
892 sqe.opcode = Self::CODE;
893 assign_fd!(sqe.fd = fd);
894 sqe.ioprio.ioprio = ioprio;
895 sqe.addr_or_splice_off_in.addr.ptr = buf as _;
896 sqe.len.len = len;
897 sqe.off_or_addr2.off = offset as _;
898 sqe.op_flags.rw_flags = rw_flags;
899 sqe.buf.buf_group = buf_group;
900 Entry(sqe)
901 }
902}
903
904opcode! {
905 pub struct Write {
916 fd: { impl sealed::UseFixed },
917 buf: { *const u8 },
918 len: { u32 },
919 ;;
920 offset: u64 = 0,
926 ioprio: u16 = 0,
927 rw_flags: types::RwFlags = types::RwFlags::empty()
928 }
929
930 pub const CODE = sys::IoringOp::Write;
931
932 pub fn build(self) -> Entry {
933 let Write {
934 fd,
935 buf, len, offset,
936 ioprio, rw_flags
937 } = self;
938
939 let mut sqe = sqe_zeroed();
940 sqe.opcode = Self::CODE;
941 assign_fd!(sqe.fd = fd);
942 sqe.ioprio.ioprio = ioprio;
943 sqe.addr_or_splice_off_in.addr.ptr = buf as _;
944 sqe.len.len = len;
945 sqe.off_or_addr2.off = offset as _;
946 sqe.op_flags.rw_flags = rw_flags;
947 Entry(sqe)
948 }
949}
950
951opcode! {
952 pub struct Fadvise {
954 fd: { impl sealed::UseFixed },
955 len: { u32 },
956 advice: { sys::Advice },
957 ;;
958 offset: u64 = 0,
959 }
960
961 pub const CODE = sys::IoringOp::Fadvise;
962
963 pub fn build(self) -> Entry {
964 let Fadvise { fd, len, advice, offset } = self;
965
966 let mut sqe = sqe_zeroed();
967 sqe.opcode = Self::CODE;
968 assign_fd!(sqe.fd = fd);
969 sqe.len.len = len;
970 sqe.off_or_addr2.off = offset as _;
971 sqe.op_flags.fadvise_advice = advice;
972 Entry(sqe)
973 }
974}
975
976opcode! {
977 pub struct Madvise {
979 addr: { *const core::ffi::c_void },
980 len: { u32 },
981 advice: { sys::Advice },
982 ;;
983 }
984
985 pub const CODE = sys::IoringOp::Madvise;
986
987 pub fn build(self) -> Entry {
988 let Madvise { addr, len, advice } = self;
989
990 let mut sqe = sqe_zeroed();
991 sqe.opcode = Self::CODE;
992 sqe.fd = -1;
993 sqe.addr_or_splice_off_in.addr.ptr = addr as _;
994 sqe.len.len = len;
995 sqe.op_flags.fadvise_advice = advice as _;
996 Entry(sqe)
997 }
998}
999
1000opcode! {
1001 pub struct Send {
1003 fd: { impl sealed::UseFixed },
1004 buf: { *const u8 },
1005 len: { u32 },
1006 ;;
1007 flags: sys::SendFlags = sys::SendFlags::empty(),
1008
1009 dest_addr: *const rustix::net::addr::SocketAddrStorage = core::ptr::null(),
1014 dest_addr_len: rustix::net::addr::SocketAddrLen = 0,
1015 }
1016
1017 pub const CODE = sys::IoringOp::Send;
1018
1019 pub fn build(self) -> Entry {
1020 let Send { fd, buf, len, flags, dest_addr, dest_addr_len } = self;
1021
1022 let mut sqe = sqe_zeroed();
1023 sqe.opcode = Self::CODE;
1024 assign_fd!(sqe.fd = fd);
1025 sqe.addr_or_splice_off_in.addr.ptr = buf as _;
1026 sqe.off_or_addr2.addr2.ptr = dest_addr as _;
1027 sqe.splice_fd_in_or_file_index_or_addr_len.addr_len.addr_len = dest_addr_len as _;
1028 sqe.len.len = len;
1029 sqe.op_flags.send_flags = flags;
1030 Entry(sqe)
1031 }
1032}
1033
1034opcode! {
1035 pub struct Recv {
1037 fd: { impl sealed::UseFixed },
1038 buf: { *mut u8 },
1039 len: { u32 },
1040 ;;
1041 flags: sys::RecvFlags = sys::RecvFlags::empty(),
1042 buf_group: u16 = 0
1043 }
1044
1045 pub const CODE = sys::IoringOp::Recv;
1046
1047 pub fn build(self) -> Entry {
1048 let Recv { fd, buf, len, flags, buf_group } = self;
1049
1050 let mut sqe = sqe_zeroed();
1051 sqe.opcode = Self::CODE;
1052 assign_fd!(sqe.fd = fd);
1053 sqe.addr_or_splice_off_in.addr.ptr = buf as _;
1054 sqe.len.len = len;
1055 sqe.op_flags.recv_flags = flags;
1056 sqe.buf.buf_group = buf_group;
1057 Entry(sqe)
1058 }
1059}
1060
1061opcode! {
1062 pub struct RecvMulti {
1078 fd: { impl sealed::UseFixed },
1079 buf_group: { u16 },
1080 ;;
1081 flags: sys::RecvFlags = sys::RecvFlags::empty(),
1082 }
1083
1084 pub const CODE = sys::IoringOp::Recv;
1085
1086 pub fn build(self) -> Entry {
1087 let RecvMulti { fd, buf_group, flags } = self;
1088
1089 let mut sqe = sqe_zeroed();
1090 sqe.opcode = Self::CODE;
1091 assign_fd!(sqe.fd = fd);
1092 sqe.op_flags.recv_flags = flags;
1093 sqe.buf.buf_group = buf_group;
1094 sqe.flags |= sys::IoringSqeFlags::BUFFER_SELECT;
1095 sqe.ioprio.recv_flags = sys::IoringRecvFlags::MULTISHOT;
1096 Entry(sqe)
1097 }
1098}
1099
1100opcode! {
1101 pub struct OpenAt2 {
1103 dirfd: { impl sealed::UseFd },
1104 pathname: { *const sys::c_char },
1105 how: { *const types::OpenHow }
1106 ;;
1107 file_index: Option<types::DestinationSlot> = None,
1108 }
1109
1110 pub const CODE = sys::IoringOp::Openat2;
1111
1112 pub fn build(self) -> Entry {
1113 let OpenAt2 { dirfd, pathname, how, file_index } = self;
1114
1115 let mut sqe = sqe_zeroed();
1116 sqe.opcode = Self::CODE;
1117 sqe.fd = dirfd;
1118 sqe.addr_or_splice_off_in.addr.ptr = pathname as _;
1119 sqe.len.len = mem::size_of::<sys::open_how>() as _;
1120 sqe.off_or_addr2.addr2.ptr = how as _;
1121 if let Some(dest) = file_index {
1122 sqe.splice_fd_in_or_file_index_or_addr_len.file_index = dest.kernel_index_arg();
1123 }
1124 Entry(sqe)
1125 }
1126}
1127
1128opcode! {
1129 pub struct EpollCtl {
1131 epfd: { impl sealed::UseFixed },
1132 fd: { impl sealed::UseFd },
1133 op: { i32 },
1134 ev: { *const types::EpollEvent },
1135 ;;
1136 }
1137
1138 pub const CODE = sys::IoringOp::EpollCtl;
1139
1140 pub fn build(self) -> Entry {
1141 let EpollCtl { epfd, fd, op, ev } = self;
1142
1143 let mut sqe = sqe_zeroed();
1144 sqe.opcode = Self::CODE;
1145 assign_fd!(sqe.fd = epfd);
1146 sqe.addr_or_splice_off_in.addr.ptr = ev as _;
1147 sqe.len.len = op as _;
1148 sqe.off_or_addr2.off = fd as _;
1149 Entry(sqe)
1150 }
1151}
1152
1153opcode! {
1156 pub struct Splice {
1161 fd_in: { impl sealed::UseFixed },
1162 off_in: { i64 },
1163 fd_out: { impl sealed::UseFixed },
1164 off_out: { i64 },
1165 len: { u32 },
1166 ;;
1167 flags: sys::SpliceFlags = sys::SpliceFlags::empty()
1169 }
1170
1171 pub const CODE = sys::IoringOp::Splice;
1172
1173 pub fn build(self) -> Entry {
1174 let Splice { fd_in, off_in, fd_out, off_out, len, mut flags } = self;
1175
1176 let mut sqe = sqe_zeroed();
1177 sqe.opcode = Self::CODE;
1178 assign_fd!(sqe.fd = fd_out);
1179 sqe.len.len = len;
1180 sqe.off_or_addr2.off = off_out as _;
1181
1182 sqe.splice_fd_in_or_file_index_or_addr_len.splice_fd_in = match fd_in {
1183 sealed::Target::Fd(fd) => fd,
1184 sealed::Target::Fixed(idx) => {
1185 flags |= sys::SpliceFlags::FD_IN_FIXED;
1186 idx as _
1187 }
1188 };
1189
1190 sqe.addr_or_splice_off_in.splice_off_in = off_in as _;
1191 sqe.op_flags.splice_flags = flags;
1192 Entry(sqe)
1193 }
1194}
1195
1196opcode! {
1197 pub struct ProvideBuffers {
1201 addr: { *mut u8 },
1202 len: { i32 },
1203 nbufs: { u16 },
1204 bgid: { u16 },
1205 bid: { u16 }
1206 ;;
1207 }
1208
1209 pub const CODE = sys::IoringOp::ProvideBuffers;
1210
1211 pub fn build(self) -> Entry {
1212 let ProvideBuffers { addr, len, nbufs, bgid, bid } = self;
1213
1214 let mut sqe = sqe_zeroed();
1215 sqe.opcode = Self::CODE;
1216 sqe.fd = nbufs as _;
1217 sqe.addr_or_splice_off_in.addr.ptr = addr as _;
1218 sqe.len.len = len as _;
1219 sqe.off_or_addr2.off = bid as _;
1220 sqe.buf.buf_group = bgid;
1221 Entry(sqe)
1222 }
1223}
1224
1225opcode! {
1226 pub struct RemoveBuffers {
1229 nbufs: { u16 },
1230 bgid: { u16 }
1231 ;;
1232 }
1233
1234 pub const CODE = sys::IoringOp::RemoveBuffers;
1235
1236 pub fn build(self) -> Entry {
1237 let RemoveBuffers { nbufs, bgid } = self;
1238
1239 let mut sqe = sqe_zeroed();
1240 sqe.opcode = Self::CODE;
1241 sqe.fd = nbufs as _;
1242 sqe.buf.buf_group = bgid;
1243 Entry(sqe)
1244 }
1245}
1246
1247opcode! {
1250 pub struct Tee {
1252 fd_in: { impl sealed::UseFixed },
1253 fd_out: { impl sealed::UseFixed },
1254 len: { u32 }
1255 ;;
1256 flags: sys::SpliceFlags = sys::SpliceFlags::empty()
1257 }
1258
1259 pub const CODE = sys::IoringOp::Tee;
1260
1261 pub fn build(self) -> Entry {
1262 let Tee { fd_in, fd_out, len, mut flags } = self;
1263
1264 let mut sqe = sqe_zeroed();
1265 sqe.opcode = Self::CODE;
1266
1267 assign_fd!(sqe.fd = fd_out);
1268 sqe.len.len = len;
1269
1270 sqe.splice_fd_in_or_file_index_or_addr_len.splice_fd_in = match fd_in {
1271 sealed::Target::Fd(fd) => fd,
1272 sealed::Target::Fixed(idx) => {
1273 flags |= sys::SpliceFlags::FD_IN_FIXED;
1274 idx as _
1275 }
1276 };
1277
1278 sqe.op_flags.splice_flags = flags;
1279
1280 Entry(sqe)
1281 }
1282}
1283
1284opcode! {
1287 pub struct Shutdown {
1290 fd: { impl sealed::UseFixed },
1291 how: { i32 },
1292 ;;
1293 }
1294
1295 pub const CODE = sys::IoringOp::Shutdown;
1296
1297 pub fn build(self) -> Entry {
1298 let Shutdown { fd, how } = self;
1299
1300 let mut sqe = sqe_zeroed();
1301 sqe.opcode = Self::CODE;
1302 assign_fd!(sqe.fd = fd);
1303 sqe.len.len = how as _;
1304 Entry(sqe)
1305 }
1306}
1307
1308opcode! {
1309 pub struct RenameAt {
1312 olddirfd: { impl sealed::UseFd },
1313 oldpath: { *const sys::c_char },
1314 newdirfd: { impl sealed::UseFd },
1315 newpath: { *const sys::c_char },
1316 ;;
1317 flags: sys::RenameFlags = sys::RenameFlags::empty()
1318 }
1319
1320 pub const CODE = sys::IoringOp::Renameat;
1321
1322 pub fn build(self) -> Entry {
1323 let RenameAt {
1324 olddirfd, oldpath,
1325 newdirfd, newpath,
1326 flags
1327 } = self;
1328
1329 let mut sqe = sqe_zeroed();
1330 sqe.opcode = Self::CODE;
1331 sqe.fd = olddirfd;
1332 sqe.addr_or_splice_off_in.addr.ptr = oldpath as _;
1333 sqe.len.len = newdirfd as _;
1334 sqe.off_or_addr2.addr2.ptr = newpath as _;
1335 sqe.op_flags.rename_flags = flags;
1336 Entry(sqe)
1337 }
1338}
1339
1340opcode! {
1341 pub struct UnlinkAt {
1344 dirfd: { impl sealed::UseFd },
1345 pathname: { *const sys::c_char },
1346 ;;
1347 flags: sys::AtFlags = sys::AtFlags::empty()
1348 }
1349
1350 pub const CODE = sys::IoringOp::Unlinkat;
1351
1352 pub fn build(self) -> Entry {
1353 let UnlinkAt { dirfd, pathname, flags } = self;
1354
1355 let mut sqe = sqe_zeroed();
1356 sqe.opcode = Self::CODE;
1357 sqe.fd = dirfd;
1358 sqe.addr_or_splice_off_in.addr.ptr = pathname as _;
1359 sqe.op_flags.unlink_flags = flags;
1360 Entry(sqe)
1361 }
1362}
1363
1364opcode! {
1367 pub struct MkDirAt {
1369 dirfd: { impl sealed::UseFd },
1370 pathname: { *const sys::c_char },
1371 ;;
1372 mode: sys::Mode = sys::Mode::empty()
1373 }
1374
1375 pub const CODE = sys::IoringOp::Mkdirat;
1376
1377 pub fn build(self) -> Entry {
1378 let MkDirAt { dirfd, pathname, mode } = self;
1379
1380 let mut sqe = sqe_zeroed();
1381 sqe.opcode = Self::CODE;
1382 sqe.fd = dirfd;
1383 sqe.addr_or_splice_off_in.addr.ptr = pathname as _;
1384 sqe.len.len = mode.into();
1385 Entry(sqe)
1386 }
1387}
1388
1389opcode! {
1390 pub struct SymlinkAt {
1392 newdirfd: { impl sealed::UseFd },
1393 target: { *const sys::c_char },
1394 linkpath: { *const sys::c_char },
1395 ;;
1396 }
1397
1398 pub const CODE = sys::IoringOp::Symlinkat;
1399
1400 pub fn build(self) -> Entry {
1401 let SymlinkAt { newdirfd, target, linkpath } = self;
1402
1403 let mut sqe = sqe_zeroed();
1404 sqe.opcode = Self::CODE;
1405 sqe.fd = newdirfd;
1406 sqe.addr_or_splice_off_in.addr.ptr = target as _;
1407 sqe.off_or_addr2.addr2.ptr = linkpath as _;
1408 Entry(sqe)
1409 }
1410}
1411
1412opcode! {
1413 pub struct LinkAt {
1415 olddirfd: { impl sealed::UseFd },
1416 oldpath: { *const sys::c_char },
1417 newdirfd: { impl sealed::UseFd },
1418 newpath: { *const sys::c_char },
1419 ;;
1420 flags: sys::AtFlags = sys::AtFlags::empty()
1421 }
1422
1423 pub const CODE = sys::IoringOp::Linkat;
1424
1425 pub fn build(self) -> Entry {
1426 let LinkAt { olddirfd, oldpath, newdirfd, newpath, flags } = self;
1427
1428 let mut sqe = sqe_zeroed();
1429 sqe.opcode = Self::CODE;
1430 sqe.fd = olddirfd as _;
1431 sqe.addr_or_splice_off_in.addr.ptr = oldpath as _;
1432 sqe.len.len = newdirfd as _;
1433 sqe.off_or_addr2.addr2.ptr = newpath as _;
1434 sqe.op_flags.hardlink_flags = flags;
1435 Entry(sqe)
1436 }
1437}
1438
1439opcode! {
1442 pub struct MsgRingData {
1444 ring_fd: { impl sealed::UseFd },
1445 result: { i32 },
1446 user_data: { sys::io_uring_user_data },
1447 user_flags: { Option<u32> },
1448 ;;
1449 opcode_flags: sys::IoringMsgringFlags = sys::IoringMsgringFlags::empty()
1450 }
1451
1452 pub const CODE = sys::IoringOp::MsgRing;
1453
1454 pub fn build(self) -> Entry {
1455 let MsgRingData { ring_fd, result, user_data, user_flags, opcode_flags } = self;
1456
1457 let mut sqe = sqe_zeroed();
1458 sqe.opcode = Self::CODE;
1459 sqe.addr_or_splice_off_in.msgring_cmd = sys::IoringMsgringCmds::Data;
1460 sqe.fd = ring_fd;
1461 sqe.len.len = result as u32;
1462 sqe.off_or_addr2.user_data = user_data;
1463 sqe.op_flags.msg_ring_flags = opcode_flags;
1464 if let Some(flags) = user_flags {
1465 sqe.splice_fd_in_or_file_index_or_addr_len.file_index = flags;
1466 unsafe {sqe.op_flags.msg_ring_flags |= sys::IoringMsgringFlags::FLAGS_PASS};
1467 }
1468 Entry(sqe)
1469 }
1470}
1471
1472opcode! {
1475 pub struct AsyncCancel2 {
1479 builder: { types::CancelBuilder }
1480 ;;
1481 }
1482
1483 pub const CODE = sys::IoringOp::AsyncCancel;
1484
1485 pub fn build(self) -> Entry {
1486 let AsyncCancel2 { builder } = self;
1487
1488 let mut sqe = sqe_zeroed();
1489 sqe.opcode = Self::CODE;
1490 sqe.fd = builder.to_fd();
1491 sqe.addr_or_splice_off_in.user_data = builder.user_data;
1492 sqe.op_flags.cancel_flags = sys::IoringAsyncCancelFlags::from_bits_retain(builder.flags.bits());
1493 Entry(sqe)
1494 }
1495}
1496
1497opcode! {
1498 pub struct UringCmd16 {
1500 fd: { impl sealed::UseFixed },
1501 cmd_op: { u32 },
1502 ;;
1503 buf_index: Option<u16> = None,
1506 cmd: [u8; 16] = [0u8; 16]
1508 }
1509
1510 pub const CODE = sys::IoringOp::UringCmd;
1511
1512 pub fn build(self) -> Entry {
1513 let UringCmd16 { fd, cmd_op, cmd, buf_index } = self;
1514
1515 let mut sqe = sqe_zeroed();
1516 sqe.opcode = Self::CODE;
1517 assign_fd!(sqe.fd = fd);
1518 sqe.off_or_addr2.cmd_op.cmd_op = cmd_op;
1519 unsafe { *sqe.addr3_or_cmd.cmd.as_mut().as_mut_ptr().cast::<[u8; 16]>() = cmd };
1520 if let Some(buf_index) = buf_index {
1521 sqe.buf.buf_index = buf_index;
1522 unsafe {
1523 sqe.op_flags.uring_cmd_flags |= sys::IoringUringCmdFlags::FIXED;
1524 }
1525 }
1526 Entry(sqe)
1527 }
1528}
1529
1530opcode! {
1531 pub struct UringCmd80 {
1533 fd: { impl sealed::UseFixed },
1534 cmd_op: { u32 },
1535 ;;
1536 buf_index: Option<u16> = None,
1539 cmd: [u8; 80] = [0u8; 80]
1541 }
1542
1543 pub const CODE = sys::IoringOp::UringCmd;
1544
1545 pub fn build(self) -> Entry128 {
1546 let UringCmd80 { fd, cmd_op, cmd, buf_index } = self;
1547
1548 let cmd1 = cmd[..16].try_into().unwrap();
1549 let cmd2 = cmd[16..].try_into().unwrap();
1550
1551 let mut sqe = sqe_zeroed();
1552 sqe.opcode = Self::CODE;
1553 assign_fd!(sqe.fd = fd);
1554 sqe.off_or_addr2.cmd_op.cmd_op = cmd_op;
1555 unsafe { *sqe.addr3_or_cmd.cmd.as_mut().as_mut_ptr().cast::<[u8; 16]>() = cmd1 };
1556 if let Some(buf_index) = buf_index {
1557 sqe.buf.buf_index = buf_index;
1558 unsafe {
1559 sqe.op_flags.uring_cmd_flags |= sys::IoringUringCmdFlags::FIXED;
1560 }
1561 }
1562 Entry128(Entry(sqe), cmd2)
1563 }
1564}
1565
1566opcode! {
1567 pub struct Socket {
1577 domain: { i32 },
1578 socket_type: { i32 },
1579 protocol: { i32 },
1580 ;;
1581 file_index: Option<types::DestinationSlot> = None,
1582 flags: types::RwFlags = types::RwFlags::empty(),
1583 }
1584
1585 pub const CODE = sys::IoringOp::Socket;
1586
1587 pub fn build(self) -> Entry {
1588 let Socket { domain, socket_type, protocol, file_index, flags } = self;
1589
1590 let mut sqe = sqe_zeroed();
1591 sqe.opcode = Self::CODE;
1592 sqe.fd = domain as _;
1593 sqe.off_or_addr2.off = socket_type as _;
1594 sqe.len.len = protocol as _;
1595 sqe.op_flags.rw_flags = flags;
1596 if let Some(dest) = file_index {
1597 sqe.splice_fd_in_or_file_index_or_addr_len.file_index = dest.kernel_index_arg();
1598 }
1599 Entry(sqe)
1600 }
1601}
1602
1603opcode! {
1604 pub struct AcceptMulti {
1610 fd: { impl sealed::UseFixed },
1611 ;;
1612 allocate_file_index: bool = false,
1613 flags: sys::SocketFlags = sys::SocketFlags::empty()
1614 }
1615
1616 pub const CODE = sys::IoringOp::Accept;
1617
1618 pub fn build(self) -> Entry {
1619 let AcceptMulti { fd, allocate_file_index, flags } = self;
1620
1621 let mut sqe = sqe_zeroed();
1622 sqe.opcode = Self::CODE;
1623 assign_fd!(sqe.fd = fd);
1624 sqe.ioprio.accept_flags = sys::IoringAcceptFlags::MULTISHOT;
1625 sqe.op_flags.accept_flags = flags;
1628 if allocate_file_index {
1629 sqe.splice_fd_in_or_file_index_or_addr_len.file_index = sys::IORING_FILE_INDEX_ALLOC as u32;
1630 }
1631 Entry(sqe)
1632 }
1633}
1634
1635opcode! {
1638 pub struct MsgRingSendFd {
1640 ring_fd: { impl sealed::UseFd },
1641 fixed_slot_src: { types::Fixed },
1642 dest_slot_index: { types::DestinationSlot },
1643 user_data: { sys::io_uring_user_data }
1644 ;;
1645 opcode_flags: sys::IoringMsgringFlags = sys::IoringMsgringFlags::empty()
1646 }
1647
1648 pub const CODE = sys::IoringOp::MsgRing;
1649
1650 pub fn build(self) -> Entry {
1651 let MsgRingSendFd { ring_fd, fixed_slot_src, dest_slot_index, user_data, opcode_flags } = self;
1652
1653 let mut sqe = sqe_zeroed();
1654 sqe.opcode = Self::CODE;
1655 sqe.addr_or_splice_off_in.msgring_cmd = sys::IoringMsgringCmds::SendFd;
1656 sqe.fd = ring_fd;
1657 sqe.off_or_addr2.user_data = user_data;
1658 sqe.addr3_or_cmd.addr3.addr3 = fixed_slot_src.0 as u64;
1659 sqe.splice_fd_in_or_file_index_or_addr_len.file_index = dest_slot_index.kernel_index_arg();
1660 sqe.op_flags.msg_ring_flags = opcode_flags;
1661 Entry(sqe)
1662 }
1663}
1664
1665opcode! {
1668 pub struct SendZc {
1682 fd: { impl sealed::UseFixed },
1683 buf: { *const u8 },
1684 len: { u32 },
1685 ;;
1686 buf_index: Option<u16> = None,
1693 dest_addr: *const sys::SocketAddrStorage = core::ptr::null(),
1694 dest_addr_len: sys::SocketAddrLen = 0,
1695 flags: sys::SendFlags = sys::SendFlags::empty(),
1696 zc_flags: sys::IoringSendFlags = sys::IoringSendFlags::empty(),
1697 }
1698
1699 pub const CODE = sys::IoringOp::SendZc;
1700
1701 pub fn build(self) -> Entry {
1702 let SendZc { fd, buf, len, buf_index, dest_addr, dest_addr_len, flags, zc_flags } = self;
1703
1704 let mut sqe = sqe_zeroed();
1705 sqe.opcode = Self::CODE;
1706 assign_fd!(sqe.fd = fd);
1707 sqe.addr_or_splice_off_in.addr.ptr = buf as _;
1708 sqe.len.len = len;
1709 sqe.op_flags.send_flags = flags;
1710 sqe.ioprio.send_flags = zc_flags;
1711 if let Some(buf_index) = buf_index {
1712 sqe.buf.buf_index = buf_index;
1713 unsafe { sqe.ioprio.send_flags |= sys::IoringSendFlags::FIXED_BUF; }
1714 }
1715 sqe.off_or_addr2.addr2.ptr = dest_addr as _;
1716 sqe.splice_fd_in_or_file_index_or_addr_len.addr_len.addr_len = dest_addr_len as _;
1717 Entry(sqe)
1718 }
1719}
1720
1721opcode! {
1724 #[derive(Debug)]
1729 pub struct SendMsgZc {
1730 fd: { impl sealed::UseFixed },
1731 msg: { *const sys::MsgHdr },
1732 ;;
1733 ioprio: u16 = 0,
1734 flags: sys::SendFlags = sys::SendFlags::empty()
1735 }
1736
1737 pub const CODE = sys::IoringOp::SendmsgZc;
1738
1739 pub fn build(self) -> Entry {
1740 let SendMsgZc { fd, msg, ioprio, flags } = self;
1741
1742 let mut sqe = sqe_zeroed();
1743 sqe.opcode = Self::CODE;
1744 assign_fd!(sqe.fd = fd);
1745 sqe.ioprio.ioprio = ioprio;
1746 sqe.addr_or_splice_off_in.addr.ptr = msg as _;
1747 sqe.len.len = 1;
1748 sqe.op_flags.send_flags = flags;
1749 Entry(sqe)
1750 }
1751}
1752
1753opcode! {
1756 #[derive(Debug)]
1765 pub struct FutexWait {
1766 futex: { *const u32 },
1767 val: { u64 },
1768 mask: { u64 },
1769 futex_flags: { sys::FutexWaitFlags },
1770 ;;
1771 flags: sys::FutexWaitvFlags = sys::FutexWaitvFlags::empty()
1772 }
1773
1774 pub const CODE = sys::IoringOp::FutexWait;
1775
1776 pub fn build(self) -> Entry {
1777 let FutexWait { futex, val, mask, futex_flags, flags } = self;
1778
1779 let mut sqe = sqe_zeroed();
1780 sqe.opcode = Self::CODE;
1781 sqe.fd = futex_flags.bits() as _;
1782 sqe.addr_or_splice_off_in.addr.ptr = futex as _;
1783 sqe.off_or_addr2.off = val;
1784 sqe.addr3_or_cmd.addr3.addr3 = mask;
1785 sqe.op_flags.futex_flags = flags;
1786 Entry(sqe)
1787 }
1788}
1789
1790opcode! {
1791 #[derive(Debug)]
1799 pub struct FutexWake {
1800 futex: { *const u32 },
1801 val: { u64 },
1802 mask: { u64 },
1803 futex_flags: { sys::FutexWaitFlags },
1804 ;;
1805 flags: sys::FutexWaitvFlags = sys::FutexWaitvFlags::empty(),
1806 }
1807
1808 pub const CODE = sys::IoringOp::FutexWake;
1809
1810 pub fn build(self) -> Entry {
1811 let FutexWake { futex, val, mask, futex_flags, flags } = self;
1812
1813 let mut sqe = sqe_zeroed();
1814 sqe.opcode = Self::CODE;
1815 sqe.fd = futex_flags.bits() as _;
1816 sqe.addr_or_splice_off_in.addr.ptr = futex as _;
1817 sqe.off_or_addr2.off = val;
1818 sqe.addr3_or_cmd.addr3.addr3 = mask;
1819 sqe.op_flags.futex_flags = flags;
1820 Entry(sqe)
1821 }
1822}
1823
1824opcode! {
1825 #[derive(Debug)]
1831 pub struct FutexWaitV {
1832 futexv: { *const types::FutexWaitV },
1833 nr_futex: { u32 },
1834 ;;
1835 flags: sys::FutexWaitvFlags = sys::FutexWaitvFlags::empty(),
1836 }
1837
1838 pub const CODE = sys::IoringOp::FutexWaitv;
1839
1840 pub fn build(self) -> Entry {
1841 let FutexWaitV { futexv, nr_futex, flags } = self;
1842
1843 let mut sqe = sqe_zeroed();
1844 sqe.opcode = Self::CODE;
1845 sqe.addr_or_splice_off_in.addr.ptr = futexv as _;
1846 sqe.len.len = nr_futex;
1847 sqe.op_flags.futex_flags = flags;
1848 Entry(sqe)
1849 }
1850}
1851
1852opcode! {
1855 #[derive(Debug)]
1860 pub struct FixedFdInstall {
1861 fd: { types::Fixed },
1862 file_flags: { sys::IoringFixedFdFlags },
1863 ;;
1864 }
1865
1866 pub const CODE = sys::IoringOp::FixedFdInstall;
1867
1868 pub fn build(self) -> Entry {
1869 let FixedFdInstall { fd, file_flags } = self;
1870
1871 let mut sqe = sqe_zeroed();
1872 sqe.opcode = Self::CODE;
1873 sqe.fd = fd.0 as _;
1874 sqe.flags = sys::IoringSqeFlags::FIXED_FILE;
1875 sqe.op_flags.install_fd_flags = file_flags;
1876 Entry(sqe)
1877 }
1878}
1879
1880opcode! {
1883 #[derive(Debug)]
1885 pub struct Ftruncate {
1886 fd: { impl sealed::UseFixed },
1887 len: { u64 },
1888 ;;
1889 }
1890
1891 pub const CODE = sys::IoringOp::Ftruncate;
1892
1893 pub fn build(self) -> Entry {
1894 let Ftruncate { fd, len } = self;
1895
1896 let mut sqe = sqe_zeroed();
1897 sqe.opcode = Self::CODE;
1898 assign_fd!(sqe.fd = fd);
1899 sqe.off_or_addr2.off = len;
1900 Entry(sqe)
1901 }
1902}
1903
1904opcode! {
1907 pub struct SendBundle {
1909 fd: { impl sealed::UseFixed },
1910 buf_group: { u16 },
1911 ;;
1912 flags: sys::SendFlags = sys::SendFlags::empty(),
1913 len: u32 = 0
1914 }
1915
1916 pub const CODE = sys::IoringOp::Send;
1917
1918 pub fn build(self) -> Entry {
1919 let SendBundle { fd, len, flags, buf_group } = self;
1920
1921 let mut sqe = sqe_zeroed();
1922 sqe.opcode = Self::CODE;
1923 assign_fd!(sqe.fd = fd);
1924 sqe.len.len = len;
1925 sqe.op_flags.send_flags = flags;
1926 sqe.ioprio.send_flags = sys::IoringSendFlags::BUNDLE;
1927 sqe.flags |= sys::IoringSqeFlags::BUFFER_SELECT;
1928 sqe.buf.buf_group = buf_group;
1929 Entry(sqe)
1930 }
1931}
1932
1933opcode! {
1934 pub struct RecvBundle {
1944 fd: { impl sealed::UseFixed },
1945 buf_group: { u16 },
1946 ;;
1947 flags: sys::RecvFlags = sys::RecvFlags::empty(),
1948 }
1949
1950 pub const CODE = sys::IoringOp::Recv;
1951
1952 pub fn build(self) -> Entry {
1953 let RecvBundle { fd, buf_group, flags } = self;
1954
1955 let mut sqe = sqe_zeroed();
1956 sqe.opcode = Self::CODE;
1957 assign_fd!(sqe.fd = fd);
1958 sqe.op_flags.recv_flags = flags;
1959 sqe.buf.buf_group = buf_group;
1960 sqe.flags |= sys::IoringSqeFlags::BUFFER_SELECT;
1961 sqe.ioprio.recv_flags = sys::IoringRecvFlags::BUNDLE;
1962 Entry(sqe)
1963 }
1964}
1965
1966opcode! {
1967 pub struct RecvMultiBundle {
1985 fd: { impl sealed::UseFixed },
1986 buf_group: { u16 },
1987 ;;
1988 flags: sys::RecvFlags = sys::RecvFlags::empty(),
1989 }
1990
1991 pub const CODE = sys::IoringOp::Recv;
1992
1993 pub fn build(self) -> Entry {
1994 let RecvMultiBundle { fd, buf_group, flags } = self;
1995
1996 let mut sqe = sqe_zeroed();
1997 sqe.opcode = Self::CODE;
1998 assign_fd!(sqe.fd = fd);
1999 sqe.op_flags.recv_flags = flags;
2000 sqe.buf.buf_group = buf_group;
2001 sqe.flags |= sys::IoringSqeFlags::BUFFER_SELECT;
2002 sqe.ioprio.recv_flags = sys::IoringRecvFlags::MULTISHOT | sys::IoringRecvFlags::BUNDLE;
2003 Entry(sqe)
2004 }
2005}