Merge pull request #1872 from masters-of-cats/better-find-cgroup-mountpoint

Respect container's cgroup path
This commit is contained in:
Michael Crosby 2018-11-16 14:06:54 -05:00 committed by GitHub
commit 76520a4bf0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 22 deletions

View File

@ -317,7 +317,7 @@ func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {
}
func (raw *cgroupData) path(subsystem string) (string, error) {
mnt, err := cgroups.FindCgroupMountpoint(subsystem)
mnt, err := cgroups.FindCgroupMountpoint(raw.root, subsystem)
// If we didn't mount the subsystem, there is no point we make the path.
if err != nil {
return "", err

View File

@ -470,7 +470,7 @@ func ExpandSlice(slice string) (string, error) {
}
func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
mountpoint, err := cgroups.FindCgroupMountpoint(subsystem)
mountpoint, err := cgroups.FindCgroupMountpoint(c.Path, subsystem)
if err != nil {
return "", err
}

View File

@ -22,31 +22,41 @@ const (
)
// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
func FindCgroupMountpoint(subsystem string) (string, error) {
mnt, _, err := FindCgroupMountpointAndRoot(subsystem)
func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem)
return mnt, err
}
func FindCgroupMountpointAndRoot(subsystem string) (string, string, error) {
func FindCgroupMountpointAndRoot(cgroupPath, subsystem string) (string, string, error) {
// We are not using mount.GetMounts() because it's super-inefficient,
// parsing it directly sped up x10 times because of not using Sscanf.
// It was one of two major performance drawbacks in container start.
if !isSubsystemAvailable(subsystem) {
return "", "", NewNotFoundError(subsystem)
}
f, err := os.Open("/proc/self/mountinfo")
if err != nil {
return "", "", err
}
defer f.Close()
scanner := bufio.NewScanner(f)
return findCgroupMountpointAndRootFromReader(f, cgroupPath, subsystem)
}
func findCgroupMountpointAndRootFromReader(reader io.Reader, cgroupPath, subsystem string) (string, string, error) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
txt := scanner.Text()
fields := strings.Split(txt, " ")
for _, opt := range strings.Split(fields[len(fields)-1], ",") {
if opt == subsystem {
return fields[4], fields[3], nil
fields := strings.Fields(txt)
if len(fields) < 5 {
continue
}
if strings.HasPrefix(fields[4], cgroupPath) {
for _, opt := range strings.Split(fields[len(fields)-1], ",") {
if opt == subsystem {
return fields[4], fields[3], nil
}
}
}
}
@ -257,7 +267,7 @@ func GetInitCgroupPath(subsystem string) (string, error) {
}
func getCgroupPathHelper(subsystem, cgroup string) (string, error) {
mnt, root, err := FindCgroupMountpointAndRoot(subsystem)
mnt, root, err := FindCgroupMountpointAndRoot("", subsystem)
if err != nil {
return "", err
}

View File

@ -372,7 +372,8 @@ func TestIgnoreCgroup2Mount(t *testing.T) {
}
}
const fakeMountInfo = ` 18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
func TestGetClosestMountpointAncestor(t *testing.T) {
fakeMountInfo := ` 18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
100 99 1:31 / /foo/bar rw,relatime - fake fake rw,fake
100 99 1:31 / /foo/bar/baz2 rw,relatime - fake fake rw,fake
100 99 1:31 / /foo/bar/baz rw,relatime - fake fake rw,fake
@ -382,21 +383,39 @@ const fakeMountInfo = ` 18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime - sysf
100 99 1:31 / /unrelated rw,relatime - fake fake rw,fake
100 99 1:31 / / rw,relatime - fake fake rw,fake
`
func TestGetClosestMountpointAncestor(t *testing.T) {
testCases := []struct {
input string
mountinfos string
output string
input string
output string
}{
{input: "/foo/bar/baz/a/b/c", mountinfos: fakeMountInfo, output: "/foo/bar/baz"},
{input: "/foo/bar/baz", mountinfos: fakeMountInfo, output: "/foo/bar/baz"},
{input: "/foo/bar/bazza", mountinfos: fakeMountInfo, output: "/foo/bar/bazza"},
{input: "/a/b/c/d", mountinfos: fakeMountInfo, output: "/"},
{input: "/foo/bar/baz/a/b/c", output: "/foo/bar/baz"},
{input: "/foo/bar/baz", output: "/foo/bar/baz"},
{input: "/foo/bar/bazza", output: "/foo/bar/bazza"},
{input: "/a/b/c/d", output: "/"},
}
for _, c := range testCases {
mountpoint := GetClosestMountpointAncestor(c.input, c.mountinfos)
mountpoint := GetClosestMountpointAncestor(c.input, fakeMountInfo)
if mountpoint != c.output {
t.Errorf("expected %s, got %s", c.output, mountpoint)
}
}
}
func TestFindCgroupMountpointAndRoot(t *testing.T) {
fakeMountInfo := `
35 27 0:29 / /foo rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,devices
35 27 0:29 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,devices
`
testCases := []struct {
cgroupPath string
output string
}{
{cgroupPath: "/sys/fs", output: "/sys/fs/cgroup/devices"},
{cgroupPath: "", output: "/foo"},
}
for _, c := range testCases {
mountpoint, _, _ := findCgroupMountpointAndRootFromReader(strings.NewReader(fakeMountInfo), c.cgroupPath, "devices")
if mountpoint != c.output {
t.Errorf("expected %s, got %s", c.output, mountpoint)
}