From 8fd88fdb31e638e9483e08fc42de2514fd4a616a Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Sat, 31 Oct 2020 13:39:33 +0200 Subject: [PATCH 01/10] linux: add fallocate() --- lib/std/os/linux.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index a126231db1..0af6467808 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -121,6 +121,16 @@ pub fn utimensat(dirfd: i32, path: ?[*:0]const u8, times: *const [2]timespec, fl return syscall4(.utimensat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(times), flags); } +pub fn fallocate(fd: i32, mode: i32, offset: usize, len: usize) usize { + return syscall4( + .fallocate, + @bitCast(usize, @as(isize, fd)), + @bitCast(usize, @as(isize, mode)), + offset, + len, + ); +} + pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize { return syscall4(.futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val), @ptrToInt(timeout)); } From 888af655e0e9a3e2f0432800942cb7f7e8989d27 Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Sun, 1 Nov 2020 11:46:08 +0200 Subject: [PATCH 02/10] Add libc signature --- lib/std/c/linux.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index d48c76c7a6..4ec2fdad33 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -87,6 +87,8 @@ pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int; +pub extern "c" fn fallocate(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int; + pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int; pub extern "c" fn sendfile( From 2fdb30a571564253d110d27329a898a1d169553c Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Sun, 1 Nov 2020 11:47:09 +0200 Subject: [PATCH 03/10] Add definitions for FALLOC_FL_ mode flags --- lib/std/os/bits/linux.zig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 8dbf21fcf2..29ea74d6a9 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -82,6 +82,27 @@ pub const AT_STATX_DONT_SYNC = 0x4000; /// Apply to the entire subtree pub const AT_RECURSIVE = 0x8000; +/// Default is extend size +pub const FALLOC_FL_KEEP_SIZE = 0x01; + +/// De-allocates range +pub const FALLOC_FL_PUNCH_HOLE = 0x02; + +/// Reserved codepoint +pub const FALLOC_FL_NO_HIDE_STALE = 0x04; + +/// Removes a range of a file without leaving a hole in the file +pub const FALLOC_FL_COLLAPSE_RANGE = 0x08; + +/// Converts a range of file to zeros preferably without issuing data IO +pub const FALLOC_FL_ZERO_RANGE = 0x10; + +/// Inserts space within the file size without overwriting any existing data +pub const FALLOC_FL_INSERT_RANGE = 0x20; + +/// Unshares shared blocks within the file size without overwriting any existing data +pub const FALLOC_FL_UNSHARE_RANGE = 0x40; + pub const FUTEX_WAIT = 0; pub const FUTEX_WAKE = 1; pub const FUTEX_FD = 2; From 2dd8613adcac695468937156f6e13dc5a4828e4c Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Sun, 1 Nov 2020 11:49:08 +0200 Subject: [PATCH 04/10] "The Traveling Wilburys' - Handle With Care" Both `offset` and `len` are `off_t`. Like the rest of the std lib we assume that `_FILE_OFFSET_BITS == 64` is always true, so that `off_t` is a `u64`. When passing to 32-bit kernels, we split these into two `u32` parameters. --- lib/std/os/linux.zig | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 0af6467808..82b146f047 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -121,14 +121,26 @@ pub fn utimensat(dirfd: i32, path: ?[*:0]const u8, times: *const [2]timespec, fl return syscall4(.utimensat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(times), flags); } -pub fn fallocate(fd: i32, mode: i32, offset: usize, len: usize) usize { - return syscall4( - .fallocate, - @bitCast(usize, @as(isize, fd)), - @bitCast(usize, @as(isize, mode)), - offset, - len, - ); +pub fn fallocate(fd: i32, mode: i32, offset: u64, len: u64) usize { + if (@sizeOf(usize) == 4) { + return syscall6( + .fallocate, + @bitCast(usize, @as(isize, fd)), + @bitCast(usize, @as(isize, mode)), + @truncate(usize, offset >> 32), + @truncate(usize, offset), + @truncate(usize, len >> 32), + @truncate(usize, len), + ); + } else { + return syscall4( + .fallocate, + @bitCast(usize, @as(isize, fd)), + @bitCast(usize, @as(isize, mode)), + offset, + len, + ); + } } pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize { From a67f140d2f1247d3996f763dd36e55cbecb09eef Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Sun, 1 Nov 2020 11:55:27 +0200 Subject: [PATCH 05/10] Add test --- lib/std/os/linux/test.zig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index 7599cfc395..24c96cdd70 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -11,6 +11,25 @@ const elf = std.elf; const expect = std.testing.expect; const fs = std.fs; +test "fallocate" { + const path = "test_fallocate"; + const file = try fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 }); + defer file.close(); + defer fs.cwd().deleteFile(path) catch {}; + + expect((try file.stat()).size == 0); + + const len: u64 = 65536; + switch (linux.getErrno(linux.fallocate(file.handle, 0, 0, len))) { + 0 => {}, + linux.ENOSYS => return error.SkipZigTest, + linux.EOPNOTSUPP => return error.SkipZigTest, + else => unreachable, + } + + expect((try file.stat()).size == len); +} + test "getpid" { expect(linux.getpid() != 0); } From c910f03a7b7a42bd742b7447e1101e07a2a12d74 Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Sun, 1 Nov 2020 13:14:32 +0200 Subject: [PATCH 06/10] Swap endianness --- lib/std/os/linux.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 82b146f047..ec250a0610 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -127,10 +127,10 @@ pub fn fallocate(fd: i32, mode: i32, offset: u64, len: u64) usize { .fallocate, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, mode)), - @truncate(usize, offset >> 32), @truncate(usize, offset), - @truncate(usize, len >> 32), + @truncate(usize, offset >> 32), @truncate(usize, len), + @truncate(usize, len >> 32), ); } else { return syscall4( From 9dec3108260638dd81dd5110bcf87d58f6834d25 Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Mon, 2 Nov 2020 09:52:33 +0200 Subject: [PATCH 07/10] Debug unhandled errno --- lib/std/os/linux/test.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index 24c96cdd70..e57ef3a6e4 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -24,7 +24,10 @@ test "fallocate" { 0 => {}, linux.ENOSYS => return error.SkipZigTest, linux.EOPNOTSUPP => return error.SkipZigTest, - else => unreachable, + else |errno| => { + std.debug.print("Unhandled Errno:" errno); + return error.SkipZigTest; + }, } expect((try file.stat()).size == len); From 067bd7e424a8e83c49bd4f3f0da5ff0ff75dc3bc Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Mon, 2 Nov 2020 09:55:25 +0200 Subject: [PATCH 08/10] Switch back to writing Zig --- lib/std/os/linux/test.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index e57ef3a6e4..f0c223e3fb 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -24,8 +24,8 @@ test "fallocate" { 0 => {}, linux.ENOSYS => return error.SkipZigTest, linux.EOPNOTSUPP => return error.SkipZigTest, - else |errno| => { - std.debug.print("Unhandled Errno:" errno); + else => |errno| { + std.debug.print("Unhandled Errno: {}", .{ errno }); return error.SkipZigTest; }, } From 78e9e131e02bba1949aab67b63e7fe94ae8b33bb Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Mon, 2 Nov 2020 12:37:55 +0200 Subject: [PATCH 09/10] Pending #5127 --- lib/std/os/linux/test.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index f0c223e3fb..fa4aecf6ca 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -12,6 +12,9 @@ const expect = std.testing.expect; const fs = std.fs; test "fallocate" { + // TODO https://github.com/ziglang/zig/issues/5127 + if (std.Target.current.cpu.arch == .mips) return error.SkipZigTest; + const path = "test_fallocate"; const file = try fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 }); defer file.close(); @@ -24,10 +27,7 @@ test "fallocate" { 0 => {}, linux.ENOSYS => return error.SkipZigTest, linux.EOPNOTSUPP => return error.SkipZigTest, - else => |errno| { - std.debug.print("Unhandled Errno: {}", .{ errno }); - return error.SkipZigTest; - }, + else => |errno| std.debug.panic("unhandled errno: {}", .{ errno }), } expect((try file.stat()).size == len); From 8193f558200da27531304b77c1e80c16bb728420 Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Tue, 3 Nov 2020 06:03:38 +0200 Subject: [PATCH 10/10] Support 32-bit big-endian targets --- lib/std/os/linux.zig | 14 ++++++++------ lib/std/os/linux/test.zig | 3 --- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index ec250a0610..60a69641eb 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -121,16 +121,18 @@ pub fn utimensat(dirfd: i32, path: ?[*:0]const u8, times: *const [2]timespec, fl return syscall4(.utimensat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(times), flags); } -pub fn fallocate(fd: i32, mode: i32, offset: u64, len: u64) usize { +pub fn fallocate(fd: i32, mode: i32, offset: u64, length: u64) usize { if (@sizeOf(usize) == 4) { + const offset_halves = splitValue64(offset); + const length_halves = splitValue64(length); return syscall6( .fallocate, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, mode)), - @truncate(usize, offset), - @truncate(usize, offset >> 32), - @truncate(usize, len), - @truncate(usize, len >> 32), + offset_halves[0], + offset_halves[1], + length_halves[0], + length_halves[1], ); } else { return syscall4( @@ -138,7 +140,7 @@ pub fn fallocate(fd: i32, mode: i32, offset: u64, len: u64) usize { @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, mode)), offset, - len, + length, ); } } diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index fa4aecf6ca..b182fa3f61 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -12,9 +12,6 @@ const expect = std.testing.expect; const fs = std.fs; test "fallocate" { - // TODO https://github.com/ziglang/zig/issues/5127 - if (std.Target.current.cpu.arch == .mips) return error.SkipZigTest; - const path = "test_fallocate"; const file = try fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 }); defer file.close();