Skip to content

Commit 88be369

Browse files
committed
Add ConvertCPUSharesToCPUWeight
The existing function, ConvertCPUSharesToCgroupV2Value, do not have a way to return an error, and thus can accept invalid cgroup v1 (cpu-shares) values and can return invalid cgroup v2 (cpu-weight) values. Add a new one, ConvertCPUSharesToCPUWeight, which is identical but can return meaningful errors. Mark the old one as deprecated. Amend the test case to test the new implementation (and, since both are using the same formula, existing implementation is tested, too, except for 0). Related to runc issue 4755. Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent 9657f5a commit 88be369

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

utils.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -413,16 +413,36 @@ func WriteCgroupProc(dir string, pid int) error {
413413
return err
414414
}
415415

416+
// ConvertCPUSharesToCgroupV2Value converts CPU shares to CPU weight.
416417
// Since the OCI spec is designed for cgroup v1, in some cases
417-
// there is need to convert from the cgroup v1 configuration to cgroup v2
418-
// the formula for cpuShares is y = (1 + ((x - 2) * 9999) / 262142)
419-
// convert from [2-262144] to [1-10000]
420-
// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)"
418+
// there is need to convert from the cgroup v1 configuration to cgroup v2.
419+
//
420+
// Deprecated: use [ConvertCPUSharesToCPUWeight] instead.
421421
func ConvertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 {
422+
// For both CPU shares and CPU weight, 0 means unset.
422423
if cpuShares == 0 {
423424
return 0
424425
}
425-
return (1 + ((cpuShares-2)*9999)/262142)
426+
return convertCPUShares(cpuShares)
427+
}
428+
429+
// ConvertCPUSharesToCPUWeight converts CPU shares (suitable for cgroup v1)
430+
// to CPU weight (suitable for cgroup v2). If the conversion is not possible,
431+
// an error is returned.
432+
func ConvertCPUSharesToCPUWeight(shares uint64) (uint64, error) {
433+
if shares == 0 {
434+
return 0, nil
435+
}
436+
if shares < 2 || shares > 262144 {
437+
return 0, errors.New("cpu-shares should be between 2 and 262144")
438+
}
439+
return convertCPUShares(shares), nil
440+
}
441+
442+
func convertCPUShares(shares uint64) uint64 {
443+
// Convert from [2-262144] to [1-10000].
444+
// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)"
445+
return 1 + ((shares-2)*9999)/262142
426446
}
427447

428448
// ConvertMemorySwapToCgroupV2Value converts MemorySwap value from OCI spec

utils_test.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -534,16 +534,27 @@ func TestGetHugePageSizeImpl(t *testing.T) {
534534
}
535535
}
536536

537-
func TestConvertCPUSharesToCgroupV2Value(t *testing.T) {
538-
cases := map[uint64]uint64{
539-
0: 0,
540-
2: 1,
541-
262144: 10000,
537+
func TestConvertCPUSharesToCPUWeight(t *testing.T) {
538+
cases := []struct {
539+
in, out uint64
540+
isErr bool
541+
}{
542+
{in: 0, out: 0},
543+
{in: 2, out: 1},
544+
{in: 262144, out: 10000},
545+
{in: 1, isErr: true},
546+
{in: 262145, isErr: true},
542547
}
543-
for i, expected := range cases {
544-
got := ConvertCPUSharesToCgroupV2Value(i)
545-
if got != expected {
546-
t.Errorf("expected ConvertCPUSharesToCgroupV2Value(%d) to be %d, got %d", i, expected, got)
548+
for _, tc := range cases {
549+
got, err := ConvertCPUSharesToCPUWeight(tc.in)
550+
if tc.isErr {
551+
if err == nil {
552+
t.Errorf("ConvertCPUSharesToCPUWeight(%d): expected error, got nil", tc.in)
553+
}
554+
} else if err != nil {
555+
t.Errorf("ConvertCPUSharesToCPUWeight(%d): expected error, got nil", tc.in)
556+
} else if got != tc.out {
557+
t.Errorf("ConvertCPUSharesToCPUWeight(%d): want %d, got %d", tc.in, tc.out, got)
547558
}
548559
}
549560
}

0 commit comments

Comments
 (0)