Use array instead of map for cgroup subsystems

Also add cpuset as the first in the list to address issues setting the
pid in any cgroup before the cpuset is populated.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2015-10-15 15:24:53 -07:00
parent 02fdc70837
commit 2554f49d5e
1 changed files with 31 additions and 22 deletions

View File

@ -16,23 +16,34 @@ import (
) )
var ( var (
subsystems = map[string]subsystem{ subsystems = subsystemSet{
"devices": &DevicesGroup{}, &CpusetGroup{},
"memory": &MemoryGroup{}, &DevicesGroup{},
"cpu": &CpuGroup{}, &MemoryGroup{},
"cpuset": &CpusetGroup{}, &CpuGroup{},
"cpuacct": &CpuacctGroup{}, &CpuacctGroup{},
"blkio": &BlkioGroup{}, &BlkioGroup{},
"hugetlb": &HugetlbGroup{}, &HugetlbGroup{},
"net_cls": &NetClsGroup{}, &NetClsGroup{},
"net_prio": &NetPrioGroup{}, &NetPrioGroup{},
"perf_event": &PerfEventGroup{}, &PerfEventGroup{},
"freezer": &FreezerGroup{}, &FreezerGroup{},
} }
CgroupProcesses = "cgroup.procs" CgroupProcesses = "cgroup.procs"
HugePageSizes, _ = cgroups.GetHugePageSize() HugePageSizes, _ = cgroups.GetHugePageSize()
) )
type subsystemSet []subsystem
func (s subsystemSet) Get(name string) subsystem {
for _, ss := range s {
if ss.Name() == name {
return ss
}
}
return nil
}
type subsystem interface { type subsystem interface {
// Name returns the name of the subsystem. // Name returns the name of the subsystem.
Name() string Name() string
@ -103,21 +114,21 @@ func (m *Manager) Apply(pid int) (err error) {
cgroups.RemovePaths(paths) cgroups.RemovePaths(paths)
} }
}() }()
for name, sys := range subsystems { for _, sys := range subsystems {
if err := sys.Apply(d); err != nil { if err := sys.Apply(d); err != nil {
return err return err
} }
// TODO: Apply should, ideally, be reentrant or be broken up into a separate // TODO: Apply should, ideally, be reentrant or be broken up into a separate
// create and join phase so that the cgroup hierarchy for a container can be // create and join phase so that the cgroup hierarchy for a container can be
// created then join consists of writing the process pids to cgroup.procs // created then join consists of writing the process pids to cgroup.procs
p, err := d.path(name) p, err := d.path(sys.Name())
if err != nil { if err != nil {
if cgroups.IsNotFound(err) { if cgroups.IsNotFound(err) {
continue continue
} }
return err return err
} }
paths[name] = p paths[sys.Name()] = p
} }
m.Paths = paths m.Paths = paths
@ -152,22 +163,21 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
defer m.mu.Unlock() defer m.mu.Unlock()
stats := cgroups.NewStats() stats := cgroups.NewStats()
for name, path := range m.Paths { for name, path := range m.Paths {
sys, ok := subsystems[name] sys := subsystems.Get(name)
if !ok || !cgroups.PathExists(path) { if sys == nil || !cgroups.PathExists(path) {
continue continue
} }
if err := sys.GetStats(path, stats); err != nil { if err := sys.GetStats(path, stats); err != nil {
return nil, err return nil, err
} }
} }
return stats, nil return stats, nil
} }
func (m *Manager) Set(container *configs.Config) error { func (m *Manager) Set(container *configs.Config) error {
for name, path := range m.Paths { for name, path := range m.Paths {
sys, ok := subsystems[name] sys := subsystems.Get(name)
if !ok || !cgroups.PathExists(path) { if sys == nil || !cgroups.PathExists(path) {
continue continue
} }
if err := sys.Set(path, container.Cgroups); err != nil { if err := sys.Set(path, container.Cgroups); err != nil {
@ -194,13 +204,12 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
prevState := m.Cgroups.Freezer prevState := m.Cgroups.Freezer
m.Cgroups.Freezer = state m.Cgroups.Freezer = state
freezer := subsystems["freezer"] freezer := subsystems.Get("freezer")
err = freezer.Set(dir, m.Cgroups) err = freezer.Set(dir, m.Cgroups)
if err != nil { if err != nil {
m.Cgroups.Freezer = prevState m.Cgroups.Freezer = prevState
return err return err
} }
return nil return nil
} }