authorgravatar for joran@ronomon.comJoran Dirk Greef <joran@ronomon.com> 2021-01-23 10:13:14+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-25 10:34:20-08:00
log68a040aec7125adca64a16276ae1b088f2c6ba15
tree6dbf81c04c6dfe3dcf93d8ac0365cc9e4e6e24e6
parent9238d125373a652a34e7d34636e237912d1350c0

linux: add fallocate() to io_uring


1 files changed, 84 insertions(+), 0 deletions(-)

lib/std/os/linux/io_uring.zig+84
...@@ -556,6 +556,22 @@ pub const IO_Uring = struct {...@@ -556,6 +556,22 @@ pub const IO_Uring = struct {
556 return sqe;556 return sqe;
557 }557 }
558558
559 /// Queues (but does not submit) an SQE to perform an `fallocate(2)`.
560 /// Returns a pointer to the SQE.
561 pub fn fallocate(
562 self: *IO_Uring,
563 user_data: u64,
564 fd: os.fd_t,
565 mode: i32,
566 offset: u64,
567 len: u64,
568 ) !*io_uring_sqe {
569 const sqe = try self.get_sqe();
570 io_uring_prep_fallocate(sqe, fd, mode, offset, len);
571 sqe.user_data = user_data;
572 return sqe;
573 }
574
559 /// Registers an array of file descriptors.575 /// Registers an array of file descriptors.
560 /// Every time a file descriptor is put in an SQE and submitted to the kernel, the kernel must576 /// Every time a file descriptor is put in an SQE and submitted to the kernel, the kernel must
561 /// retrieve a reference to the file, and once I/O has completed the file reference must be577 /// retrieve a reference to the file, and once I/O has completed the file reference must be
...@@ -894,6 +910,30 @@ pub fn io_uring_prep_timeout_remove(sqe: *io_uring_sqe, timeout_user_data: u64,...@@ -894,6 +910,30 @@ pub fn io_uring_prep_timeout_remove(sqe: *io_uring_sqe, timeout_user_data: u64,
894 };910 };
895}911}
896912
913pub fn io_uring_prep_fallocate(
914 sqe: *io_uring_sqe,
915 fd: os.fd_t,
916 mode: i32,
917 offset: u64,
918 len: u64,
919) void {
920 sqe.* = .{
921 .opcode = .FALLOCATE,
922 .flags = 0,
923 .ioprio = 0,
924 .fd = fd,
925 .off = offset,
926 .addr = len,
927 .len = @intCast(u32, mode),
928 .rw_flags = 0,
929 .user_data = 0,
930 .buf_index = 0,
931 .personality = 0,
932 .splice_fd_in = 0,
933 .__pad2 = [2]u64{ 0, 0 },
934 };
935}
936
897test "structs/offsets/entries" {937test "structs/offsets/entries" {
898 if (builtin.os.tag != .linux) return error.SkipZigTest;938 if (builtin.os.tag != .linux) return error.SkipZigTest;
899939
...@@ -1395,3 +1435,47 @@ test "timeout_remove" {...@@ -1395,3 +1435,47 @@ test "timeout_remove" {
1395 .flags = 0,1435 .flags = 0,
1396 }, cqe_timeout_remove);1436 }, cqe_timeout_remove);
1397}1437}
1438
1439test "fallocate" {
1440 if (builtin.os.tag != .linux) return error.SkipZigTest;
1441
1442 var ring = IO_Uring.init(1, 0) catch |err| switch (err) {
1443 error.SystemOutdated => return error.SkipZigTest,
1444 error.PermissionDenied => return error.SkipZigTest,
1445 else => return err,
1446 };
1447 defer ring.deinit();
1448
1449 const path = "test_io_uring_fallocate";
1450 const file = try std.fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 });
1451 defer file.close();
1452 defer std.fs.cwd().deleteFile(path) catch {};
1453
1454 testing.expectEqual(@as(u64, 0), (try file.stat()).size);
1455
1456 const len: u64 = 65536;
1457 const sqe = try ring.fallocate(0xaaaaaaaa, file.handle, 0, 0, len);
1458 testing.expectEqual(linux.IORING_OP.FALLOCATE, sqe.opcode);
1459 testing.expectEqual(file.handle, sqe.fd);
1460 testing.expectEqual(@as(u32, 1), try ring.submit());
1461
1462 const cqe = try ring.copy_cqe();
1463 switch (-cqe.res) {
1464 0 => {},
1465 // This kernel's io_uring does not yet implement fallocate():
1466 linux.EINVAL => return error.SkipZigTest,
1467 // This kernel does not implement fallocate():
1468 linux.ENOSYS => return error.SkipZigTest,
1469 // The filesystem containing the file referred to by fd does not support this operation;
1470 // or the mode is not supported by the filesystem containing the file referred to by fd:
1471 linux.EOPNOTSUPP => return error.SkipZigTest,
1472 else => |errno| std.debug.panic("unhandled errno: {}", .{errno}),
1473 }
1474 testing.expectEqual(linux.io_uring_cqe{
1475 .user_data = 0xaaaaaaaa,
1476 .res = 0,
1477 .flags = 0,
1478 }, cqe);
1479
1480 testing.expectEqual(len, (try file.stat()).size);
1481}