authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2022-09-24 19:18:01+03:30
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-05 15:43:39-04:00
logaea617c60be848ed372343e08465bb0ac6cb7b85
tree4408094ab9c82d28d2b5486308b73ba1226e7649
parent28288dcbbf5258fe7461bbe0f6b2feeba0c2de5d

std.os: take advantage of the freebsd's copy_file_range


3 files changed, 47 insertions(+), 31 deletions(-)

lib/std/c/freebsd.zig+2
...@@ -1440,6 +1440,7 @@ pub const E = enum(u16) {...@@ -1440,6 +1440,7 @@ pub const E = enum(u16) {
1440 CAPMODE = 94, // Not permitted in capability mode1440 CAPMODE = 94, // Not permitted in capability mode
1441 NOTRECOVERABLE = 95, // State not recoverable1441 NOTRECOVERABLE = 95, // State not recoverable
1442 OWNERDEAD = 96, // Previous owner died1442 OWNERDEAD = 96, // Previous owner died
1443 INTEGRITY = 97, // Integrity check failed
1443 _,1444 _,
1444};1445};
14451446
...@@ -1875,3 +1876,4 @@ pub const MFD = struct {...@@ -1875,3 +1876,4 @@ pub const MFD = struct {
1875};1876};
18761877
1877pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int;1878pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int;
1879pub extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*off_t, fd_out: fd_t, off_out: ?*off_t, len: usize, flags: u32) usize;
lib/std/os.zig+44-31
...@@ -6314,6 +6314,7 @@ pub const CopyFileRangeError = error{...@@ -6314,6 +6314,7 @@ pub const CopyFileRangeError = error{
6314 Unseekable,6314 Unseekable,
6315 PermissionDenied,6315 PermissionDenied,
6316 SwapFile,6316 SwapFile,
6317 CorruptedData,
6317} || PReadError || PWriteError || UnexpectedError;6318} || PReadError || PWriteError || UnexpectedError;
63186319
6319var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);6320var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);
...@@ -6339,44 +6340,56 @@ var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);...@@ -6339,44 +6340,56 @@ var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);
6339///6340///
6340/// These systems support in-kernel data copying:6341/// These systems support in-kernel data copying:
6341/// * Linux 4.5 (cross-filesystem 5.3)6342/// * Linux 4.5 (cross-filesystem 5.3)
6343/// * FreeBSD 13.0
6342///6344///
6343/// Other systems fall back to calling `pread` / `pwrite`.6345/// Other systems fall back to calling `pread` / `pwrite`.
6344///6346///
6345/// Maximum offsets on Linux are `math.maxInt(i64)`.6347/// Maximum offsets on Linux and FreeBSD are `math.maxInt(i64)`.
6346pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {6348pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {
6347 const call_cfr = comptime if (builtin.os.tag == .wasi)6349 if ((comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0 }) orelse false) or
6348 // WASI-libc doesn't have copy_file_range.6350 ((comptime builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse false and
6349 false6351 std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok) and
6350 else if (builtin.link_libc)6352 has_copy_file_range_syscall.load(.Monotonic)))
6351 std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok6353 {
6352 else
6353 builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true;
6354
6355 if (call_cfr and has_copy_file_range_syscall.load(.Monotonic)) {
6356 var off_in_copy = @bitCast(i64, off_in);6354 var off_in_copy = @bitCast(i64, off_in);
6357 var off_out_copy = @bitCast(i64, off_out);6355 var off_out_copy = @bitCast(i64, off_out);
63586356
6359 const rc = system.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags);6357 while (true) {
6360 switch (system.getErrno(rc)) {6358 const rc = system.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags);
6361 .SUCCESS => return @intCast(usize, rc),6359 if (builtin.os.tag == .freebsd) {
6362 .BADF => return error.FilesOpenedWithWrongFlags,6360 switch (system.getErrno(rc)) {
6363 .FBIG => return error.FileTooBig,6361 .SUCCESS => return @intCast(usize, rc),
6364 .IO => return error.InputOutput,6362 .BADF => return error.FilesOpenedWithWrongFlags,
6365 .ISDIR => return error.IsDir,6363 .FBIG => return error.FileTooBig,
6366 .NOMEM => return error.OutOfMemory,6364 .IO => return error.InputOutput,
6367 .NOSPC => return error.NoSpaceLeft,6365 .ISDIR => return error.IsDir,
6368 .OVERFLOW => return error.Unseekable,6366 .NOSPC => return error.NoSpaceLeft,
6369 .PERM => return error.PermissionDenied,6367 .INVAL => break, // these may not be regular files, try fallback
6370 .TXTBSY => return error.SwapFile,6368 .INTEGRITY => return error.CorruptedData,
6371 // these may not be regular files, try fallback6369 .INTR => continue,
6372 .INVAL => {},6370 else => |err| return unexpectedErrno(err),
6373 // support for cross-filesystem copy added in Linux 5.3, use fallback6371 }
6374 .XDEV => {},6372 } else { // assume linux
6375 // syscall added in Linux 4.5, use fallback6373 switch (system.getErrno(rc)) {
6376 .NOSYS => {6374 .SUCCESS => return @intCast(usize, rc),
6377 has_copy_file_range_syscall.store(false, .Monotonic);6375 .BADF => return error.FilesOpenedWithWrongFlags,
6378 },6376 .FBIG => return error.FileTooBig,
6379 else => |err| return unexpectedErrno(err),6377 .IO => return error.InputOutput,
6378 .ISDIR => return error.IsDir,
6379 .NOSPC => return error.NoSpaceLeft,
6380 .INVAL => break, // these may not be regular files, try fallback
6381 .NOMEM => return error.OutOfMemory,
6382 .OVERFLOW => return error.Unseekable,
6383 .PERM => return error.PermissionDenied,
6384 .TXTBSY => return error.SwapFile,
6385 .XDEV => break, // support for cross-filesystem copy added in Linux 5.3, use fallback
6386 .NOSYS => { // syscall added in Linux 4.5, use fallback
6387 has_copy_file_range_syscall.store(false, .Monotonic);
6388 break;
6389 },
6390 else => |err| return unexpectedErrno(err),
6391 }
6392 }
6380 }6393 }
6381 }6394 }
63826395
src/link.zig+1
...@@ -457,6 +457,7 @@ pub const File = struct {...@@ -457,6 +457,7 @@ pub const File = struct {
457 Unseekable,457 Unseekable,
458 PermissionDenied,458 PermissionDenied,
459 SwapFile,459 SwapFile,
460 CorruptedData,
460 SystemResources,461 SystemResources,
461 OperationAborted,462 OperationAborted,
462 BrokenPipe,463 BrokenPipe,