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,40 @@ import (
14
15
"github.com/opencontainers/runc/libcontainer/configs"
15
16
)
16
17
18
+ var (
19
+ cpusetLock sync.Mutex
20
+ cpusetPrefix = "cpuset."
21
+ cpusetFastPath bool
22
+ )
23
+
24
+ func cpusetFile (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
+ return cpusetPrefix + name
35
+ }
36
+
37
+ err := unix .Access (filepath .Join (path , cpusetPrefix + name ), unix .F_OK )
38
+ if err == nil {
39
+ // Use the fast path only if we can access one type of mount for cpuset already
40
+ cpusetFastPath = true
41
+ } else {
42
+ err = unix .Access (filepath .Join (path , name ), unix .F_OK )
43
+ if err == nil {
44
+ cpusetPrefix = ""
45
+ cpusetFastPath = true
46
+ }
47
+ }
48
+
49
+ return cpusetPrefix + name
50
+ }
51
+
17
52
type CpusetGroup struct {}
18
53
19
54
func (s * CpusetGroup ) Name () string {
@@ -26,12 +61,12 @@ func (s *CpusetGroup) Apply(path string, r *configs.Resources, pid int) error {
26
61
27
62
func (s * CpusetGroup ) Set (path string , r * configs.Resources ) error {
28
63
if r .CpusetCpus != "" {
29
- if err := cgroups .WriteFile (path , "cpuset. cpus" , r .CpusetCpus ); err != nil {
64
+ if err := cgroups .WriteFile (path , cpusetFile ( path , " cpus") , r .CpusetCpus ); err != nil {
30
65
return err
31
66
}
32
67
}
33
68
if r .CpusetMems != "" {
34
- if err := cgroups .WriteFile (path , "cpuset. mems" , r .CpusetMems ); err != nil {
69
+ if err := cgroups .WriteFile (path , cpusetFile ( path , " mems") , r .CpusetMems ); err != nil {
35
70
return err
36
71
}
37
72
}
@@ -83,57 +118,57 @@ func getCpusetStat(path string, file string) ([]uint16, error) {
83
118
func (s * CpusetGroup ) GetStats (path string , stats * cgroups.Stats ) error {
84
119
var err error
85
120
86
- stats .CPUSetStats .CPUs , err = getCpusetStat (path , "cpuset. cpus" )
121
+ stats .CPUSetStats .CPUs , err = getCpusetStat (path , cpusetFile ( path , " cpus") )
87
122
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
88
123
return err
89
124
}
90
125
91
- stats .CPUSetStats .CPUExclusive , err = fscommon .GetCgroupParamUint (path , "cpuset. cpu_exclusive" )
126
+ stats .CPUSetStats .CPUExclusive , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " cpu_exclusive") )
92
127
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
93
128
return err
94
129
}
95
130
96
- stats .CPUSetStats .Mems , err = getCpusetStat (path , "cpuset. mems" )
131
+ stats .CPUSetStats .Mems , err = getCpusetStat (path , cpusetFile ( path , " mems") )
97
132
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
98
133
return err
99
134
}
100
135
101
- stats .CPUSetStats .MemHardwall , err = fscommon .GetCgroupParamUint (path , "cpuset. mem_hardwall" )
136
+ stats .CPUSetStats .MemHardwall , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " mem_hardwall") )
102
137
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
103
138
return err
104
139
}
105
140
106
- stats .CPUSetStats .MemExclusive , err = fscommon .GetCgroupParamUint (path , "cpuset. mem_exclusive" )
141
+ stats .CPUSetStats .MemExclusive , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " mem_exclusive") )
107
142
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
108
143
return err
109
144
}
110
145
111
- stats .CPUSetStats .MemoryMigrate , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_migrate" )
146
+ stats .CPUSetStats .MemoryMigrate , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " memory_migrate") )
112
147
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
113
148
return err
114
149
}
115
150
116
- stats .CPUSetStats .MemorySpreadPage , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_spread_page" )
151
+ stats .CPUSetStats .MemorySpreadPage , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " memory_spread_page") )
117
152
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
118
153
return err
119
154
}
120
155
121
- stats .CPUSetStats .MemorySpreadSlab , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_spread_slab" )
156
+ stats .CPUSetStats .MemorySpreadSlab , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " memory_spread_slab") )
122
157
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
123
158
return err
124
159
}
125
160
126
- stats .CPUSetStats .MemoryPressure , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_pressure" )
161
+ stats .CPUSetStats .MemoryPressure , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " memory_pressure") )
127
162
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
128
163
return err
129
164
}
130
165
131
- stats .CPUSetStats .SchedLoadBalance , err = fscommon .GetCgroupParamUint (path , "cpuset. sched_load_balance" )
166
+ stats .CPUSetStats .SchedLoadBalance , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " sched_load_balance") )
132
167
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
133
168
return err
134
169
}
135
170
136
- stats .CPUSetStats .SchedRelaxDomainLevel , err = fscommon .GetCgroupParamInt (path , "cpuset. sched_relax_domain_level" )
171
+ stats .CPUSetStats .SchedRelaxDomainLevel , err = fscommon .GetCgroupParamInt (path , cpusetFile ( path , " sched_relax_domain_level") )
137
172
if err != nil && ! errors .Is (err , os .ErrNotExist ) {
138
173
return err
139
174
}
@@ -172,10 +207,10 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error
172
207
}
173
208
174
209
func getCpusetSubsystemSettings (parent string ) (cpus , mems string , err error ) {
175
- if cpus , err = cgroups .ReadFile (parent , "cpuset. cpus" ); err != nil {
210
+ if cpus , err = cgroups .ReadFile (parent , cpusetFile ( parent , " cpus") ); err != nil {
176
211
return
177
212
}
178
- if mems , err = cgroups .ReadFile (parent , "cpuset. mems" ); err != nil {
213
+ if mems , err = cgroups .ReadFile (parent , cpusetFile ( parent , " mems") ); err != nil {
179
214
return
180
215
}
181
216
return cpus , mems , nil
@@ -221,12 +256,12 @@ func cpusetCopyIfNeeded(current, parent string) error {
221
256
}
222
257
223
258
if isEmptyCpuset (currentCpus ) {
224
- if err := cgroups .WriteFile (current , "cpuset. cpus" , parentCpus ); err != nil {
259
+ if err := cgroups .WriteFile (current , cpusetFile ( current , " cpus") , parentCpus ); err != nil {
225
260
return err
226
261
}
227
262
}
228
263
if isEmptyCpuset (currentMems ) {
229
- if err := cgroups .WriteFile (current , "cpuset. mems" , parentMems ); err != nil {
264
+ if err := cgroups .WriteFile (current , cpusetFile ( current , " mems") , parentMems ); err != nil {
230
265
return err
231
266
}
232
267
}
0 commit comments