mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
8f1b4d4a6f
This is a better place as cgroups itself is using these.
Should help with moving more stuff common in between fs and fs2 to
fscommon.
Looks big, but this is just moving the code around:
fscommon/{fscommon,open}.go -> cgroups/file.go
fscommon/fscommon_test.go -> cgroups/file_test.go
and fixes for TestMode moved to a different package.
There's no functional change.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
129 lines
3.4 KiB
Go
129 lines
3.4 KiB
Go
// +build linux
|
|
|
|
package fscommon
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
|
)
|
|
|
|
var (
|
|
ErrNotValidFormat = errors.New("line is not a valid key value format")
|
|
|
|
OpenFile = cgroups.OpenFile
|
|
ReadFile = cgroups.ReadFile
|
|
WriteFile = cgroups.WriteFile
|
|
)
|
|
|
|
// ParseUint converts a string to an uint64 integer.
|
|
// Negative values are returned at zero as, due to kernel bugs,
|
|
// some of the memory cgroup stats can be negative.
|
|
func ParseUint(s string, base, bitSize int) (uint64, error) {
|
|
value, err := strconv.ParseUint(s, base, bitSize)
|
|
if err != nil {
|
|
intValue, intErr := strconv.ParseInt(s, base, bitSize)
|
|
// 1. Handle negative values greater than MinInt64 (and)
|
|
// 2. Handle negative values lesser than MinInt64
|
|
if intErr == nil && intValue < 0 {
|
|
return 0, nil
|
|
} else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
return value, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// ParseKeyValue parses a space-separated "name value" kind of cgroup
|
|
// parameter and returns its key as a string, and its value as uint64
|
|
// (ParseUint is used to convert the value). For example,
|
|
// "io_service_bytes 1234" will be returned as "io_service_bytes", 1234.
|
|
func ParseKeyValue(t string) (string, uint64, error) {
|
|
parts := strings.SplitN(t, " ", 3)
|
|
if len(parts) != 2 {
|
|
return "", 0, fmt.Errorf("line %q is not in key value format", t)
|
|
}
|
|
|
|
value, err := ParseUint(parts[1], 10, 64)
|
|
if err != nil {
|
|
return "", 0, fmt.Errorf("unable to convert to uint64: %v", err)
|
|
}
|
|
|
|
return parts[0], value, nil
|
|
}
|
|
|
|
// GetValueByKey reads a key-value pairs from the specified cgroup file,
|
|
// and returns a value of the specified key. ParseUint is used for value
|
|
// conversion.
|
|
func GetValueByKey(path, file, key string) (uint64, error) {
|
|
content, err := cgroups.ReadFile(path, file)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
lines := strings.Split(string(content), "\n")
|
|
for _, line := range lines {
|
|
arr := strings.Split(line, " ")
|
|
if len(arr) == 2 && arr[0] == key {
|
|
return ParseUint(arr[1], 10, 64)
|
|
}
|
|
}
|
|
|
|
return 0, nil
|
|
}
|
|
|
|
// GetCgroupParamUint reads a single uint64 value from the specified cgroup file.
|
|
// If the value read is "max", the math.MaxUint64 is returned.
|
|
func GetCgroupParamUint(path, file string) (uint64, error) {
|
|
contents, err := GetCgroupParamString(path, file)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
contents = strings.TrimSpace(contents)
|
|
if contents == "max" {
|
|
return math.MaxUint64, nil
|
|
}
|
|
|
|
res, err := ParseUint(contents, 10, 64)
|
|
if err != nil {
|
|
return res, fmt.Errorf("unable to parse file %q", path+"/"+file)
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
// GetCgroupParamInt reads a single int64 value from specified cgroup file.
|
|
// If the value read is "max", the math.MaxInt64 is returned.
|
|
func GetCgroupParamInt(path, file string) (int64, error) {
|
|
contents, err := cgroups.ReadFile(path, file)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
contents = strings.TrimSpace(contents)
|
|
if contents == "max" {
|
|
return math.MaxInt64, nil
|
|
}
|
|
|
|
res, err := strconv.ParseInt(contents, 10, 64)
|
|
if err != nil {
|
|
return res, fmt.Errorf("unable to parse %q as a int from Cgroup file %q", contents, path+"/"+file)
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
// GetCgroupParamString reads a string from the specified cgroup file.
|
|
func GetCgroupParamString(path, file string) (string, error) {
|
|
contents, err := cgroups.ReadFile(path, file)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return strings.TrimSpace(contents), nil
|
|
}
|