diff --git a/libcontainer/cgroups/fs2/memory.go b/libcontainer/cgroups/fs2/memory.go index f1db078613e..a0c619b5c97 100644 --- a/libcontainer/cgroups/fs2/memory.go +++ b/libcontainer/cgroups/fs2/memory.go @@ -32,11 +32,16 @@ func numToStr(value int64) (ret string) { } func setMemory(dirPath string, cgroup *configs.Cgroup) error { - if val := numToStr(cgroup.Resources.MemorySwap); val != "" { + swap, err := cgroups.ConvertMemorySwapToCgroupV2Value(cgroup.Resources.MemorySwap, cgroup.Resources.Memory) + if err != nil { + return err + } + if val := numToStr(swap); val != "" { if err := fscommon.WriteFile(dirPath, "memory.swap.max", val); err != nil { return err } } + if val := numToStr(cgroup.Resources.Memory); val != "" { if err := fscommon.WriteFile(dirPath, "memory.max", val); err != nil { return err diff --git a/libcontainer/cgroups/systemd/unified_hierarchy.go b/libcontainer/cgroups/systemd/unified_hierarchy.go index 7fab68fc450..2dffc34e076 100644 --- a/libcontainer/cgroups/systemd/unified_hierarchy.go +++ b/libcontainer/cgroups/systemd/unified_hierarchy.go @@ -84,6 +84,15 @@ func (m *UnifiedManager) Apply(pid int) error { newProp("MemoryMax", uint64(c.Resources.Memory))) } + swap, err := cgroups.ConvertMemorySwapToCgroupV2Value(c.Resources.MemorySwap, c.Resources.Memory) + if err != nil { + return err + } + if swap > 0 { + properties = append(properties, + newProp("MemorySwapMax", uint64(swap))) + } + if c.Resources.CpuWeight != 0 { properties = append(properties, newProp("CPUWeight", c.Resources.CpuWeight)) diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go index 51b743e2ce3..778a4de9cc2 100644 --- a/libcontainer/cgroups/utils.go +++ b/libcontainer/cgroups/utils.go @@ -623,3 +623,22 @@ func ConvertCPUQuotaCPUPeriodToCgroupV2Value(quota int64, period uint64) string } return fmt.Sprintf("%d %d", quota, period) } + +// ConvertMemorySwapToCgroupV2Value converts MemorySwap value for cgroup v2 +// drivers. Since Resources.MemorySwap is define as memory+swap combined, +// while in cgroup v2 swap is a separate value, a conversion is needed. +func ConvertMemorySwapToCgroupV2Value(memorySwap, memory int64) (int64, error) { + if memorySwap <= 0 { + return memorySwap, nil + } + + if memory <= 0 { + return 0, errors.New("unable to set swap limit without memory limit") + + } + if memory > memorySwap { + return 0, errors.New("memory+swap limit should be > memory limit") + } + + return memorySwap - memory, nil +}