diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2019-07-08 10:16:13 +0200 |
---|---|---|
committer | Giuseppe Scrivano <gscrivan@redhat.com> | 2019-07-10 10:54:35 +0200 |
commit | bbe03e61a375416180432fbd9d00d23a7c2a4714 (patch) | |
tree | 959eb8a850da9f9ba10d5e0cfb0fe213d20c4fdb | |
parent | 551edd287e7cb31327d18c3ebc0d2e6b1160c235 (diff) | |
download | podman-bbe03e61a375416180432fbd9d00d23a7c2a4714.tar.gz podman-bbe03e61a375416180432fbd9d00d23a7c2a4714.tar.bz2 podman-bbe03e61a375416180432fbd9d00d23a7c2a4714.zip |
cgroups: support creating cgroupsv2 paths
drop the limitation of not supporting creating new cgroups v2 paths.
Every controller enabled /sys/fs/cgroup will be propagated down to the
created path. This won't work for rootless cgroupsv2, but it is not
an issue for now, as this code is used only by CRI-O.
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r-- | pkg/cgroups/blkio.go | 2 | ||||
-rw-r--r-- | pkg/cgroups/cgroups.go | 52 | ||||
-rw-r--r-- | pkg/cgroups/cpu.go | 2 | ||||
-rw-r--r-- | pkg/cgroups/cpuset.go | 19 | ||||
-rw-r--r-- | pkg/cgroups/memory.go | 2 | ||||
-rw-r--r-- | pkg/cgroups/pids.go | 3 |
6 files changed, 66 insertions, 14 deletions
diff --git a/pkg/cgroups/blkio.go b/pkg/cgroups/blkio.go index ca9107d97..9c2a811d9 100644 --- a/pkg/cgroups/blkio.go +++ b/pkg/cgroups/blkio.go @@ -30,7 +30,7 @@ func (c *blkioHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error // Create the cgroup func (c *blkioHandler) Create(ctr *CgroupControl) (bool, error) { if ctr.cgroup2 { - return false, fmt.Errorf("io create not implemented for cgroup v2") + return false, nil } return ctr.createCgroupDirectory(Blkio) } diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go index d6c19212b..1dad45d7f 100644 --- a/pkg/cgroups/cgroups.go +++ b/pkg/cgroups/cgroups.go @@ -149,6 +149,51 @@ func (c *CgroupControl) getCgroupv1Path(name string) string { return filepath.Join(cgroupRoot, name, c.path) } +// createCgroupv2Path creates the cgroupv2 path and enables all the available controllers +func createCgroupv2Path(path string) (Err error) { + content, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers") + if err != nil { + return errors.Wrapf(err, "read /sys/fs/cgroup/cgroup.controllers") + } + if !filepath.HasPrefix(path, "/sys/fs/cgroup") { + return fmt.Errorf("invalid cgroup path %s", path) + } + + res := "" + for i, c := range strings.Split(strings.TrimSpace(string(content)), " ") { + if i == 0 { + res = fmt.Sprintf("+%s", c) + } else { + res = res + fmt.Sprintf(" +%s", c) + } + } + resByte := []byte(res) + + current := "/sys/fs" + elements := strings.Split(path, "/") + for i, e := range elements[3:] { + current = filepath.Join(current, e) + if i > 0 { + if err := os.Mkdir(current, 0755); err != nil { + if !os.IsExist(err) { + return errors.Wrapf(err, "mkdir %s", path) + } + } else { + // If the directory was created, be sure it is not left around on errors. + defer func() { + if Err != nil { + os.Remove(current) + } + }() + } + } + if err := ioutil.WriteFile(filepath.Join(current, "cgroup.subtree_control"), resByte, 0755); err != nil { + return errors.Wrapf(err, "write %s", filepath.Join(current, "cgroup.subtree_control")) + } + } + return nil +} + // initialize initializes the specified hierarchy func (c *CgroupControl) initialize() (err error) { createdSoFar := map[string]controllerHandler{} @@ -161,6 +206,11 @@ func (c *CgroupControl) initialize() (err error) { } } }() + if c.cgroup2 { + if err := createCgroupv2Path(filepath.Join(cgroupRoot, c.path)); err != nil { + return errors.Wrapf(err, "error creating cgroup path %s", c.path) + } + } for name, handler := range handlers { created, err := handler.Create(c) if err != nil { @@ -341,7 +391,7 @@ func (c *CgroupControl) AddPid(pid int) error { pidString := []byte(fmt.Sprintf("%d\n", pid)) if c.cgroup2 { - p := filepath.Join(cgroupRoot, c.path, "tasks") + p := filepath.Join(cgroupRoot, c.path, "cgroup.procs") if err := ioutil.WriteFile(p, pidString, 0644); err != nil { return errors.Wrapf(err, "write %s", p) } diff --git a/pkg/cgroups/cpu.go b/pkg/cgroups/cpu.go index 8640d490e..c9325946b 100644 --- a/pkg/cgroups/cpu.go +++ b/pkg/cgroups/cpu.go @@ -61,7 +61,7 @@ func (c *cpuHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error { // Create the cgroup func (c *cpuHandler) Create(ctr *CgroupControl) (bool, error) { if ctr.cgroup2 { - return false, fmt.Errorf("cpu create not implemented for cgroup v2") + return false, nil } return ctr.createCgroupDirectory(CPU) } diff --git a/pkg/cgroups/cpuset.go b/pkg/cgroups/cpuset.go index 9aef493c9..25d2f7f76 100644 --- a/pkg/cgroups/cpuset.go +++ b/pkg/cgroups/cpuset.go @@ -14,19 +14,23 @@ import ( type cpusetHandler struct { } -func cpusetCopyFileFromParent(dir, file string) ([]byte, error) { +func cpusetCopyFileFromParent(dir, file string, cgroupv2 bool) ([]byte, error) { if dir == cgroupRoot { return nil, fmt.Errorf("could not find parent to initialize cpuset %s", file) } path := filepath.Join(dir, file) - data, err := ioutil.ReadFile(path) + parentPath := path + if cgroupv2 { + parentPath = fmt.Sprintf("%s.effective", parentPath) + } + data, err := ioutil.ReadFile(parentPath) if err != nil { return nil, errors.Wrapf(err, "open %s", path) } if len(strings.Trim(string(data), "\n")) != 0 { return data, nil } - data, err = cpusetCopyFileFromParent(filepath.Dir(dir), file) + data, err = cpusetCopyFileFromParent(filepath.Dir(dir), file, cgroupv2) if err != nil { return nil, err } @@ -36,9 +40,9 @@ func cpusetCopyFileFromParent(dir, file string) ([]byte, error) { return data, nil } -func cpusetCopyFromParent(path string) error { +func cpusetCopyFromParent(path string, cgroupv2 bool) error { for _, file := range []string{"cpuset.cpus", "cpuset.mems"} { - if _, err := cpusetCopyFileFromParent(path, file); err != nil { + if _, err := cpusetCopyFileFromParent(path, file, cgroupv2); err != nil { return err } } @@ -60,14 +64,15 @@ func (c *cpusetHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) erro // Create the cgroup func (c *cpusetHandler) Create(ctr *CgroupControl) (bool, error) { if ctr.cgroup2 { - return false, fmt.Errorf("cpuset create not implemented for cgroup v2") + path := filepath.Join(cgroupRoot, ctr.path) + return true, cpusetCopyFromParent(path, true) } created, err := ctr.createCgroupDirectory(CPUset) if !created || err != nil { return created, err } - return true, cpusetCopyFromParent(ctr.getCgroupv1Path(CPUset)) + return true, cpusetCopyFromParent(ctr.getCgroupv1Path(CPUset), false) } // Destroy the cgroup diff --git a/pkg/cgroups/memory.go b/pkg/cgroups/memory.go index 0505eac40..80e88d17c 100644 --- a/pkg/cgroups/memory.go +++ b/pkg/cgroups/memory.go @@ -26,7 +26,7 @@ func (c *memHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error { // Create the cgroup func (c *memHandler) Create(ctr *CgroupControl) (bool, error) { if ctr.cgroup2 { - return false, fmt.Errorf("memory create not implemented for cgroup v2") + return false, nil } return ctr.createCgroupDirectory(Memory) } diff --git a/pkg/cgroups/pids.go b/pkg/cgroups/pids.go index c90dc1c02..ffbde100d 100644 --- a/pkg/cgroups/pids.go +++ b/pkg/cgroups/pids.go @@ -35,9 +35,6 @@ func (c *pidHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error { // Create the cgroup func (c *pidHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, fmt.Errorf("pid create not implemented for cgroup v2") - } return ctr.createCgroupDirectory(Pids) } |