]> Cypherpunks repositories - gostls13.git/commitdiff
internal/syscall/unix: consolidate kernelVersion implementations
authorKir Kolyshkin <kolyshkin@gmail.com>
Thu, 18 Aug 2022 20:43:47 +0000 (13:43 -0700)
committerGopher Robot <gobot@golang.org>
Sat, 3 Sep 2022 18:39:45 +0000 (18:39 +0000)
Currently, there are 3 functions returning Linux kernel version numbers.

Two of them are identical:
 - in net, initially added by commit 0a9dd47dd817904e;
 - in internal/poll, initially added by commit 1c7650aa93bd53;

(both were later fixed by commit 66c02645062561a).

The third one is a more complex, regexp-based implementation in
runtime/pprof, which is only used for a test.

Instead of adding one more, let's consolidate existing ones.

Remove the complex implementation, and move the simple one into
internal/syscall/unix. Use it from all the three places mentioned above.

Change-Id: I4a34d9ca47257743c16def30e4dd634e36056091
Reviewed-on: https://go-review.googlesource.com/c/go/+/424896
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Kirill Kolyshkin <kolyshkin@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/internal/poll/copy_file_range_linux.go
src/internal/syscall/unix/kernel_version_linux.go [new file with mode: 0644]
src/internal/syscall/unix/kernel_version_other.go [new file with mode: 0644]
src/net/sock_linux.go
src/net/sock_linux_test.go
src/runtime/pprof/pprof_test.go
src/runtime/pprof/uname_linux_test.go [deleted file]
src/runtime/pprof/uname_other_test.go [deleted file]

index c2347ba7f2f689e45866e4b8d4fe0aa313935816..ba33f5145d4896cb34bfe1a14d34fba35e727669 100644 (file)
@@ -17,46 +17,11 @@ var (
 
 const maxCopyFileRangeRound = 1 << 30
 
-func kernelVersion() (major int, minor int) {
-       var uname syscall.Utsname
-       if err := syscall.Uname(&uname); err != nil {
-               return
-       }
-
-       rl := uname.Release
-       var values [2]int
-       vi := 0
-       value := 0
-       for _, c := range rl {
-               if '0' <= c && c <= '9' {
-                       value = (value * 10) + int(c-'0')
-               } else {
-                       // Note that we're assuming N.N.N here.  If we see anything else we are likely to
-                       // mis-parse it.
-                       values[vi] = value
-                       vi++
-                       if vi >= len(values) {
-                               break
-                       }
-                       value = 0
-               }
-       }
-       switch vi {
-       case 0:
-               return 0, 0
-       case 1:
-               return values[0], 0
-       case 2:
-               return values[0], values[1]
-       }
-       return
-}
-
 // CopyFileRange copies at most remain bytes of data from src to dst, using
 // the copy_file_range system call. dst and src must refer to regular files.
 func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err error) {
        kernelVersion53Once.Do(func() {
-               major, minor := kernelVersion()
+               major, minor := unix.KernelVersion()
                // copy_file_range(2) is broken in various ways on kernels older than 5.3,
                // see issue #42400 and
                // https://man7.org/linux/man-pages/man2/copy_file_range.2.html#VERSIONS
diff --git a/src/internal/syscall/unix/kernel_version_linux.go b/src/internal/syscall/unix/kernel_version_linux.go
new file mode 100644 (file)
index 0000000..bb1d4de
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2022 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"
+)
+
+// 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.
+func KernelVersion() (major int, minor int) {
+       var uname syscall.Utsname
+       if err := syscall.Uname(&uname); err != nil {
+               return
+       }
+
+       rl := uname.Release
+       var values [2]int
+       vi := 0
+       value := 0
+       for _, c := range rl {
+               if '0' <= c && c <= '9' {
+                       value = (value * 10) + int(c-'0')
+               } else {
+                       // Note that we're assuming N.N.N here.
+                       // If we see anything else, we are likely to mis-parse it.
+                       values[vi] = value
+                       vi++
+                       if vi >= len(values) {
+                               break
+                       }
+                       value = 0
+               }
+       }
+       switch vi {
+       case 0:
+               return 0, 0
+       case 1:
+               return values[0], 0
+       case 2:
+               return values[0], values[1]
+       }
+       return
+}
diff --git a/src/internal/syscall/unix/kernel_version_other.go b/src/internal/syscall/unix/kernel_version_other.go
new file mode 100644 (file)
index 0000000..00af9f2
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2022 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 !linux
+
+package unix
+
+func KernelVersion() (major int, minor int) {
+       return 0, 0
+}
index 2513f9ba7b9779cb68e00c011b99ff9d2c4c613c..cffe9a236fc7f13da6d0085923dc58102582aa7b 100644 (file)
@@ -4,42 +4,10 @@
 
 package net
 
-import "syscall"
-
-func kernelVersion() (major int, minor int) {
-       var uname syscall.Utsname
-       if err := syscall.Uname(&uname); err != nil {
-               return
-       }
-
-       rl := uname.Release
-       var values [2]int
-       vi := 0
-       value := 0
-       for _, c := range rl {
-               if c >= '0' && c <= '9' {
-                       value = (value * 10) + int(c-'0')
-               } else {
-                       // Note that we're assuming N.N.N here.  If we see anything else we are likely to
-                       // mis-parse it.
-                       values[vi] = value
-                       vi++
-                       if vi >= len(values) {
-                               break
-                       }
-                       value = 0
-               }
-       }
-       switch vi {
-       case 0:
-               return 0, 0
-       case 1:
-               return values[0], 0
-       case 2:
-               return values[0], values[1]
-       }
-       return
-}
+import (
+       "internal/syscall/unix"
+       "syscall"
+)
 
 // Linux stores the backlog as:
 //
@@ -50,7 +18,7 @@ func kernelVersion() (major int, minor int) {
 //
 // See issue 5030 and 41470.
 func maxAckBacklog(n int) int {
-       major, minor := kernelVersion()
+       major, minor := unix.KernelVersion()
        size := 16
        if major > 4 || (major == 4 && minor >= 1) {
                size = 32
index 5df02935c3ce693c1a6ccf7372133844cfa40e46..11303cfff1e64670c098cc48e060a152dcd1bfa3 100644 (file)
@@ -5,12 +5,13 @@
 package net
 
 import (
+       "internal/syscall/unix"
        "testing"
 )
 
 func TestMaxAckBacklog(t *testing.T) {
        n := 196602
-       major, minor := kernelVersion()
+       major, minor := unix.KernelVersion()
        backlog := maxAckBacklog(n)
        expected := 1<<16 - 1
        if major > 4 || (major == 4 && minor >= 1) {
index 28b8f4319e68c6fc03c4de4e1301efe56ff9ffa3..31a4024be819df72fd86ed24d7fb619d41859be0 100644 (file)
@@ -12,6 +12,7 @@ import (
        "fmt"
        "internal/abi"
        "internal/profile"
+       "internal/syscall/unix"
        "internal/testenv"
        "io"
        "math"
@@ -116,11 +117,8 @@ func TestCPUProfileMultithreadMagnitude(t *testing.T) {
 
        // Linux [5.9,5.16) has a kernel bug that can break CPU timers on newly
        // created threads, breaking our CPU accounting.
-       major, minor, patch, err := linuxKernelVersion()
-       if err != nil {
-               t.Errorf("Error determining kernel version: %v", err)
-       }
-       t.Logf("Running on Linux %d.%d.%d", major, minor, patch)
+       major, minor := unix.KernelVersion()
+       t.Logf("Running on Linux %d.%d", major, minor)
        defer func() {
                if t.Failed() {
                        t.Logf("Failure of this test may indicate that your system suffers from a known Linux kernel bug fixed on newer kernels. See https://golang.org/issue/49065.")
diff --git a/src/runtime/pprof/uname_linux_test.go b/src/runtime/pprof/uname_linux_test.go
deleted file mode 100644 (file)
index 8374c83..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2021 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 linux
-
-package pprof
-
-import (
-       "fmt"
-       "regexp"
-       "strconv"
-       "syscall"
-)
-
-var versionRe = regexp.MustCompile(`^(\d+)(?:\.(\d+)(?:\.(\d+))).*$`)
-
-func linuxKernelVersion() (major, minor, patch int, err error) {
-       var uname syscall.Utsname
-       if err := syscall.Uname(&uname); err != nil {
-               return 0, 0, 0, err
-       }
-
-       buf := make([]byte, 0, len(uname.Release))
-       for _, b := range uname.Release {
-               if b == 0 {
-                       break
-               }
-               buf = append(buf, byte(b))
-       }
-       rl := string(buf)
-
-       m := versionRe.FindStringSubmatch(rl)
-       if m == nil {
-               return 0, 0, 0, fmt.Errorf("error matching version number in %q", rl)
-       }
-
-       v, err := strconv.ParseInt(m[1], 10, 64)
-       if err != nil {
-               return 0, 0, 0, fmt.Errorf("error parsing major version %q in %s: %w", m[1], rl, err)
-       }
-       major = int(v)
-
-       if len(m) >= 3 {
-               v, err := strconv.ParseInt(m[2], 10, 64)
-               if err != nil {
-                       return 0, 0, 0, fmt.Errorf("error parsing minor version %q in %s: %w", m[2], rl, err)
-               }
-               minor = int(v)
-       }
-
-       if len(m) >= 4 {
-               v, err := strconv.ParseInt(m[3], 10, 64)
-               if err != nil {
-                       return 0, 0, 0, fmt.Errorf("error parsing patch version %q in %s: %w", m[3], rl, err)
-               }
-               patch = int(v)
-       }
-
-       return
-}
diff --git a/src/runtime/pprof/uname_other_test.go b/src/runtime/pprof/uname_other_test.go
deleted file mode 100644 (file)
index 3276407..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2021 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 !linux
-
-package pprof
-
-import (
-       "errors"
-)
-
-func linuxKernelVersion() (major, minor, patch int, err error) {
-       return 0, 0, 0, errors.New("not running on linux")
-}