Skip to content

Commit

Permalink
Merge pull request #2499 from kolyshkin/find-cgroup-mountpoint-fastpath
Browse files Browse the repository at this point in the history
cgroupv1/FindCgroupMountpoint: add a fast path
  • Loading branch information
AkihiroSuda authored Aug 4, 2020
2 parents 234d15e + a73ce38 commit f668854
Showing 1 changed file with 54 additions and 3 deletions.
57 changes: 54 additions & 3 deletions libcontainer/cgroups/v1_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ import (
"os"
"path/filepath"
"strings"
"syscall"

securejoin "github.com/cyphar/filepath-securejoin"
"golang.org/x/sys/unix"
)

// Code in this source file are specific to cgroup v1,
// and must not be used from any cgroup v2 code.

const (
CgroupNamePrefix = "name="
defaultPrefix = "/sys/fs/cgroup"
)

var (
Expand Down Expand Up @@ -43,11 +48,59 @@ func IsNotFound(err error) bool {
return ok
}

func tryDefaultPath(cgroupPath, subsystem string) string {
if !strings.HasPrefix(defaultPrefix, cgroupPath) {
return ""
}

// remove possible prefix
subsystem = strings.TrimPrefix(subsystem, CgroupNamePrefix)

// Make sure we're still under defaultPrefix, and resolve
// a possible symlink (like cpu -> cpu,cpuacct).
path, err := securejoin.SecureJoin(defaultPrefix, subsystem)
if err != nil {
return ""
}

// (1) path should be a directory.
st, err := os.Lstat(path)
if err != nil || !st.IsDir() {
return ""
}

// (2) path should be a mount point.
pst, err := os.Lstat(filepath.Dir(path))
if err != nil {
return ""
}

if st.Sys().(*syscall.Stat_t).Dev == pst.Sys().(*syscall.Stat_t).Dev {
// parent dir has the same dev -- path is not a mount point
return ""
}

// (3) path should have 'cgroup' fs type.
fst := unix.Statfs_t{}
err = unix.Statfs(path, &fst)
if err != nil || fst.Type != unix.CGROUP_SUPER_MAGIC {
return ""
}

return path
}

// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
if IsCgroup2UnifiedMode() {
return "", errUnified
}

// Avoid parsing mountinfo by trying the default path first, if possible.
if path := tryDefaultPath(cgroupPath, subsystem); path != "" {
return path, nil
}

mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem)
return mnt, err
}
Expand All @@ -57,9 +110,7 @@ func FindCgroupMountpointAndRoot(cgroupPath, subsystem string) (string, string,
return "", "", errUnified
}

// 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.
// Avoid parsing mountinfo by checking if subsystem is valid/available.
if !isSubsystemAvailable(subsystem) {
return "", "", NewNotFoundError(subsystem)
}
Expand Down

0 comments on commit f668854

Please sign in to comment.