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 fd        the filedescriptor
226      * @param flags     the flags.
227      * @param userData  the user data that identify a previous submitted {@link IoUringIoOps} that should be cancelled.
228      *                  The value to use here is returned by {@link IoUringIoRegistration#submit(IoOps)}.
229      * @param data      the data
230      * @return          ops.
231      */
232     static IoUringIoOps newAsyncCancel(int fd, byte flags, long userData, short data) {
233         // Best effort to cancel the
234         return new IoUringIoOps(Native.IORING_OP_ASYNC_CANCEL, flags, (short) 0, fd, 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         return new IoUringIoOps(Native.IORING_OP_CLOSE, flags, (short) 0, fd, 0L, 0L, 0, 0, data,
248                 (short) 0, (short) 0, 0, 0);
249     }
250 
251     /**
252      * Returns a new {@code OP_POLL_ADD} {@link IoUringIoOps}.
253      *
254      * @param fd        the filedescriptor
255      * @param flags     the flags.
256      * @param mask      the mask.
257      * @param data      the data
258      * @return          ops.
259      */
260     static IoUringIoOps newPollAdd(int fd, byte flags, int mask, short data) {
261         return new IoUringIoOps(Native.IORING_OP_POLL_ADD, flags, (short) 0, fd, 0L, 0L, 0, mask, data,
262                 (short) 0, (short) 0, 0, 0);
263     }
264 
265     /**
266      * Returns a new {@code OP_SENDMSG} {@link IoUringIoOps}.
267      *
268      * @param fd        the filedescriptor
269      * @param flags     the flags.
270      * @param msgFlags  the msg flags.
271      * @param data      the data
272      * @return          ops.
273      */
274     static IoUringIoOps newSendmsg(int fd, byte flags, int msgFlags, long address, short data) {
275         return new IoUringIoOps(Native.IORING_OP_SENDMSG, flags, (short) 0, fd, 0L, address, 1, msgFlags, data,
276                 (short) 0, (short) 0, 0, 0);
277     }
278 
279     /**
280      * Returns a new {@code OP_CONNECT} {@link IoUringIoOps}.
281      *
282      * @param fd                    the filedescriptor
283      * @param flags                 the flags.
284      * @param remoteMemoryAddress   the memory address of the sockaddr_storage.
285      * @param data                  the data
286      * @return                      ops.
287      */
288     static IoUringIoOps newConnect(int fd, byte flags, long remoteMemoryAddress, short data) {
289         return new IoUringIoOps(Native.IORING_OP_CONNECT, flags, (short) 0, fd, Native.SIZEOF_SOCKADDR_STORAGE,
290                 remoteMemoryAddress, 0, 0, data, (short) 0, (short) 0, 0, 0);
291     }
292 
293     /**
294      * Returns a new {@code OP_POLL_REMOVE} {@link IoUringIoOps}.
295      *
296      * @param fd        the filedescriptor
297      * @param flags     the flags.
298      * @param userData  the user data that identify a previous submitted {@link IoUringIoOps} that should be cancelled.
299      *                  The value to use here is returned by {@link IoUringIoRegistration#submit(IoOps)}.
300      * @param data      the data
301      * @return          ops.
302      */
303     static IoUringIoOps newPollRemove(int fd, byte flags, long userData, short data) {
304         return new IoUringIoOps(Native.IORING_OP_POLL_REMOVE, flags, (short) 0, fd, 0, userData, 0, 0, data,
305                 (short) 0, (short) 0, 0, 0);
306     }
307 
308     /**
309      * Returns a new {@code OP_ACCEPT} {@link IoUringIoOps}.
310      *
311      * @param fd                                    the filedescriptor
312      * @param flags                                 the flags.
313      * @param acceptedAddressMemoryAddress          the memory address of the sockaddr_storage.
314      * @param acceptedAddressLengthMemoryAddress    the memory address of the length that will be updated once a new
315      *                                              connection was accepted.
316      * @param data                                  the data
317      * @return                                      ops.
318      */
319     static IoUringIoOps newAccept(int fd, byte flags, int acceptFlags, long acceptedAddressMemoryAddress,
320                                          long acceptedAddressLengthMemoryAddress, short data) {
321 
322         return new IoUringIoOps(Native.IORING_OP_ACCEPT, flags, (short) 0, fd, acceptedAddressLengthMemoryAddress,
323                 acceptedAddressMemoryAddress, 0, acceptFlags, data, (short) 0, (short) 0, 0, 0);
324     }
325 
326     /**
327      * Returns a new {@code OP_WRITEV} {@link IoUringIoOps}.
328      *
329      * @param fd                                    the filedescriptor
330      * @param flags                                 the flags.
331      * @param writevFlags                           the writev flags.
332      * @param memoryAddress                         the memory address of the io_vec array.
333      * @param length                                the length of the io_vec array.
334      * @param data                                  the data
335      * @return                                      ops.
336      */
337     static IoUringIoOps newWritev(int fd, byte flags, int writevFlags, long memoryAddress,
338                                          int length, short data) {
339         return new IoUringIoOps(Native.IORING_OP_WRITEV, flags, (short) 0, fd,
340                 0, memoryAddress, length, writevFlags, data, (short) 0, (short) 0, 0, 0);
341     }
342 
343     /**
344      * Returns a new {@code OP_WRITE} {@link IoUringIoOps}.
345      *
346      * @param fd                                    the filedescriptor
347      * @param flags                                 the flags.
348      * @param writeFlags                            the write flags.
349      * @param memoryAddress                         the memory address of the buffer
350      * @param length                                the length of the buffer.
351      * @param data                                  the data
352      * @return                                      ops.
353      */
354     static IoUringIoOps newWrite(
355             int fd, byte flags, int writeFlags, long memoryAddress, int length, short data) {
356         return new IoUringIoOps(Native.IORING_OP_WRITE, flags, (short) 0, fd,
357                 0, memoryAddress, length, writeFlags, data, (short) 0, (short) 0, 0, 0);
358     }
359 
360     /**
361      * Returns a new {@code OP_RECV} {@link IoUringIoOps}.
362      *
363      * @param fd                                    the filedescriptor
364      * @param flags                                 the flags.
365      * @param recvFlags                             the recv flags.
366      * @param memoryAddress                         the memory address of the buffer
367      * @param length                                the length of the buffer.
368      * @param data                                  the data
369      * @return                                      ops.
370      */
371     static IoUringIoOps newRecv(
372             int fd, byte flags, int recvFlags, long memoryAddress, int length, short data) {
373         return new IoUringIoOps(Native.IORING_OP_RECV, flags, (short) 0, fd,
374                 0, memoryAddress, length, recvFlags, data, (short) 0, (short) 0, 0, 0);
375     }
376 
377     /**
378      * Returns a new {@code OP_RECVMSG} {@link IoUringIoOps}.
379      *
380      * @param fd                                    the filedescriptor
381      * @param flags                                 the flags.
382      * @param msgFlags                              the recvmsg flags.
383      * @param memoryAddress                         the memory address of the msghdr struct
384      * @param data                                  the data
385      * @return                                      ops.
386      */
387     static IoUringIoOps newRecvmsg(int fd, byte flags, int msgFlags, long memoryAddress, short data) {
388         return new IoUringIoOps(
389                 Native.IORING_OP_RECVMSG, flags, (short) 0, fd, 0L, memoryAddress, 1, msgFlags, data,
390                 (short) 0, (short) 0, 0, 0);
391     }
392 
393     /**
394      * Returns a new {@code OP_SEND} {@link IoUringIoOps}.
395      *
396      * @param fd                                    the filedescriptor
397      * @param flags                                 the flags.
398      * @param sendFlags                             the send flags.
399      * @param memoryAddress                         the memory address of the buffer.
400      * @param length                                the length of the buffer.
401      * @param data                                  the data
402      * @return                                      ops.
403      */
404     static IoUringIoOps newSend(
405             int fd, byte flags, int sendFlags, long memoryAddress, int length, short data) {
406         return new IoUringIoOps(Native.IORING_OP_SEND, flags, (short) 0, fd,
407                 memoryAddress, 0L, length, sendFlags, data, (short) 0, (short) 0, 0, 0);
408     }
409 
410     /**
411      * Returns a new {@code OP_SHUTDOWN} {@link IoUringIoOps}.
412      *
413      * @param fd                                    the filedescriptor
414      * @param flags                                 the flags.
415      * @param how                                   how the shutdown will be done.
416      * @param data                                  the data
417      * @return                                      ops.
418      */
419     static IoUringIoOps newShutdown(int fd, byte flags, int how, short data) {
420         return new IoUringIoOps(Native.IORING_OP_SHUTDOWN, flags, (short) 0, fd, 0, 0, how, 0, data,
421                 (short) 0, (short) 0, 0, 0);
422     }
423 
424     /**
425      *
426      * Returns a new {@code OP_SPLICE} {@link IoUringIoOps}.
427      *
428      * @param fd_in                                     the filedescriptor
429      * @param off_in                                    the filedescriptor offset
430      * @param fd_out                                    the filedescriptor
431      * @param off_out                                   the filedescriptor offset
432      * @param nbytes                                    splice bytes
433      * @param splice_flags                              the flag
434      * @param data                                      the data
435      * @return                                          ops.
436      */
437     static IoUringIoOps newSplice(int fd_in, long off_in,
438                                          int fd_out, long off_out,
439                                          int nbytes,
440                                          int splice_flags,
441                                          short data) {
442         return new IoUringIoOps(
443                 Native.IORING_OP_SPLICE, (byte) 0, (short) 0, fd_out, off_out, off_in,
444                 nbytes, splice_flags, data, (short) 0, (short) 0, fd_in, 0
445         );
446     }
447 }