diff --git a/libcontainer/cgroups/fs2/io.go b/libcontainer/cgroups/fs2/io.go index 4c4d656c10e..b8c13c4ac51 100644 --- a/libcontainer/cgroups/fs2/io.go +++ b/libcontainer/cgroups/fs2/io.go @@ -30,7 +30,16 @@ func setIo(dirPath string, cgroup *configs.Cgroup) error { filename := "io.bfq.weight" if err := fscommon.WriteFile(dirPath, filename, strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil { - return err + // if io.bfq.weight does not exist, then bfq module is not loaded. + // Fallback to use io.weight with a conversion scheme + if os.IsNotExist(err) { + v := cgroups.ConvertBlkIOToIOWeightValue(cgroup.Resources.BlkioWeight) + if err := fscommon.WriteFile(dirPath, "io.weight", strconv.FormatUint(v, 10)); err != nil { + return err + } + } else { + return err + } } } for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice { diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go index a542b538eef..f6d04d58519 100644 --- a/libcontainer/cgroups/utils.go +++ b/libcontainer/cgroups/utils.go @@ -439,3 +439,14 @@ func ConvertMemorySwapToCgroupV2Value(memorySwap, memory int64) (int64, error) { return memorySwap - memory, nil } + +// 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 BlkIOWeight to IOWeight is y = (1 + (x - 10) * 9999 / 990) +// convert linearly from [10-1000] to [1-10000] +func ConvertBlkIOToIOWeightValue(blkIoWeight uint16) uint64 { + if blkIoWeight == 0 { + return 0 + } + return uint64(1 + (uint64(blkIoWeight)-10)*9999/990) +} diff --git a/libcontainer/cgroups/utils_test.go b/libcontainer/cgroups/utils_test.go index 0f621f25ccf..f7ed4db1bbb 100644 --- a/libcontainer/cgroups/utils_test.go +++ b/libcontainer/cgroups/utils_test.go @@ -642,3 +642,17 @@ func TestConvertMemorySwapToCgroupV2Value(t *testing.T) { } } } + +func TestConvertBlkIOToIOWeightValue(t *testing.T) { + cases := map[uint16]uint64{ + 0: 0, + 10: 1, + 1000: 10000, + } + for i, expected := range cases { + got := ConvertBlkIOToIOWeightValue(i) + if got != expected { + t.Errorf("expected ConvertBlkIOToIOWeightValue(%d) to be %d, got %d", i, expected, got) + } + } +} diff --git a/tests/integration/cgroups.bats b/tests/integration/cgroups.bats index bb3e2dfe40a..d900f008116 100644 --- a/tests/integration/cgroups.bats +++ b/tests/integration/cgroups.bats @@ -195,8 +195,12 @@ function setup() { [ "$status" -eq 0 ] runc exec test_cgroups_unified sh -c 'cat /sys/fs/cgroup/io.bfq.weight' - [ "$status" -eq 0 ] - [ "$output" = 'default 750' ] + if [[ "$status" -eq 0 ]]; then + [ "$output" = 'default 750' ] + else + runc exec test_cgroups_unified sh -c 'cat /sys/fs/cgroup/io.weight' + [ "$output" = 'default 7475' ] + fi } @test "runc run (cgroup v2 resources.unified only)" {