Skip to content

Commit 8c6f386

Browse files
tomaszduda23kolyshkin
authored andcommitted
support cgroup v1 mounted with noprefix
Signed-off-by: Tomasz Duda <[email protected]>
1 parent 8ed1850 commit 8c6f386

File tree

1 file changed

+54
-17
lines changed

1 file changed

+54
-17
lines changed

libcontainer/cgroups/fs/cpuset.go

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"path/filepath"
77
"strconv"
88
"strings"
9+
"sync"
910

1011
"golang.org/x/sys/unix"
1112

@@ -14,6 +15,42 @@ import (
1415
"github.com/opencontainers/runc/libcontainer/configs"
1516
)
1617

18+
var (
19+
cpusetLock sync.Mutex
20+
cpusetNoPrefix bool
21+
cpusetFastPath bool
22+
)
23+
24+
func getCpusetFile(path string, name string) string {
25+
cpusetLock.Lock()
26+
defer cpusetLock.Unlock()
27+
28+
// Only the v1 cpuset cgroup is allowed to mount with noprefix.
29+
// See kernel source: https://github.com/torvalds/linux/blob/2e1b3cc9d7f790145a80cb705b168f05dab65df2/kernel/cgroup/cgroup-v1.c#L1070
30+
// Cpuset cannot be mounted with and without prefix simultaneously.
31+
// Commonly used in Android environments.
32+
33+
if !cpusetFastPath {
34+
err := unix.Access(filepath.Join(path, "cpuset."+name), unix.F_OK)
35+
if err == nil {
36+
// Use the fast path only if we can access one type of mount for cpuset already
37+
cpusetFastPath = true
38+
} else {
39+
err = unix.Access(filepath.Join(path, name), unix.F_OK)
40+
if err == nil {
41+
cpusetNoPrefix = true
42+
cpusetFastPath = true
43+
}
44+
}
45+
}
46+
47+
if cpusetNoPrefix {
48+
return name
49+
}
50+
51+
return "cpuset." + name
52+
}
53+
1754
type CpusetGroup struct{}
1855

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

2764
func (s *CpusetGroup) Set(path string, r *configs.Resources) error {
2865
if r.CpusetCpus != "" {
29-
if err := cgroups.WriteFile(path, "cpuset.cpus", r.CpusetCpus); err != nil {
66+
if err := cgroups.WriteFile(path, getCpusetFile(path, "cpus"), r.CpusetCpus); err != nil {
3067
return err
3168
}
3269
}
3370
if r.CpusetMems != "" {
34-
if err := cgroups.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil {
71+
if err := cgroups.WriteFile(path, getCpusetFile(path, "mems"), r.CpusetMems); err != nil {
3572
return err
3673
}
3774
}
@@ -83,57 +120,57 @@ func getCpusetStat(path string, file string) ([]uint16, error) {
83120
func (s *CpusetGroup) GetStats(path string, stats *cgroups.Stats) error {
84121
var err error
85122

86-
stats.CPUSetStats.CPUs, err = getCpusetStat(path, "cpuset.cpus")
123+
stats.CPUSetStats.CPUs, err = getCpusetStat(path, getCpusetFile(path, "cpus"))
87124
if err != nil && !errors.Is(err, os.ErrNotExist) {
88125
return err
89126
}
90127

91-
stats.CPUSetStats.CPUExclusive, err = fscommon.GetCgroupParamUint(path, "cpuset.cpu_exclusive")
128+
stats.CPUSetStats.CPUExclusive, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "cpu_exclusive"))
92129
if err != nil && !errors.Is(err, os.ErrNotExist) {
93130
return err
94131
}
95132

96-
stats.CPUSetStats.Mems, err = getCpusetStat(path, "cpuset.mems")
133+
stats.CPUSetStats.Mems, err = getCpusetStat(path, getCpusetFile(path, "mems"))
97134
if err != nil && !errors.Is(err, os.ErrNotExist) {
98135
return err
99136
}
100137

101-
stats.CPUSetStats.MemHardwall, err = fscommon.GetCgroupParamUint(path, "cpuset.mem_hardwall")
138+
stats.CPUSetStats.MemHardwall, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "mem_hardwall"))
102139
if err != nil && !errors.Is(err, os.ErrNotExist) {
103140
return err
104141
}
105142

106-
stats.CPUSetStats.MemExclusive, err = fscommon.GetCgroupParamUint(path, "cpuset.mem_exclusive")
143+
stats.CPUSetStats.MemExclusive, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "mem_exclusive"))
107144
if err != nil && !errors.Is(err, os.ErrNotExist) {
108145
return err
109146
}
110147

111-
stats.CPUSetStats.MemoryMigrate, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_migrate")
148+
stats.CPUSetStats.MemoryMigrate, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "memory_migrate"))
112149
if err != nil && !errors.Is(err, os.ErrNotExist) {
113150
return err
114151
}
115152

116-
stats.CPUSetStats.MemorySpreadPage, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_spread_page")
153+
stats.CPUSetStats.MemorySpreadPage, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "memory_spread_page"))
117154
if err != nil && !errors.Is(err, os.ErrNotExist) {
118155
return err
119156
}
120157

121-
stats.CPUSetStats.MemorySpreadSlab, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_spread_slab")
158+
stats.CPUSetStats.MemorySpreadSlab, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "memory_spread_slab"))
122159
if err != nil && !errors.Is(err, os.ErrNotExist) {
123160
return err
124161
}
125162

126-
stats.CPUSetStats.MemoryPressure, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_pressure")
163+
stats.CPUSetStats.MemoryPressure, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "memory_pressure"))
127164
if err != nil && !errors.Is(err, os.ErrNotExist) {
128165
return err
129166
}
130167

131-
stats.CPUSetStats.SchedLoadBalance, err = fscommon.GetCgroupParamUint(path, "cpuset.sched_load_balance")
168+
stats.CPUSetStats.SchedLoadBalance, err = fscommon.GetCgroupParamUint(path, getCpusetFile(path, "sched_load_balance"))
132169
if err != nil && !errors.Is(err, os.ErrNotExist) {
133170
return err
134171
}
135172

136-
stats.CPUSetStats.SchedRelaxDomainLevel, err = fscommon.GetCgroupParamInt(path, "cpuset.sched_relax_domain_level")
173+
stats.CPUSetStats.SchedRelaxDomainLevel, err = fscommon.GetCgroupParamInt(path, getCpusetFile(path, "sched_relax_domain_level"))
137174
if err != nil && !errors.Is(err, os.ErrNotExist) {
138175
return err
139176
}
@@ -172,10 +209,10 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error
172209
}
173210

174211
func getCpusetSubsystemSettings(parent string) (cpus, mems string, err error) {
175-
if cpus, err = cgroups.ReadFile(parent, "cpuset.cpus"); err != nil {
212+
if cpus, err = cgroups.ReadFile(parent, getCpusetFile(parent, "cpus")); err != nil {
176213
return
177214
}
178-
if mems, err = cgroups.ReadFile(parent, "cpuset.mems"); err != nil {
215+
if mems, err = cgroups.ReadFile(parent, getCpusetFile(parent, "mems")); err != nil {
179216
return
180217
}
181218
return cpus, mems, nil
@@ -221,12 +258,12 @@ func cpusetCopyIfNeeded(current, parent string) error {
221258
}
222259

223260
if isEmptyCpuset(currentCpus) {
224-
if err := cgroups.WriteFile(current, "cpuset.cpus", parentCpus); err != nil {
261+
if err := cgroups.WriteFile(current, getCpusetFile(current, "cpus"), parentCpus); err != nil {
225262
return err
226263
}
227264
}
228265
if isEmptyCpuset(currentMems) {
229-
if err := cgroups.WriteFile(current, "cpuset.mems", parentMems); err != nil {
266+
if err := cgroups.WriteFile(current, getCpusetFile(current, "mems"), parentMems); err != nil {
230267
return err
231268
}
232269
}

0 commit comments

Comments
 (0)