authorgravatar for vincent@rischmann.frVincent Rischmann <vincent@rischmann.fr> 2022-05-16 19:02:22+02:00
committergravatar for vincent@rischmann.frVincent Rischmann <vincent@rischmann.fr> 2022-05-25 13:53:09+02:00
log52dd468cc3e279e7d1a764c2c3f6fde13a404a14
treed929de65162c14a889d875f6457bd821d46a390e
parent7b3e5ce0b3d3e6c8e24dd147d23eec3fe5088d74

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.

1 files changed, 27 insertions(+), 6 deletions(-)

lib/std/os/linux/io_uring.zig+27-6
...@@ -358,17 +358,38 @@ pub const IO_Uring = struct {...@@ -358,17 +358,38 @@ pub const IO_Uring = struct {
358 return sqe;358 return sqe;
359 }359 }
360360
361 /// Used to select how the read should be handled.
362 pub const ReadBuffer = union(enum) {
363 /// io_uring will read directly into this buffer
364 buffer: []u8,
365
366 /// 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.
368 /// `len` controls the number of bytes to read into the selected buffer.
369 buffer_selection: struct {
370 group_id: u16,
371 len: usize,
372 },
373 };
374
361 /// Queues (but does not submit) an SQE to perform a `read(2)`.375 /// Queues (but does not submit) an SQE to perform a `read(2)`.
362 /// Returns a pointer to the SQE.376 /// Returns a pointer to the SQE.
363 pub fn read(377 pub fn read(
364 self: *IO_Uring,378 self: *IO_Uring,
365 user_data: u64,379 user_data: u64,
366 fd: os.fd_t,380 fd: os.fd_t,
367 buffer: []u8,381 buffer: ReadBuffer,
368 offset: u64,382 offset: u64,
369 ) !*io_uring_sqe {383 ) !*io_uring_sqe {
370 const sqe = try self.get_sqe();384 const sqe = try self.get_sqe();
371 io_uring_prep_read(sqe, fd, buffer, offset);385 switch (buffer) {
386 .buffer => |slice| io_uring_prep_read(sqe, fd, slice, offset),
387 .buffer_selection => |selection| {
388 io_uring_prep_rw(.READ, sqe, fd, 0, selection.len, offset);
389 sqe.flags |= linux.IOSQE_BUFFER_SELECT;
390 sqe.buf_index = selection.group_id;
391 },
392 }
372 sqe.user_data = user_data;393 sqe.user_data = user_data;
373 return sqe;394 return sqe;
374 }395 }
...@@ -1778,7 +1799,7 @@ test "write/read" {...@@ -1778,7 +1799,7 @@ test "write/read" {
1778 try testing.expectEqual(linux.IORING_OP.WRITE, sqe_write.opcode);1799 try testing.expectEqual(linux.IORING_OP.WRITE, sqe_write.opcode);
1779 try testing.expectEqual(@as(u64, 10), sqe_write.off);1800 try testing.expectEqual(@as(u64, 10), sqe_write.off);
1780 sqe_write.flags |= linux.IOSQE_IO_LINK;1801 sqe_write.flags |= linux.IOSQE_IO_LINK;
1781 const sqe_read = try ring.read(0x22222222, fd, buffer_read[0..], 10);1802 const sqe_read = try ring.read(0x22222222, fd, .{ .buffer = buffer_read[0..] }, 10);
1782 try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode);1803 try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode);
1783 try testing.expectEqual(@as(u64, 10), sqe_read.off);1804 try testing.expectEqual(@as(u64, 10), sqe_read.off);
1784 try testing.expectEqual(@as(u32, 2), try ring.submit());1805 try testing.expectEqual(@as(u32, 2), try ring.submit());
...@@ -2520,7 +2541,7 @@ test "register_files_update" {...@@ -2520,7 +2541,7 @@ test "register_files_update" {
25202541
2521 var buffer = [_]u8{42} ** 128;2542 var buffer = [_]u8{42} ** 128;
2522 {2543 {
2523 const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0);2544 const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0);
2524 try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);2545 try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);
2525 sqe.flags |= linux.IOSQE_FIXED_FILE;2546 sqe.flags |= linux.IOSQE_FIXED_FILE;
25262547
...@@ -2541,7 +2562,7 @@ test "register_files_update" {...@@ -2541,7 +2562,7 @@ test "register_files_update" {
25412562
2542 {2563 {
2543 // Next read should still work since fd_index in the registered file descriptors hasn't been updated yet.2564 // Next read should still work since fd_index in the registered file descriptors hasn't been updated yet.
2544 const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0);2565 const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0);
2545 try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);2566 try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);
2546 sqe.flags |= linux.IOSQE_FIXED_FILE;2567 sqe.flags |= linux.IOSQE_FIXED_FILE;
25472568
...@@ -2558,7 +2579,7 @@ test "register_files_update" {...@@ -2558,7 +2579,7 @@ test "register_files_update" {
25582579
2559 {2580 {
2560 // Now this should fail since both fds are sparse (-1)2581 // Now this should fail since both fds are sparse (-1)
2561 const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0);2582 const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0);
2562 try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);2583 try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode);
2563 sqe.flags |= linux.IOSQE_FIXED_FILE;2584 sqe.flags |= linux.IOSQE_FIXED_FILE;
25642585