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 }