From 4dd3d464a46168c591d627083dda9968d0c3e16e Mon Sep 17 00:00:00 2001 From: david Date: Wed, 15 Dec 2021 13:41:39 +0100 Subject: [PATCH 1/6] Add isolated cpu parsing Signed-off-by: david --- fixtures.ttar | 5 +++++ sysfs/system_cpu.go | 47 ++++++++++++++++++++++++++++++++++++++++ sysfs/system_cpu_test.go | 40 ++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/fixtures.ttar b/fixtures.ttar index e005ee94a..50294186f 100644 --- a/fixtures.ttar +++ b/fixtures.ttar @@ -6462,6 +6462,11 @@ Mode: 644 Directory: fixtures/sys/devices/system/cpu/cpufreq/policy1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/devices/system/cpu/isolated +Lines: 1 +1,2-7,9 +Mode: 664 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/system/node Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sysfs/system_cpu.go b/sysfs/system_cpu.go index 40fc94b43..46ac5cb5a 100644 --- a/sysfs/system_cpu.go +++ b/sysfs/system_cpu.go @@ -16,8 +16,11 @@ package sysfs import ( + "fmt" + "io/ioutil" "os" "path/filepath" + "strconv" "strings" "golang.org/x/sync/errgroup" @@ -237,3 +240,47 @@ func parseCpufreqCpuinfo(cpuPath string) (*SystemCPUCpufreqStats, error) { SetSpeed: stringOut[4], }, nil } + +func (fs FS) IsolatedCPUs() ([]uint16, error) { + isolcpus, err := ioutil.ReadFile(fs.sys.Path("devices/system/cpu/isolated")) + if err != nil { + return nil, fmt.Errorf("failed to read isolcpus from sysfs: %w", err) + } + + return parseIsolCpus(isolcpus) +} + +func parseIsolCpus(data []byte) ([]uint16, error) { + isolcpus_str := strings.TrimRight(string(data), "\n") + + var isolcpus_int = []uint16{} + + for _, cpu := range strings.Split(isolcpus_str, ",") { + if cpu == "" { + continue + } + if strings.Contains(cpu, "-") { + ranges := strings.Split(cpu, "-") + startRange, err := strconv.Atoi(ranges[0]) + if err != nil { + return nil, err + } + endRange, err := strconv.Atoi(ranges[1]) + if err != nil { + return nil, err + } + + for i := startRange; i <= endRange; i++ { + isolcpus_int = append(isolcpus_int, uint16(i)) + } + continue + } + + _cpu, err := strconv.Atoi(cpu) + if err != nil { + return nil, err + } + isolcpus_int = append(isolcpus_int, uint16(_cpu)) + } + return isolcpus_int, nil +} diff --git a/sysfs/system_cpu_test.go b/sysfs/system_cpu_test.go index 522b58b56..4603f8928 100644 --- a/sysfs/system_cpu_test.go +++ b/sysfs/system_cpu_test.go @@ -140,3 +140,43 @@ func TestSystemCpufreq(t *testing.T) { t.Errorf("Result not correct: want %v, have %v", systemCpufreq, c) } } + +func TestIsolatedParsingCPU(t *testing.T) { + var testParams = []struct { + in []byte + res []uint16 + err error + }{ + {[]byte(""), []uint16{}, nil}, + {[]byte("1\n"), []uint16{1}, nil}, + {[]byte("1"), []uint16{1}, nil}, + {[]byte("1,2"), []uint16{1, 2}, nil}, + {[]byte("1-2"), []uint16{1, 2}, nil}, + {[]byte("1-3"), []uint16{1, 2, 3}, nil}, + {[]byte("1,2-4"), []uint16{1, 2, 3, 4}, nil}, + {[]byte("1,3-4"), []uint16{1, 3, 4}, nil}, + {[]byte("1,3-4,7,20-21"), []uint16{1, 3, 4, 7, 20, 21}, nil}, + } + for _, params := range testParams { + t.Run("blabla", func(t *testing.T) { + res, err := parseIsolCpus(params.in) + if !reflect.DeepEqual(res, params.res) { + t.Fatalf("should have %v result: got %v", params.res, res) + } + if err != params.err { + t.Fatalf("should have %v error: got %v", params.err, err) + } + }) + } +} +func TestIsolatedCPUs(t *testing.T) { + fs, err := NewFS(sysTestFixtures) + if err != nil { + t.Fatal(err) + } + isolated, err := fs.IsolatedCPUs() + expected := []uint16{1, 2, 3, 4, 5, 6, 7, 9} + if !reflect.DeepEqual(isolated, expected) { + t.Errorf("Result not correct: want %v, have %v", expected, isolated) + } +} From 6dbc86e5d18f9dec075f92a0488eb124ec1353f3 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 16 Dec 2021 12:35:37 +0100 Subject: [PATCH 2/6] Address PR comments Signed-off-by: david --- sysfs/system_cpu.go | 24 +++++++++++++----------- sysfs/system_cpu_test.go | 13 +++++++++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/sysfs/system_cpu.go b/sysfs/system_cpu.go index 46ac5cb5a..1b19868f7 100644 --- a/sysfs/system_cpu.go +++ b/sysfs/system_cpu.go @@ -247,40 +247,42 @@ func (fs FS) IsolatedCPUs() ([]uint16, error) { return nil, fmt.Errorf("failed to read isolcpus from sysfs: %w", err) } - return parseIsolCpus(isolcpus) + return parseIsolCPUs(isolcpus) } -func parseIsolCpus(data []byte) ([]uint16, error) { - isolcpus_str := strings.TrimRight(string(data), "\n") +func parseIsolCPUs(data []byte) ([]uint16, error) { - var isolcpus_int = []uint16{} + var isolcpusInt = []uint16{} - for _, cpu := range strings.Split(isolcpus_str, ",") { + for _, cpu := range strings.Split(strings.TrimRight(string(data), "\n"), ",") { if cpu == "" { continue } if strings.Contains(cpu, "-") { ranges := strings.Split(cpu, "-") + if len(ranges) != 2 { + return nil, fmt.Errorf("invalid cpu range: %s", cpu) + } startRange, err := strconv.Atoi(ranges[0]) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid cpu start range: %w", err) } endRange, err := strconv.Atoi(ranges[1]) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid cpu start range: %w", err) } for i := startRange; i <= endRange; i++ { - isolcpus_int = append(isolcpus_int, uint16(i)) + isolcpusInt = append(isolcpusInt, uint16(i)) } continue } - _cpu, err := strconv.Atoi(cpu) + cpuN, err := strconv.Atoi(cpu) if err != nil { return nil, err } - isolcpus_int = append(isolcpus_int, uint16(_cpu)) + isolcpusInt = append(isolcpusInt, uint16(cpuN)) } - return isolcpus_int, nil + return isolcpusInt, nil } diff --git a/sysfs/system_cpu_test.go b/sysfs/system_cpu_test.go index 4603f8928..40305f547 100644 --- a/sysfs/system_cpu_test.go +++ b/sysfs/system_cpu_test.go @@ -16,6 +16,7 @@ package sysfs import ( + "errors" "reflect" "testing" ) @@ -156,16 +157,24 @@ func TestIsolatedParsingCPU(t *testing.T) { {[]byte("1,2-4"), []uint16{1, 2, 3, 4}, nil}, {[]byte("1,3-4"), []uint16{1, 3, 4}, nil}, {[]byte("1,3-4,7,20-21"), []uint16{1, 3, 4, 7, 20, 21}, nil}, + + {[]byte("1,"), []uint16{1}, nil}, + {[]byte("1,2-"), nil, errors.New(`invalid cpu start range: strconv.Atoi: parsing "": invalid syntax`)}, + {[]byte("1,-3"), nil, errors.New(`invalid cpu start range: strconv.Atoi: parsing "": invalid syntax`)}, } for _, params := range testParams { t.Run("blabla", func(t *testing.T) { - res, err := parseIsolCpus(params.in) + res, err := parseIsolCPUs(params.in) if !reflect.DeepEqual(res, params.res) { t.Fatalf("should have %v result: got %v", params.res, res) } - if err != params.err { + if err != nil && params.err != nil && err.Error() != params.err.Error() { + t.Fatalf("should have '%v' error: got '%v'", params.err, err) + } + if (err == nil || params.err == nil) && err != params.err { t.Fatalf("should have %v error: got %v", params.err, err) } + }) } } From 3c9a07cccd36119bd31b64500a4811789a28b0fa Mon Sep 17 00:00:00 2001 From: david Date: Thu, 16 Dec 2021 12:38:41 +0100 Subject: [PATCH 3/6] Fix start/end range message Signed-off-by: david --- sysfs/system_cpu.go | 2 +- sysfs/system_cpu_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sysfs/system_cpu.go b/sysfs/system_cpu.go index 1b19868f7..260c18161 100644 --- a/sysfs/system_cpu.go +++ b/sysfs/system_cpu.go @@ -269,7 +269,7 @@ func parseIsolCPUs(data []byte) ([]uint16, error) { } endRange, err := strconv.Atoi(ranges[1]) if err != nil { - return nil, fmt.Errorf("invalid cpu start range: %w", err) + return nil, fmt.Errorf("invalid cpu end range: %w", err) } for i := startRange; i <= endRange; i++ { diff --git a/sysfs/system_cpu_test.go b/sysfs/system_cpu_test.go index 40305f547..04a49dc07 100644 --- a/sysfs/system_cpu_test.go +++ b/sysfs/system_cpu_test.go @@ -159,7 +159,7 @@ func TestIsolatedParsingCPU(t *testing.T) { {[]byte("1,3-4,7,20-21"), []uint16{1, 3, 4, 7, 20, 21}, nil}, {[]byte("1,"), []uint16{1}, nil}, - {[]byte("1,2-"), nil, errors.New(`invalid cpu start range: strconv.Atoi: parsing "": invalid syntax`)}, + {[]byte("1,2-"), nil, errors.New(`invalid cpu end range: strconv.Atoi: parsing "": invalid syntax`)}, {[]byte("1,-3"), nil, errors.New(`invalid cpu start range: strconv.Atoi: parsing "": invalid syntax`)}, } for _, params := range testParams { From 69d2f6971ea081b3777c939dfb4cbc905a233fee Mon Sep 17 00:00:00 2001 From: david Date: Fri, 17 Dec 2021 16:13:26 +0100 Subject: [PATCH 4/6] rename to parseIsolatedCPUs Signed-off-by: david --- sysfs/system_cpu.go | 4 ++-- sysfs/system_cpu_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sysfs/system_cpu.go b/sysfs/system_cpu.go index 260c18161..15ec163f9 100644 --- a/sysfs/system_cpu.go +++ b/sysfs/system_cpu.go @@ -247,10 +247,10 @@ func (fs FS) IsolatedCPUs() ([]uint16, error) { return nil, fmt.Errorf("failed to read isolcpus from sysfs: %w", err) } - return parseIsolCPUs(isolcpus) + return parseIsolatedCPUs(isolcpus) } -func parseIsolCPUs(data []byte) ([]uint16, error) { +func parseIsolatedCPUs(data []byte) ([]uint16, error) { var isolcpusInt = []uint16{} diff --git a/sysfs/system_cpu_test.go b/sysfs/system_cpu_test.go index 04a49dc07..4b1e37394 100644 --- a/sysfs/system_cpu_test.go +++ b/sysfs/system_cpu_test.go @@ -164,7 +164,7 @@ func TestIsolatedParsingCPU(t *testing.T) { } for _, params := range testParams { t.Run("blabla", func(t *testing.T) { - res, err := parseIsolCPUs(params.in) + res, err := parseIsolatedCPUs(params.in) if !reflect.DeepEqual(res, params.res) { t.Fatalf("should have %v result: got %v", params.res, res) } From f94150532375e4b17c508002a89173934d88de2a Mon Sep 17 00:00:00 2001 From: david Date: Fri, 17 Dec 2021 21:21:40 +0100 Subject: [PATCH 5/6] Do not wrap error Signed-off-by: david --- sysfs/system_cpu.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysfs/system_cpu.go b/sysfs/system_cpu.go index 15ec163f9..7c46c2eaf 100644 --- a/sysfs/system_cpu.go +++ b/sysfs/system_cpu.go @@ -244,7 +244,7 @@ func parseCpufreqCpuinfo(cpuPath string) (*SystemCPUCpufreqStats, error) { func (fs FS) IsolatedCPUs() ([]uint16, error) { isolcpus, err := ioutil.ReadFile(fs.sys.Path("devices/system/cpu/isolated")) if err != nil { - return nil, fmt.Errorf("failed to read isolcpus from sysfs: %w", err) + return nil, err } return parseIsolatedCPUs(isolcpus) From 7d3f3399dc911b07ccf9ff32094f836f7b95ef45 Mon Sep 17 00:00:00 2001 From: david Date: Sat, 18 Dec 2021 13:36:40 +0100 Subject: [PATCH 6/6] also check error is nil Signed-off-by: david --- sysfs/system_cpu_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sysfs/system_cpu_test.go b/sysfs/system_cpu_test.go index 4b1e37394..0ae9f0fd9 100644 --- a/sysfs/system_cpu_test.go +++ b/sysfs/system_cpu_test.go @@ -188,4 +188,7 @@ func TestIsolatedCPUs(t *testing.T) { if !reflect.DeepEqual(isolated, expected) { t.Errorf("Result not correct: want %v, have %v", expected, isolated) } + if err != nil { + t.Errorf("Error not correct: want %v, have %v", nil, err) + } }