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 newConnect( 295 fd, flags, 296 remoteMemoryAddress, Native.SIZEOF_SOCKADDR_STORAGE, 297 data 298 ); 299 } 300 301 /** 302 * Returns a new {@code OP_CONNECT} {@link IoUringIoOps}. 303 * 304 * @param fd the filedescriptor 305 * @param flags the flags. 306 * @param remoteMemoryAddress the memory address of the sockaddr_storage. 307 * @param addrLen then remoteMemory storage length. 308 * @param data the data 309 * @return ops. 310 */ 311 static IoUringIoOps newConnect(int fd, byte flags, long remoteMemoryAddress, int addrLen, short data) { 312 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L695 313 return new IoUringIoOps(Native.IORING_OP_CONNECT, flags, (short) 0, fd, addrLen, 314 remoteMemoryAddress, 0, 0, data, (short) 0, (short) 0, 0, 0); 315 } 316 317 /** 318 * Returns a new {@code OP_ACCEPT} {@link IoUringIoOps}. 319 * 320 * @param fd the filedescriptor 321 * @param flags the flags. 322 * @param acceptFlags the flags for ACCEPT itself 323 * @param ioPrio io_prio 324 * @param acceptedAddressMemoryAddress the memory address of the sockaddr_storage. 325 * @param acceptedAddressLengthMemoryAddress the memory address of the length that will be updated once a new 326 * connection was accepted. 327 * @param data the data 328 * @return ops. 329 */ 330 static IoUringIoOps newAccept(int fd, byte flags, int acceptFlags, short ioPrio, long acceptedAddressMemoryAddress, 331 long acceptedAddressLengthMemoryAddress, short data) { 332 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L625 333 return new IoUringIoOps(Native.IORING_OP_ACCEPT, flags, ioPrio, fd, acceptedAddressLengthMemoryAddress, 334 acceptedAddressMemoryAddress, 0, acceptFlags, data, (short) 0, (short) 0, 0, 0); 335 } 336 337 /** 338 * Returns a new {@code OP_WRITEV} {@link IoUringIoOps}. 339 * 340 * @param fd the filedescriptor 341 * @param flags the flags. 342 * @param writevFlags the writev flags. 343 * @param memoryAddress the memory address of the io_vec array. 344 * @param length the length of the io_vec array. 345 * @param data the data 346 * @return ops. 347 */ 348 static IoUringIoOps newWritev(int fd, byte flags, int writevFlags, long memoryAddress, 349 int length, short data) { 350 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L500 351 return new IoUringIoOps(Native.IORING_OP_WRITEV, flags, (short) 0, fd, 352 0, memoryAddress, length, writevFlags, data, (short) 0, (short) 0, 0, 0); 353 } 354 355 /** 356 * Returns a new {@code OP_WRITE} {@link IoUringIoOps}. 357 * 358 * @param fd the filedescriptor 359 * @param flags the flags. 360 * @param writeFlags the write 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 newWrite( 367 int fd, byte flags, int writeFlags, long memoryAddress, int length, short data) { 368 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L794 369 return new IoUringIoOps(Native.IORING_OP_WRITE, flags, (short) 0, fd, 370 0, memoryAddress, length, writeFlags, data, (short) 0, (short) 0, 0, 0); 371 } 372 373 /** 374 * Returns a new {@code OP_RECV} {@link IoUringIoOps}. 375 * 376 * @param fd the filedescriptor 377 * @param flags the flags. 378 * @param ioPrio the ioPrio. 379 * @param recvFlags the recv flags. 380 * @param memoryAddress the memory address of the buffer 381 * @param length the length of the buffer. 382 * @param data the data 383 * @return ops. 384 */ 385 static IoUringIoOps newRecv( 386 int fd, byte flags, short ioPrio, int recvFlags, long memoryAddress, int length, short data) { 387 return newRecv(fd, flags, ioPrio, recvFlags, memoryAddress, length, data, (short) 0); 388 } 389 390 static IoUringIoOps newRecv( 391 int fd, byte flags, short ioPrio, int recvFlags, long memoryAddress, int length, short data, short bid) { 392 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L898 393 return new IoUringIoOps(Native.IORING_OP_RECV, flags, ioPrio, fd, 394 0, memoryAddress, length, recvFlags, data, bid, (short) 0, 0, 0); 395 } 396 397 /** 398 * Returns a new {@code OP_RECVMSG} {@link IoUringIoOps}. 399 * 400 * @param fd the filedescriptor 401 * @param flags the flags. 402 * @param msgFlags the recvmsg flags. 403 * @param memoryAddress the memory address of the msghdr struct 404 * @param data the data 405 * @return ops. 406 */ 407 static IoUringIoOps newRecvmsg(int fd, byte flags, int msgFlags, long memoryAddress, short data) { 408 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L523 409 return new IoUringIoOps( 410 Native.IORING_OP_RECVMSG, flags, (short) 0, fd, 0L, memoryAddress, 1, msgFlags, data, 411 (short) 0, (short) 0, 0, 0); 412 } 413 414 /** 415 * Returns a new {@code OP_SEND} {@link IoUringIoOps}. 416 * 417 * @param fd the filedescriptor 418 * @param flags the flags. 419 * @param sendFlags the send flags. 420 * @param memoryAddress the memory address of the buffer. 421 * @param length the length of the buffer. 422 * @param data the data 423 * @return ops. 424 */ 425 static IoUringIoOps newSend( 426 int fd, byte flags, int sendFlags, long memoryAddress, int length, short data) { 427 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L839 428 return new IoUringIoOps(Native.IORING_OP_SEND, flags, (short) 0, fd, 429 0, memoryAddress, length, sendFlags, data, (short) 0, (short) 0, 0, 0); 430 } 431 432 /** 433 * Returns a new {@code OP_SHUTDOWN} {@link IoUringIoOps}. 434 * 435 * @param fd the filedescriptor 436 * @param flags the flags. 437 * @param how how the shutdown will be done. 438 * @param data the data 439 * @return ops. 440 */ 441 static IoUringIoOps newShutdown(int fd, byte flags, int how, short data) { 442 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L1023 443 return new IoUringIoOps(Native.IORING_OP_SHUTDOWN, flags, (short) 0, fd, 0, 0, how, 0, data, 444 (short) 0, (short) 0, 0, 0); 445 } 446 447 /** 448 * 449 * Returns a new {@code OP_SPLICE} {@link IoUringIoOps}. 450 * 451 * @param fd_in the filedescriptor 452 * @param off_in the filedescriptor offset 453 * @param fd_out the filedescriptor 454 * @param off_out the filedescriptor offset 455 * @param nbytes splice bytes 456 * @param splice_flags the flag 457 * @param data the data 458 * @return ops. 459 */ 460 static IoUringIoOps newSplice(int fd_in, long off_in, 461 int fd_out, long off_out, 462 int nbytes, 463 int splice_flags, 464 short data) { 465 // See https://github.com/axboe/liburing/blob/liburing-2.8/src/include/liburing.h#L454 466 return new IoUringIoOps( 467 Native.IORING_OP_SPLICE, (byte) 0, (short) 0, fd_out, off_out, off_in, 468 nbytes, splice_flags, data, (short) 0, (short) 0, fd_in, 0 469 ); 470 } 471 }