diff --git a/libcontainer/cgroups/systemd/common.go b/libcontainer/cgroups/systemd/common.go index 7df198caa..61f2d69f0 100644 --- a/libcontainer/cgroups/systemd/common.go +++ b/libcontainer/cgroups/systemd/common.go @@ -432,3 +432,35 @@ func addCpuQuota(conn *systemdDbus.Conn, properties *[]systemdDbus.Property, quo newProp("CPUQuotaPerSecUSec", cpuQuotaPerSecUSec)) } } + +func addCpuset(conn *systemdDbus.Conn, props *[]systemdDbus.Property, cpus, mems string) error { + if cpus == "" && mems == "" { + return nil + } + + // systemd only supports AllowedCPUs/AllowedMemoryNodes since v244 + sdVer := systemdVersion(conn) + if sdVer < 244 { + return nil + } + + if cpus != "" { + bits, err := rangeToBits(cpus) + if err != nil { + return fmt.Errorf("resources.CPU.Cpus=%q conversion error: %w", + cpus, err) + } + *props = append(*props, + newProp("AllowedCPUs", bits)) + } + if mems != "" { + bits, err := rangeToBits(mems) + if err != nil { + return fmt.Errorf("resources.CPU.Mems=%q conversion error: %w", + mems, err) + } + *props = append(*props, + newProp("AllowedMemoryNodes", bits)) + } + return nil +} diff --git a/libcontainer/cgroups/systemd/v1.go b/libcontainer/cgroups/systemd/v1.go index 2679b9993..64af1d94b 100644 --- a/libcontainer/cgroups/systemd/v1.go +++ b/libcontainer/cgroups/systemd/v1.go @@ -90,6 +90,11 @@ func genV1ResourcesProperties(c *configs.Cgroup, conn *systemdDbus.Conn) ([]syst newProp("TasksMax", uint64(r.PidsLimit))) } + err = addCpuset(conn, &properties, r.CpusetCpus, r.CpusetMems) + if err != nil { + return nil, err + } + return properties, nil } diff --git a/libcontainer/cgroups/systemd/v2.go b/libcontainer/cgroups/systemd/v2.go index 5691b43df..782e4b5b4 100644 --- a/libcontainer/cgroups/systemd/v2.go +++ b/libcontainer/cgroups/systemd/v2.go @@ -201,6 +201,11 @@ func genV2ResourcesProperties(c *configs.Cgroup, conn *systemdDbus.Conn) ([]syst newProp("TasksMax", uint64(r.PidsLimit))) } + err = addCpuset(conn, &properties, r.CpusetCpus, r.CpusetMems) + if err != nil { + return nil, err + } + // ignore r.KernelMemory // convert Resources.Unified map to systemd properties diff --git a/tests/integration/update.bats b/tests/integration/update.bats index 908ce0ccb..c03e7c6de 100644 --- a/tests/integration/update.bats +++ b/tests/integration/update.bats @@ -392,7 +392,63 @@ EOF check_systemd_value "TasksMax" 10 } +@test "update cpuset parameters via resources.CPU" { + [[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup + requires smp + + local AllowedCPUs='AllowedCPUs' AllowedMemoryNodes='AllowedMemoryNodes' + # these properties require systemd >= v244 + if [ "$(systemd_version)" -lt 244 ]; then + # a hack to skip checks, see check_systemd_value() + AllowedCPUs='unsupported' + AllowedMemoryNodes='unsupported' + fi + + update_config ' .linux.resources.CPU |= { + "Cpus": "0", + "Mems": "0" + }' "${BUSYBOX_BUNDLE}" + runc run -d --console-socket "$CONSOLE_SOCKET" test_update + [ "$status" -eq 0 ] + + # check that initial values were properly set + check_systemd_value "$AllowedCPUs" 0 + check_systemd_value "$AllowedMemoryNodes" 0 + + runc update -r - test_update <= v244 [[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup requires cgroups_v2 smp