build(deps): bump github.com/intel/goresctrl from 0.3.0 to 0.5.0

Bumps [github.com/intel/goresctrl](https://github.com/intel/goresctrl) from 0.3.0 to 0.5.0.
- [Release notes](https://github.com/intel/goresctrl/releases)
- [Commits](https://github.com/intel/goresctrl/compare/v0.3.0...v0.5.0)

---
updated-dependencies:
- dependency-name: github.com/intel/goresctrl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2023-12-14 03:37:26 +00:00
committed by GitHub
parent a901236bf0
commit fc4b78c05c
25 changed files with 215 additions and 1671 deletions

View File

@@ -23,84 +23,86 @@ limitations under the License.
// Outputs:
// Option 1: Write blockio parameters of a class to a cgroup directory.
// Option 2: Return blockio parameters of a class in a OCI LinuxBlockIO
// structure, that can be passed to OCI-compliant container
// runtime.
//
// structure, that can be passed to OCI-compliant container
// runtime.
//
// Notes:
// - Using Weight requires bfq or cfq I/O scheduler to be
// effective for the block devices where Weight is used.
// - Using Weight requires bfq or cfq I/O scheduler to be
// effective for the block devices where Weight is used.
//
// Configuration example:
//
// Classes:
// Classes:
//
// # Define a blockio class "LowPrioThrottled".
// # Containers in this class will be throttled and handled as
// # low priority in the I/O scheduler.
// # Define a blockio class "LowPrioThrottled".
// # Containers in this class will be throttled and handled as
// # low priority in the I/O scheduler.
//
// LowPrioThrottled:
// LowPrioThrottled:
//
// # Weight without a Devices list specifies the default
// # I/O scheduler weight for all devices
// # that are not explicitly mentioned in following items.
// # This will be written to cgroups(.bfq).weight.
// # Weights range from 10 to 1000, the default is 100.
// # Weight without a Devices list specifies the default
// # I/O scheduler weight for all devices
// # that are not explicitly mentioned in following items.
// # This will be written to cgroups(.bfq).weight.
// # Weights range from 10 to 1000, the default is 100.
//
// - Weight: 80
// - Weight: 80
//
// # Set all parameters for all /dev/sd* and /dev/vd* block
// # devices.
// # Set all parameters for all /dev/sd* and /dev/vd* block
// # devices.
//
// - Devices:
// - /dev/sd[a-z]
// - /dev/vd[a-z]
// ThrottleReadBps: 50M # max read bytes per second
// ThrottleWriteBps: 10M # max write bytes per second
// ThrottleReadIOPS: 10k # max read io operations per second
// ThrottleWriteIOPS: 5k # max write io operations per second
// Weight: 50 # I/O scheduler (cfq/bfq) weight for
// # these devices will be written to
// # cgroups(.bfq).weight_device
// - Devices:
// - /dev/sd[a-z]
// - /dev/vd[a-z]
// ThrottleReadBps: 50M # max read bytes per second
// ThrottleWriteBps: 10M # max write bytes per second
// ThrottleReadIOPS: 10k # max read io operations per second
// ThrottleWriteIOPS: 5k # max write io operations per second
// Weight: 50 # I/O scheduler (cfq/bfq) weight for
// # these devices will be written to
// # cgroups(.bfq).weight_device
//
// # Set parameters particularly for SSD devices.
// # This configuration overrides above configurations for those
// # /dev/sd* and /dev/vd* devices whose disk id contains "SSD".
// # Set parameters particularly for SSD devices.
// # This configuration overrides above configurations for those
// # /dev/sd* and /dev/vd* devices whose disk id contains "SSD".
//
// - Devices:
// - /dev/disk/by-id/*SSD*
// ThrottleReadBps: 100M
// ThrottleWriteBps: 40M
// # Not mentioning Throttle*IOPS means no I/O operations
// # throttling on matching devices.
// Weight: 50
// - Devices:
// - /dev/disk/by-id/*SSD*
// ThrottleReadBps: 100M
// ThrottleWriteBps: 40M
// # Not mentioning Throttle*IOPS means no I/O operations
// # throttling on matching devices.
// Weight: 50
//
// # Define a blockio class "HighPrioFullSpeed".
// # There is no throttling on these containers, and
// # they will be prioritized by the I/O scheduler.
// # Define a blockio class "HighPrioFullSpeed".
// # There is no throttling on these containers, and
// # they will be prioritized by the I/O scheduler.
//
// HighPrioFullSpeed:
// - Weight: 400
// HighPrioFullSpeed:
// - Weight: 400
//
// Usage example:
// blockio.SetLogger(logrus.New())
// if err := blockio.SetConfigFromFile("/etc/containers/blockio.yaml", false); err != nil {
// return err
// }
// // Output option 1: write directly to cgroup "/mytestgroup"
// if err := blockio.SetCgroupClass("/mytestgroup", "LowPrioThrottled"); err != nil {
// return err
// }
// // Output option 2: OCI LinuxBlockIO of a blockio class
// if lbio, err := blockio.OciLinuxBlockIO("LowPrioThrottled"); err != nil {
// return err
// } else {
// fmt.Printf("OCI LinuxBlockIO for LowPrioThrottled:\n%+v\n", lbio)
// }
//
// blockio.SetLogger(logrus.New())
// if err := blockio.SetConfigFromFile("/etc/containers/blockio.yaml", false); err != nil {
// return err
// }
// // Output option 1: write directly to cgroup "/mytestgroup"
// if err := blockio.SetCgroupClass("/mytestgroup", "LowPrioThrottled"); err != nil {
// return err
// }
// // Output option 2: OCI LinuxBlockIO of a blockio class
// if lbio, err := blockio.OciLinuxBlockIO("LowPrioThrottled"); err != nil {
// return err
// } else {
// fmt.Printf("OCI LinuxBlockIO for LowPrioThrottled:\n%+v\n", lbio)
// }
package blockio
import (
"errors"
"fmt"
"io/ioutil"
stdlog "log"
"os"
"path/filepath"
@@ -113,10 +115,9 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
"sigs.k8s.io/yaml"
"github.com/hashicorp/go-multierror"
"github.com/intel/goresctrl/pkg/cgroups"
grclog "github.com/intel/goresctrl/pkg/log"
goresctrlpath "github.com/intel/goresctrl/pkg/path"
)
const (
@@ -146,11 +147,12 @@ var classBlockIO = map[string]cgroups.BlockIOParameters{}
// SetLogger sets the logger instance to be used by the package.
// Examples:
// // Log to standard logger:
// stdlog := log.New(os.Stderr, "blockio:", 0)
// blockio.SetLogger(goresctrllog.NewLoggerWrapper(stdlog))
// // Log to logrus:
// blockio.SetLogger(logrus.New())
//
// // Log to standard logger:
// stdlog := log.New(os.Stderr, "blockio:", 0)
// blockio.SetLogger(goresctrllog.NewLoggerWrapper(stdlog))
// // Log to logrus:
// blockio.SetLogger(logrus.New())
func SetLogger(l grclog.Logger) {
log = l
}
@@ -158,7 +160,7 @@ func SetLogger(l grclog.Logger) {
// SetConfigFromFile reads and applies blockio configuration from the
// filesystem.
func SetConfigFromFile(filename string, force bool) error {
if data, err := ioutil.ReadFile(filename); err == nil {
if data, err := os.ReadFile(filename); err == nil {
if err = SetConfigFromData(data, force); err != nil {
return fmt.Errorf("failed to set configuration from file %q: %s", filename, err)
}
@@ -237,13 +239,14 @@ func SetCgroupClass(group string, class string) error {
// Returns schedulers in a map: {"/dev/sda": "bfq"}
func getCurrentIOSchedulers() (map[string]string, error) {
var ios = map[string]string{}
schedulerFiles, err := filepath.Glob(sysfsBlockDeviceIOSchedulerPaths)
glob := goresctrlpath.Path(sysfsBlockDeviceIOSchedulerPaths)
schedulerFiles, err := filepath.Glob(glob)
if err != nil {
return ios, fmt.Errorf("error in I/O scheduler wildcards %#v: %w", sysfsBlockDeviceIOSchedulerPaths, err)
return ios, fmt.Errorf("error in I/O scheduler wildcards %#v: %w", glob, err)
}
for _, schedulerFile := range schedulerFiles {
devName := strings.SplitN(schedulerFile, "/", 5)[3]
schedulerDataB, err := ioutil.ReadFile(schedulerFile)
schedulerDataB, err := os.ReadFile(schedulerFile)
if err != nil {
// A block device may be disconnected.
log.Errorf("failed to read current I/O scheduler %#v: %v\n", schedulerFile, err)
@@ -272,27 +275,27 @@ func getCurrentIOSchedulers() (map[string]string, error) {
// deviceParametersToCgBlockIO converts single blockio class parameters into cgroups blkio format.
func devicesParametersToCgBlockIO(dps []DevicesParameters, currentIOSchedulers map[string]string) (cgroups.BlockIOParameters, error) {
var errors *multierror.Error
errs := []error{}
blkio := cgroups.NewBlockIOParameters()
for _, dp := range dps {
var err error
var weight, throttleReadBps, throttleWriteBps, throttleReadIOPS, throttleWriteIOPS int64
weight, err = parseAndValidateQuantity("Weight", dp.Weight, -1, 10, 1000)
errors = multierror.Append(errors, err)
errs = append(errs, err)
throttleReadBps, err = parseAndValidateQuantity("ThrottleReadBps", dp.ThrottleReadBps, -1, 0, -1)
errors = multierror.Append(errors, err)
errs = append(errs, err)
throttleWriteBps, err = parseAndValidateQuantity("ThrottleWriteBps", dp.ThrottleWriteBps, -1, 0, -1)
errors = multierror.Append(errors, err)
errs = append(errs, err)
throttleReadIOPS, err = parseAndValidateQuantity("ThrottleReadIOPS", dp.ThrottleReadIOPS, -1, 0, -1)
errors = multierror.Append(errors, err)
errs = append(errs, err)
throttleWriteIOPS, err = parseAndValidateQuantity("ThrottleWriteIOPS", dp.ThrottleWriteIOPS, -1, 0, -1)
errors = multierror.Append(errors, err)
errs = append(errs, err)
if dp.Devices == nil {
if weight > -1 {
blkio.Weight = weight
}
if throttleReadBps > -1 || throttleWriteBps > -1 || throttleReadIOPS > -1 || throttleWriteIOPS > -1 {
errors = multierror.Append(errors, fmt.Errorf("ignoring throttling (rbps=%#v wbps=%#v riops=%#v wiops=%#v): Devices not listed",
errs = append(errs, fmt.Errorf("ignoring throttling (rbps=%#v wbps=%#v riops=%#v wiops=%#v): Devices not listed",
dp.ThrottleReadBps, dp.ThrottleWriteBps, dp.ThrottleReadIOPS, dp.ThrottleWriteIOPS))
}
} else {
@@ -330,7 +333,7 @@ func devicesParametersToCgBlockIO(dps []DevicesParameters, currentIOSchedulers m
}
}
}
return blkio, errors.ErrorOrNil()
return blkio, errors.Join(errs...)
}
// parseAndValidateQuantity parses quantities, like "64 M", and validates that they are in given range.
@@ -369,7 +372,7 @@ var currentPlatform platformInterface = defaultPlatform{}
func (dpm defaultPlatform) configurableBlockDevices(devWildcards []string) ([]tBlockDeviceInfo, error) {
// Return map {devNode: tBlockDeviceInfo}
// Example: {"/dev/sda": {Major:8, Minor:0, Origin:"from symlink /dev/disk/by-id/ata-VendorXSSD from wildcard /dev/disk/by-id/*SSD*"}}
var errors *multierror.Error
errs := []error{}
blockDevices := []tBlockDeviceInfo{}
var origin string
@@ -379,11 +382,11 @@ func (dpm defaultPlatform) configurableBlockDevices(devWildcards []string) ([]tB
for _, devWildcard := range devWildcards {
devWildcardMatches, err := filepath.Glob(devWildcard)
if err != nil {
errors = multierror.Append(errors, fmt.Errorf("bad device wildcard %#v: %w", devWildcard, err))
errs = append(errs, fmt.Errorf("bad device wildcard %#v: %w", devWildcard, err))
continue
}
if len(devWildcardMatches) == 0 {
errors = multierror.Append(errors, fmt.Errorf("device wildcard %#v does not match any device nodes", devWildcard))
errs = append(errs, fmt.Errorf("device wildcard %#v does not match any device nodes", devWildcard))
continue
}
for _, devMatch := range devWildcardMatches {
@@ -402,7 +405,7 @@ func (dpm defaultPlatform) configurableBlockDevices(devWildcards []string) ([]tB
for devMatch, devOrigin := range devMatches {
realDevNode, err := filepath.EvalSymlinks(devMatch)
if err != nil {
errors = multierror.Append(errors, fmt.Errorf("cannot filepath.EvalSymlinks(%#v): %w", devMatch, err))
errs = append(errs, fmt.Errorf("cannot filepath.EvalSymlinks(%#v): %w", devMatch, err))
continue
}
if realDevNode != devMatch {
@@ -422,27 +425,23 @@ func (dpm defaultPlatform) configurableBlockDevices(devWildcards []string) ([]tB
}
fileInfo, err := os.Stat(devRealpath)
if err != nil {
errors = multierror.Append(errors, fmt.Errorf("cannot os.Stat(%#v): %w%s", devRealpath, err, origin))
errs = append(errs, fmt.Errorf("cannot os.Stat(%#v): %w%s", devRealpath, err, origin))
continue
}
fileMode := fileInfo.Mode()
if fileMode&os.ModeDevice == 0 {
errors = multierror.Append(errors, fmt.Errorf("file %#v is not a device%s", devRealpath, origin))
errs = append(errs, fmt.Errorf("file %#v is not a device%s", devRealpath, origin))
continue
}
if fileMode&os.ModeCharDevice != 0 {
errors = multierror.Append(errors, fmt.Errorf("file %#v is a character device%s", devRealpath, origin))
errs = append(errs, fmt.Errorf("file %#v is a character device%s", devRealpath, origin))
continue
}
sys, ok := fileInfo.Sys().(*syscall.Stat_t)
major := unix.Major(uint64(sys.Rdev))
minor := unix.Minor(uint64(sys.Rdev))
if !ok {
errors = multierror.Append(errors, fmt.Errorf("cannot get syscall stat_t from %#v: %w%s", devRealpath, err, origin))
continue
}
if minor&0xf != 0 {
errors = multierror.Append(errors, fmt.Errorf("skipping %#v: cannot weight/throttle partitions%s", devRealpath, origin))
errs = append(errs, fmt.Errorf("cannot get syscall stat_t from %#v: %w%s", devRealpath, err, origin))
continue
}
blockDevices = append(blockDevices, tBlockDeviceInfo{
@@ -452,5 +451,5 @@ func (dpm defaultPlatform) configurableBlockDevices(devWildcards []string) ([]tB
Origin: devOrigin,
})
}
return blockDevices, errors.ErrorOrNil()
return blockDevices, errors.Join(errs...)
}

View File

@@ -15,11 +15,10 @@
package cgroups
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/hashicorp/go-multierror"
)
// cgroups blkio parameter filenames.
@@ -35,9 +34,10 @@ var blkioThrottleWriteIOPSFiles = []string{"blkio.throttle.write_iops_device"}
// Effects of Weight and Rate values in SetBlkioParameters():
// Value | Effect
// -------+-------------------------------------------------------------------
// -1 | Do not write to cgroups, value is missing.
// 0 | Write to cgroups, will clear the setting as specified in cgroups blkio interface.
// other | Write to cgroups, sets the value.
//
// -1 | Do not write to cgroups, value is missing.
// 0 | Write to cgroups, will clear the setting as specified in cgroups blkio interface.
// other | Write to cgroups, sets the value.
type BlockIOParameters struct {
Weight int64
WeightDevice DeviceWeights
@@ -142,7 +142,7 @@ type devMajMin struct {
// ResetBlkioParameters adds new, changes existing and removes missing blockIO parameters in cgroupsDir.
func ResetBlkioParameters(groupDir string, blockIO BlockIOParameters) error {
var errors *multierror.Error
errs := []error{}
oldBlockIO, _ := GetBlkioParameters(groupDir)
newBlockIO := NewBlockIOParameters()
newBlockIO.Weight = blockIO.Weight
@@ -151,8 +151,8 @@ func ResetBlkioParameters(groupDir string, blockIO BlockIOParameters) error {
newBlockIO.ThrottleWriteBpsDevice = resetDevRates(oldBlockIO.ThrottleWriteBpsDevice, blockIO.ThrottleWriteBpsDevice)
newBlockIO.ThrottleReadIOPSDevice = resetDevRates(oldBlockIO.ThrottleReadIOPSDevice, blockIO.ThrottleReadIOPSDevice)
newBlockIO.ThrottleWriteIOPSDevice = resetDevRates(oldBlockIO.ThrottleWriteIOPSDevice, blockIO.ThrottleWriteIOPSDevice)
errors = multierror.Append(errors, SetBlkioParameters(groupDir, newBlockIO))
return errors.ErrorOrNil()
errs = append(errs, SetBlkioParameters(groupDir, newBlockIO))
return errors.Join(errs...)
}
// resetDevWeights adds wanted weight parameters to new and resets unwanted weights.
@@ -189,16 +189,16 @@ func resetDevRates(old, wanted []DeviceRate) []DeviceRate {
// GetBlkioParameters returns BlockIO parameters from files in cgroups blkio controller directory.
func GetBlkioParameters(group string) (BlockIOParameters, error) {
var errors *multierror.Error
errs := []error{}
blockIO := NewBlockIOParameters()
errors = multierror.Append(errors, readWeight(group, blkioWeightFiles, &blockIO.Weight))
errors = multierror.Append(errors, readDeviceParameters(group, blkioWeightDeviceFiles, &blockIO.WeightDevice))
errors = multierror.Append(errors, readDeviceParameters(group, blkioThrottleReadBpsFiles, &blockIO.ThrottleReadBpsDevice))
errors = multierror.Append(errors, readDeviceParameters(group, blkioThrottleWriteBpsFiles, &blockIO.ThrottleWriteBpsDevice))
errors = multierror.Append(errors, readDeviceParameters(group, blkioThrottleReadIOPSFiles, &blockIO.ThrottleReadIOPSDevice))
errors = multierror.Append(errors, readDeviceParameters(group, blkioThrottleWriteIOPSFiles, &blockIO.ThrottleWriteIOPSDevice))
return blockIO, errors.ErrorOrNil()
errs = append(errs, readWeight(group, blkioWeightFiles, &blockIO.Weight))
errs = append(errs, readDeviceParameters(group, blkioWeightDeviceFiles, &blockIO.WeightDevice))
errs = append(errs, readDeviceParameters(group, blkioThrottleReadBpsFiles, &blockIO.ThrottleReadBpsDevice))
errs = append(errs, readDeviceParameters(group, blkioThrottleWriteBpsFiles, &blockIO.ThrottleWriteBpsDevice))
errs = append(errs, readDeviceParameters(group, blkioThrottleReadIOPSFiles, &blockIO.ThrottleReadIOPSDevice))
errs = append(errs, readDeviceParameters(group, blkioThrottleWriteIOPSFiles, &blockIO.ThrottleWriteIOPSDevice))
return blockIO, errors.Join(errs...)
}
// readWeight parses int64 from a cgroups entry.
@@ -217,7 +217,7 @@ func readWeight(groupDir string, filenames []string, rv *int64) error {
// readDeviceParameters parses device lines used for weights and throttling rates.
func readDeviceParameters(groupDir string, filenames []string, params DeviceParameters) error {
var errors *multierror.Error
errs := []error{}
contents, err := readFirstFile(groupDir, filenames)
if err != nil {
return err
@@ -230,38 +230,38 @@ func readDeviceParameters(groupDir string, filenames []string, params DevicePara
// Expect syntax MAJOR:MINOR VALUE
devVal := strings.Split(line, " ")
if len(devVal) != 2 {
errors = multierror.Append(errors, fmt.Errorf("invalid line %q, single space expected", line))
errs = append(errs, fmt.Errorf("invalid line %q, single space expected", line))
continue
}
majMin := strings.Split(devVal[0], ":")
if len(majMin) != 2 {
errors = multierror.Append(errors, fmt.Errorf("invalid line %q, single colon expected before space", line))
errs = append(errs, fmt.Errorf("invalid line %q, single colon expected before space", line))
continue
}
major, majErr := strconv.ParseInt(majMin[0], 10, 64)
minor, minErr := strconv.ParseInt(majMin[1], 10, 64)
value, valErr := strconv.ParseInt(devVal[1], 10, 64)
if majErr != nil || minErr != nil || valErr != nil {
errors = multierror.Append(errors, fmt.Errorf("invalid number when parsing \"major:minor value\" from \"%s:%s %s\"", majMin[0], majMin[1], devVal[1]))
errs = append(errs, fmt.Errorf("invalid number when parsing \"major:minor value\" from \"%s:%s %s\"", majMin[0], majMin[1], devVal[1]))
continue
}
params.Append(major, minor, value)
}
return errors.ErrorOrNil()
return errors.Join(errs...)
}
// readFirstFile returns contents of the first successfully read entry.
func readFirstFile(groupDir string, filenames []string) (string, error) {
var errors *multierror.Error
errs := []error{}
// If reading all the files fails, return list of read errors.
for _, filename := range filenames {
content, err := Blkio.Group(groupDir).Read(filename)
if err == nil {
return content, nil
}
errors = multierror.Append(errors, err)
errs = append(errs, err)
}
err := errors.ErrorOrNil()
err := errors.Join(errs...)
if err != nil {
return "", fmt.Errorf("could not read any of files %q: %w", filenames, err)
}
@@ -270,40 +270,40 @@ func readFirstFile(groupDir string, filenames []string) (string, error) {
// SetBlkioParameters writes BlockIO parameters to files in cgroups blkio contoller directory.
func SetBlkioParameters(group string, blockIO BlockIOParameters) error {
var errors *multierror.Error
errs := []error{}
if blockIO.Weight >= 0 {
errors = multierror.Append(errors, writeFirstFile(group, blkioWeightFiles, "%d", blockIO.Weight))
errs = append(errs, writeFirstFile(group, blkioWeightFiles, "%d", blockIO.Weight))
}
for _, wd := range blockIO.WeightDevice {
errors = multierror.Append(errors, writeFirstFile(group, blkioWeightDeviceFiles, "%d:%d %d", wd.Major, wd.Minor, wd.Weight))
errs = append(errs, writeFirstFile(group, blkioWeightDeviceFiles, "%d:%d %d", wd.Major, wd.Minor, wd.Weight))
}
for _, rd := range blockIO.ThrottleReadBpsDevice {
errors = multierror.Append(errors, writeFirstFile(group, blkioThrottleReadBpsFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate))
errs = append(errs, writeFirstFile(group, blkioThrottleReadBpsFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate))
}
for _, rd := range blockIO.ThrottleWriteBpsDevice {
errors = multierror.Append(errors, writeFirstFile(group, blkioThrottleWriteBpsFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate))
errs = append(errs, writeFirstFile(group, blkioThrottleWriteBpsFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate))
}
for _, rd := range blockIO.ThrottleReadIOPSDevice {
errors = multierror.Append(errors, writeFirstFile(group, blkioThrottleReadIOPSFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate))
errs = append(errs, writeFirstFile(group, blkioThrottleReadIOPSFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate))
}
for _, rd := range blockIO.ThrottleWriteIOPSDevice {
errors = multierror.Append(errors, writeFirstFile(group, blkioThrottleWriteIOPSFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate))
errs = append(errs, writeFirstFile(group, blkioThrottleWriteIOPSFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate))
}
return errors.ErrorOrNil()
return errors.Join(errs...)
}
// writeFirstFile writes content to the first existing file in the list under groupDir.
func writeFirstFile(groupDir string, filenames []string, format string, args ...interface{}) error {
var errors *multierror.Error
errs := []error{}
// Returns list of errors from writes, list of single error due to all filenames missing or nil on success.
for _, filename := range filenames {
if err := Blkio.Group(groupDir).Write(filename, format, args...); err != nil {
errors = multierror.Append(errors, err)
errs = append(errs, err)
continue
}
return nil
}
err := errors.ErrorOrNil()
err := errors.Join(errs...)
if err != nil {
data := fmt.Sprintf(format, args...)
return fmt.Errorf("writing all files %v failed, errors: %w, content %q", filenames, err, data)

View File

@@ -31,7 +31,7 @@ type Controller int
// Group represents a control group.
type Group string
//nolint
// nolint
const (
// UnkownController represents a controller of unknown type.
UnknownController Controller = iota
@@ -105,7 +105,7 @@ func (c Controller) String() string {
// Path returns the absolute path of the given controller.
func (c Controller) Path() string {
return path.Join(mountDir, c.String())
return cgroupPath(c.String())
}
// RelPath returns the relative path of the given controller.
@@ -115,7 +115,7 @@ func (c Controller) RelPath() string {
// Group returns the given group for the controller.
func (c Controller) Group(group string) Group {
return Group(path.Join(mountDir, c.String(), group))
return Group(cgroupPath(c.String(), group))
}
// AsGroup returns the group for the given absolute directory path.
@@ -125,7 +125,7 @@ func AsGroup(absDir string) Group {
// Controller returns the controller for the group.
func (g Group) Controller() Controller {
relPath := strings.TrimPrefix(string(g), mountDir+"/")
relPath := strings.TrimPrefix(string(g), cgroupPath()+"/")
split := strings.SplitN(relPath, "/", 2)
if len(split) > 0 {
return controllerDirs[split[0]]
@@ -232,6 +232,6 @@ func (g Group) writePids(entry string, pids ...string) error {
// error returns a formatted group-specific error.
func (g Group) errorf(format string, args ...interface{}) error {
name := strings.TrimPrefix(string(g), mountDir+"/")
name := strings.TrimPrefix(string(g), cgroupPath()+"/")
return fmt.Errorf("cgroup "+name+": "+format, args...)
}

View File

@@ -15,11 +15,10 @@
package cgroups
import (
"path"
"path/filepath"
goresctrlpath "github.com/intel/goresctrl/pkg/path"
)
//nolint
// nolint
const (
// Tasks is a cgroup's "tasks" entry.
Tasks = "tasks"
@@ -37,39 +36,18 @@ const (
CpusetMems = "cpuset.mems"
)
var (
// mount is the parent directory for per-controller cgroupfs mounts.
mountDir = "/sys/fs/cgroup"
// v2Dir is the parent directory for per-controller cgroupfs mounts.
v2Dir = path.Join(mountDir, "unified")
// KubeletRoot is the --cgroup-root option the kubelet is running with.
KubeletRoot = ""
)
const cgroupBasePath = "sys/fs/cgroup"
// GetMountDir returns the common mount point for cgroup v1 controllers.
func GetMountDir() string {
return mountDir
}
// SetMountDir sets the common mount point for the cgroup v1 controllers.
func SetMountDir(dir string) {
v2, _ := filepath.Rel(mountDir, v2Dir)
mountDir = dir
if v2 != "" {
v2Dir = path.Join(mountDir, v2)
}
return cgroupPath()
}
// GetV2Dir returns the cgroup v2 unified mount directory.
func GetV2Dir() string {
return v2Dir
return cgroupPath("unified")
}
// SetV2Dir sets the unified cgroup v2 mount directory.
func SetV2Dir(dir string) {
if dir[0] == '/' {
v2Dir = dir
} else {
v2Dir = path.Join(mountDir, v2Dir)
}
func cgroupPath(elems ...string) string {
return goresctrlpath.Path(append([]string{cgroupBasePath}, elems...)...)
}

35
vendor/github.com/intel/goresctrl/pkg/path/path.go generated vendored Normal file
View File

@@ -0,0 +1,35 @@
/*
Copyright 2023 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package path
import "path/filepath"
// RootDir is a helper for handling system directory paths
type RootDir string
var prefix RootDir = "/"
// Path returns a full path to a file under RootDir
func (d RootDir) Path(elems ...string) string {
return filepath.Join(append([]string{string(d)}, elems...)...)
}
// SetPrefix sets the global path prefix to use for all system files.
func SetPrefix(p string) { prefix = RootDir(p) }
// Path returns a path to a file, prefixed with the global prefix.
func Path(elems ...string) string { return prefix.Path(elems...) }

View File

@@ -19,7 +19,6 @@ package rdt
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
@@ -336,6 +335,6 @@ func readFileBitmask(path string) (bitmask, error) {
}
func readFileString(path string) (string, error) {
data, err := ioutil.ReadFile(path)
data, err := os.ReadFile(path)
return strings.TrimSpace(string(data)), err
}

View File

@@ -25,28 +25,28 @@ limitations under the License.
// Monitoring (MBM).
//
// Basic usage example:
// rdt.SetLogger(logrus.New())
//
// if err := rdt.Initialize(""); err != nil {
// return fmt.Errorf("RDT not supported: %v", err)
// }
// rdt.SetLogger(logrus.New())
//
// if err := rdt.SetConfigFromFile("/path/to/rdt.conf.yaml", false); err != nil {
// return fmt.Errorf("RDT configuration failed: %v", err)
// }
// if err := rdt.Initialize(""); err != nil {
// return fmt.Errorf("RDT not supported: %v", err)
// }
//
// if cls, ok := rdt.GetClass("my-class"); ok {
// // Set PIDs 12345 and 12346 to class "my-class"
// if err := cls.AddPids("12345", "12346"); err != nil {
// return fmt.Errorf("failed to add PIDs to RDT class: %v", err)
// }
// }
// if err := rdt.SetConfigFromFile("/path/to/rdt.conf.yaml", false); err != nil {
// return fmt.Errorf("RDT configuration failed: %v", err)
// }
//
// if cls, ok := rdt.GetClass("my-class"); ok {
// // Set PIDs 12345 and 12346 to class "my-class"
// if err := cls.AddPids("12345", "12346"); err != nil {
// return fmt.Errorf("failed to add PIDs to RDT class: %v", err)
// }
// }
package rdt
import (
"errors"
"fmt"
"io/ioutil"
stdlog "log"
"os"
"path/filepath"
@@ -244,7 +244,7 @@ func SetConfigFromData(data []byte, force bool) error {
// SetConfigFromFile reads configuration from the filesystem and reconfigures
// the resctrl filesystem.
func SetConfigFromFile(path string, force bool) error {
data, err := ioutil.ReadFile(path)
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("failed to read config file: %v", err)
}
@@ -490,11 +490,11 @@ func (c *control) pruneMonGroups() error {
}
func (c *control) readRdtFile(rdtPath string) ([]byte, error) {
return ioutil.ReadFile(filepath.Join(info.resctrlPath, rdtPath))
return os.ReadFile(filepath.Join(info.resctrlPath, rdtPath))
}
func (c *control) writeRdtFile(rdtPath string, data []byte) error {
if err := ioutil.WriteFile(filepath.Join(info.resctrlPath, rdtPath), data, 0644); err != nil {
if err := os.WriteFile(filepath.Join(info.resctrlPath, rdtPath), data, 0644); err != nil {
return c.cmdError(err)
}
return nil
@@ -728,7 +728,7 @@ func (r *resctrlGroup) GetMonData() MonData {
}
func (r *resctrlGroup) getMonL3Data() (MonL3Data, error) {
files, err := ioutil.ReadDir(r.path("mon_data"))
files, err := os.ReadDir(r.path("mon_data"))
if err != nil {
return nil, err
}
@@ -759,7 +759,7 @@ func (r *resctrlGroup) getMonL3Data() (MonL3Data, error) {
}
func (r *resctrlGroup) getMonLeafData(path string) (MonLeafData, error) {
files, err := ioutil.ReadDir(r.path(path))
files, err := os.ReadDir(r.path(path))
if err != nil {
return nil, err
}
@@ -826,7 +826,7 @@ func (m *monGroup) GetAnnotations() map[string]string {
}
func resctrlGroupsFromFs(prefix string, path string) ([]string, error) {
files, err := ioutil.ReadDir(path)
files, err := os.ReadDir(path)
if err != nil {
return nil, err
}

View File

@@ -20,12 +20,13 @@ import (
"encoding/binary"
"fmt"
"os"
goresctrlpath "github.com/intel/goresctrl/pkg/path"
)
func ReadMSR(cpu ID, msr int64) (uint64, error) {
str := fmt.Sprintf("/dev/cpu/%d/msr", cpu)
file, err := os.Open(str)
path := goresctrlpath.Path("dev/cpu", fmt.Sprintf("%d", cpu), "msr")
file, err := os.Open(path)
if err != nil {
return 0, err
}

View File

@@ -18,26 +18,25 @@ package utils
import (
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
goresctrlpath "github.com/intel/goresctrl/pkg/path"
)
const (
SysfsUncoreBasepath = "/sys/devices/system/cpu/intel_uncore_frequency/"
SysfsUncoreBasepath = "sys/devices/system/cpu/intel_uncore_frequency"
SysfsCpuBasepath = "sys/devices/system/cpu"
)
func setCPUFreqValue(cpu ID, setting string, value int) error {
path := fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/%s", cpu, setting)
return writeFileInt(path, value)
return writeFileInt(cpuFreqPath(cpu, setting), value)
}
// GetCPUFreqValue returns information of the currently used CPU frequency
func GetCPUFreqValue(cpu ID, setting string) (int, error) {
str := fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/%s", cpu, setting)
raw, err := ioutil.ReadFile(str)
raw, err := os.ReadFile(cpuFreqPath(cpu, setting))
if err != nil {
return 0, err
}
@@ -50,6 +49,10 @@ func GetCPUFreqValue(cpu ID, setting string) (int, error) {
return value, nil
}
func cpuFreqPath(cpu ID, setting string) string {
return goresctrlpath.Path(SysfsCpuBasepath, fmt.Sprintf("cpu%d", cpu), "cpufreq", setting)
}
// SetCPUScalingMinFreq sets the scaling_min_freq value of a given CPU
func SetCPUScalingMinFreq(cpu ID, freq int) error {
return setCPUFreqValue(cpu, "scaling_min_freq", freq)
@@ -84,7 +87,7 @@ func SetCPUsScalingMaxFreq(cpus []ID, freq int) error {
// UncoreFreqAvailable returns true if the uncore frequency control functions are available.
func UncoreFreqAvailable() bool {
_, err := os.Stat(SysfsUncoreBasepath)
_, err := os.Stat(goresctrlpath.Path(SysfsUncoreBasepath))
return err == nil
}
@@ -99,7 +102,7 @@ func SetUncoreMaxFreq(pkg, die ID, freqKhz int) error {
}
func uncoreFreqPath(pkg, die ID, attribute string) string {
return fmt.Sprintf(SysfsUncoreBasepath+"package_%02d_die_%02d/%s", pkg, die, attribute)
return goresctrlpath.Path(SysfsUncoreBasepath, fmt.Sprintf("package_%02d_die_%02d", pkg, die), attribute)
}
func getUncoreFreqValue(pkg, die ID, attribute string) (int, error) {
@@ -123,11 +126,11 @@ func setUncoreFreqValue(pkg, die ID, attribute string, value int) error {
}
func writeFileInt(path string, value int) error {
return ioutil.WriteFile(path, []byte(strconv.Itoa(value)), 0644)
return os.WriteFile(path, []byte(strconv.Itoa(value)), 0644)
}
func readFileInt(path string) (int, error) {
data, err := ioutil.ReadFile(path)
data, err := os.ReadFile(path)
if err != nil {
return 0, err
}