authorgravatar for vincent@rischmann.frVincent Rischmann <vincent@rischmann.fr> 2022-05-20 20:41:56+02:00
committergravatar for vincent@rischmann.frVincent Rischmann <vincent@rischmann.fr> 2022-05-25 13:53:09+02:00
log3c58d3e281fca421879fe1d2ae7943bd31dccc0e
tree421c69a07e284a488a8d3ecaf29c9acc57c82a28
parentacb8af468f496dadbc7550196d7ba05fb8efd586

io_uring: replace the readv method with a read on a new ReadBuffer type

readv() is essentially identical to read() except for the buffer type, this simplifies the API for the caller at the cost of not clearly mapping to the liburing C API.

1 files changed, 11 insertions(+), 20 deletions(-)

lib/std/os/linux/io_uring.zig+11-20
...@@ -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 buffer363 /// io_uring will read directly into this buffer
364 buffer: []u8,364 buffer: []u8,
365365
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 };
374377
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 }
411419
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" {
17151706
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;
17211712
...@@ -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;
17681759
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);
17721763