View Javadoc
1   /*
2    * Copyright 2024 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.uring;
17  
18  import io.netty.channel.IoOps;
19  
20  /**
21   * {@link IoOps} for implementation for
22   * <a href="https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h">Io_uring</a>.
23   */
24  public final class IoUringIoOps implements IoOps {
25  
26      private final byte opcode;
27      private final byte flags;
28      private final short ioPrio;
29      private final int fd;
30      private final long union1;
31      private final long union2;
32      private final int len;
33      private final int union3;
34      private final long data;
35      private final short personality;
36      private final short union4;
37      private final int union5;
38      private final long union6;
39  
40      /**
41       * Create a new instance which represents the {@code io_uring_sqe} struct.
42       * @deprecated use
43       * {@link #IoUringIoOps(byte, byte, short, int, long, long, int, int, long, short, short, int, long)} instead.
44       */
45      @Deprecated
46      public IoUringIoOps(byte opcode, byte flags, short ioPrio, int fd, long union1, long union2, int len, int union3,
47                          short data, short union4, short personality, int union5, long union6) {
48          this(opcode, flags, ioPrio, fd, union1, union2, len, union3, (long) data, union4, personality, union5, union6);
49      }
50  
51      /**
52       * Create a new instance which represents the {@code io_uring_sqe} struct.
53       *
54       * <pre>{@code
55       *  struct io_uring_sqe {
56       *      __u8    opcode;    // type of operation for this sqe
57       *      __u8    flags;     // IOSQE_ flags
58       *      __u16   ioprio;    // ioprio for the request
59       *      __s32   fd;        // file descriptor to do IO on
60       *
61       *      union {            // union1
62       *          __u64 off;     // offset into file
63       *          __u64 addr2;
64       *          struct {
65       *              __u32 cmd_op;
66       *              __u32 __pad1;
67       *          };
68       *      };
69       *
70       *      union {             // union2
71       *          __u64 addr;    // pointer to buffer or iovecs
72       *          __u64 splice_off_in;
73       *          struct {
74       *              __u32 level;
75       *              __u32 optname;
76       *          };
77       *      };
78       *      __u32 len;        // buffer size or number of iovecs
79       *
80       *      union {           // union3
81       *          __kernel_rwf_t rw_flags;
82       *          __u32 fsync_flags;
83       *          __u16 poll_events;    // compatibility
84       *          __u32 poll32_events; // word-reversed for BE
85       *          __u32 sync_range_flags;
86       *          __u32 msg_flags;
87       *          __u32 timeout_flags;
88       *          __u32 accept_flags;
89       *          __u32 cancel_flags;
90       *          __u32 open_flags;
91       *          __u32 statx_flags;
92       *          __u32 fadvise_advice;
93       *          __u32 splice_flags;
94       *          __u32 rename_flags;
95       *          __u32 unlink_flags;
96       *          __u32 hardlink_flags;
97       *          __u32 xeattr_flags;
98       *          __u32 msg_ring_flags;
99       *          __u32 uring_cmd_flags;
100      *          __u32 waitid_flags;
101      *          __u32 futex_flags;
102      *          __u32 install_fd_flags;
103      *          __u32 nop_flags;
104      *      };
105      *      __u64 user_data;    // data to be passed back at completion time
106      *                          // pack this to avoid bogus arm OABI complaints
107      *
108      *      union {             // union4
109      *
110      *          // index into fixed buffers, if used
111      *          __u16 buf_index;
112      *          // for grouped buffer selection
113      *          __u16 buf_group;
114      *      }__attribute__((packed));
115      *      // personality to use, if used
116      *      __u16 personality;
117      *
118      *      union {            // union5
119      *
120      *          __s32 splice_fd_in;
121      *          __u32 file_index;
122      *          __u32 optlen;
123      *          struct {
124      *              __u16 addr_len;
125      *              __u16 __pad3[ 1];
126      *          };
127      *      };
128      *
129      *      union {           // union6
130      *
131      *          struct {
132      *              __u64 addr3;
133      *              __u64 __pad2[ 1];
134      *          };
135      *          __u64 optval;
136      *          //
137      *          // If the ring is initialized with IORING_SETUP_SQE128, then
138      *          // this field is used for 80 bytes of arbitrary command data
139      *          __u8 cmd[ 0];
140      *      };
141      *  };
142      * }
143      * </pre>
144      */
145     public IoUringIoOps(byte opcode, byte flags, short ioPrio, int fd, long union1, long union2, int len, int union3,
146                         long data, short union4, short personality, int union5, long union6) {
147         this.opcode = opcode;
148         this.flags = flags;
149         this.ioPrio = ioPrio;
150         this.fd = fd;
151         this.union1 = union1;
152         this.union2 = union2;
153         this.len = len;
154         this.union3 = union3;
155         this.data = data;
156         this.union4 = union4;
157         this.personality = personality;
158         this.union5 = union5;
159         this.union6 = union6;
160     }
161 
162     byte opcode() {
163         return opcode;
164     }
165 
166     byte flags() {
167         return flags;
168     }
169 
170     short ioPrio() {
171         return ioPrio;
172     }
173 
174     int fd() {
175         return fd;
176     }
177 
178     long union1() {
179         return union1;
180     }
181 
182     long union2() {
183         return union2;
184     }
185 
186     int len() {
187         return len;
188     }
189 
190     int union3() {
191         return union3;
192     }
193 
194     /**
195      * Returns the data that is passed as part of this {@link IoUringIoOps}.
196      *
197      * @return  data.
198      * @deprecated use {@link #userData()} instead.
199      */
200     @Deprecated
201     short data() {
202         return (short) data;
203     }
204 
205     long userData() {
206         return data;
207     }
208 
209     short personality() {
210         return personality;
211     }
212 
213     short union4() {
214         return union4;
215     }
216 
217     int union5() {
218         return union5;
219     }
220 
221     long union6() {
222         return union6;
223     }
224 
225     @Override
226     public String toString() {
227         return "IOUringIoOps{" +
228                 "opcode=" + opcode +
229                 ", flags=" + flags +
230                 ", ioPrio=" + ioPrio +
231                 ", fd=" + fd +
232                 ", union1=" + union1 +
233                 ", union2=" + union2 +
234                 ", len=" + len +
235                 ", union3=" + union3 +
236                 ", data=" + data +
237                 ", union4=" + union4 +
238                 ", personality=" + personality +
239                 ", union5=" + union5 +
240                 ", union6=" + union6 +
241                 '}';
242     }
243 
244     /**
245      * Returns a new {@code OP_ASYNC_CANCEL} {@link IoUringIoOps}.
246      *
247      * @param flags     the flags.
248      * @param userData  the user data that identify a previous submitted {@link IoUringIoOps} that should be cancelled.
249      *                  The value to use here is returned by {@link io.netty.channel.IoRegistration#submit(IoOps)}.
250      * @param data      the data
251      * @return          ops.
252      */
253     static IoUringIoOps newAsyncCancel(byte flags, long userData, short data) {
254         // Best effort to cancel the
255         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L679
256         return new IoUringIoOps(Native.IORING_OP_ASYNC_CANCEL, flags, (short) 0, -1, 0, userData, 0, 0,
257                 data, (short) 0, (short) 0, 0, 0);
258     }
259 
260     /**
261      * Returns a new {@code OP_CLOSE} {@link IoUringIoOps}.
262      *
263      * @param fd        the filedescriptor
264      * @param flags     the flags.
265      * @param data      the data
266      * @return          ops.
267      */
268     static IoUringIoOps newClose(int fd, byte flags, short data) {
269         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L764
270         return new IoUringIoOps(Native.IORING_OP_CLOSE, flags, (short) 0, fd, 0L, 0L, 0, 0, data,
271                 (short) 0, (short) 0, 0, 0);
272     }
273 
274     /**
275      * Returns a new {@code OP_POLL_ADD} {@link IoUringIoOps}.
276      *
277      * @param fd        the filedescriptor
278      * @param flags     the flags.
279      * @param mask      the mask.
280      * @param len       the len.
281      * @param data      the data.
282      * @return          ops.
283      */
284     static IoUringIoOps newPollAdd(int fd, byte flags, int mask, int len, short data) {
285         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L554
286         return new IoUringIoOps(Native.IORING_OP_POLL_ADD, flags, (short) 0, fd, 0L, 0L, len, mask, data,
287                 (short) 0, (short) 0, 0, 0);
288     }
289 
290     /**
291      * Returns a new {@code OP_SENDMSG} {@link IoUringIoOps}.
292      *
293      * @param fd        the filedescriptor
294      * @param flags     the flags.
295      * @param msgFlags  the msg flags.
296      * @param data      the data
297      * @return          ops.
298      */
299     static IoUringIoOps newSendmsg(int fd, byte flags, int msgFlags, long address, short data) {
300         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L539
301         return new IoUringIoOps(Native.IORING_OP_SENDMSG, flags, (short) 0, fd, 0L, address, 1, msgFlags, data,
302                 (short) 0, (short) 0, 0, 0);
303     }
304 
305     /**
306      * Returns a new {@code OP_CONNECT} {@link IoUringIoOps}.
307      *
308      * @param fd                    the filedescriptor
309      * @param flags                 the flags.
310      * @param remoteMemoryAddress   the memory address of the sockaddr_storage.
311      * @param data                  the data
312      * @return                      ops.
313      */
314     static IoUringIoOps newConnect(int fd, byte flags, long remoteMemoryAddress, short data) {
315         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L695
316         return newConnect(
317                 fd, flags,
318                 remoteMemoryAddress, Native.SIZEOF_SOCKADDR_STORAGE,
319                 data
320         );
321     }
322 
323     /**
324      * Returns a new {@code OP_CONNECT} {@link IoUringIoOps}.
325      *
326      * @param fd                    the filedescriptor
327      * @param flags                 the flags.
328      * @param remoteMemoryAddress   the memory address of the sockaddr_storage.
329      * @param addrLen               then remoteMemory storage length.
330      * @param data                  the data
331      * @return                      ops.
332      */
333     static IoUringIoOps newConnect(int fd, byte flags, long remoteMemoryAddress, int addrLen, short data) {
334         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L695
335         return new IoUringIoOps(Native.IORING_OP_CONNECT, flags, (short) 0, fd, addrLen,
336                 remoteMemoryAddress, 0, 0, data, (short) 0, (short) 0, 0, 0);
337     }
338 
339     /**
340      * Returns a new {@code OP_ACCEPT} {@link IoUringIoOps}.
341      *
342      * @param fd                                    the filedescriptor
343      * @param flags                                 the flags.
344      * @param acceptFlags                           the flags for ACCEPT itself
345      * @param ioPrio                                io_prio
346      * @param acceptedAddressMemoryAddress          the memory address of the sockaddr_storage.
347      * @param acceptedAddressLengthMemoryAddress    the memory address of the length that will be updated once a new
348      *                                              connection was accepted.
349      * @param data                                  the data
350      * @return                                      ops.
351      */
352     static IoUringIoOps newAccept(int fd, byte flags, int acceptFlags, short ioPrio, long acceptedAddressMemoryAddress,
353                                          long acceptedAddressLengthMemoryAddress, short data) {
354         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L625
355         return new IoUringIoOps(Native.IORING_OP_ACCEPT, flags, ioPrio, fd, acceptedAddressLengthMemoryAddress,
356                 acceptedAddressMemoryAddress, 0, acceptFlags, data, (short) 0, (short) 0, 0, 0);
357     }
358 
359     /**
360      * Returns a new {@code OP_WRITEV} {@link IoUringIoOps}.
361      *
362      * @param fd                                    the filedescriptor
363      * @param flags                                 the flags.
364      * @param writevFlags                           the writev flags.
365      * @param memoryAddress                         the memory address of the io_vec array.
366      * @param length                                the length of the io_vec array.
367      * @param data                                  the data
368      * @return                                      ops.
369      */
370     static IoUringIoOps newWritev(int fd, byte flags, int writevFlags, long memoryAddress,
371                                          int length, short data) {
372         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L500
373         return new IoUringIoOps(Native.IORING_OP_WRITEV, flags, (short) 0, fd,
374                 0, memoryAddress, length, writevFlags, data, (short) 0, (short) 0, 0, 0);
375     }
376 
377     /**
378      * Returns a new {@code OP_WRITE} {@link IoUringIoOps}.
379      *
380      * @param fd                                    the filedescriptor
381      * @param flags                                 the flags.
382      * @param writeFlags                            the write flags.
383      * @param memoryAddress                         the memory address of the buffer
384      * @param length                                the length of the buffer.
385      * @param data                                  the data
386      * @return                                      ops.
387      */
388     static IoUringIoOps newWrite(
389             int fd, byte flags, int writeFlags, long memoryAddress, int length, short data) {
390         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L794
391         return new IoUringIoOps(Native.IORING_OP_WRITE, flags, (short) 0, fd,
392                 0, memoryAddress, length, writeFlags, data, (short) 0, (short) 0, 0, 0);
393     }
394 
395     /**
396      * Returns a new {@code OP_RECV} {@link IoUringIoOps}.
397      *
398      * @param fd                                    the filedescriptor
399      * @param flags                                 the flags.
400      * @param ioPrio                                the ioPrio.
401      * @param recvFlags                             the recv flags.
402      * @param memoryAddress                         the memory address of the buffer
403      * @param length                                the length of the buffer.
404      * @param data                                  the data
405      * @return                                      ops.
406      */
407     static IoUringIoOps newRecv(
408             int fd, byte flags, short ioPrio, int recvFlags, long memoryAddress, int length, short data) {
409         return newRecv(fd, flags, ioPrio, recvFlags, memoryAddress, length, data, (short) 0);
410     }
411 
412     static IoUringIoOps newRecv(
413             int fd, byte flags, short ioPrio, int recvFlags, long memoryAddress, int length, short data, short bid) {
414         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L898
415         return new IoUringIoOps(Native.IORING_OP_RECV, flags, ioPrio, fd,
416                 0, memoryAddress, length, recvFlags, data, bid, (short) 0, 0, 0);
417     }
418 
419     static IoUringIoOps newSendZc(
420             int fd, long memoryAddress, int length,
421             int flags, short data, int zcFlags) {
422         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L867
423         return new IoUringIoOps(Native.IORING_OP_SEND_ZC, (byte) 0, (byte) zcFlags, fd,
424                 0, memoryAddress, length, flags, data, (short) 0, (short) 0, 0, 0);
425     }
426 
427     static IoUringIoOps newSendmsgZc(int fd, byte flags, int msgFlags, long address, short data) {
428         return new IoUringIoOps(Native.IORING_OP_SENDMSG_ZC, flags, (short) 0, fd, 0L, address, 1, msgFlags, data,
429                 (short) 0, (short) 0, 0, 0);
430     }
431 
432     /**
433      * Returns a new {@code OP_RECVMSG} {@link IoUringIoOps}.
434      *
435      * @param fd                                    the filedescriptor
436      * @param flags                                 the flags.
437      * @param msgFlags                              the recvmsg flags.
438      * @param memoryAddress                         the memory address of the msghdr struct
439      * @param data                                  the data
440      * @return                                      ops.
441      */
442     static IoUringIoOps newRecvmsg(int fd, byte flags, int msgFlags, long memoryAddress, short data) {
443         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L523
444         return new IoUringIoOps(
445                 Native.IORING_OP_RECVMSG, flags, (short) 0, fd, 0L, memoryAddress, 1, msgFlags, data,
446                 (short) 0, (short) 0, 0, 0);
447     }
448 
449     /**
450      * Returns a new {@code OP_SEND} {@link IoUringIoOps}.
451      *
452      * @param fd                                    the filedescriptor
453      * @param flags                                 the flags.
454      * @param sendFlags                             the send flags.
455      * @param memoryAddress                         the memory address of the buffer.
456      * @param length                                the length of the buffer.
457      * @param data                                  the data
458      * @return                                      ops.
459      */
460     static IoUringIoOps newSend(
461             int fd, byte flags, int sendFlags, long memoryAddress, int length, short data) {
462         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L839
463         return new IoUringIoOps(Native.IORING_OP_SEND, flags, (short) 0, fd,
464                 0, memoryAddress, length, sendFlags, data, (short) 0, (short) 0, 0, 0);
465     }
466 
467     /**
468      * Returns a new {@code OP_SHUTDOWN} {@link IoUringIoOps}.
469      *
470      * @param fd                                    the filedescriptor
471      * @param flags                                 the flags.
472      * @param how                                   how the shutdown will be done.
473      * @param data                                  the data
474      * @return                                      ops.
475      */
476     static IoUringIoOps newShutdown(int fd, byte flags, int how, short data) {
477         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L1023
478         return new IoUringIoOps(Native.IORING_OP_SHUTDOWN, flags, (short) 0, fd, 0, 0, how, 0, data,
479                 (short) 0, (short) 0, 0, 0);
480     }
481 
482     /**
483      *
484      * Returns a new {@code OP_SPLICE} {@link IoUringIoOps}.
485      *
486      * @param fd_in                                     the filedescriptor
487      * @param off_in                                    the filedescriptor offset
488      * @param fd_out                                    the filedescriptor
489      * @param off_out                                   the filedescriptor offset
490      * @param nbytes                                    splice bytes
491      * @param splice_flags                              the flag
492      * @param data                                      the data
493      * @return                                          ops.
494      */
495     static IoUringIoOps newSplice(int fd_in, long off_in,
496                                          int fd_out, long off_out,
497                                          int nbytes,
498                                          int splice_flags,
499                                          short data) {
500         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L454
501         return new IoUringIoOps(
502                 Native.IORING_OP_SPLICE, (byte) 0, (short) 0, fd_out, off_out, off_in,
503                 nbytes, splice_flags, data, (short) 0, (short) 0, fd_in, 0
504         );
505     }
506 }