Skip to content

Commit 7f7144d

Browse files
committed
Initial v2 resources.unified systemd support
In case systemd is used as cgroups manager, and a user sets some resources using unified resource map (as per [1]), systemd is not aware of any parameters, so there will be a discrepancy between the cgroupfs state and systemd unit state. Let's try to fix that by converting known unified resources to systemd properties. Currently, this is only implemented for pids.max as a POC. Some other parameters (that might or might not have systemd unit property equivalents) are: $ ls -l | grep w- -rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.freeze -rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.max.depth -rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.max.descendants -rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.procs -rw-r--r--. 1 root root 0 Oct 21 09:43 cgroup.subtree_control -rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.threads -rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.type -rw-r--r--. 1 root root 0 Oct 22 10:30 cpu.max -rw-r--r--. 1 root root 0 Oct 10 13:57 cpu.pressure -rw-r--r--. 1 root root 0 Oct 22 10:30 cpuset.cpus -rw-r--r--. 1 root root 0 Oct 22 10:30 cpuset.cpus.partition -rw-r--r--. 1 root root 0 Oct 22 10:30 cpuset.mems -rw-r--r--. 1 root root 0 Oct 22 10:30 cpu.weight -rw-r--r--. 1 root root 0 Oct 22 10:30 cpu.weight.nice -rw-r--r--. 1 root root 0 Oct 22 10:30 hugetlb.1GB.max -rw-r--r--. 1 root root 0 Oct 22 10:30 hugetlb.1GB.rsvd.max -rw-r--r--. 1 root root 0 Oct 22 10:30 hugetlb.2MB.max -rw-r--r--. 1 root root 0 Oct 22 10:30 hugetlb.2MB.rsvd.max -rw-r--r--. 1 root root 0 Oct 22 10:30 io.bfq.weight -rw-r--r--. 1 root root 0 Oct 22 10:30 io.latency -rw-r--r--. 1 root root 0 Oct 22 10:30 io.max -rw-r--r--. 1 root root 0 Oct 10 13:57 io.pressure -rw-r--r--. 1 root root 0 Oct 22 10:30 io.weight -rw-r--r--. 1 root root 0 Oct 10 13:57 memory.high -rw-r--r--. 1 root root 0 Oct 10 13:57 memory.low -rw-r--r--. 1 root root 0 Oct 10 13:57 memory.max -rw-r--r--. 1 root root 0 Oct 10 13:57 memory.min -rw-r--r--. 1 root root 0 Oct 10 13:57 memory.oom.group -rw-r--r--. 1 root root 0 Oct 10 13:57 memory.pressure -rw-r--r--. 1 root root 0 Oct 10 13:57 memory.swap.high -rw-r--r--. 1 root root 0 Oct 10 13:57 memory.swap.max Surely, it is a manual conversion for every such case... [1] opencontainers/runtime-spec#1040 Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent f879d3a commit 7f7144d

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

libcontainer/cgroups/systemd/v2.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
package systemd
44

55
import (
6+
"fmt"
7+
"math"
68
"os"
79
"path/filepath"
810
"strconv"
@@ -34,6 +36,47 @@ func NewUnifiedManager(config *configs.Cgroup, path string, rootless bool) cgrou
3436
}
3537
}
3638

39+
// unifiedResToSystemdProps tries to convert from Cgroup.Resources.Unified
40+
// key/value map (where key is cgroupfs file name) to systemd unit properties.
41+
// This is on a best-effort basis, so the properties that are not known
42+
// (to this function and/or systemd) are ignored (but logged with "debug"
43+
// log level).
44+
//
45+
// For the list of keys, see https://www.kernel.org/doc/Documentation/cgroup-v2.txt
46+
//
47+
// For the list of systemd unit properties, see systemd.resource-control(5).
48+
func unifiedResToSystemdProps(res map[string]string) (props []systemdDbus.Property, _ error) {
49+
for k, v := range res {
50+
if strings.Contains(k, "/") {
51+
return nil, fmt.Errorf("unified resource %q must be a file name (no slashes)", k)
52+
}
53+
sk := strings.SplitN(k, ".", 2)
54+
if len(sk) != 2 {
55+
return nil, fmt.Errorf("unified resource %q must be in the form CONTROLLER.PARAMETER", k)
56+
}
57+
switch k {
58+
case "pids.max":
59+
num := uint64(math.MaxUint64)
60+
if v != "max" {
61+
var err error
62+
num, err = strconv.ParseUint(v, 10, 64)
63+
if err != nil {
64+
return nil, fmt.Errorf("unified resource %q value conversion error: %w", k, err)
65+
}
66+
}
67+
props = append(props,
68+
newProp("TasksAccounting", true),
69+
newProp("TasksMax", uint64(num)))
70+
default:
71+
// Ignore the unknown resource here -- will still be
72+
// applied in Set which calls fs2.Set.
73+
logrus.Debugf("don't know how to convert unified resource %q=%q to systemd unit property; skipping (will still be applied to cgroupfs)", k, v)
74+
}
75+
}
76+
77+
return props, nil
78+
}
79+
3780
func genV2ResourcesProperties(c *configs.Cgroup, conn *systemdDbus.Conn) ([]systemdDbus.Property, error) {
3881
var properties []systemdDbus.Property
3982
r := c.Resources
@@ -82,6 +125,15 @@ func genV2ResourcesProperties(c *configs.Cgroup, conn *systemdDbus.Conn) ([]syst
82125

83126
// ignore r.KernelMemory
84127

128+
// convert Resources.Unified map to systemd properties
129+
if r.Unified != nil {
130+
unifiedProps, err := unifiedResToSystemdProps(r.Unified)
131+
if err != nil {
132+
return nil, err
133+
}
134+
properties = append(properties, unifiedProps...)
135+
}
136+
85137
return properties, nil
86138
}
87139

tests/integration/cgroups.bats

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ function setup() {
216216
echo "$output" | grep -q '^memory.max:10485760$'
217217
echo "$output" | grep -q '^pids.max:99$'
218218
echo "$output" | grep -q '^cpu.max:10000 100000$'
219+
220+
check_systemd_value "TasksMax" 99
219221
}
220222

221223
@test "runc run (cgroup v2 resources.unified override)" {
@@ -226,7 +228,8 @@ function setup() {
226228
| .linux.resources.memorySwap |= {"limit": 33554432}
227229
| .linux.resources.unified |= {
228230
"memory.min": "131072",
229-
"memory.max": "10485760"
231+
"memory.max": "10485760",
232+
"pids.max": "42"
230233
}' "$BUSYBOX_BUNDLE"
231234

232235
runc run -d --console-socket "$CONSOLE_SOCKET" test_cgroups_unified
@@ -239,4 +242,9 @@ function setup() {
239242
runc exec test_cgroups_unified cat /sys/fs/cgroup/memory.max
240243
[ "$status" -eq 0 ]
241244
[ "$output" = '10485760' ]
245+
246+
runc exec test_cgroups_unified cat /sys/fs/cgroup/pids.max
247+
[ "$status" -eq 0 ]
248+
[ "$output" = '42' ]
249+
check_systemd_value "TasksMax" 42
242250
}

0 commit comments

Comments
 (0)