diff --git a/fs/fs.go b/fs/fs.go index d14179d..e5efeaa 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -14,33 +14,37 @@ import ( "github.com/opencontainers/cgroups/fscommon" ) -var subsystems = []subsystem{ - &CpusetGroup{}, - &DevicesGroup{}, - &MemoryGroup{}, - &CpuGroup{}, - &CpuacctGroup{}, - &PidsGroup{}, - &BlkioGroup{}, - &HugetlbGroup{}, - &NetClsGroup{}, - &NetPrioGroup{}, - &PerfEventGroup{}, - &FreezerGroup{}, - &RdmaGroup{}, - &NameGroup{GroupName: "name=systemd", Join: true}, - &NameGroup{GroupName: "misc", Join: true, GroupID: cgroups.Misc}, -} - -var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist") +// subsystems returns the list of supported subsystems. It is initialized +// lazily to avoid doing any filesystem access during package initialization. +var subsystems = sync.OnceValue(func() []subsystem { + ss := []subsystem{ + &CpusetGroup{}, + &DevicesGroup{}, + &MemoryGroup{}, + &CpuGroup{}, + &CpuacctGroup{}, + &PidsGroup{}, + &BlkioGroup{}, + &HugetlbGroup{}, + &NetClsGroup{}, + &NetPrioGroup{}, + &PerfEventGroup{}, + &FreezerGroup{}, + &RdmaGroup{}, + &NameGroup{GroupName: "name=systemd", Join: true}, + &NameGroup{GroupName: "misc", Join: true, GroupID: cgroups.Misc}, + } -func init() { // If using cgroups-hybrid mode then add a "" controller indicating // it should join the cgroups v2. if cgroups.IsCgroup2HybridMode() { - subsystems = append(subsystems, &NameGroup{GroupName: "", Join: true}) + ss = append(ss, &NameGroup{GroupName: "", Join: true}) } -} + + return ss +}) + +var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist") type subsystem interface { // Name returns the name of the subsystem. @@ -114,7 +118,7 @@ func (m *Manager) Apply(pid int) (retErr error) { c := m.cgroups - for _, sys := range subsystems { + for _, sys := range subsystems() { name := sys.Name() p, ok := m.paths[name] if !ok { @@ -199,7 +203,7 @@ func (m *Manager) Stats(opts *cgroups.StatsOptions) (*cgroups.Stats, error) { } stats := cgroups.NewStats() - for _, sys := range subsystems { + for _, sys := range subsystems() { path := m.paths[sys.Name()] if path == "" { continue @@ -228,7 +232,7 @@ func (m *Manager) Set(r *cgroups.Resources) error { m.mu.Lock() defer m.mu.Unlock() - for _, sys := range subsystems { + for _, sys := range subsystems() { path := m.paths[sys.Name()] if err := sys.Set(path, r); err != nil { // When rootless is true, errors from the device subsystem diff --git a/fs/paths.go b/fs/paths.go index edbe041..68768a7 100644 --- a/fs/paths.go +++ b/fs/paths.go @@ -32,7 +32,7 @@ func initPaths(cg *cgroups.Cgroup) (map[string]string, error) { } paths := make(map[string]string) - for _, sys := range subsystems { + for _, sys := range subsystems() { name := sys.Name() path, err := subsysPath(root, inner, name) if err != nil {