| ... | @@ -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 | } |
| 360 | | 360 | |
| | 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" { |
| 2520 | | 2541 | |
| 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; |
| 2526 | | 2547 | |
| ... | @@ -2541,7 +2562,7 @@ test "register_files_update" { | ... | @@ -2541,7 +2562,7 @@ test "register_files_update" { |
| 2541 | | 2562 | |
| 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; |
| 2547 | | 2568 | |
| ... | @@ -2558,7 +2579,7 @@ test "register_files_update" { | ... | @@ -2558,7 +2579,7 @@ test "register_files_update" { |
| 2558 | | 2579 | |
| 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; |
| 2564 | | 2585 | |