diff options
| author | Andy Pan <i@andypan.me> | 2024-08-10 11:26:02 +0800 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-08-15 19:23:02 +0000 |
| commit | f7cdadafbee0c7d78fcfd6c5281a82c6c7ac2a50 (patch) | |
| tree | 76c5707803833139e186f06a4e903b1b32791dab /src/internal/syscall | |
| parent | 2693f77b3583585172810427e12a634b28d34493 (diff) | |
| download | go-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.go | 48 | ||||
| -rw-r--r-- | src/internal/syscall/unix/kernel_version_freebsd_test.go | 23 | ||||
| -rw-r--r-- | src/internal/syscall/unix/kernel_version_linux.go | 8 | ||||
| -rw-r--r-- | src/internal/syscall/unix/kernel_version_other.go | 2 | ||||
| -rw-r--r-- | src/internal/syscall/unix/sysnum_freebsd.go | 7 |
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 |
