aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Rischmann <vincent@rischmann.fr>2022-05-16 19:02:22 +0200
committerVincent Rischmann <vincent@rischmann.fr>2022-05-25 13:53:09 +0200
commit52dd468cc3e279e7d1a764c2c3f6fde13a404a14 (patch)
treed929de65162c14a889d875f6457bd821d46a390e
parent7b3e5ce0b3d3e6c8e24dd147d23eec3fe5088d74 (diff)
downloadzig-52dd468cc3e279e7d1a764c2c3f6fde13a404a14.tar.gz
zig-52dd468cc3e279e7d1a764c2c3f6fde13a404a14.zip
io_uring: change read() to use a ReadBuffer instead
Reads can be done in two ways with io_uring: * using a simple buffer * using a automatic buffer selection which requires the user to have provided a number of buffers before ReadBuffer let's the caller choose where the data should be read.
-rw-r--r--lib/std/os/linux/io_uring.zig33
1 files changed, 27 insertions, 6 deletions
diff --git a/lib/std/os/linux/io_uring.zig b/lib/std/os/linux/io_uring.zig
index 9646a923d7..74e6416102 100644
--- a/lib/std/os/linux/io_uring.zig
+++ b/lib/std/os/linux/io_uring.zig
@@ -358,17 +358,38 @@ pub const IO_Uring = struct {
return sqe;
}
+ /// Used to select how the read should be handled.
+ pub const ReadBuffer = union(enum) {
+ /// io_uring will read directly into this buffer
+ buffer: []u8,
+
+ /// io_uring will select a buffer that has previously been provided with `provide_buffers`.
+ /// The buffer group reference by `group_id` must contain at least one buffer for the read to work.
+ /// `len` controls the number of bytes to read into the selected buffer.
+ buffer_selection: struct {
+ group_id: u16,
+ len: usize,
+ },
+ };
+
/// Queues (but does not submit) an SQE to perform a `read(2)`.
/// Returns a pointer to the SQE.
pub fn read(
self: *IO_Uring,
user_data: u64,
fd: os.fd_t,
- buffer: []u8,
+ buffer: ReadBuffer,
offset: u64,
) !*io_uring_sqe {
const sqe = try self.get_sqe();
- io_uring_prep_read(sqe, fd, buffer, offset);
+ switch (buffer) {
+ .buffer => |slice| io_uring_prep_read(sqe, fd, slice, offset),
+ .buffer_selection => |selection| {
+ io_uring_prep_rw(.READ, sqe, fd, 0, selection.len, offset);
+ sqe.flags |= linux.IOSQE_BUFFER_SELECT;
+ sqe.buf_index = selection.group_id;
+ },
+ }
sqe.user_data = user_data;
return sqe;
}
@@ -1778,7 +1799,7 @@ test "write/read" {
try testing.expectEqual(linux.IORING_OP.WRITE, sqe_write.opcode);
try testing.expectEqual(@as(u64, 10), sqe_write.off);
sqe_write.flags |= linux.IOSQE_IO_LINK;
- const sqe_read = try ring.read(0x22222222, fd, buffer_read[0..], 10);
+ const sqe_read = try ring.read(0x22222222, fd, .{ .buffer = buffer_read[0..] }, 10);
try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode);
try testing.expectEqual(@as(u64, 10), sqe_read.off);
try testing.expectEqual(@as(u32, 2), try ring.submit());
@@ -2520,7 +2541,7 @@ test "register_files_update" {
var buffer = [_]u8{42} ** 128;
{
- const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0);
+ const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0);
try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);
sqe.flags |= linux.IOSQE_FIXED_FILE;
@@ -2541,7 +2562,7 @@ test "register_files_update" {
{
// Next read should still work since fd_index in the registered file descriptors hasn't been updated yet.
- const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0);
+ const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0);
try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);
sqe.flags |= linux.IOSQE_FIXED_FILE;
@@ -2558,7 +2579,7 @@ test "register_files_update" {
{
// Now this should fail since both fds are sparse (-1)
- const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0);
+ const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0);
try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);
sqe.flags |= linux.IOSQE_FIXED_FILE;