diff --git a/utils.go b/utils.go index 98b6a07..aa340db 100644 --- a/utils.go +++ b/utils.go @@ -413,16 +413,36 @@ func WriteCgroupProc(dir string, pid int) error { return err } +// ConvertCPUSharesToCgroupV2Value converts CPU shares to CPU weight. // Since the OCI spec is designed for cgroup v1, in some cases -// there is need to convert from the cgroup v1 configuration to cgroup v2 -// the formula for cpuShares is y = (1 + ((x - 2) * 9999) / 262142) -// convert from [2-262144] to [1-10000] -// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)" +// there is need to convert from the cgroup v1 configuration to cgroup v2. +// +// Deprecated: use [ConvertCPUSharesToCPUWeight] instead. func ConvertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 { + // For both CPU shares and CPU weight, 0 means unset. if cpuShares == 0 { return 0 } - return (1 + ((cpuShares-2)*9999)/262142) + return convertCPUShares(cpuShares) +} + +// ConvertCPUSharesToCPUWeight converts CPU shares (suitable for cgroup v1) +// to CPU weight (suitable for cgroup v2). If the conversion is not possible, +// an error is returned. +func ConvertCPUSharesToCPUWeight(shares uint64) (uint64, error) { + if shares == 0 { + return 0, nil + } + if shares < 2 || shares > 262144 { + return 0, errors.New("cpu-shares should be between 2 and 262144") + } + return convertCPUShares(shares), nil +} + +func convertCPUShares(shares uint64) uint64 { + // Convert from [2-262144] to [1-10000]. + // 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)" + return 1 + ((shares-2)*9999)/262142 } // ConvertMemorySwapToCgroupV2Value converts MemorySwap value from OCI spec diff --git a/utils_test.go b/utils_test.go index 2d30373..618843c 100644 --- a/utils_test.go +++ b/utils_test.go @@ -534,16 +534,27 @@ func TestGetHugePageSizeImpl(t *testing.T) { } } -func TestConvertCPUSharesToCgroupV2Value(t *testing.T) { - cases := map[uint64]uint64{ - 0: 0, - 2: 1, - 262144: 10000, +func TestConvertCPUSharesToCPUWeight(t *testing.T) { + cases := []struct { + in, out uint64 + isErr bool + }{ + {in: 0, out: 0}, + {in: 2, out: 1}, + {in: 262144, out: 10000}, + {in: 1, isErr: true}, + {in: 262145, isErr: true}, } - for i, expected := range cases { - got := ConvertCPUSharesToCgroupV2Value(i) - if got != expected { - t.Errorf("expected ConvertCPUSharesToCgroupV2Value(%d) to be %d, got %d", i, expected, got) + for _, tc := range cases { + got, err := ConvertCPUSharesToCPUWeight(tc.in) + if tc.isErr { + if err == nil { + t.Errorf("ConvertCPUSharesToCPUWeight(%d): expected error, got nil", tc.in) + } + } else if err != nil { + t.Errorf("ConvertCPUSharesToCPUWeight(%d): expected error, got nil", tc.in) + } else if got != tc.out { + t.Errorf("ConvertCPUSharesToCPUWeight(%d): want %d, got %d", tc.in, tc.out, got) } } }