| ... | ... | @@ -358,17 +358,38 @@ pub const IO_Uring = struct { |
| 358 | 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 | 375 | /// Queues (but does not submit) an SQE to perform a `read(2)`. |
| 362 | 376 | /// Returns a pointer to the SQE. |
| 363 | 377 | pub fn read( |
| 364 | 378 | self: *IO_Uring, |
| 365 | 379 | user_data: u64, |
| 366 | 380 | fd: os.fd_t, |
| 367 | | buffer: []u8, |
| 381 | buffer: ReadBuffer, |
| 368 | 382 | offset: u64, |
| 369 | 383 | ) !*io_uring_sqe { |
| 370 | 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 | 393 | sqe.user_data = user_data; |
| 373 | 394 | return sqe; |
| 374 | 395 | } |
| ... | ... | @@ -1778,7 +1799,7 @@ test "write/read" { |
| 1778 | 1799 | try testing.expectEqual(linux.IORING_OP.WRITE, sqe_write.opcode); |
| 1779 | 1800 | try testing.expectEqual(@as(u64, 10), sqe_write.off); |
| 1780 | 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 | 1803 | try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode); |
| 1783 | 1804 | try testing.expectEqual(@as(u64, 10), sqe_read.off); |
| 1784 | 1805 | try testing.expectEqual(@as(u32, 2), try ring.submit()); |
| ... | ... | @@ -2520,7 +2541,7 @@ test "register_files_update" { |
| 2520 | 2541 | |
| 2521 | 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 | 2545 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); |
| 2525 | 2546 | sqe.flags |= linux.IOSQE_FIXED_FILE; |
| 2526 | 2547 | |
| ... | ... | @@ -2541,7 +2562,7 @@ test "register_files_update" { |
| 2541 | 2562 | |
| 2542 | 2563 | { |
| 2543 | 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 | 2566 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); |
| 2546 | 2567 | sqe.flags |= linux.IOSQE_FIXED_FILE; |
| 2547 | 2568 | |
| ... | ... | @@ -2558,7 +2579,7 @@ test "register_files_update" { |
| 2558 | 2579 | |
| 2559 | 2580 | { |
| 2560 | 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 | 2583 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); |
| 2563 | 2584 | sqe.flags |= linux.IOSQE_FIXED_FILE; |
| 2564 | 2585 | |