diff --git a/libcontainer/cgroups/fs/apply_raw.go b/libcontainer/cgroups/fs/apply_raw.go index 22d82acb4e2..ca697ae8404 100644 --- a/libcontainer/cgroups/fs/apply_raw.go +++ b/libcontainer/cgroups/fs/apply_raw.go @@ -317,6 +317,20 @@ func writeFile(dir, file, data string) error { return nil } +func writeFileIfExist(dir, file, data string) error { + if dir == "" { + return writeFile(dir, file, data) + } + + if _, err := os.Stat(filepath.Join(dir, file)); err != nil { + if !os.IsExist(err) { + return nil + } + } + + return writeFile(dir, file, data) +} + func readFile(dir, file string) (string, error) { data, err := ioutil.ReadFile(filepath.Join(dir, file)) return string(data), err diff --git a/libcontainer/cgroups/fs/memory.go b/libcontainer/cgroups/fs/memory.go index ad395a5d621..9a01e7f2907 100644 --- a/libcontainer/cgroups/fs/memory.go +++ b/libcontainer/cgroups/fs/memory.go @@ -162,6 +162,24 @@ func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error { return err } + if v := cgroup.Resources.MemoryForceEmptyCtl; v != -1 { + if err := writeFileIfExist(path, "memory.force_empty_ctl", strconv.FormatInt(v, 10)); err != nil { + return err + } + } + + if v := cgroup.Resources.MemoryWmarkRatio; v >= 0 && v <= 100 { + if err := writeFileIfExist(path, "memory.wmark_ratio", strconv.FormatInt(v, 10)); err != nil { + return err + } + } + + if v := cgroup.Resources.MemoryExtraInBytes; v > 0 { + if err := writeFileIfExist(path, "memory.extra_in_bytes", strconv.FormatInt(v, 10)); err != nil { + return err + } + } + if cgroup.Resources.KernelMemory != 0 { if err := setKernelMemory(path, cgroup.Resources.KernelMemory); err != nil { return err diff --git a/libcontainer/configs/cgroup_linux.go b/libcontainer/configs/cgroup_linux.go index e15a662f522..9f7131b3d66 100644 --- a/libcontainer/configs/cgroup_linux.go +++ b/libcontainer/configs/cgroup_linux.go @@ -57,6 +57,18 @@ type Resources struct { // Kernel memory limit for TCP use (in bytes) KernelMemoryTCP int64 `json:"kernel_memory_tcp"` + // MemoryWmarkRatio is an integer value representing this container's memory low water mark percentage. + // The value of memory low water mark is memory.limit_in_bytes * MemoryWmarkRatio. + // The range is in [0, 100]. + MemoryWmarkRatio int64 `json:"memory_wmark_ratio"` + + // MemoryExtra is an integer value representing this container's memory high water mark percentage. + // The range is in [0, 100]. + MemoryExtraInBytes int64 `json:"memory_extra_in_bytes"` + + // MemoryForceEmptyCtl represents whether to reclaim the page cache when deleting cgroup + MemoryForceEmptyCtl int64 `json:"memory_force_empty_ctl"` + // CPU shares (relative weight vs. other containers) CpuShares uint64 `json:"cpu_shares"` diff --git a/libcontainer/specconv/spec_linux.go b/libcontainer/specconv/spec_linux.go index ab841a7e522..95f5e1f1323 100644 --- a/libcontainer/specconv/spec_linux.go +++ b/libcontainer/specconv/spec_linux.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "path/filepath" + "strconv" "strings" "time" @@ -283,6 +284,27 @@ func createCgroupConfig(opts *CreateOpts) (*configs.Cgroup, error) { Resources: &configs.Resources{}, } + // deal with data passed in spec annotations + if spec.Annotations != nil { + if v, ok := spec.Annotations["__memory_wmark_ratio"]; ok { + if n, err := strconv.ParseInt(v, 10, 64); err == nil { + c.Resources.MemoryWmarkRatio = n + } + } + + if v, ok := spec.Annotations["__memory_extra_in_bytes"]; ok { + if n, err := strconv.ParseInt(v, 10, 64); err == nil { + c.Resources.MemoryExtraInBytes = n + } + } + + if v, ok := spec.Annotations["__memory_force_empty_ctl"]; ok { + if n, err := strconv.ParseInt(v, 10, 64); err == nil { + c.Resources.MemoryForceEmptyCtl = n + } + } + } + if spec.Linux != nil && spec.Linux.CgroupsPath != "" { myCgroupPath = libcontainerUtils.CleanPath(spec.Linux.CgroupsPath) if useSystemdCgroup { diff --git a/update.go b/update.go index 133be999685..f57f005dc85 100644 --- a/update.go +++ b/update.go @@ -253,6 +253,7 @@ other options are ignored. config.Cgroups.Resources.MemoryReservation = *r.Memory.Reservation config.Cgroups.Resources.MemorySwap = *r.Memory.Swap config.Cgroups.Resources.PidsLimit = r.Pids.Limit + config.Cgroups.Resources.MemoryWmarkRatio = -1 return container.Set(config) },