Skip to content

Commit b1c8cf4

Browse files
committed
merge #4513 into opencontainers/runc:main
Tomasz Duda (1): support cgroup v1 mounted with noprefix LGTMs: kolyshkin cyphar
2 parents 145f43f + 050e8eb commit b1c8cf4

File tree

1 file changed

+52
-17
lines changed

1 file changed

+52
-17
lines changed

fs/cpuset.go

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

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

1213
"github.com/opencontainers/runc/libcontainer/cgroups"
1314
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
1415
)
1516

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

1853
func (s *CpusetGroup) Name() string {
@@ -25,12 +60,12 @@ func (s *CpusetGroup) Apply(path string, r *cgroups.Resources, pid int) error {
2560

2661
func (s *CpusetGroup) Set(path string, r *cgroups.Resources) error {
2762
if r.CpusetCpus != "" {
28-
if err := cgroups.WriteFile(path, "cpuset.cpus", r.CpusetCpus); err != nil {
63+
if err := cgroups.WriteFile(path, cpusetFile(path, "cpus"), r.CpusetCpus); err != nil {
2964
return err
3065
}
3166
}
3267
if r.CpusetMems != "" {
33-
if err := cgroups.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil {
68+
if err := cgroups.WriteFile(path, cpusetFile(path, "mems"), r.CpusetMems); err != nil {
3469
return err
3570
}
3671
}
@@ -79,57 +114,57 @@ func getCpusetStat(path string, file string) ([]uint16, error) {
79114
func (s *CpusetGroup) GetStats(path string, stats *cgroups.Stats) error {
80115
var err error
81116

82-
stats.CPUSetStats.CPUs, err = getCpusetStat(path, "cpuset.cpus")
117+
stats.CPUSetStats.CPUs, err = getCpusetStat(path, cpusetFile(path, "cpus"))
83118
if err != nil && !errors.Is(err, os.ErrNotExist) {
84119
return err
85120
}
86121

87-
stats.CPUSetStats.CPUExclusive, err = fscommon.GetCgroupParamUint(path, "cpuset.cpu_exclusive")
122+
stats.CPUSetStats.CPUExclusive, err = fscommon.GetCgroupParamUint(path, cpusetFile(path, "cpu_exclusive"))
88123
if err != nil && !errors.Is(err, os.ErrNotExist) {
89124
return err
90125
}
91126

92-
stats.CPUSetStats.Mems, err = getCpusetStat(path, "cpuset.mems")
127+
stats.CPUSetStats.Mems, err = getCpusetStat(path, cpusetFile(path, "mems"))
93128
if err != nil && !errors.Is(err, os.ErrNotExist) {
94129
return err
95130
}
96131

97-
stats.CPUSetStats.MemHardwall, err = fscommon.GetCgroupParamUint(path, "cpuset.mem_hardwall")
132+
stats.CPUSetStats.MemHardwall, err = fscommon.GetCgroupParamUint(path, cpusetFile(path, "mem_hardwall"))
98133
if err != nil && !errors.Is(err, os.ErrNotExist) {
99134
return err
100135
}
101136

102-
stats.CPUSetStats.MemExclusive, err = fscommon.GetCgroupParamUint(path, "cpuset.mem_exclusive")
137+
stats.CPUSetStats.MemExclusive, err = fscommon.GetCgroupParamUint(path, cpusetFile(path, "mem_exclusive"))
103138
if err != nil && !errors.Is(err, os.ErrNotExist) {
104139
return err
105140
}
106141

107-
stats.CPUSetStats.MemoryMigrate, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_migrate")
142+
stats.CPUSetStats.MemoryMigrate, err = fscommon.GetCgroupParamUint(path, cpusetFile(path, "memory_migrate"))
108143
if err != nil && !errors.Is(err, os.ErrNotExist) {
109144
return err
110145
}
111146

112-
stats.CPUSetStats.MemorySpreadPage, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_spread_page")
147+
stats.CPUSetStats.MemorySpreadPage, err = fscommon.GetCgroupParamUint(path, cpusetFile(path, "memory_spread_page"))
113148
if err != nil && !errors.Is(err, os.ErrNotExist) {
114149
return err
115150
}
116151

117-
stats.CPUSetStats.MemorySpreadSlab, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_spread_slab")
152+
stats.CPUSetStats.MemorySpreadSlab, err = fscommon.GetCgroupParamUint(path, cpusetFile(path, "memory_spread_slab"))
118153
if err != nil && !errors.Is(err, os.ErrNotExist) {
119154
return err
120155
}
121156

122-
stats.CPUSetStats.MemoryPressure, err = fscommon.GetCgroupParamUint(path, "cpuset.memory_pressure")
157+
stats.CPUSetStats.MemoryPressure, err = fscommon.GetCgroupParamUint(path, cpusetFile(path, "memory_pressure"))
123158
if err != nil && !errors.Is(err, os.ErrNotExist) {
124159
return err
125160
}
126161

127-
stats.CPUSetStats.SchedLoadBalance, err = fscommon.GetCgroupParamUint(path, "cpuset.sched_load_balance")
162+
stats.CPUSetStats.SchedLoadBalance, err = fscommon.GetCgroupParamUint(path, cpusetFile(path, "sched_load_balance"))
128163
if err != nil && !errors.Is(err, os.ErrNotExist) {
129164
return err
130165
}
131166

132-
stats.CPUSetStats.SchedRelaxDomainLevel, err = fscommon.GetCgroupParamInt(path, "cpuset.sched_relax_domain_level")
167+
stats.CPUSetStats.SchedRelaxDomainLevel, err = fscommon.GetCgroupParamInt(path, cpusetFile(path, "sched_relax_domain_level"))
133168
if err != nil && !errors.Is(err, os.ErrNotExist) {
134169
return err
135170
}
@@ -168,10 +203,10 @@ func (s *CpusetGroup) ApplyDir(dir string, r *cgroups.Resources, pid int) error
168203
}
169204

170205
func getCpusetSubsystemSettings(parent string) (cpus, mems string, err error) {
171-
if cpus, err = cgroups.ReadFile(parent, "cpuset.cpus"); err != nil {
206+
if cpus, err = cgroups.ReadFile(parent, cpusetFile(parent, "cpus")); err != nil {
172207
return
173208
}
174-
if mems, err = cgroups.ReadFile(parent, "cpuset.mems"); err != nil {
209+
if mems, err = cgroups.ReadFile(parent, cpusetFile(parent, "mems")); err != nil {
175210
return
176211
}
177212
return cpus, mems, nil
@@ -217,12 +252,12 @@ func cpusetCopyIfNeeded(current, parent string) error {
217252
}
218253

219254
if isEmptyCpuset(currentCpus) {
220-
if err := cgroups.WriteFile(current, "cpuset.cpus", parentCpus); err != nil {
255+
if err := cgroups.WriteFile(current, cpusetFile(current, "cpus"), parentCpus); err != nil {
221256
return err
222257
}
223258
}
224259
if isEmptyCpuset(currentMems) {
225-
if err := cgroups.WriteFile(current, "cpuset.mems", parentMems); err != nil {
260+
if err := cgroups.WriteFile(current, cpusetFile(current, "mems"), parentMems); err != nil {
226261
return err
227262
}
228263
}

0 commit comments

Comments
 (0)