@@ -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+
1651type CpusetGroup struct {}
1752
1853func (s * CpusetGroup ) Name () string {
@@ -25,12 +60,12 @@ func (s *CpusetGroup) Apply(path string, r *cgroups.Resources, pid int) error {
2560
2661func (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 }
@@ -82,57 +117,57 @@ func getCpusetStat(path string, file string) ([]uint16, error) {
82117func (s * CpusetGroup ) GetStats (path string , stats * cgroups.Stats ) error {
83118 var err error
84119
85- stats .CPUSetStats .CPUs , err = getCpusetStat (path , "cpuset. cpus" )
120+ stats .CPUSetStats .CPUs , err = getCpusetStat (path , cpusetFile ( path , " cpus") )
86121 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
87122 return err
88123 }
89124
90- stats .CPUSetStats .CPUExclusive , err = fscommon .GetCgroupParamUint (path , "cpuset. cpu_exclusive" )
125+ stats .CPUSetStats .CPUExclusive , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " cpu_exclusive") )
91126 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
92127 return err
93128 }
94129
95- stats .CPUSetStats .Mems , err = getCpusetStat (path , "cpuset. mems" )
130+ stats .CPUSetStats .Mems , err = getCpusetStat (path , cpusetFile ( path , " mems") )
96131 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
97132 return err
98133 }
99134
100- stats .CPUSetStats .MemHardwall , err = fscommon .GetCgroupParamUint (path , "cpuset. mem_hardwall" )
135+ stats .CPUSetStats .MemHardwall , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " mem_hardwall") )
101136 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
102137 return err
103138 }
104139
105- stats .CPUSetStats .MemExclusive , err = fscommon .GetCgroupParamUint (path , "cpuset. mem_exclusive" )
140+ stats .CPUSetStats .MemExclusive , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " mem_exclusive") )
106141 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
107142 return err
108143 }
109144
110- stats .CPUSetStats .MemoryMigrate , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_migrate" )
145+ stats .CPUSetStats .MemoryMigrate , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " memory_migrate") )
111146 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
112147 return err
113148 }
114149
115- stats .CPUSetStats .MemorySpreadPage , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_spread_page" )
150+ stats .CPUSetStats .MemorySpreadPage , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " memory_spread_page") )
116151 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
117152 return err
118153 }
119154
120- stats .CPUSetStats .MemorySpreadSlab , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_spread_slab" )
155+ stats .CPUSetStats .MemorySpreadSlab , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " memory_spread_slab") )
121156 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
122157 return err
123158 }
124159
125- stats .CPUSetStats .MemoryPressure , err = fscommon .GetCgroupParamUint (path , "cpuset. memory_pressure" )
160+ stats .CPUSetStats .MemoryPressure , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " memory_pressure") )
126161 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
127162 return err
128163 }
129164
130- stats .CPUSetStats .SchedLoadBalance , err = fscommon .GetCgroupParamUint (path , "cpuset. sched_load_balance" )
165+ stats .CPUSetStats .SchedLoadBalance , err = fscommon .GetCgroupParamUint (path , cpusetFile ( path , " sched_load_balance") )
131166 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
132167 return err
133168 }
134169
135- stats .CPUSetStats .SchedRelaxDomainLevel , err = fscommon .GetCgroupParamInt (path , "cpuset. sched_relax_domain_level" )
170+ stats .CPUSetStats .SchedRelaxDomainLevel , err = fscommon .GetCgroupParamInt (path , cpusetFile ( path , " sched_relax_domain_level") )
136171 if err != nil && ! errors .Is (err , os .ErrNotExist ) {
137172 return err
138173 }
@@ -171,10 +206,10 @@ func (s *CpusetGroup) ApplyDir(dir string, r *cgroups.Resources, pid int) error
171206}
172207
173208func getCpusetSubsystemSettings (parent string ) (cpus , mems string , err error ) {
174- if cpus , err = cgroups .ReadFile (parent , "cpuset. cpus" ); err != nil {
209+ if cpus , err = cgroups .ReadFile (parent , cpusetFile ( parent , " cpus") ); err != nil {
175210 return
176211 }
177- if mems , err = cgroups .ReadFile (parent , "cpuset. mems" ); err != nil {
212+ if mems , err = cgroups .ReadFile (parent , cpusetFile ( parent , " mems") ); err != nil {
178213 return
179214 }
180215 return cpus , mems , nil
@@ -220,12 +255,12 @@ func cpusetCopyIfNeeded(current, parent string) error {
220255 }
221256
222257 if isEmptyCpuset (currentCpus ) {
223- if err := cgroups .WriteFile (current , "cpuset. cpus" , parentCpus ); err != nil {
258+ if err := cgroups .WriteFile (current , cpusetFile ( current , " cpus") , parentCpus ); err != nil {
224259 return err
225260 }
226261 }
227262 if isEmptyCpuset (currentMems ) {
228- if err := cgroups .WriteFile (current , "cpuset. mems" , parentMems ); err != nil {
263+ if err := cgroups .WriteFile (current , cpusetFile ( current , " mems") , parentMems ); err != nil {
229264 return err
230265 }
231266 }
0 commit comments