Skip to content

Commit

Permalink
helpers: fix reading cpu stats on cgroup v2
Browse files Browse the repository at this point in the history
read quota and limit from cpu.max, and convert cpu.weight to the range
expected with cgroup v1.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Mar 25, 2021
1 parent 291c215 commit 32ecf85
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 11 deletions.
73 changes: 62 additions & 11 deletions container/common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package common
import (
"fmt"
"io/ioutil"
"math"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -122,18 +123,43 @@ func GetSpec(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoF
cpuRoot, ok := cgroupPaths["cpu"]
if ok {
if utils.FileExists(cpuRoot) {
spec.HasCpu = true
spec.Cpu.Limit = readUInt64(cpuRoot, "cpu.shares")
spec.Cpu.Period = readUInt64(cpuRoot, "cpu.cfs_period_us")
quota := readString(cpuRoot, "cpu.cfs_quota_us")

if quota != "" && quota != "-1" {
val, err := strconv.ParseUint(quota, 10, 64)
if err != nil {
klog.Errorf("GetSpec: Failed to parse CPUQuota from %q: %s", path.Join(cpuRoot, "cpu.cfs_quota_us"), err)
} else {
spec.Cpu.Quota = val
if !cgroups.IsCgroup2UnifiedMode() {
spec.HasCpu = true
spec.Cpu.Limit = readUInt64(cpuRoot, "cpu.shares")
spec.Cpu.Period = readUInt64(cpuRoot, "cpu.cfs_period_us")
quota := readString(cpuRoot, "cpu.cfs_quota_us")

if quota != "" && quota != "-1" {
val, err := strconv.ParseUint(quota, 10, 64)
if err != nil {
klog.Errorf("GetSpec: Failed to parse CPUQuota from %q: %s", path.Join(cpuRoot, "cpu.cfs_quota_us"), err)
} else {
spec.Cpu.Quota = val
}
}
} else {
spec.HasCpu = true

weight := readUInt64(cpuRoot, "cpu.weight")
if weight > 0 {
limit, err := convertCPUWeightToCPULimit(weight)
if err != nil {
klog.Errorf("GetSpec: Failed to read CPULimit from %q: %s", path.Join(cpuRoot, "cpu.weight"), err)
} else {
spec.Cpu.Limit = limit
}
}
max := readString(cpuRoot, "cpu.max")
if max != "" {
splits := strings.SplitN(max, " ", 2)
if len(splits) != 2 {
klog.Errorf("GetSpec: Failed to parse CPUmax from %q", path.Join(cpuRoot, "cpu.max"))
} else {
spec.Cpu.Quota = parseUint64String(splits[0])
spec.Cpu.Period = parseUint64String(splits[1])
}
}

}
}
}
Expand Down Expand Up @@ -224,6 +250,31 @@ func readString(dirpath string, file string) string {
return strings.TrimSpace(string(out))
}

// Convert from [1-10000] to [2-262144]
func convertCPUWeightToCPULimit(weight uint64) (uint64, error) {
if weight < 1 || weight > 10000 {
return 0, fmt.Errorf("convertCPUWeightToCPULimit: invalid cpu weight: %v", weight)
}
return 2 + ((weight-1)*262142)/9999, nil
}

func parseUint64String(strValue string) uint64 {
if strValue == "max" {
return math.MaxUint64
}
if strValue == "" {
return 0
}

val, err := strconv.ParseUint(strValue, 10, 64)
if err != nil {
klog.Errorf("readUInt64: Failed to parse int %q: %s", strValue, err)
return 0
}

return val
}

func readUInt64(dirpath string, file string) uint64 {
out := readString(dirpath, file)
if out == "" || out == "max" {
Expand Down
25 changes: 25 additions & 0 deletions container/common/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,28 @@ func BenchmarkListDirectories(b *testing.B) {
}
}
}

func TestConvertCpuWeightToCpuLimit(t *testing.T) {
limit, err := convertCPUWeightToCPULimit(1)
if err != nil {
t.Fatalf("Error in convertCPUWeightToCPULimit: %s", err)
}
if limit != 2 {
t.Fatalf("convertCPUWeightToCPULimit(1) != 2")
}
limit, err = convertCPUWeightToCPULimit(10000)
if err != nil {
t.Fatalf("Error in convertCPUWeightToCPULimit: %s", err)
}
if limit != 262144 {
t.Fatalf("convertCPUWeightToCPULimit(10000) != 262144")
}
_, err = convertCPUWeightToCPULimit(0)
if err == nil {
t.Fatalf("convertCPUWeightToCPULimit(0) must raise an error")
}
_, err = convertCPUWeightToCPULimit(10001)
if err == nil {
t.Fatalf("convertCPUWeightToCPULimit(10001) must raise an error")
}
}

0 comments on commit 32ecf85

Please sign in to comment.