6
6
"path/filepath"
7
7
"strconv"
8
8
"strings"
9
+ "sync"
9
10
10
11
"golang.org/x/sys/unix"
11
12
@@ -14,6 +15,42 @@ import (
14
15
"github.com/opencontainers/runc/libcontainer/configs"
15
16
)
16
17
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
+
17
54
type CpusetGroup struct {}
18
55
19
56
func (s * CpusetGroup ) Name () string {
@@ -26,12 +63,12 @@ func (s *CpusetGroup) Apply(path string, r *configs.Resources, pid int) error {
26
63
27
64
func (s * CpusetGroup ) Set (path string , r * configs.Resources ) error {
28
65
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 {
30
67
return err
31
68
}
32
69
}
33
70
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 {
35
72
return err
36
73
}
37
74
}
@@ -83,57 +120,57 @@ func getCpusetStat(path string, file string) ([]uint16, error) {
83
120
func (s * CpusetGroup ) GetStats (path string , stats * cgroups.Stats ) error {
84
121
var err error
85
122
86
- stats .CPUSetStats .CPUs , err = getCpusetStat (path , "cpuset. cpus" )
123
+ stats .CPUSetStats .CPUs , err = getCpusetStat (path , getCpusetFile ( path , " cpus") )
87
124
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
88
125
return err
89
126
}
90
127
91
- stats .CPUSetStats .CPUExclusive , err = fscommon .GetCgroupParamUint (path , "cpuset. cpu_exclusive" )
128
+ stats .CPUSetStats .CPUExclusive , err = fscommon .GetCgroupParamUint (path , getCpusetFile ( path , " cpu_exclusive") )
92
129
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
93
130
return err
94
131
}
95
132
96
- stats .CPUSetStats .Mems , err = getCpusetStat (path , "cpuset. mems" )
133
+ stats .CPUSetStats .Mems , err = getCpusetStat (path , getCpusetFile ( path , " mems") )
97
134
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
98
135
return err
99
136
}
100
137
101
- stats .CPUSetStats .MemHardwall , err = fscommon .GetCgroupParamUint (path , "cpuset. mem_hardwall" )
138
+ stats .CPUSetStats .MemHardwall , err = fscommon .GetCgroupParamUint (path , getCpusetFile ( path , " mem_hardwall") )
102
139
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
103
140
return err
104
141
}
105
142
106
- stats .CPUSetStats .MemExclusive , err = fscommon .GetCgroupParamUint (path , "cpuset. mem_exclusive" )
143
+ stats .CPUSetStats .MemExclusive , err = fscommon .GetCgroupParamUint (path , getCpusetFile ( path , " mem_exclusive") )
107
144
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
108
145
return err
109
146
}
110
147
111
- stats .CPUSetStats .MemoryMigrate , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_migrate" )
148
+ stats .CPUSetStats .MemoryMigrate , err = fscommon .GetCgroupParamUint (path , getCpusetFile ( path , " memory_migrate") )
112
149
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
113
150
return err
114
151
}
115
152
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") )
117
154
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
118
155
return err
119
156
}
120
157
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") )
122
159
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
123
160
return err
124
161
}
125
162
126
- stats .CPUSetStats .MemoryPressure , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_pressure" )
163
+ stats .CPUSetStats .MemoryPressure , err = fscommon .GetCgroupParamUint (path , getCpusetFile ( path , " memory_pressure") )
127
164
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
128
165
return err
129
166
}
130
167
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") )
132
169
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
133
170
return err
134
171
}
135
172
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") )
137
174
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
138
175
return err
139
176
}
@@ -172,10 +209,10 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error
172
209
}
173
210
174
211
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 {
176
213
return
177
214
}
178
- if mems , err = cgroups .ReadFile (parent , "cpuset. mems" ); err != nil {
215
+ if mems , err = cgroups .ReadFile (parent , getCpusetFile ( parent , " mems") ); err != nil {
179
216
return
180
217
}
181
218
return cpus , mems , nil
@@ -221,12 +258,12 @@ func cpusetCopyIfNeeded(current, parent string) error {
221
258
}
222
259
223
260
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 {
225
262
return err
226
263
}
227
264
}
228
265
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 {
230
267
return err
231
268
}
232
269
}
0 commit comments