Allow updating kmem.limit_in_bytes if initialized at cgroup creation
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
parent
4ad7bbc172
commit
27814ee120
|
@ -5,6 +5,7 @@ package fs
|
|||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
)
|
||||
|
||||
type MemoryGroup struct {
|
||||
|
@ -33,7 +35,7 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
|
|||
}
|
||||
}
|
||||
// We have to set kernel memory here, as we can't change it once
|
||||
// processes have been attached.
|
||||
// processes have been attached to the cgroup.
|
||||
if err := s.SetKernelMemory(path, d.config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -55,9 +57,44 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
|
|||
}
|
||||
|
||||
func (s *MemoryGroup) SetKernelMemory(path string, cgroup *configs.Cgroup) error {
|
||||
// This has to be done separately because it has special constraints (it
|
||||
// can't be done after there are processes attached to the cgroup).
|
||||
if cgroup.Resources.KernelMemory > 0 {
|
||||
// This has to be done separately because it has special
|
||||
// constraints (it can only be initialized before setting up a
|
||||
// hierarchy or adding a task to the cgroups. However, if
|
||||
// sucessfully initialized, it can be updated anytime afterwards)
|
||||
if cgroup.Resources.KernelMemory != 0 {
|
||||
kmemInitialized := false
|
||||
// Is kmem.limit_in_bytes already set?
|
||||
kmemValue, err := getCgroupParamUint(path, "memory.kmem.limit_in_bytes")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch system.GetLongBit() {
|
||||
case 32:
|
||||
kmemInitialized = uint32(kmemValue) != uint32(math.MaxUint32)
|
||||
case 64:
|
||||
kmemInitialized = kmemValue != uint64(math.MaxUint64)
|
||||
}
|
||||
|
||||
if !kmemInitialized {
|
||||
// If hierarchy is set, we can't change the limit
|
||||
usesHierarchy, err := getCgroupParamUint(path, "memory.use_hierarchy")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if usesHierarchy != 0 {
|
||||
return fmt.Errorf("cannot initialize kmem.limit_in_bytes if use_hierarchy is already set")
|
||||
}
|
||||
|
||||
// If there's already tasks in the cgroup, we can't change the limit either
|
||||
tasks, err := getCgroupParamString(path, "tasks")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tasks != "" {
|
||||
return fmt.Errorf("cannot initialize kmem.limit_in_bytes after task have joined this cgroup")
|
||||
}
|
||||
}
|
||||
|
||||
if err := writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(cgroup.Resources.KernelMemory, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -113,6 +150,10 @@ func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := s.SetKernelMemory(path, cgroup); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cgroup.Resources.MemoryReservation != 0 {
|
||||
if err := writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil {
|
||||
return err
|
||||
|
|
|
@ -214,11 +214,9 @@ func (m *Manager) Apply(pid int) error {
|
|||
newProp("BlockIOWeight", uint64(c.Resources.BlkioWeight)))
|
||||
}
|
||||
|
||||
// We need to set kernel memory before processes join cgroup because
|
||||
// kmem.limit_in_bytes can only be set when the cgroup is empty.
|
||||
// And swap memory limit needs to be set after memory limit, only
|
||||
// memory limit is handled by systemd, so it's kind of ugly here.
|
||||
if c.Resources.KernelMemory > 0 {
|
||||
// We have to set kernel memory here, as we can't change it once
|
||||
// processes have been attached to the cgroup.
|
||||
if c.Resources.KernelMemory != 0 {
|
||||
if err := setKernelMemory(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -469,11 +467,5 @@ func setKernelMemory(c *configs.Cgroup) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(path, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This doesn't get called by manager.Set, so we need to do it here.
|
||||
s := &fs.MemoryGroup{}
|
||||
return s.SetKernelMemory(path, c)
|
||||
return os.MkdirAll(path, 0755)
|
||||
}
|
||||
|
|
|
@ -10,3 +10,7 @@ import "C"
|
|||
func GetClockTicks() int {
|
||||
return int(C.sysconf(C._SC_CLK_TCK))
|
||||
}
|
||||
|
||||
func GetLongBit() int {
|
||||
return int(C.sysconf(C._SC_LONG_BIT))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue