@@ -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 }
@@ -79,57 +114,57 @@ func getCpusetStat(path string, file string) ([]uint16, error) {
79114func (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
170205func 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