@@ -16,7 +16,9 @@ package policy
1616
1717import (
1818 "encoding/json"
19+ "errors"
1920 "io/ioutil"
21+ "os"
2022 "path/filepath"
2123 "sort"
2224 "strconv"
@@ -121,6 +123,9 @@ func (cs *ConstraintSet) parseCPU(value string) error {
121123 } else {
122124 spec = value
123125 }
126+ if len (spec ) == 0 {
127+ return policyError ("missing CPU constraint value" )
128+ }
124129
125130 switch {
126131 case kind == "cgroup" || spec [0 ] == '/' :
@@ -163,11 +168,25 @@ func (cs *ConstraintSet) parseCPUQuantity(value string) error {
163168}
164169
165170func (cs * ConstraintSet ) parseCPUFromCgroup (dir string ) error {
166- cpusetDir := cgroups .Cpuset .Path ()
167- if ! strings .HasPrefix (dir , cpusetDir + "/" ) {
168- dir = filepath .Join (cpusetDir , dir )
171+ pathToCpuset := func (outPath * string , fragments ... string ) bool {
172+ * outPath = filepath .Join (filepath .Join (fragments ... ), "cpuset.cpus" )
173+ _ , err := os .Stat (* outPath )
174+ return ! errors .Is (err , os .ErrNotExist )
175+ }
176+ path := ""
177+ switch {
178+ case len (dir ) == 0 :
179+ return policyError ("empty CPU cgroup constraint" )
180+ case dir [0 ] == '/' && pathToCpuset (& path , dir ):
181+ // dir is a direct, absolute path to an existing cgroup
182+ case pathToCpuset (& path , cgroups .GetMountDir (), dir ):
183+ // dir is a relative path starting from the cgroup mount point
184+ case pathToCpuset (& path , cgroups .Cpuset .Path (), dir ):
185+ // dir is a relative path starting from the cpuset controller (cgroup v1)
186+ default :
187+ // dir is none of the previous
188+ return policyError ("failed to find cpuset.cpus for CPU cgroup constraint %q" , dir )
169189 }
170- path := filepath .Join (dir , "cpuset.cpus" )
171190 bytes , err := ioutil .ReadFile (path )
172191 if err != nil {
173192 return policyError ("failed read CPU cpuset cgroup constraint %q: %v" ,
0 commit comments