262 lines
8.0 KiB
Diff
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
|
|
|