Skip to content

Commit

Permalink
cgroupv1/systemd: rework Apply/joinCgroups
Browse files Browse the repository at this point in the history
We call joinCgroups() from Apply, and in there we iterate through the
list of subsystems, calling getSubsystemPath() for each. This is
expensive, since every getSubsystemPath() involves parsing mountinfo.

At the end of Apply(), we iterate through the list of subsystems to fill
the m.paths, again calling getSubsystemPath() for every subsystem.

As a result, we parse mountinfo about 20 times here.

Let's find the paths first and reuse m.paths in joinCgroups().

Signed-off-by: Kir Kolyshkin <[email protected]>
  • Loading branch information
kolyshkin committed May 30, 2020
1 parent da089c0 commit c6ce3be
Showing 1 changed file with 20 additions and 36 deletions.
56 changes: 20 additions & 36 deletions libcontainer/cgroups/systemd/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,16 @@ func (m *legacyManager) Apply(pid int) error {
return err
}

if err := joinCgroups(c, pid); err != nil {
return err
}

paths := make(map[string]string)
for _, s := range legacySubsystems {
subsystemPath, err := getSubsystemPath(m.cgroups, s.Name())
if err != nil {
// Even if it's `not found` error, we'll return err
// because devices cgroup is hard requirement for
// container security.
if s.Name() == "devices" {
return err
}
// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
if cgroupv1.IsNotFound(err) {
continue
Expand All @@ -221,6 +223,11 @@ func (m *legacyManager) Apply(pid int) error {
paths[s.Name()] = subsystemPath
}
m.paths = paths

if err := m.joinCgroups(pid); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -249,48 +256,25 @@ func (m *legacyManager) Path(subsys string) string {
return m.paths[subsys]
}

func join(c *configs.Cgroup, subsystem string, pid int) (string, error) {
path, err := getSubsystemPath(c, subsystem)
if err != nil {
return "", err
}

if err := os.MkdirAll(path, 0755); err != nil {
return "", err
}
if err := cgroups.WriteCgroupProc(path, pid); err != nil {
return "", err
}
return path, nil
}

func joinCgroups(c *configs.Cgroup, pid int) error {
func (m *legacyManager) joinCgroups(pid int) error {
for _, sys := range legacySubsystems {
name := sys.Name()
switch name {
case "name=systemd":
// let systemd handle this
case "cpuset":
path, err := getSubsystemPath(c, name)
if err != nil && !cgroupv1.IsNotFound(err) {
return err
}
s := &fs.CpusetGroup{}
if err := s.ApplyDir(path, c, pid); err != nil {
return err
if path, ok := m.paths[name]; ok {
s := &fs.CpusetGroup{}
if err := s.ApplyDir(path, m.cgroups, pid); err != nil {
return err
}
}
default:
_, err := join(c, name, pid)
if err != nil {
// Even if it's `not found` error, we'll return err
// because devices cgroup is hard requirement for
// container security.
if name == "devices" {
if path, ok := m.paths[name]; ok {
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
// For other subsystems, omit the `not found` error
// because they are optional.
if !cgroupv1.IsNotFound(err) {
if err := cgroups.WriteCgroupProc(path, pid); err != nil {
return err
}
}
Expand Down

0 comments on commit c6ce3be

Please sign in to comment.