Skip to content

Commit

Permalink
support cgroup v1 mounted with noprefix
Browse files Browse the repository at this point in the history
Signed-off-by: Tomasz Duda <[email protected]>
  • Loading branch information
tomaszduda23 committed Nov 6, 2024
1 parent d9eecde commit 9e8dc7b
Showing 1 changed file with 56 additions and 17 deletions.
73 changes: 56 additions & 17 deletions libcontainer/cgroups/fs/cpuset.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"

"golang.org/x/sys/unix"

Expand All @@ -14,6 +15,44 @@ import (
"github.com/opencontainers/runc/libcontainer/configs"
)

var (
cpusetLock sync.Mutex
cpusetNoPrefix bool
cpusetFastPath bool
)

func getCpusetFile(path string, name string) string {
cpusetLock.Lock()
defer cpusetLock.Unlock()

// only allowed cgroup to mount with no prefix is v1 cpuset
// https://github.com/torvalds/linux/blob/2e1b3cc9d7f790145a80cb705b168f05dab65df2/kernel/cgroup/cgroup-v1.c#L1070
// it cannot be mounted with and without prefix at the same time
// it happens to be used on Android.

if !cpusetFastPath {
fd, err := cgroups.OpenFile(path, "cpuset."+name, unix.O_RDONLY)
if err == nil {
fd.Close()
// use fast path only if we can access one type of mount for cpuset already
cpusetFastPath = true
} else {
fd, err = cgroups.OpenFile(path, name, unix.O_RDONLY)
if err == nil {
fd.Close()
cpusetNoPrefix = true
cpusetFastPath = true
}
}
}

if cpusetNoPrefix {
return name
}

return "cpuset." + name
}

type CpusetGroup struct{}

func (s *CpusetGroup) Name() string {
Expand All @@ -26,12 +65,12 @@ func (s *CpusetGroup) Apply(path string, r *configs.Resources, pid int) error {

func (s *CpusetGroup) Set(path string, r *configs.Resources) error {
if r.CpusetCpus != "" {
if err := cgroups.WriteFile(path, "cpuset.cpus", r.CpusetCpus); err != nil {
if err := cgroups.WriteFile(path, getCpusetFile(path, "cpus"), r.CpusetCpus); err != nil {
return err
}
}
if r.CpusetMems != "" {
if err := cgroups.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil {
if err := cgroups.WriteFile(path, getCpusetFile(path, "mems"), r.CpusetMems); err != nil {
return err
}
}
Expand Down Expand Up @@ -83,57 +122,57 @@ func getCpusetStat(path string, file string) ([]uint16, error) {
func (s *CpusetGroup) GetStats(path string, stats *cgroups.Stats) error {
var err error

stats.CPUSetStats.CPUs, err = getCpusetStat(path, "cpuset.cpus")
stats.CPUSetStats.CPUs, err = getCpusetStat(path, getCpusetFile(path, "cpus"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.CPUExclusive, err = fscommon.GetCgroupParamUint(path, "cpuset.cpu_exclusive")
stats.CPUSetStats.CPUExclusive, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "cpu_exclusive"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.Mems, err = getCpusetStat(path, "cpuset.mems")
stats.CPUSetStats.Mems, err = getCpusetStat(path, getCpusetFile(path, "mems"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.MemHardwall, err = fscommon.GetCgroupParamUint(path, "cpuset.mem_hardwall")
stats.CPUSetStats.MemHardwall, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "mem_hardwall"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.MemExclusive, err = fscommon.GetCgroupParamUint(path, "cpuset.mem_exclusive")
stats.CPUSetStats.MemExclusive, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "mem_exclusive"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.MemoryMigrate, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_migrate")
stats.CPUSetStats.MemoryMigrate, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "memory_migrate"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.MemorySpreadPage, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_spread_page")
stats.CPUSetStats.MemorySpreadPage, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "memory_spread_page"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.MemorySpreadSlab, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_spread_slab")
stats.CPUSetStats.MemorySpreadSlab, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "memory_spread_slab"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.MemoryPressure, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_pressure")
stats.CPUSetStats.MemoryPressure, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "memory_pressure"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.SchedLoadBalance, err = fscommon.GetCgroupParamUint(path, "cpuset.sched_load_balance")
stats.CPUSetStats.SchedLoadBalance, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "sched_load_balance"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}

stats.CPUSetStats.SchedRelaxDomainLevel, err = fscommon.GetCgroupParamInt(path, "cpuset.sched_relax_domain_level")
stats.CPUSetStats.SchedRelaxDomainLevel, err = fscommon.GetCgroupParamInt(path, getCpusetFile(path, "sched_relax_domain_level"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}
Expand Down Expand Up @@ -172,10 +211,10 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error
}

func getCpusetSubsystemSettings(parent string) (cpus, mems string, err error) {
if cpus, err = cgroups.ReadFile(parent, "cpuset.cpus"); err != nil {
if cpus, err = cgroups.ReadFile(parent, getCpusetFile(parent, "cpus")); err != nil {
return
}
if mems, err = cgroups.ReadFile(parent, "cpuset.mems"); err != nil {
if mems, err = cgroups.ReadFile(parent, getCpusetFile(parent, "mems")); err != nil {
return
}
return cpus, mems, nil
Expand Down Expand Up @@ -221,12 +260,12 @@ func cpusetCopyIfNeeded(current, parent string) error {
}

if isEmptyCpuset(currentCpus) {
if err := cgroups.WriteFile(current, "cpuset.cpus", parentCpus); err != nil {
if err := cgroups.WriteFile(current, getCpusetFile(current, "cpus"), parentCpus); err != nil {
return err
}
}
if isEmptyCpuset(currentMems) {
if err := cgroups.WriteFile(current, "cpuset.mems", parentMems); err != nil {
if err := cgroups.WriteFile(current, getCpusetFile(current, "mems"), parentMems); err != nil {
return err
}
}
Expand Down

0 comments on commit 9e8dc7b

Please sign in to comment.