@@ -5,13 +5,15 @@ package fs
55import (
66 "bufio"
77 "fmt"
8+ "math"
89 "os"
910 "path/filepath"
1011 "strconv"
1112 "strings"
1213
1314 "github.com/opencontainers/runc/libcontainer/cgroups"
1415 "github.com/opencontainers/runc/libcontainer/configs"
16+ "github.com/opencontainers/runc/libcontainer/system"
1517)
1618
1719type MemoryGroup struct {
@@ -33,7 +35,7 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
3335 }
3436 }
3537 // We have to set kernel memory here, as we can't change it once
36- // processes have been attached.
38+ // processes have been attached to the cgroup .
3739 if err := s .SetKernelMemory (path , d .config ); err != nil {
3840 return err
3941 }
@@ -55,9 +57,44 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
5557}
5658
5759func (s * MemoryGroup ) SetKernelMemory (path string , cgroup * configs.Cgroup ) error {
58- // This has to be done separately because it has special constraints (it
59- // can't be done after there are processes attached to the cgroup).
60- if cgroup .Resources .KernelMemory > 0 {
60+ // This has to be done separately because it has special
61+ // constraints (it can only be initialized before setting up a
62+ // hierarchy or adding a task to the cgroups. However, if
63+ // sucessfully initialized, it can be updated anytime afterwards)
64+ if cgroup .Resources .KernelMemory != 0 {
65+ kmemInitialized := false
66+ // Is kmem.limit_in_bytes already set?
67+ kmemValue , err := getCgroupParamUint (path , "memory.kmem.limit_in_bytes" )
68+ if err != nil {
69+ return err
70+ }
71+ switch system .GetLongBit () {
72+ case 32 :
73+ kmemInitialized = uint32 (kmemValue ) != uint32 (math .MaxUint32 )
74+ case 64 :
75+ kmemInitialized = kmemValue != uint64 (math .MaxUint64 )
76+ }
77+
78+ if ! kmemInitialized {
79+ // If hierarchy is set, we can't change the limit
80+ usesHierarchy , err := getCgroupParamUint (path , "memory.use_hierarchy" )
81+ if err != nil {
82+ return err
83+ }
84+ if usesHierarchy != 0 {
85+ return fmt .Errorf ("cannot initialize kmem.limit_in_bytes if use_hierarchy is already set" )
86+ }
87+
88+ // If there's already tasks in the cgroup, we can't change the limit either
89+ tasks , err := getCgroupParamString (path , "tasks" )
90+ if err != nil {
91+ return err
92+ }
93+ if tasks != "" {
94+ return fmt .Errorf ("cannot initialize kmem.limit_in_bytes after task have joined this cgroup" )
95+ }
96+ }
97+
6198 if err := writeFile (path , "memory.kmem.limit_in_bytes" , strconv .FormatInt (cgroup .Resources .KernelMemory , 10 )); err != nil {
6299 return err
63100 }
@@ -113,6 +150,10 @@ func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
113150 return err
114151 }
115152
153+ if err := s .SetKernelMemory (path , cgroup ); err != nil {
154+ return err
155+ }
156+
116157 if cgroup .Resources .MemoryReservation != 0 {
117158 if err := writeFile (path , "memory.soft_limit_in_bytes" , strconv .FormatInt (cgroup .Resources .MemoryReservation , 10 )); err != nil {
118159 return err
0 commit comments