@@ -5,14 +5,14 @@ import (
55 "fmt"
66 "os"
77 "path"
8+ "strconv"
89 "strings"
910 "sync"
1011
1112 "github.com/containerd/cgroups/v3"
1213 "github.com/containerd/cgroups/v3/cgroup1"
1314 "github.com/containerd/containerd/pkg/seccomp"
1415 "github.com/containerd/log"
15- "github.com/docker/docker/pkg/parsers"
1616 "github.com/moby/sys/mountinfo"
1717)
1818
@@ -320,7 +320,7 @@ func readProcBool(path string) bool {
320320const defaultMaxCPUs = 8192
321321
322322func isCpusetListAvailable (requested , available string ) (bool , error ) {
323- parsedAvailable , err := parsers . ParseUintList (available )
323+ parsedAvailable , err := parseUintList (available , 0 )
324324 if err != nil {
325325 return false , err
326326 }
@@ -341,7 +341,7 @@ func isCpusetListAvailable(requested, available string) (bool, error) {
341341 maxCPUs = m
342342 }
343343 }
344- parsedRequested , err := parsers . ParseUintListMaximum (requested , maxCPUs )
344+ parsedRequested , err := parseUintList (requested , maxCPUs )
345345 if err != nil {
346346 return false , err
347347 }
@@ -352,3 +352,61 @@ func isCpusetListAvailable(requested, available string) (bool, error) {
352352 }
353353 return true , nil
354354}
355+
356+ // parseUintList parses and validates the specified string as the value
357+ // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
358+ // one of the formats below. Note that duplicates are actually allowed in the
359+ // input string. It returns a `map[int]bool` with available elements from `val`
360+ // set to `true`. Values larger than `maximum` cause an error if max is non zero,
361+ // in order to stop the map becoming excessively large.
362+ // Supported formats:
363+ //
364+ // 7
365+ // 1-6
366+ // 0,3-4,7,8-10
367+ // 0-0,0,1-7
368+ // 03,1-3 <- this is gonna get parsed as [1,2,3]
369+ // 3,2,1
370+ // 0-2,3,1
371+ func parseUintList (val string , maximum int ) (map [int ]bool , error ) {
372+ if val == "" {
373+ return map [int ]bool {}, nil
374+ }
375+
376+ availableInts := make (map [int ]bool )
377+ split := strings .Split (val , "," )
378+ errInvalidFormat := fmt .Errorf ("invalid format: %s" , val )
379+
380+ for _ , r := range split {
381+ if ! strings .Contains (r , "-" ) {
382+ v , err := strconv .Atoi (r )
383+ if err != nil {
384+ return nil , errInvalidFormat
385+ }
386+ if maximum != 0 && v > maximum {
387+ return nil , fmt .Errorf ("value of out range, maximum is %d" , maximum )
388+ }
389+ availableInts [v ] = true
390+ } else {
391+ minS , maxS , _ := strings .Cut (r , "-" )
392+ minAvailable , err := strconv .Atoi (minS )
393+ if err != nil {
394+ return nil , errInvalidFormat
395+ }
396+ maxAvailable , err := strconv .Atoi (maxS )
397+ if err != nil {
398+ return nil , errInvalidFormat
399+ }
400+ if maxAvailable < minAvailable {
401+ return nil , errInvalidFormat
402+ }
403+ if maximum != 0 && maxAvailable > maximum {
404+ return nil , fmt .Errorf ("value of out range, maximum is %d" , maximum )
405+ }
406+ for i := minAvailable ; i <= maxAvailable ; i ++ {
407+ availableInts [i ] = true
408+ }
409+ }
410+ }
411+ return availableInts , nil
412+ }
0 commit comments