runc/patch/0022-runc-cgroup-apply-method-modify.patch
2023-07-28 09:46:10 +08:00

262 lines
8.0 KiB
Diff

From 6477190927cec5e20393c303bf7a4049539273bf Mon Sep 17 00:00:00 2001
From: zhongjiawei <zhongjiawei1@huawei.com>
Date: Wed, 26 Jul 2023 15:25:25 +0800
Subject: [PATCH] runc:cgroup apply method modify
---
libcontainer/cgroups/fs/cpuset.go | 12 +++-
libcontainer/cgroups/fs/files.go | 27 +++-----
libcontainer/cgroups/fs/utils.go | 97 +++++++++++++++++++++++++++++
libcontainer/rootfs_linux.go | 1 +
libcontainer/standard_init_linux.go | 6 +-
5 files changed, 120 insertions(+), 23 deletions(-)
create mode 100644 libcontainer/cgroups/fs/utils.go
diff --git a/libcontainer/cgroups/fs/cpuset.go b/libcontainer/cgroups/fs/cpuset.go
index ef9164b..01388f7 100644
--- a/libcontainer/cgroups/fs/cpuset.go
+++ b/libcontainer/cgroups/fs/cpuset.go
@@ -1,6 +1,7 @@
package fs
import (
+ "fmt"
"errors"
"io/ioutil"
"os"
@@ -145,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 {
@@ -352,14 +353,19 @@ 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..9dcc54b 100644
--- a/libcontainer/cgroups/fs/files.go
+++ b/libcontainer/cgroups/fs/files.go
@@ -13,34 +13,29 @@ import (
"fmt"
"strconv"
+ "path/filepath"
+
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
- "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 {
return err
}
@@ -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 e7de071..499d753 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 542edba..cd962c8 100644
--- a/libcontainer/standard_init_linux.go
+++ b/libcontainer/standard_init_linux.go
@@ -6,6 +6,8 @@ import (
"os"
"os/exec"
"strconv"
+ "strings"
+ "syscall"
"time"
"github.com/opencontainers/runtime-spec/specs-go"
@@ -260,11 +262,11 @@ func (l *linuxStandardInit) Init() error {
}()
select {
- case chErr := <- ch:
+ case chErr := <-ch:
if chErr != nil {
return chErr
}
- case <- time.After(120 * time.Second):
+ case <-time.After(120 * time.Second):
return fmt.Errorf("wait for the fifo to be opened on the other side timeout ")
}
// Close the O_PATH fifofd fd before exec because the kernel resets
--
2.33.0