From f13f53d6e1e52cff83168814a96c376178360ea3 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 10 Feb 2021 15:03:45 +0100 Subject: [PATCH 1/4] utils: skip empty lines Signed-off-by: Giuseppe Scrivano (cherry picked from commit f4fd25a005ae00afe7574bd4eb9a428a6b5c81dd) --- utils/utils_supported.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/utils_supported.go b/utils/utils_supported.go index 6f517dc72e..dfa0b486ad 100644 --- a/utils/utils_supported.go +++ b/utils/utils_supported.go @@ -183,6 +183,9 @@ func moveUnderCgroup(cgroup, subtree string, processes []uint32) error { return err } for _, pid := range bytes.Split(processesData, []byte("\n")) { + if len(pid) == 0 { + continue + } if _, err := f.Write(pid); err != nil { logrus.Warnf("Cannot move process %s to cgroup %q", string(pid), newCgroup) } From 5bae803757e008a959790bc4489c71fe446edb7c Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 10 Feb 2021 19:33:34 +0100 Subject: [PATCH 2/4] utils: ignore unified on cgroupv1 if not present Signed-off-by: Giuseppe Scrivano (cherry picked from commit 9196a5ce36a559cc0d10230194f93a61b40e870a) --- utils/utils_supported.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/utils/utils_supported.go b/utils/utils_supported.go index dfa0b486ad..9a1c82ee6b 100644 --- a/utils/utils_supported.go +++ b/utils/utils_supported.go @@ -150,6 +150,11 @@ func moveUnderCgroup(cgroup, subtree string, processes []uint32) error { // If it is not using unified mode, the cgroup v2 hierarchy is // usually mounted under /sys/fs/cgroup/unified cgroupRoot = filepath.Join(cgroupRoot, "unified") + + // Ignore the unified mount if it doesn't exist + if _, err := os.Stat(cgroupRoot); err != nil && os.IsNotExist(err) { + continue + } } else if parts[1] != "" { // Assume the controller is mounted at /sys/fs/cgroup/$CONTROLLER. controller := strings.TrimPrefix(parts[1], "name=") From 66dc8355df0904a6ef1e3abe6808d95348c07d93 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 10 Feb 2021 18:27:04 +0100 Subject: [PATCH 3/4] utils: create parent cgroups Signed-off-by: Giuseppe Scrivano (cherry picked from commit 1b5f3ed24d367cc30432b8a260d1e9465b979c2b) --- utils/utils_supported.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/utils_supported.go b/utils/utils_supported.go index 9a1c82ee6b..7a0417c6c2 100644 --- a/utils/utils_supported.go +++ b/utils/utils_supported.go @@ -166,7 +166,7 @@ func moveUnderCgroup(cgroup, subtree string, processes []uint32) error { parentCgroup = parts[2] } newCgroup := filepath.Join(cgroupRoot, parentCgroup, subtree) - if err := os.Mkdir(newCgroup, 0755); err != nil && !os.IsExist(err) { + if err := os.MkdirAll(newCgroup, 0755); err != nil && !os.IsExist(err) { return err } From f74a195e5e90f7bae51fc160c168c0233835ef08 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 10 Feb 2021 14:46:08 +0100 Subject: [PATCH 4/4] utils: takes the longest path on cgroup v1 now getCgroupProcess takes the longest path on cgroup v1, instead of complaining if the paths are different. This should help when --cgroups=split is used on cgroup v1 and the process cgroups look like: $ cat /proc/self/cgroup 11:pids:/user.slice/user-0.slice/session-4.scope 10:blkio:/ 9:cpuset:/ 8:devices:/user.slice 7:freezer:/ 6:memory:/user.slice/user-0.slice/session-4.scope 5:net_cls,net_prio:/ 4:hugetlb:/ 3:cpu,cpuacct:/ 2:perf_event:/ Signed-off-by: Giuseppe Scrivano (cherry picked from commit 660a06f2f79fc1edf68e286ee452ceb9dcd5e03a) --- test/e2e/common_test.go | 7 +++++++ test/e2e/run_test.go | 31 +++++++++++++++++++++++++++++++ utils/utils_supported.go | 11 ++--------- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index a870117d93..8a452f3403 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -600,6 +600,13 @@ func SkipIfNotRootless(reason string) { } } +func SkipIfNotSystemd(manager, reason string) { + checkReason(reason) + if manager != "systemd" { + ginkgo.Skip("[notSystemd]: " + reason) + } +} + func SkipIfNotFedora() { info := GetHostDistributionInfo() if info.Distribution != "fedora" { diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 19060ecdc4..7d367cccf5 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1185,6 +1185,37 @@ USER mail` Expect(found).To(BeTrue()) }) + It("podman run with cgroups=split", func() { + SkipIfNotSystemd(podmanTest.CgroupManager, "do not test --cgroups=split if not running on systemd") + SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users") + SkipIfRemote("--cgroups=split cannot be used in remote mode") + + container := podmanTest.Podman([]string{"run", "--rm", "--cgroups=split", ALPINE, "cat", "/proc/self/cgroup"}) + container.WaitWithDefaultTimeout() + Expect(container.ExitCode()).To(Equal(0)) + lines := container.OutputToStringArray() + + cgroup := "" + for _, line := range lines { + parts := strings.SplitN(line, ":", 3) + if !CGROUPSV2 { + // ignore unified on cgroup v1 + // both runc and crun do not set it. + if parts[1] == "" { + continue + } + } + if parts[2] == "/" { + continue + } + if cgroup == "" { + cgroup = parts[2] + continue + } + Expect(cgroup).To(Equal(parts[2])) + } + }) + It("podman run with cgroups=disabled runs without cgroups", func() { SkipIfRootless("FIXME: I believe this should work but need to fix this test") SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users") diff --git a/utils/utils_supported.go b/utils/utils_supported.go index 7a0417c6c2..73313cf5ee 100644 --- a/utils/utils_supported.go +++ b/utils/utils_supported.go @@ -81,16 +81,9 @@ func getCgroupProcess(procFile string) (string, error) { cgroup = line[3:] break } - // root cgroup, skip it - if parts[2] == "/" { - continue - } - // The process must have the same cgroup path for all controllers - // The OCI runtime spec file allow us to specify only one path. - if cgroup != "/" && cgroup != parts[2] { - return "", errors.Errorf("cgroup configuration not supported, the process is in two different cgroups") + if len(parts[2]) > len(cgroup) { + cgroup = parts[2] } - cgroup = parts[2] } if cgroup == "/" { return "", errors.Errorf("could not find cgroup mount in %q", procFile)