aboutsummaryrefslogtreecommitdiff
path: root/src/internal/syscall
diff options
context:
space:
mode:
authorAndy Pan <i@andypan.me>2024-08-10 11:26:02 +0800
committerGopher Robot <gobot@golang.org>2024-08-15 19:23:02 +0000
commitf7cdadafbee0c7d78fcfd6c5281a82c6c7ac2a50 (patch)
tree76c5707803833139e186f06a4e903b1b32791dab /src/internal/syscall
parent2693f77b3583585172810427e12a634b28d34493 (diff)
downloadgo-f7cdadafbee0c7d78fcfd6c5281a82c6c7ac2a50.tar.xz
internal,os: employ copy_file_range(2) for file-to-file copying on FreeBSD
FreeBSD 13.0 introduced the Linux-compatible copy_file_range(2) system call, we should make use of it. Ref: https://www.gnu.org/software/gnulib/manual/html_node/copy_005ffile_005frange.html https://reviews.freebsd.org/D20584?id=60021 https://man.freebsd.org/cgi/man.cgi?copy_file_range(2) Change-Id: I75edb5629717289c8887be436613d3a8b3820bdc Reviewed-on: https://go-review.googlesource.com/c/go/+/604655 Run-TryBot: Andy Pan <panjf2000@gmail.com> Reviewed-by: Carlos Amedee <carlos@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
Diffstat (limited to 'src/internal/syscall')
-rw-r--r--src/internal/syscall/unix/copy_file_range_unix.go (renamed from src/internal/syscall/unix/copy_file_range_linux.go)2
-rw-r--r--src/internal/syscall/unix/kernel_version_freebsd.go48
-rw-r--r--src/internal/syscall/unix/kernel_version_freebsd_test.go23
-rw-r--r--src/internal/syscall/unix/kernel_version_linux.go8
-rw-r--r--src/internal/syscall/unix/kernel_version_other.go2
-rw-r--r--src/internal/syscall/unix/sysnum_freebsd.go7
6 files changed, 84 insertions, 6 deletions
diff --git a/src/internal/syscall/unix/copy_file_range_linux.go b/src/internal/syscall/unix/copy_file_range_unix.go
index cf0a279a7a..16a434219e 100644
--- a/src/internal/syscall/unix/copy_file_range_linux.go
+++ b/src/internal/syscall/unix/copy_file_range_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build freebsd || linux
+
package unix
import (
diff --git a/src/internal/syscall/unix/kernel_version_freebsd.go b/src/internal/syscall/unix/kernel_version_freebsd.go
new file mode 100644
index 0000000000..ef9ee136f3
--- /dev/null
+++ b/src/internal/syscall/unix/kernel_version_freebsd.go
@@ -0,0 +1,48 @@
+// Copyright 2024 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 (
+ "sync"
+ "syscall"
+)
+
+// KernelVersion returns major and minor kernel version numbers
+// parsed from the syscall.Sysctl("kern.osrelease")'s value,
+// or (0, 0) if the version can't be obtained or parsed.
+func KernelVersion() (major, minor int) {
+ release, err := syscall.Sysctl("kern.osrelease")
+ if err != nil {
+ return 0, 0
+ }
+
+ parseNext := func() (n int) {
+ for i, c := range release {
+ if c == '.' {
+ release = release[i+1:]
+ return
+ }
+ if '0' <= c && c <= '9' {
+ n = n*10 + int(c-'0')
+ }
+ }
+ release = ""
+ return
+ }
+
+ major = parseNext()
+ minor = parseNext()
+
+ return
+}
+
+// SupportCopyFileRange reports whether the kernel supports the copy_file_range(2).
+// This function will examine both the kernel version and the availability of the system call.
+var SupportCopyFileRange = sync.OnceValue(func() bool {
+ // The copy_file_range() function first appeared in FreeBSD 13.0.
+ major, _ := KernelVersion()
+ _, err := CopyFileRange(0, nil, 0, nil, 0, 0)
+ return major >= 13 && err != syscall.ENOSYS
+})
diff --git a/src/internal/syscall/unix/kernel_version_freebsd_test.go b/src/internal/syscall/unix/kernel_version_freebsd_test.go
new file mode 100644
index 0000000000..694440e325
--- /dev/null
+++ b/src/internal/syscall/unix/kernel_version_freebsd_test.go
@@ -0,0 +1,23 @@
+// Copyright 2024 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_test
+
+import (
+ "internal/syscall/unix"
+ "syscall"
+ "testing"
+)
+
+func TestSupportCopyFileRange(t *testing.T) {
+ major, minor := unix.KernelVersion()
+ t.Logf("Running on FreeBSD %d.%d\n", major, minor)
+
+ _, err := unix.CopyFileRange(0, nil, 0, nil, 0, 0)
+ want := err != syscall.ENOSYS
+ got := unix.SupportCopyFileRange()
+ if want != got {
+ t.Fatalf("SupportCopyFileRange, got %t; want %t", got, want)
+ }
+}
diff --git a/src/internal/syscall/unix/kernel_version_linux.go b/src/internal/syscall/unix/kernel_version_linux.go
index 71e8aa4c57..f3656288ef 100644
--- a/src/internal/syscall/unix/kernel_version_linux.go
+++ b/src/internal/syscall/unix/kernel_version_linux.go
@@ -8,11 +8,9 @@ import (
"syscall"
)
-// KernelVersion returns major and minor kernel version numbers, parsed from
-// the syscall.Uname's Release field, or 0, 0 if the version can't be obtained
-// or parsed.
-//
-// Currently only implemented for Linux.
+// KernelVersion returns major and minor kernel version numbers
+// parsed from the syscall.Uname's Release field, or (0, 0) if
+// the version can't be obtained or parsed.
func KernelVersion() (major, minor int) {
var uname syscall.Utsname
if err := syscall.Uname(&uname); err != nil {
diff --git a/src/internal/syscall/unix/kernel_version_other.go b/src/internal/syscall/unix/kernel_version_other.go
index fc65c1c823..91c14b31d9 100644
--- a/src/internal/syscall/unix/kernel_version_other.go
+++ b/src/internal/syscall/unix/kernel_version_other.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !linux && !solaris
+//go:build !freebsd && !linux && !solaris
package unix
diff --git a/src/internal/syscall/unix/sysnum_freebsd.go b/src/internal/syscall/unix/sysnum_freebsd.go
new file mode 100644
index 0000000000..2c81110409
--- /dev/null
+++ b/src/internal/syscall/unix/sysnum_freebsd.go
@@ -0,0 +1,7 @@
+// Copyright 2024 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
+
+const copyFileRangeTrap uintptr = 569