@@ -4,8 +4,11 @@ package cgroups
44
55import (
66 "context"
7+ "errors"
78 "fmt"
9+ "math/big"
810 "path/filepath"
11+ "strconv"
912 "strings"
1013
1114 systemdDbus "github.com/coreos/go-systemd/v22/dbus"
@@ -53,7 +56,10 @@ func systemdCreate(resources *configs.Resources, path string, c *systemdDbus.Con
5356 properties = append (properties , p )
5457 }
5558
56- uMap , sMap , bMap , iMap , structMap := resourcesToProps (resources , v2 )
59+ uMap , sMap , bMap , iMap , structMap , res_err := resourcesToProps (resources , v2 )
60+ if res_err != nil {
61+ return res_err
62+ }
5763 for k , v := range uMap {
5864 p := systemdDbus.Property {
5965 Name : k ,
@@ -142,7 +148,7 @@ func systemdDestroyConn(path string, c *systemdDbus.Conn) error {
142148 return nil
143149}
144150
145- func resourcesToProps (res * configs.Resources , v2 bool ) (map [string ]uint64 , map [string ]string , map [string ][]byte , map [string ]int64 , map [string ][]BlkioDev ) {
151+ func resourcesToProps (res * configs.Resources , v2 bool ) (map [string ]uint64 , map [string ]string , map [string ][]byte , map [string ]int64 , map [string ][]BlkioDev , error ) {
146152 bMap := make (map [string ][]byte )
147153 // this array is not used but will be once more resource limits are added
148154 sMap := make (map [string ]string )
@@ -179,11 +185,19 @@ func resourcesToProps(res *configs.Resources, v2 bool) (map[string]uint64, map[s
179185
180186 // CPUSet
181187 if res .CpusetCpus != "" {
182- bits := []byte (res .CpusetCpus )
188+ bits , err := rangeToBits (res .CpusetCpus )
189+ if err != nil {
190+ return nil , nil , nil , nil , nil , fmt .Errorf ("resources.CpusetCpus=%q conversion error: %w" ,
191+ res .CpusetCpus , err )
192+ }
183193 bMap ["AllowedCPUs" ] = bits
184194 }
185195 if res .CpusetMems != "" {
186- bits := []byte (res .CpusetMems )
196+ bits , err := rangeToBits (res .CpusetMems )
197+ if err != nil {
198+ return nil , nil , nil , nil , nil , fmt .Errorf ("resources.CpusetMems=%q conversion error: %w" ,
199+ res .CpusetMems , err )
200+ }
187201 bMap ["AllowedMemoryNodes" ] = bits
188202 }
189203
@@ -258,5 +272,53 @@ func resourcesToProps(res *configs.Resources, v2 bool) (map[string]uint64, map[s
258272 }
259273 }
260274
261- return uMap , sMap , bMap , iMap , structMap
275+ return uMap , sMap , bMap , iMap , structMap , nil
276+ }
277+
278+ func rangeToBits (str string ) ([]byte , error ) {
279+ bits := new (big.Int )
280+
281+ for _ , r := range strings .Split (str , "," ) {
282+ // allow extra spaces around
283+ r = strings .TrimSpace (r )
284+ // allow empty elements (extra commas)
285+ if r == "" {
286+ continue
287+ }
288+ startr , endr , ok := strings .Cut (r , "-" )
289+ if ok {
290+ start , err := strconv .ParseUint (startr , 10 , 32 )
291+ if err != nil {
292+ return nil , err
293+ }
294+ end , err := strconv .ParseUint (endr , 10 , 32 )
295+ if err != nil {
296+ return nil , err
297+ }
298+ if start > end {
299+ return nil , errors .New ("invalid range: " + r )
300+ }
301+ for i := start ; i <= end ; i ++ {
302+ bits .SetBit (bits , int (i ), 1 )
303+ }
304+ } else {
305+ val , err := strconv .ParseUint (startr , 10 , 32 )
306+ if err != nil {
307+ return nil , err
308+ }
309+ bits .SetBit (bits , int (val ), 1 )
310+ }
311+ }
312+
313+ ret := bits .Bytes ()
314+ if len (ret ) == 0 {
315+ // do not allow empty values
316+ return nil , errors .New ("empty value" )
317+ }
318+
319+ // fit cpuset parsing order in systemd
320+ for l , r := 0 , len (ret )- 1 ; l < r ; l , r = l + 1 , r - 1 {
321+ ret [l ], ret [r ] = ret [r ], ret [l ]
322+ }
323+ return ret , nil
262324}
0 commit comments