From a156e02c16c1e0e71ba0477a27734b8d38f41cf7 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 5 Apr 2023 13:16:58 +0200 Subject: [PATCH] internal/syscall/unix: fix PosixFallocate error check on freebsd The posix_fallocate syscall returns the result in r1 rather than in errno: > If successful, posix_fallocate() returns zero. It returns an error on failure, without > setting errno. Source: https://man.freebsd.org/cgi/man.cgi?query=posix_fallocate&sektion=2&n=1 Adjust the PosixFallocate wrappers on freebsd to account for that. Also, CL 479715 used the same syscall wrapper for 386 and arm. However, on arm the syscall argument order is different. The wrapper was generated using mksyscall.go from the golang.org/x/sys/unix package, adjusting the r1 check correspondingly. Fixes #59352 Change-Id: I9a4e8e4546237010bc5e730c4988a2a476264cf4 Reviewed-on: https://go-review.googlesource.com/c/go/+/481621 Reviewed-by: Cherry Mui Run-TryBot: Tobias Klauser Reviewed-by: Yuval Pavel Zholkover Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/cmd/link/internal/ld/fallocate_test.go | 3 ++- src/cmd/link/internal/ld/outbuf_freebsd.go | 12 ++++++++-- .../syscall/unix/at_sysnum_freebsd.go | 5 +++-- .../syscall/unix/fallocate_freebsd_32bit.go | 20 ----------------- .../syscall/unix/fallocate_freebsd_386.go | 17 ++++++++++++++ .../syscall/unix/fallocate_freebsd_64bit.go | 11 +++++----- .../syscall/unix/fallocate_freebsd_arm.go | 22 +++++++++++++++++++ 7 files changed, 59 insertions(+), 31 deletions(-) delete mode 100644 src/internal/syscall/unix/fallocate_freebsd_32bit.go create mode 100644 src/internal/syscall/unix/fallocate_freebsd_386.go create mode 100644 src/internal/syscall/unix/fallocate_freebsd_arm.go diff --git a/src/cmd/link/internal/ld/fallocate_test.go b/src/cmd/link/internal/ld/fallocate_test.go index ad77be536fc..d95fec788a6 100644 --- a/src/cmd/link/internal/ld/fallocate_test.go +++ b/src/cmd/link/internal/ld/fallocate_test.go @@ -7,6 +7,7 @@ package ld import ( + "errors" "os" "path/filepath" "syscall" @@ -26,7 +27,7 @@ func TestFallocate(t *testing.T) { // Try fallocate first. for { err = out.fallocate(1 << 10) - if err == syscall.EOPNOTSUPP { // The underlying file system may not support fallocate + if errors.Is(err, errors.ErrUnsupported) || err == errNoFallocate { // The underlying file system may not support fallocate t.Skip("fallocate is not supported") } if err == syscall.EINTR { diff --git a/src/cmd/link/internal/ld/outbuf_freebsd.go b/src/cmd/link/internal/ld/outbuf_freebsd.go index 5ff17300c19..7e718c1408e 100644 --- a/src/cmd/link/internal/ld/outbuf_freebsd.go +++ b/src/cmd/link/internal/ld/outbuf_freebsd.go @@ -6,8 +6,16 @@ package ld -import "internal/syscall/unix" +import ( + "internal/syscall/unix" + "syscall" +) func (out *OutBuf) fallocate(size uint64) error { - return unix.PosixFallocate(int(out.f.Fd()), 0, int64(size)) + err := unix.PosixFallocate(int(out.f.Fd()), 0, int64(size)) + // ZFS on FreeBSD does not support posix_fallocate and returns EINVAL in that case. + if err == syscall.EINVAL { + return errNoFallocate + } + return err } diff --git a/src/internal/syscall/unix/at_sysnum_freebsd.go b/src/internal/syscall/unix/at_sysnum_freebsd.go index adfbbcb92b4..530f5c2a2b8 100644 --- a/src/internal/syscall/unix/at_sysnum_freebsd.go +++ b/src/internal/syscall/unix/at_sysnum_freebsd.go @@ -10,6 +10,7 @@ const ( AT_REMOVEDIR = 0x800 AT_SYMLINK_NOFOLLOW = 0x200 - unlinkatTrap uintptr = syscall.SYS_UNLINKAT - openatTrap uintptr = syscall.SYS_OPENAT + unlinkatTrap uintptr = syscall.SYS_UNLINKAT + openatTrap uintptr = syscall.SYS_OPENAT + posixFallocateTrap uintptr = syscall.SYS_POSIX_FALLOCATE ) diff --git a/src/internal/syscall/unix/fallocate_freebsd_32bit.go b/src/internal/syscall/unix/fallocate_freebsd_32bit.go deleted file mode 100644 index d821eea81c3..00000000000 --- a/src/internal/syscall/unix/fallocate_freebsd_32bit.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd && (386 || arm) - -package unix - -import "syscall" - -// FreeBSD posix_fallocate system call number. -const posixFallocateTrap uintptr = 530 - -func PosixFallocate(fd int, off int64, size int64) error { - _, _, errno := syscall.Syscall6(posixFallocateTrap, uintptr(fd), uintptr(off), uintptr(off>>32), uintptr(size), uintptr(size>>32), 0) - if errno != 0 { - return errno - } - return nil -} diff --git a/src/internal/syscall/unix/fallocate_freebsd_386.go b/src/internal/syscall/unix/fallocate_freebsd_386.go new file mode 100644 index 00000000000..535b23dbc5b --- /dev/null +++ b/src/internal/syscall/unix/fallocate_freebsd_386.go @@ -0,0 +1,17 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +import "syscall" + +func PosixFallocate(fd int, off int64, size int64) error { + // If successful, posix_fallocate() returns zero. It returns an error on failure, without + // setting errno. See https://man.freebsd.org/cgi/man.cgi?query=posix_fallocate&sektion=2&n=1 + r1, _, _ := syscall.Syscall6(posixFallocateTrap, uintptr(fd), uintptr(off), uintptr(off>>32), uintptr(size), uintptr(size>>32), 0) + if r1 != 0 { + return syscall.Errno(r1) + } + return nil +} diff --git a/src/internal/syscall/unix/fallocate_freebsd_64bit.go b/src/internal/syscall/unix/fallocate_freebsd_64bit.go index f1ef6e347ca..a9d52283f06 100644 --- a/src/internal/syscall/unix/fallocate_freebsd_64bit.go +++ b/src/internal/syscall/unix/fallocate_freebsd_64bit.go @@ -8,13 +8,12 @@ package unix import "syscall" -// FreeBSD posix_fallocate system call number. -const posixFallocateTrap uintptr = 530 - func PosixFallocate(fd int, off int64, size int64) error { - _, _, errno := syscall.Syscall(posixFallocateTrap, uintptr(fd), uintptr(off), uintptr(size)) - if errno != 0 { - return errno + // If successful, posix_fallocate() returns zero. It returns an error on failure, without + // setting errno. See https://man.freebsd.org/cgi/man.cgi?query=posix_fallocate&sektion=2&n=1 + r1, _, _ := syscall.Syscall(posixFallocateTrap, uintptr(fd), uintptr(off), uintptr(size)) + if r1 != 0 { + return syscall.Errno(r1) } return nil } diff --git a/src/internal/syscall/unix/fallocate_freebsd_arm.go b/src/internal/syscall/unix/fallocate_freebsd_arm.go new file mode 100644 index 00000000000..1ded50f3b9a --- /dev/null +++ b/src/internal/syscall/unix/fallocate_freebsd_arm.go @@ -0,0 +1,22 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +import "syscall" + +func PosixFallocate(fd int, off int64, size int64) error { + // If successful, posix_fallocate() returns zero. It returns an error on failure, without + // setting errno. See https://man.freebsd.org/cgi/man.cgi?query=posix_fallocate&sektion=2&n=1 + // + // The padding 0 argument is needed because the ARM calling convention requires that if an + // argument (off in this case) needs double-word alignment (8-byte), the NCRN (next core + // register number) is rounded up to the next even register number. + // See https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aapcs32/aapcs32.rst#parameter-passing + r1, _, _ := syscall.Syscall6(posixFallocateTrap, uintptr(fd), 0, uintptr(off), uintptr(off>>32), uintptr(size), uintptr(size>>32)) + if r1 != 0 { + return syscall.Errno(r1) + } + return nil +}