| ... | @@ -363,6 +363,9 @@ pub const IO_Uring = struct { | ... | @@ -363,6 +363,9 @@ pub const IO_Uring = struct { |
| 363 | /// io_uring will read directly into this buffer | 363 | /// io_uring will read directly into this buffer |
| 364 | buffer: []u8, | 364 | buffer: []u8, |
| 365 | | 365 | |
| | 366 | /// io_uring will read directly into these buffers using readv. |
| | 367 | iovecs: []const os.iovec, |
| | 368 | |
| 366 | /// io_uring will select a buffer that has previously been provided with `provide_buffers`. | 369 | /// io_uring will select a buffer that has previously been provided with `provide_buffers`. |
| 367 | /// The buffer group reference by `group_id` must contain at least one buffer for the read to work. | 370 | /// The buffer group reference by `group_id` must contain at least one buffer for the read to work. |
| 368 | /// `len` controls the number of bytes to read into the selected buffer. | 371 | /// `len` controls the number of bytes to read into the selected buffer. |
| ... | @@ -372,7 +375,11 @@ pub const IO_Uring = struct { | ... | @@ -372,7 +375,11 @@ pub const IO_Uring = struct { |
| 372 | }, | 375 | }, |
| 373 | }; | 376 | }; |
| 374 | | 377 | |
| 375 | /// Queues (but does not submit) an SQE to perform a `read(2)`. | 378 | /// Queues (but does not submit) an SQE to perform a `read(2)` or `preadv` depending on the buffer type. |
| | 379 | /// * Reading into a `ReadBuffer.buffer` uses `read(2)` |
| | 380 | /// * Reading into a `ReadBuffer.iovecs` uses `preadv(2)` |
| | 381 | /// If you want to do a `preadv2()` then set `rw_flags` on the returned SQE. See https://linux.die.net/man/2/preadv. |
| | 382 | /// |
| 376 | /// Returns a pointer to the SQE. | 383 | /// Returns a pointer to the SQE. |
| 377 | pub fn read( | 384 | pub fn read( |
| 378 | self: *IO_Uring, | 385 | self: *IO_Uring, |
| ... | @@ -384,6 +391,7 @@ pub const IO_Uring = struct { | ... | @@ -384,6 +391,7 @@ pub const IO_Uring = struct { |
| 384 | const sqe = try self.get_sqe(); | 391 | const sqe = try self.get_sqe(); |
| 385 | switch (buffer) { | 392 | switch (buffer) { |
| 386 | .buffer => |slice| io_uring_prep_read(sqe, fd, slice, offset), | 393 | .buffer => |slice| io_uring_prep_read(sqe, fd, slice, offset), |
| | 394 | .iovecs => |vecs| io_uring_prep_readv(sqe, fd, vecs, offset), |
| 387 | .buffer_selection => |selection| { | 395 | .buffer_selection => |selection| { |
| 388 | io_uring_prep_rw(.READ, sqe, fd, 0, selection.len, offset); | 396 | io_uring_prep_rw(.READ, sqe, fd, 0, selection.len, offset); |
| 389 | sqe.flags |= linux.IOSQE_BUFFER_SELECT; | 397 | sqe.flags |= linux.IOSQE_BUFFER_SELECT; |
| ... | @@ -409,23 +417,6 @@ pub const IO_Uring = struct { | ... | @@ -409,23 +417,6 @@ pub const IO_Uring = struct { |
| 409 | return sqe; | 417 | return sqe; |
| 410 | } | 418 | } |
| 411 | | 419 | |
| 412 | /// Queues (but does not submit) an SQE to perform a `preadv()`. | | |
| 413 | /// Returns a pointer to the SQE so that you can further modify the SQE for advanced use cases. | | |
| 414 | /// For example, if you want to do a `preadv2()` then set `rw_flags` on the returned SQE. | | |
| 415 | /// See https://linux.die.net/man/2/preadv. | | |
| 416 | pub fn readv( | | |
| 417 | self: *IO_Uring, | | |
| 418 | user_data: u64, | | |
| 419 | fd: os.fd_t, | | |
| 420 | iovecs: []const os.iovec, | | |
| 421 | offset: u64, | | |
| 422 | ) !*io_uring_sqe { | | |
| 423 | const sqe = try self.get_sqe(); | | |
| 424 | io_uring_prep_readv(sqe, fd, iovecs, offset); | | |
| 425 | sqe.user_data = user_data; | | |
| 426 | return sqe; | | |
| 427 | } | | |
| 428 | | | |
| 429 | /// Queues (but does not submit) an SQE to perform a IORING_OP_READ_FIXED. | 420 | /// Queues (but does not submit) an SQE to perform a IORING_OP_READ_FIXED. |
| 430 | /// The `buffer` provided must be registered with the kernel by calling `register_buffers` first. | 421 | /// The `buffer` provided must be registered with the kernel by calling `register_buffers` first. |
| 431 | /// The `buffer_index` must be the same as its index in the array provided to `register_buffers`. | 422 | /// The `buffer_index` must be the same as its index in the array provided to `register_buffers`. |
| ... | @@ -1715,7 +1706,7 @@ test "readv" { | ... | @@ -1715,7 +1706,7 @@ test "readv" { |
| 1715 | | 1706 | |
| 1716 | var buffer = [_]u8{42} ** 128; | 1707 | var buffer = [_]u8{42} ** 128; |
| 1717 | var iovecs = [_]os.iovec{os.iovec{ .iov_base = &buffer, .iov_len = buffer.len }}; | 1708 | var iovecs = [_]os.iovec{os.iovec{ .iov_base = &buffer, .iov_len = buffer.len }}; |
| 1718 | const sqe = try ring.readv(0xcccccccc, fd_index, iovecs[0..], 0); | 1709 | const sqe = try ring.read(0xcccccccc, fd_index, .{ .iovecs = iovecs[0..] }, 0); |
| 1719 | try testing.expectEqual(linux.IORING_OP.READV, sqe.opcode); | 1710 | try testing.expectEqual(linux.IORING_OP.READV, sqe.opcode); |
| 1720 | sqe.flags |= linux.IOSQE_FIXED_FILE; | 1711 | sqe.flags |= linux.IOSQE_FIXED_FILE; |
| 1721 | | 1712 | |
| ... | @@ -1766,7 +1757,7 @@ test "writev/fsync/readv" { | ... | @@ -1766,7 +1757,7 @@ test "writev/fsync/readv" { |
| 1766 | try testing.expectEqual(fd, sqe_fsync.fd); | 1757 | try testing.expectEqual(fd, sqe_fsync.fd); |
| 1767 | sqe_fsync.flags |= linux.IOSQE_IO_LINK; | 1758 | sqe_fsync.flags |= linux.IOSQE_IO_LINK; |
| 1768 | | 1759 | |
| 1769 | const sqe_readv = try ring.readv(0xffffffff, fd, iovecs_read[0..], 17); | 1760 | const sqe_readv = try ring.read(0xffffffff, fd, .{ .iovecs = iovecs_read[0..] }, 17); |
| 1770 | try testing.expectEqual(linux.IORING_OP.READV, sqe_readv.opcode); | 1761 | try testing.expectEqual(linux.IORING_OP.READV, sqe_readv.opcode); |
| 1771 | try testing.expectEqual(@as(u64, 17), sqe_readv.off); | 1762 | try testing.expectEqual(@as(u64, 17), sqe_readv.off); |
| 1772 | | 1763 | |