runc/patch/0028-runc-cgroup-apply-method-modify.patch
2023-01-05 17:23:54 +08:00

268 lines
8.0 KiB
Diff

From 6ae765b2529fbfde33c3562834308add80bd34e2 Mon Sep 17 00:00:00 2001
From: zhongjiawei <zhongjiawei1@huawei.com>
Date: Thu, 5 Jan 2023 16:51:24 +0800
Subject: [PATCH] runc:cgroup apply method modify
---
libcontainer/cgroups/fs/cpuset.go | 15 ++++-
libcontainer/cgroups/fs/files.go | 23 +++----
libcontainer/cgroups/fs/utils.go | 97 +++++++++++++++++++++++++++++
libcontainer/rootfs_linux.go | 1 +
libcontainer/standard_init_linux.go | 4 +-
main.go | 1 -
6 files changed, 119 insertions(+), 22 deletions(-)
create mode 100644 libcontainer/cgroups/fs/utils.go
diff --git a/libcontainer/cgroups/fs/cpuset.go b/libcontainer/cgroups/fs/cpuset.go
index 989f4ec..379407e 100644
--- a/libcontainer/cgroups/fs/cpuset.go
+++ b/libcontainer/cgroups/fs/cpuset.go
@@ -1,7 +1,9 @@
package fs
import (
+ "fmt"
"errors"
+ "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -9,6 +11,7 @@ import (
"golang.org/x/sys/unix"
+ "github.com/sirupsen/logrus"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
"github.com/opencontainers/runc/libcontainer/configs"
@@ -143,7 +146,7 @@ func (s *CpusetGroup) setCpuset(path, cpuset string) error {
func (s *CpusetGroup) Set(path string, r *configs.Resources) error {
var ret error
if r.CpusetCpus != "" {
- return s.setCpuset(path, cgroup.Resources.CpusetCpus)
+ return s.setCpuset(path, r.CpusetCpus)
}
if r.CpusetMems != "" {
if err := cgroups.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil {
@@ -350,14 +353,20 @@ func cpusetEnsureParent(current string) error {
// cpusetCopyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent
// directory to the current directory if the file's contents are 0
func cpusetCopyIfNeeded(current, parent string) error {
- if currentCpus, currentMems, err := getCpusetSubsystemSettings(current); err != nil {
+ var (
+ err error
+ currentCpus, currentMems string
+ parentCpus, parentMems string
+ )
+
+ if currentCpus, currentMems, err = getCpusetSubsystemSettings(current); err != nil {
ret := fmt.Errorf("failed copy current cgroup setting, %v", err)
if _, err := os.Stat(current); err != nil {
ret = fmt.Errorf("%v, %v", ret, err)
}
return ret
}
- if parentCpus, parentMems, err := getCpusetSubsystemSettings(parent); err != nil {
+ if parentCpus, parentMems, err = getCpusetSubsystemSettings(parent); err != nil {
ret := fmt.Errorf("failed copy parent cgroup setting, %v", err)
if _, err := os.Stat(parent); err != nil {
ret = fmt.Errorf("%v, %v", ret, err)
diff --git a/libcontainer/cgroups/fs/files.go b/libcontainer/cgroups/fs/files.go
index 3315cda..b02743c 100644
--- a/libcontainer/cgroups/fs/files.go
+++ b/libcontainer/cgroups/fs/files.go
@@ -18,27 +18,22 @@ import (
"path/filepath"
)
-type FilesGroup struct {
-}
+type FilesGroup struct {}
func (s *FilesGroup) Name() string {
return "files"
}
-func (s *FilesGroup) Apply(d *cgroupData) error {
- _, err := d.join("files")
- if err != nil && !cgroups.IsNotFound(err) {
- return err
- }
- return nil
+func (s *FilesGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
-func (s *FilesGroup) Set(path string, cgroup *configs.Cgroup) error {
- if cgroup.Resources.FilesLimit != 0 {
+func (s *FilesGroup) Set(path string, r *configs.Resources) error {
+ if r.FilesLimit != 0 {
// "max" is the fallback value.
limit := "max"
- if cgroup.Resources.FilesLimit > 0 {
- limit = strconv.FormatInt(cgroup.Resources.FilesLimit, 10)
+ if r.FilesLimit > 0 {
+ limit = strconv.FormatInt(r.FilesLimit, 10)
}
if err := writeFile(path, "files.limit", limit); err != nil {
@@ -49,10 +44,6 @@ func (s *FilesGroup) Set(path string, cgroup *configs.Cgroup) error {
return nil
}
-func (s *FilesGroup) Remove(d *cgroupData) error {
- return removePath(d.path("files"))
-}
-
func (s *FilesGroup) GetStats(path string, stats *cgroups.Stats) error {
usage, err := getCgroupParamUint(path, "files.usage")
if err != nil {
diff --git a/libcontainer/cgroups/fs/utils.go b/libcontainer/cgroups/fs/utils.go
new file mode 100644
index 0000000..38820a8
--- /dev/null
+++ b/libcontainer/cgroups/fs/utils.go
@@ -0,0 +1,97 @@
+// +build linux
+
+package fs
+
+import (
+ "errors"
+ "os"
+ "fmt"
+ "io/ioutil"
+ "path/filepath"
+ "strconv"
+ "strings"
+)
+
+var (
+ ErrNotValidFormat = errors.New("line is not a valid key value format")
+)
+
+// Saturates negative values at zero and returns a uint64.
+// Due to kernel bugs, some of the memory cgroup stats can be negative.
+func parseUint(s string, base, bitSize int) (uint64, error) {
+ value, err := strconv.ParseUint(s, base, bitSize)
+ if err != nil {
+ intValue, intErr := strconv.ParseInt(s, base, bitSize)
+ // 1. Handle negative values greater than MinInt64 (and)
+ // 2. Handle negative values lesser than MinInt64
+ if intErr == nil && intValue < 0 {
+ return 0, nil
+ } else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 {
+ return 0, nil
+ }
+
+ return value, err
+ }
+
+ return value, nil
+}
+
+// Parses a cgroup param and returns as name, value
+// i.e. "io_service_bytes 1234" will return as io_service_bytes, 1234
+func getCgroupParamKeyValue(t string) (string, uint64, error) {
+ parts := strings.Fields(t)
+ switch len(parts) {
+ case 2:
+ value, err := parseUint(parts[1], 10, 64)
+ if err != nil {
+ return "", 0, fmt.Errorf("unable to convert param value (%q) to uint64: %v", parts[1], err)
+ }
+
+ return parts[0], value, nil
+ default:
+ return "", 0, ErrNotValidFormat
+ }
+}
+
+// Gets a single uint64 value from the specified cgroup file.
+func getCgroupParamUint(cgroupPath, cgroupFile string) (uint64, error) {
+ fileName := filepath.Join(cgroupPath, cgroupFile)
+ contents, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ return 0, err
+ }
+
+ res, err := parseUint(strings.TrimSpace(string(contents)), 10, 64)
+ if err != nil {
+ return res, fmt.Errorf("unable to parse %q as a uint from Cgroup file %q", string(contents), fileName)
+ }
+ return res, nil
+}
+
+// Gets a string value from the specified cgroup file
+func getCgroupParamString(cgroupPath, cgroupFile string) (string, error) {
+ contents, err := ioutil.ReadFile(filepath.Join(cgroupPath, cgroupFile))
+ if err != nil {
+ return "", err
+ }
+
+ return strings.TrimSpace(string(contents)), nil
+}
+
+func writeFile(dir, file, data string) error {
+ // Normally dir should not be empty, one case is that cgroup subsystem
+ // is not mounted, we will get empty dir, and we want it fail here.
+ if dir == "" {
+ return fmt.Errorf("no such directory for %s", file)
+ }
+ if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700); err != nil {
+ ret := fmt.Errorf("failed to write %v to %v: %v", data, file, err)
+ if _, err = os.Stat(dir); err != nil {
+ ret = fmt.Errorf("%v, failed to stat %v, %v", ret, dir, err)
+ }
+
+ return ret
+ }
+ return nil
+}
+
diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
index 4dbe9f4..0bf1729 100644
--- a/libcontainer/rootfs_linux.go
+++ b/libcontainer/rootfs_linux.go
@@ -10,6 +10,7 @@ import (
"path/filepath"
"strconv"
"strings"
+ "syscall"
"time"
securejoin "github.com/cyphar/filepath-securejoin"
diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go
index 99e7003..c288c88 100644
--- a/libcontainer/standard_init_linux.go
+++ b/libcontainer/standard_init_linux.go
@@ -3,11 +3,11 @@ package libcontainer
import (
"errors"
"fmt"
- "io/ioutil"
"os"
"os/exec"
- "path/filepath"
"strconv"
+ "strings"
+ "syscall"
"time"
"github.com/opencontainers/runtime-spec/specs-go"
diff --git a/main.go b/main.go
index e624347..e52a2ea 100644
--- a/main.go
+++ b/main.go
@@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"io"
- "log/syslog"
"os"
"path/filepath"
"runtime"
--
2.30.0