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 short 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       *
43       * <pre>{@code
44       *  struct io_uring_sqe {
45       *      __u8    opcode;    // type of operation for this sqe
46       *      __u8    flags;     // IOSQE_ flags
47       *      __u16   ioprio;    // ioprio for the request
48       *      __s32   fd;        // file descriptor to do IO on
49       *
50       *      union {            // union1
51       *          __u64 off;     // offset into file
52       *          __u64 addr2;
53       *          struct {
54       *              __u32 cmd_op;
55       *              __u32 __pad1;
56       *          };
57       *      };
58       *
59       *      union {             // union2
60       *          __u64 addr;    // pointer to buffer or iovecs
61       *          __u64 splice_off_in;
62       *          struct {
63       *              __u32 level;
64       *              __u32 optname;
65       *          };
66       *      };
67       *      __u32 len;        // buffer size or number of iovecs
68       *
69       *      union {           // union3
70       *          __kernel_rwf_t rw_flags;
71       *          __u32 fsync_flags;
72       *          __u16 poll_events;    // compatibility
73       *          __u32 poll32_events; // word-reversed for BE
74       *          __u32 sync_range_flags;
75       *          __u32 msg_flags;
76       *          __u32 timeout_flags;
77       *          __u32 accept_flags;
78       *          __u32 cancel_flags;
79       *          __u32 open_flags;
80       *          __u32 statx_flags;
81       *          __u32 fadvise_advice;
82       *          __u32 splice_flags;
83       *          __u32 rename_flags;
84       *          __u32 unlink_flags;
85       *          __u32 hardlink_flags;
86       *          __u32 xeattr_flags;
87       *          __u32 msg_ring_flags;
88       *          __u32 uring_cmd_flags;
89       *          __u32 waitid_flags;
90       *          __u32 futex_flags;
91       *          __u32 install_fd_flags;
92       *          __u32 nop_flags;
93       *      };
94       *      __u64 user_data;    // data to be passed back at completion time
95       *                          // pack this to avoid bogus arm OABI complaints
96       *
97       *      union {             // union4
98       *
99       *          // index into fixed buffers, if used
100      *          __u16 buf_index;
101      *          // for grouped buffer selection
102      *          __u16 buf_group;
103      *      }__attribute__((packed));
104      *      // personality to use, if used
105      *      __u16 personality;
106      *
107      *      union {            // union5
108      *
109      *          __s32 splice_fd_in;
110      *          __u32 file_index;
111      *          __u32 optlen;
112      *          struct {
113      *              __u16 addr_len;
114      *              __u16 __pad3[ 1];
115      *          };
116      *      };
117      *
118      *      union {           // union6
119      *
120      *          struct {
121      *              __u64 addr3;
122      *              __u64 __pad2[ 1];
123      *          };
124      *          __u64 optval;
125      *          //
126      *          // If the ring is initialized with IORING_SETUP_SQE128, then
127      *          // this field is used for 80 bytes of arbitrary command data
128      *          __u8 cmd[ 0];
129      *      };
130      *  };
131      * }
132      * </pre>
133      */
134     public IoUringIoOps(byte opcode, byte flags, short ioPrio, int fd, long union1, long union2, int len, int union3,
135                         short data, short union4, short personality, int union5, long union6) {
136         this.opcode = opcode;
137         this.flags = flags;
138         this.ioPrio = ioPrio;
139         this.fd = fd;
140         this.union1 = union1;
141         this.union2 = union2;
142         this.len = len;
143         this.union3 = union3;
144         this.data = data;
145         this.union4 = union4;
146         this.personality = personality;
147         this.union5 = union5;
148         this.union6 = union6;
149     }
150 
151     byte opcode() {
152         return opcode;
153     }
154 
155     byte flags() {
156         return flags;
157     }
158 
159     short ioPrio() {
160         return ioPrio;
161     }
162 
163     int fd() {
164         return fd;
165     }
166 
167     long union1() {
168         return union1;
169     }
170 
171     long union2() {
172         return union2;
173     }
174 
175     int len() {
176         return len;
177     }
178 
179     int union3() {
180         return union3;
181     }
182 
183     short data() {
184         return data;
185     }
186 
187     short personality() {
188         return personality;
189     }
190 
191     short union4() {
192         return union4;
193     }
194 
195     int union5() {
196         return union5;
197     }
198 
199     long union6() {
200         return union6;
201     }
202 
203     @Override
204     public String toString() {
205         return "IOUringIoOps{" +
206                 "opcode=" + opcode +
207                 ", flags=" + flags +
208                 ", ioPrio=" + ioPrio +
209                 ", fd=" + fd +
210                 ", union1=" + union1 +
211                 ", union2=" + union2 +
212                 ", len=" + len +
213                 ", union3=" + union3 +
214                 ", data=" + data +
215                 ", union4=" + union4 +
216                 ", personality=" + personality +
217                 ", union5=" + union5 +
218                 ", union6=" + union6 +
219                 '}';
220     }
221 
222     /**
223      * Returns a new {@code OP_ASYNC_CANCEL} {@link IoUringIoOps}.
224      *
225      * @param flags     the flags.
226      * @param userData  the user data that identify a previous submitted {@link IoUringIoOps} that should be cancelled.
227      *                  The value to use here is returned by {@link io.netty.channel.IoRegistration#submit(IoOps)}.
228      * @param data      the data
229      * @return          ops.
230      */
231     static IoUringIoOps newAsyncCancel(byte flags, long userData, short data) {
232         // Best effort to cancel the
233         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L679
234         return new IoUringIoOps(Native.IORING_OP_ASYNC_CANCEL, flags, (short) 0, -1, 0, userData, 0, 0,
235                 data, (short) 0, (short) 0, 0, 0);
236     }
237 
238     /**
239      * Returns a new {@code OP_CLOSE} {@link IoUringIoOps}.
240      *
241      * @param fd        the filedescriptor
242      * @param flags     the flags.
243      * @param data      the data
244      * @return          ops.
245      */
246     static IoUringIoOps newClose(int fd, byte flags, short data) {
247         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L764
248         return new IoUringIoOps(Native.IORING_OP_CLOSE, flags, (short) 0, fd, 0L, 0L, 0, 0, data,
249                 (short) 0, (short) 0, 0, 0);
250     }
251 
252     /**
253      * Returns a new {@code OP_POLL_ADD} {@link IoUringIoOps}.
254      *
255      * @param fd        the filedescriptor
256      * @param flags     the flags.
257      * @param mask      the mask.
258      * @param len       the len.
259      * @param data      the data.
260      * @return          ops.
261      */
262     static IoUringIoOps newPollAdd(int fd, byte flags, int mask, int len, short data) {
263         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L554
264         return new IoUringIoOps(Native.IORING_OP_POLL_ADD, flags, (short) 0, fd, 0L, 0L, len, mask, data,
265                 (short) 0, (short) 0, 0, 0);
266     }
267 
268     /**
269      * Returns a new {@code OP_SENDMSG} {@link IoUringIoOps}.
270      *
271      * @param fd        the filedescriptor
272      * @param flags     the flags.
273      * @param msgFlags  the msg flags.
274      * @param data      the data
275      * @return          ops.
276      */
277     static IoUringIoOps newSendmsg(int fd, byte flags, int msgFlags, long address, short data) {
278         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L539
279         return new IoUringIoOps(Native.IORING_OP_SENDMSG, flags, (short) 0, fd, 0L, address, 1, msgFlags, data,
280                 (short) 0, (short) 0, 0, 0);
281     }
282 
283     /**
284      * Returns a new {@code OP_CONNECT} {@link IoUringIoOps}.
285      *
286      * @param fd                    the filedescriptor
287      * @param flags                 the flags.
288      * @param remoteMemoryAddress   the memory address of the sockaddr_storage.
289      * @param data                  the data
290      * @return                      ops.
291      */
292     static IoUringIoOps newConnect(int fd, byte flags, long remoteMemoryAddress, short data) {
293         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L695
294         return new IoUringIoOps(Native.IORING_OP_CONNECT, flags, (short) 0, fd, Native.SIZEOF_SOCKADDR_STORAGE,
295                 remoteMemoryAddress, 0, 0, data, (short) 0, (short) 0, 0, 0);
296     }
297 
298     /**
299      * Returns a new {@code OP_ACCEPT} {@link IoUringIoOps}.
300      *
301      * @param fd                                    the filedescriptor
302      * @param flags                                 the flags.
303      * @param acceptFlags                           the flags for ACCEPT itself
304      * @param ioPrio                                io_prio
305      * @param acceptedAddressMemoryAddress          the memory address of the sockaddr_storage.
306      * @param acceptedAddressLengthMemoryAddress    the memory address of the length that will be updated once a new
307      *                                              connection was accepted.
308      * @param data                                  the data
309      * @return                                      ops.
310      */
311     static IoUringIoOps newAccept(int fd, byte flags, int acceptFlags, short ioPrio, long acceptedAddressMemoryAddress,
312                                          long acceptedAddressLengthMemoryAddress, short data) {
313         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L625
314         return new IoUringIoOps(Native.IORING_OP_ACCEPT, flags, ioPrio, fd, acceptedAddressLengthMemoryAddress,
315                 acceptedAddressMemoryAddress, 0, acceptFlags, data, (short) 0, (short) 0, 0, 0);
316     }
317 
318     /**
319      * Returns a new {@code OP_WRITEV} {@link IoUringIoOps}.
320      *
321      * @param fd                                    the filedescriptor
322      * @param flags                                 the flags.
323      * @param writevFlags                           the writev flags.
324      * @param memoryAddress                         the memory address of the io_vec array.
325      * @param length                                the length of the io_vec array.
326      * @param data                                  the data
327      * @return                                      ops.
328      */
329     static IoUringIoOps newWritev(int fd, byte flags, int writevFlags, long memoryAddress,
330                                          int length, short data) {
331         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L500
332         return new IoUringIoOps(Native.IORING_OP_WRITEV, flags, (short) 0, fd,
333                 0, memoryAddress, length, writevFlags, data, (short) 0, (short) 0, 0, 0);
334     }
335 
336     /**
337      * Returns a new {@code OP_WRITE} {@link IoUringIoOps}.
338      *
339      * @param fd                                    the filedescriptor
340      * @param flags                                 the flags.
341      * @param writeFlags                            the write flags.
342      * @param memoryAddress                         the memory address of the buffer
343      * @param length                                the length of the buffer.
344      * @param data                                  the data
345      * @return                                      ops.
346      */
347     static IoUringIoOps newWrite(
348             int fd, byte flags, int writeFlags, long memoryAddress, int length, short data) {
349         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L794
350         return new IoUringIoOps(Native.IORING_OP_WRITE, flags, (short) 0, fd,
351                 0, memoryAddress, length, writeFlags, data, (short) 0, (short) 0, 0, 0);
352     }
353 
354     /**
355      * Returns a new {@code OP_RECV} {@link IoUringIoOps}.
356      *
357      * @param fd                                    the filedescriptor
358      * @param flags                                 the flags.
359      * @param ioPrio                                the ioPrio.
360      * @param recvFlags                             the recv flags.
361      * @param memoryAddress                         the memory address of the buffer
362      * @param length                                the length of the buffer.
363      * @param data                                  the data
364      * @return                                      ops.
365      */
366     static IoUringIoOps newRecv(
367             int fd, byte flags, short ioPrio, int recvFlags, long memoryAddress, int length, short data) {
368         return newRecv(fd, flags, ioPrio, recvFlags, memoryAddress, length, data, (short) 0);
369     }
370 
371     static IoUringIoOps newRecv(
372             int fd, byte flags, short ioPrio, int recvFlags, long memoryAddress, int length, short data, short bid) {
373         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L898
374         return new IoUringIoOps(Native.IORING_OP_RECV, flags, ioPrio, fd,
375                 0, memoryAddress, length, recvFlags, data, bid, (short) 0, 0, 0);
376     }
377 
378     /**
379      * Returns a new {@code OP_RECVMSG} {@link IoUringIoOps}.
380      *
381      * @param fd                                    the filedescriptor
382      * @param flags                                 the flags.
383      * @param msgFlags                              the recvmsg flags.
384      * @param memoryAddress                         the memory address of the msghdr struct
385      * @param data                                  the data
386      * @return                                      ops.
387      */
388     static IoUringIoOps newRecvmsg(int fd, byte flags, int msgFlags, long memoryAddress, short data) {
389         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L523
390         return new IoUringIoOps(
391                 Native.IORING_OP_RECVMSG, flags, (short) 0, fd, 0L, memoryAddress, 1, msgFlags, data,
392                 (short) 0, (short) 0, 0, 0);
393     }
394 
395     /**
396      * Returns a new {@code OP_SEND} {@link IoUringIoOps}.
397      *
398      * @param fd                                    the filedescriptor
399      * @param flags                                 the flags.
400      * @param sendFlags                             the send flags.
401      * @param memoryAddress                         the memory address of the buffer.
402      * @param length                                the length of the buffer.
403      * @param data                                  the data
404      * @return                                      ops.
405      */
406     static IoUringIoOps newSend(
407             int fd, byte flags, int sendFlags, long memoryAddress, int length, short data) {
408         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L839
409         return new IoUringIoOps(Native.IORING_OP_SEND, flags, (short) 0, fd,
410                 0, memoryAddress, length, sendFlags, data, (short) 0, (short) 0, 0, 0);
411     }
412 
413     /**
414      * Returns a new {@code OP_SHUTDOWN} {@link IoUringIoOps}.
415      *
416      * @param fd                                    the filedescriptor
417      * @param flags                                 the flags.
418      * @param how                                   how the shutdown will be done.
419      * @param data                                  the data
420      * @return                                      ops.
421      */
422     static IoUringIoOps newShutdown(int fd, byte flags, int how, short data) {
423         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L1023
424         return new IoUringIoOps(Native.IORING_OP_SHUTDOWN, flags, (short) 0, fd, 0, 0, how, 0, data,
425                 (short) 0, (short) 0, 0, 0);
426     }
427 
428     /**
429      *
430      * Returns a new {@code OP_SPLICE} {@link IoUringIoOps}.
431      *
432      * @param fd_in                                     the filedescriptor
433      * @param off_in                                    the filedescriptor offset
434      * @param fd_out                                    the filedescriptor
435      * @param off_out                                   the filedescriptor offset
436      * @param nbytes                                    splice bytes
437      * @param splice_flags                              the flag
438      * @param data                                      the data
439      * @return                                          ops.
440      */
441     static IoUringIoOps newSplice(int fd_in, long off_in,
442                                          int fd_out, long off_out,
443                                          int nbytes,
444                                          int splice_flags,
445                                          short data) {
446         // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L454
447         return new IoUringIoOps(
448                 Native.IORING_OP_SPLICE, (byte) 0, (short) 0, fd_out, off_out, off_in,
449                 nbytes, splice_flags, data, (short) 0, (short) 0, fd_in, 0
450         );
451     }
452 }