From f24aa06ef6accfc3912e172df06abcf2b7c59fed Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 18 Jun 2025 16:56:00 -0700 Subject: [PATCH 1/2] libct: State: ensure Resources is not nil Since opencontainers/cgroups v0.0.2 (commit b206a015), all stuct Resources fields are annotated with "omitempty" attribute. As a result, the loaded configuration may have Resources == nil. It is totally OK (rootless containers may have no resources configured) except since commit 6c5441e5, cgroup v1 fs manager requires Resources to be set in the call to NewManager (this is a cgroup v1 deficiency, or maybe our implementation deficiency, or both). To work around this, let's add code to ensure Resources is never nil after loading from state.json. Signed-off-by: Kir Kolyshkin --- libcontainer/factory_linux.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go index d222d6b42..b799e4a98 100644 --- a/libcontainer/factory_linux.go +++ b/libcontainer/factory_linux.go @@ -164,6 +164,10 @@ func loadState(root string) (*State, error) { if err := json.NewDecoder(f).Decode(&state); err != nil { return nil, err } + // Cgroup v1 fs manager expect Resources to never be nil. + if state.Config.Cgroups.Resources == nil { + state.Config.Cgroups.Resources = &cgroups.Resources{} + } return state, nil } From da90947848788dd65e8a766723bca85ec452662a Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 18 Jun 2025 15:00:34 -0700 Subject: [PATCH 2/2] deps: bump cgroups to v0.0.3, fix tests For changelog, see https://github.com/opencontainers/cgroups/releases/tag/v0.0.3 This fixes two runc issues: 1. JSON incompatibility introduced in cgroups v0.0.2 (see https://github.com/opencontainers/cgroups/pull/22). 2. Bad CPU shares to CPU weight conversion (see https://github.com/opencontainers/runc/issues/4772). Due to item 2, modify some tests accordingly. Signed-off-by: Kir Kolyshkin --- go.mod | 2 +- go.sum | 4 +-- tests/integration/helpers.bash | 13 ++++++++- tests/integration/update.bats | 5 ++-- .../opencontainers/cgroups/config_linux.go | 2 +- .../opencontainers/cgroups/utils.go | 27 ++++++++++++++----- vendor/modules.txt | 2 +- 7 files changed, 40 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 3544a1b6a..25a62ca65 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/moby/sys/user v0.4.0 github.com/moby/sys/userns v0.1.0 github.com/mrunalp/fileutils v0.5.1 - github.com/opencontainers/cgroups v0.0.2 + github.com/opencontainers/cgroups v0.0.3 github.com/opencontainers/runtime-spec v1.2.2-0.20250401095657-e935f995dd67 github.com/opencontainers/selinux v1.12.0 github.com/seccomp/libseccomp-golang v0.11.0 diff --git a/go.sum b/go.sum index f09a27ac7..5878e5bb1 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/opencontainers/cgroups v0.0.2 h1:A+mAPPMfgKNCEZUUtibESFx06uvhAmvo8sSz3Abwk7o= -github.com/opencontainers/cgroups v0.0.2/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= +github.com/opencontainers/cgroups v0.0.3 h1:Jc9dWh/0YLGjdy6J/9Ln8NM5BfTA4W2BY0GMozy3aDU= +github.com/opencontainers/cgroups v0.0.3/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/runtime-spec v1.2.2-0.20250401095657-e935f995dd67 h1:Q+KewUGTMamIe6Q39xCD/T1NC1POmaTlWnhjikCrZHA= github.com/opencontainers/runtime-spec v1.2.2-0.20250401095657-e935f995dd67/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8= diff --git a/tests/integration/helpers.bash b/tests/integration/helpers.bash index 669bbb16c..da279c7cf 100755 --- a/tests/integration/helpers.bash +++ b/tests/integration/helpers.bash @@ -352,7 +352,18 @@ function check_cpu_shares() { local shares=$1 if [ -v CGROUP_V2 ]; then - local weight=$((1 + ((shares - 2) * 9999) / 262142)) + # Same formula as ConvertCPUSharesToCgroupV2Value. + local weight + weight=$(awk -v shares="$shares" ' + BEGIN { + if (shares == 0) { print 0; exit } + if (shares <= 2) { print 1; exit } + if (shares >= 262144) { print 10000; exit } + l = log(shares) / log(2) + exponent = (l*l + 125*l) / 612.0 - 7.0/34.0 + print int(exp(exponent * log(10)) + 0.99) + }') + check_cpu_weight "$weight" else check_cgroup_value "cpu.shares" "$shares" diff --git a/tests/integration/update.bats b/tests/integration/update.bats index 27af565b7..461fac479 100644 --- a/tests/integration/update.bats +++ b/tests/integration/update.bats @@ -545,10 +545,9 @@ EOF runc run -d --console-socket "$CONSOLE_SOCKET" test_update [ "$status" -eq 0 ] - # Check that initial values were properly set. + # Check that initial values (from setup) were properly set. check_cpu_quota 500000 1000000 - # Initial cpu shares of 100 corresponds to weight of 4. - check_cpu_weight 4 + check_cpu_shares 100 check_systemd_value "TasksMax" 20 runc update -r - test_update <= 262144 { + return 10000 + } + l := math.Log2(float64(cpuShares)) + // Quadratic function which fits min, max, and default. + exponent := (l*l+125*l)/612.0 - 7.0/34.0 + + return uint64(math.Ceil(math.Pow(10, exponent))) } // ConvertMemorySwapToCgroupV2Value converts MemorySwap value from OCI spec diff --git a/vendor/modules.txt b/vendor/modules.txt index a08b66fdc..86aaddac8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -51,7 +51,7 @@ github.com/moby/sys/userns # github.com/mrunalp/fileutils v0.5.1 ## explicit; go 1.13 github.com/mrunalp/fileutils -# github.com/opencontainers/cgroups v0.0.2 +# github.com/opencontainers/cgroups v0.0.3 ## explicit; go 1.23.0 github.com/opencontainers/cgroups github.com/opencontainers/cgroups/devices