diff --git a/go.mod b/go.mod index 7ad560acf..9aabe5690 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/google/uuid v1.5.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/intel/goresctrl v0.5.0 + github.com/intel/goresctrl v0.6.0 github.com/klauspost/compress v1.17.4 github.com/minio/sha256-simd v1.0.1 github.com/moby/locker v1.0.1 diff --git a/go.sum b/go.sum index 4bf400b3b..8d9bf22e7 100644 --- a/go.sum +++ b/go.sum @@ -177,8 +177,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/intel/goresctrl v0.5.0 h1:kcDhjE3ZF/mNrJuRzLS3LY2Hp6atFaF1XVFBT7SVL2g= -github.com/intel/goresctrl v0.5.0/go.mod h1:mIe63ggylWYr0cU/l8n11FAkesqfvuP3oktIsxvu0T0= +github.com/intel/goresctrl v0.6.0 h1:lOqo9o+uXtqPwSB4vpd1greUcWlkBSTPdnbTFgRILf4= +github.com/intel/goresctrl v0.6.0/go.mod h1:Qg+rhwvfW78p22OJi649sCH71bJIBX7zT0b+IGe69eE= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= diff --git a/vendor/github.com/intel/goresctrl/pkg/blockio/blockio.go b/vendor/github.com/intel/goresctrl/pkg/blockio/blockio.go index 06c88b33f..46250042e 100644 --- a/vendor/github.com/intel/goresctrl/pkg/blockio/blockio.go +++ b/vendor/github.com/intel/goresctrl/pkg/blockio/blockio.go @@ -115,7 +115,6 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "sigs.k8s.io/yaml" - "github.com/intel/goresctrl/pkg/cgroups" grclog "github.com/intel/goresctrl/pkg/log" goresctrlpath "github.com/intel/goresctrl/pkg/path" ) @@ -143,7 +142,7 @@ var log grclog.Logger = grclog.NewLoggerWrapper(stdlog.New(os.Stderr, "[ blockio // classBlockIO connects user-defined block I/O classes to // corresponding cgroups blockio controller parameters. -var classBlockIO = map[string]cgroups.BlockIOParameters{} +var classBlockIO = map[string]BlockIOParameters{} // SetLogger sets the logger instance to be used by the package. // Examples: @@ -173,7 +172,7 @@ func SetConfigFromFile(filename string, force bool) error { // SetConfigFromData parses and applies configuration from data. func SetConfigFromData(data []byte, force bool) error { config := &Config{} - if err := yaml.Unmarshal(data, &config); err != nil { + if err := yaml.UnmarshalStrict(data, &config); err != nil { return err } return SetConfig(config, force) @@ -184,7 +183,7 @@ func SetConfig(opt *Config, force bool) error { if opt == nil { // Setting nil configuration clears current configuration. // SetConfigFromData([]byte(""), dontcare) arrives here. - classBlockIO = map[string]cgroups.BlockIOParameters{} + classBlockIO = map[string]BlockIOParameters{} return nil } @@ -193,7 +192,7 @@ func SetConfig(opt *Config, force bool) error { log.Warnf("configuration validation partly disabled due to I/O scheduler detection error %#v", ioSchedulerDetectionError.Error()) } - classBlockIO = map[string]cgroups.BlockIOParameters{} + classBlockIO = map[string]BlockIOParameters{} // Create cgroup blockio parameters for each blockio class for class := range opt.Classes { cgBlockIO, err := devicesParametersToCgBlockIO(opt.Classes[class], currentIOSchedulers) @@ -219,22 +218,6 @@ func GetClasses() []string { return classNames } -// SetCgroupClass sets cgroup blkio controller parameters to match -// blockio class. "group" is the cgroup directory of the container -// without mountpoint and controller (blkio) directories: -// "/kubepods/burstable/POD_ID/CONTAINER_ID". -func SetCgroupClass(group string, class string) error { - cgBlockIO, ok := classBlockIO[class] - if !ok { - return fmt.Errorf("no BlockIO parameters for class %#v", class) - } - err := cgroups.ResetBlkioParameters(group, cgBlockIO) - if err != nil { - return fmt.Errorf("assigning container in cgroup %q to class %#v failed: %w", group, class, err) - } - return nil -} - // getCurrentIOSchedulers returns currently active I/O scheduler used for each block device in the system. // Returns schedulers in a map: {"/dev/sda": "bfq"} func getCurrentIOSchedulers() (map[string]string, error) { @@ -274,9 +257,9 @@ 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) { +func devicesParametersToCgBlockIO(dps []DevicesParameters, currentIOSchedulers map[string]string) (BlockIOParameters, error) { errs := []error{} - blkio := cgroups.NewBlockIOParameters() + blkio := NewBlockIOParameters() for _, dp := range dps { var err error var weight, throttleReadBps, throttleWriteBps, throttleReadIOPS, throttleWriteIOPS int64 diff --git a/vendor/github.com/intel/goresctrl/pkg/blockio/cgroups.go b/vendor/github.com/intel/goresctrl/pkg/blockio/cgroups.go new file mode 100644 index 000000000..d17751f91 --- /dev/null +++ b/vendor/github.com/intel/goresctrl/pkg/blockio/cgroups.go @@ -0,0 +1,103 @@ +// Copyright 2020-2021 Intel Corporation. All Rights Reserved. +// +// 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 blockio + +// BlockIOParameters contains cgroups blockio controller parameters. +// +// 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. +type BlockIOParameters struct { + Weight int64 + WeightDevice DeviceWeights + ThrottleReadBpsDevice DeviceRates + ThrottleWriteBpsDevice DeviceRates + ThrottleReadIOPSDevice DeviceRates + ThrottleWriteIOPSDevice DeviceRates +} + +// DeviceWeight contains values for +// - blkio.[io-scheduler].weight +type DeviceWeight struct { + Major int64 + Minor int64 + Weight int64 +} + +// DeviceRate contains values for +// - blkio.throttle.read_bps_device +// - blkio.throttle.write_bps_device +// - blkio.throttle.read_iops_device +// - blkio.throttle.write_iops_device +type DeviceRate struct { + Major int64 + Minor int64 + Rate int64 +} + +// DeviceWeights contains weights for devices. +type DeviceWeights []DeviceWeight + +// DeviceRates contains throttling rates for devices. +type DeviceRates []DeviceRate + +// NewBlockIOParameters creates new BlockIOParameters instance. +func NewBlockIOParameters() BlockIOParameters { + return BlockIOParameters{ + Weight: -1, + } +} + +// DeviceParameters interface provides functions common to DeviceWeights and DeviceRates. +type DeviceParameters interface { + Append(maj, min, val int64) + Update(maj, min, val int64) +} + +// Append appends (major, minor, value) to DeviceWeights slice. +func (w *DeviceWeights) Append(maj, min, val int64) { + *w = append(*w, DeviceWeight{Major: maj, Minor: min, Weight: val}) +} + +// Append appends (major, minor, value) to DeviceRates slice. +func (r *DeviceRates) Append(maj, min, val int64) { + *r = append(*r, DeviceRate{Major: maj, Minor: min, Rate: val}) +} + +// Update updates device weight in DeviceWeights slice, or appends it if not found. +func (w *DeviceWeights) Update(maj, min, val int64) { + for index, devWeight := range *w { + if devWeight.Major == maj && devWeight.Minor == min { + (*w)[index].Weight = val + return + } + } + w.Append(maj, min, val) +} + +// Update updates device rate in DeviceRates slice, or appends it if not found. +func (r *DeviceRates) Update(maj, min, val int64) { + for index, devRate := range *r { + if devRate.Major == maj && devRate.Minor == min { + (*r)[index].Rate = val + return + } + } + r.Append(maj, min, val) +} diff --git a/vendor/github.com/intel/goresctrl/pkg/blockio/oci.go b/vendor/github.com/intel/goresctrl/pkg/blockio/oci.go index 1b30808aa..9684e9520 100644 --- a/vendor/github.com/intel/goresctrl/pkg/blockio/oci.go +++ b/vendor/github.com/intel/goresctrl/pkg/blockio/oci.go @@ -20,8 +20,6 @@ import ( "fmt" oci "github.com/opencontainers/runtime-spec/specs-go" - - "github.com/intel/goresctrl/pkg/cgroups" ) // OciLinuxBlockIO returns OCI LinuxBlockIO structure corresponding to the class. @@ -43,7 +41,7 @@ func OciLinuxBlockIO(class string) (*oci.LinuxBlockIO, error) { return &ociBlockio, nil } -func ociLinuxWeightDevices(dws cgroups.DeviceWeights) []oci.LinuxWeightDevice { +func ociLinuxWeightDevices(dws DeviceWeights) []oci.LinuxWeightDevice { if len(dws) == 0 { return nil } @@ -57,7 +55,7 @@ func ociLinuxWeightDevices(dws cgroups.DeviceWeights) []oci.LinuxWeightDevice { return olwds } -func ociLinuxThrottleDevices(drs cgroups.DeviceRates) []oci.LinuxThrottleDevice { +func ociLinuxThrottleDevices(drs DeviceRates) []oci.LinuxThrottleDevice { if len(drs) == 0 { return nil } diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupblkio.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupblkio.go deleted file mode 100644 index a12a6e822..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupblkio.go +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2020-2021 Intel Corporation. All Rights Reserved. -// -// 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 cgroups - -import ( - "errors" - "fmt" - "strconv" - "strings" -) - -// cgroups blkio parameter filenames. -var blkioWeightFiles = []string{"blkio.bfq.weight", "blkio.weight"} -var blkioWeightDeviceFiles = []string{"blkio.bfq.weight_device", "blkio.weight_device"} -var blkioThrottleReadBpsFiles = []string{"blkio.throttle.read_bps_device"} -var blkioThrottleWriteBpsFiles = []string{"blkio.throttle.write_bps_device"} -var blkioThrottleReadIOPSFiles = []string{"blkio.throttle.read_iops_device"} -var blkioThrottleWriteIOPSFiles = []string{"blkio.throttle.write_iops_device"} - -// BlockIOParameters contains cgroups blockio controller parameters. -// -// 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. -type BlockIOParameters struct { - Weight int64 - WeightDevice DeviceWeights - ThrottleReadBpsDevice DeviceRates - ThrottleWriteBpsDevice DeviceRates - ThrottleReadIOPSDevice DeviceRates - ThrottleWriteIOPSDevice DeviceRates -} - -// DeviceWeight contains values for -// - blkio.[io-scheduler].weight -type DeviceWeight struct { - Major int64 - Minor int64 - Weight int64 -} - -// DeviceRate contains values for -// - blkio.throttle.read_bps_device -// - blkio.throttle.write_bps_device -// - blkio.throttle.read_iops_device -// - blkio.throttle.write_iops_device -type DeviceRate struct { - Major int64 - Minor int64 - Rate int64 -} - -// DeviceWeights contains weights for devices. -type DeviceWeights []DeviceWeight - -// DeviceRates contains throttling rates for devices. -type DeviceRates []DeviceRate - -// DeviceParameters interface provides functions common to DeviceWeights and DeviceRates. -type DeviceParameters interface { - Append(maj, min, val int64) - Update(maj, min, val int64) -} - -// Append appends (major, minor, value) to DeviceWeights slice. -func (w *DeviceWeights) Append(maj, min, val int64) { - *w = append(*w, DeviceWeight{Major: maj, Minor: min, Weight: val}) -} - -// Append appends (major, minor, value) to DeviceRates slice. -func (r *DeviceRates) Append(maj, min, val int64) { - *r = append(*r, DeviceRate{Major: maj, Minor: min, Rate: val}) -} - -// Update updates device weight in DeviceWeights slice, or appends it if not found. -func (w *DeviceWeights) Update(maj, min, val int64) { - for index, devWeight := range *w { - if devWeight.Major == maj && devWeight.Minor == min { - (*w)[index].Weight = val - return - } - } - w.Append(maj, min, val) -} - -// Update updates device rate in DeviceRates slice, or appends it if not found. -func (r *DeviceRates) Update(maj, min, val int64) { - for index, devRate := range *r { - if devRate.Major == maj && devRate.Minor == min { - (*r)[index].Rate = val - return - } - } - r.Append(maj, min, val) -} - -// NewBlockIOParameters creates new BlockIOParameters instance. -func NewBlockIOParameters() BlockIOParameters { - return BlockIOParameters{ - Weight: -1, - } -} - -// NewDeviceWeight creates new DeviceWeight instance. -func NewDeviceWeight() DeviceWeight { - return DeviceWeight{ - Major: -1, - Minor: -1, - Weight: -1, - } -} - -// NewDeviceRate creates new DeviceRate instance. -func NewDeviceRate() DeviceRate { - return DeviceRate{ - Major: -1, - Minor: -1, - Rate: -1, - } -} - -type devMajMin struct { - Major int64 - Minor int64 -} - -// ResetBlkioParameters adds new, changes existing and removes missing blockIO parameters in cgroupsDir. -func ResetBlkioParameters(groupDir string, blockIO BlockIOParameters) error { - errs := []error{} - oldBlockIO, _ := GetBlkioParameters(groupDir) - newBlockIO := NewBlockIOParameters() - newBlockIO.Weight = blockIO.Weight - newBlockIO.WeightDevice = resetDevWeights(oldBlockIO.WeightDevice, blockIO.WeightDevice) - newBlockIO.ThrottleReadBpsDevice = resetDevRates(oldBlockIO.ThrottleReadBpsDevice, blockIO.ThrottleReadBpsDevice) - newBlockIO.ThrottleWriteBpsDevice = resetDevRates(oldBlockIO.ThrottleWriteBpsDevice, blockIO.ThrottleWriteBpsDevice) - newBlockIO.ThrottleReadIOPSDevice = resetDevRates(oldBlockIO.ThrottleReadIOPSDevice, blockIO.ThrottleReadIOPSDevice) - newBlockIO.ThrottleWriteIOPSDevice = resetDevRates(oldBlockIO.ThrottleWriteIOPSDevice, blockIO.ThrottleWriteIOPSDevice) - errs = append(errs, SetBlkioParameters(groupDir, newBlockIO)) - return errors.Join(errs...) -} - -// resetDevWeights adds wanted weight parameters to new and resets unwanted weights. -func resetDevWeights(old, wanted []DeviceWeight) []DeviceWeight { - new := []DeviceWeight{} - seenDev := map[devMajMin]bool{} - for _, wdp := range wanted { - seenDev[devMajMin{wdp.Major, wdp.Minor}] = true - new = append(new, wdp) - } - for _, wdp := range old { - if !seenDev[devMajMin{wdp.Major, wdp.Minor}] { - new = append(new, DeviceWeight{wdp.Major, wdp.Minor, 0}) - } - } - return new -} - -// resetDevRates adds wanted rate parameters to new and resets unwanted rates. -func resetDevRates(old, wanted []DeviceRate) []DeviceRate { - new := []DeviceRate{} - seenDev := map[devMajMin]bool{} - for _, rdp := range wanted { - new = append(new, rdp) - seenDev[devMajMin{rdp.Major, rdp.Minor}] = true - } - for _, rdp := range old { - if !seenDev[devMajMin{rdp.Major, rdp.Minor}] { - new = append(new, DeviceRate{rdp.Major, rdp.Minor, 0}) - } - } - return new -} - -// GetBlkioParameters returns BlockIO parameters from files in cgroups blkio controller directory. -func GetBlkioParameters(group string) (BlockIOParameters, error) { - errs := []error{} - blockIO := NewBlockIOParameters() - - 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. -func readWeight(groupDir string, filenames []string, rv *int64) error { - contents, err := readFirstFile(groupDir, filenames) - if err != nil { - return err - } - parsed, err := strconv.ParseInt(strings.TrimSuffix(contents, "\n"), 10, 64) - if err != nil { - return fmt.Errorf("parsing weight from %#v found in %v failed: %w", contents, filenames, err) - } - *rv = parsed - return nil -} - -// readDeviceParameters parses device lines used for weights and throttling rates. -func readDeviceParameters(groupDir string, filenames []string, params DeviceParameters) error { - errs := []error{} - contents, err := readFirstFile(groupDir, filenames) - if err != nil { - return err - } - for _, line := range strings.Split(contents, "\n") { - // Device weight files may have "default NNN" line at the beginning. Skip it. - if line == "" || strings.HasPrefix(line, "default ") { - continue - } - // Expect syntax MAJOR:MINOR VALUE - devVal := strings.Split(line, " ") - if len(devVal) != 2 { - errs = append(errs, fmt.Errorf("invalid line %q, single space expected", line)) - continue - } - majMin := strings.Split(devVal[0], ":") - if len(majMin) != 2 { - 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 { - 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.Join(errs...) -} - -// readFirstFile returns contents of the first successfully read entry. -func readFirstFile(groupDir string, filenames []string) (string, 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 - } - errs = append(errs, err) - } - err := errors.Join(errs...) - if err != nil { - return "", fmt.Errorf("could not read any of files %q: %w", filenames, err) - } - return "", nil -} - -// SetBlkioParameters writes BlockIO parameters to files in cgroups blkio contoller directory. -func SetBlkioParameters(group string, blockIO BlockIOParameters) error { - errs := []error{} - if blockIO.Weight >= 0 { - errs = append(errs, writeFirstFile(group, blkioWeightFiles, "%d", blockIO.Weight)) - } - for _, wd := range blockIO.WeightDevice { - errs = append(errs, writeFirstFile(group, blkioWeightDeviceFiles, "%d:%d %d", wd.Major, wd.Minor, wd.Weight)) - } - for _, rd := range blockIO.ThrottleReadBpsDevice { - errs = append(errs, writeFirstFile(group, blkioThrottleReadBpsFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate)) - } - for _, rd := range blockIO.ThrottleWriteBpsDevice { - errs = append(errs, writeFirstFile(group, blkioThrottleWriteBpsFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate)) - } - for _, rd := range blockIO.ThrottleReadIOPSDevice { - errs = append(errs, writeFirstFile(group, blkioThrottleReadIOPSFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate)) - } - for _, rd := range blockIO.ThrottleWriteIOPSDevice { - errs = append(errs, writeFirstFile(group, blkioThrottleWriteIOPSFiles, "%d:%d %d", rd.Major, rd.Minor, rd.Rate)) - } - 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 { - 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 { - errs = append(errs, err) - continue - } - return nil - } - 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) - } - return nil -} diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupcontrol.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupcontrol.go deleted file mode 100644 index f5a1b8bc2..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupcontrol.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2020-2021 Intel Corporation. All Rights Reserved. -// -// 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 cgroups - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "os" - "path" - "strings" - "syscall" -) - -// Controller is our enumerated type for cgroup controllers. -type Controller int - -// Group represents a control group. -type Group string - -// nolint -const ( - // UnkownController represents a controller of unknown type. - UnknownController Controller = iota - // blkio cgroup controller. - Blkio - // cpu cgroup controller. - Cpu - // cpuacct cgroup controller. - Cpuacct - // cpuset cgroup controller. - Cpuset - // devices cgroup controller. - Devices - // freezer cgroup controller. - Freezer - // hugetlb cgroup controller. - Hugetlb - // memory cgroup controller. - Memory - // net_cls cgroup controller. - NetCls - // net_prio cgroup controller. - NetPrio - // per_event cgroup controller. - PerfEvent - // pids cgroup controller. - Pids -) - -var ( - // controllerNames maps controllers to names/relative paths. - controllerNames = map[Controller]string{ - Blkio: "blkio", - Cpu: "cpu", - Cpuacct: "cpuacct", - Cpuset: "cpuset", - Devices: "devices", - Freezer: "freezer", - Hugetlb: "hugetlb", - Memory: "memory", - NetCls: "net_cls", - NetPrio: "net_prio", - PerfEvent: "perf_event", - Pids: "pids", - } - - // controllerNames maps controllers to names/relative paths. - controllerDirs = map[string]Controller{ - "blkio": Blkio, - "cpu": Cpu, - "cpuacct": Cpuacct, - "cpuset": Cpuset, - "devices": Devices, - "freezer": Freezer, - "hugetlb": Hugetlb, - "memory": Memory, - "net_cls": NetCls, - "net_prio": NetPrio, - "perf_event": PerfEvent, - "pids": Pids, - } -) - -// String returns the name of the given controller. -func (c Controller) String() string { - if name, ok := controllerNames[c]; ok { - return name - } - return "unknown" -} - -// Path returns the absolute path of the given controller. -func (c Controller) Path() string { - return cgroupPath(c.String()) -} - -// RelPath returns the relative path of the given controller. -func (c Controller) RelPath() string { - return c.String() -} - -// Group returns the given group for the controller. -func (c Controller) Group(group string) Group { - return Group(cgroupPath(c.String(), group)) -} - -// AsGroup returns the group for the given absolute directory path. -func AsGroup(absDir string) Group { - return Group(absDir) -} - -// Controller returns the controller for the group. -func (g Group) Controller() Controller { - relPath := strings.TrimPrefix(string(g), cgroupPath()+"/") - split := strings.SplitN(relPath, "/", 2) - if len(split) > 0 { - return controllerDirs[split[0]] - } - return UnknownController -} - -// GetTasks reads the pids of threads currently assigned to the group. -func (g Group) GetTasks() ([]string, error) { - return g.readPids(Tasks) -} - -// GetProcesses reads the pids of processes currently assigned to the group. -func (g Group) GetProcesses() ([]string, error) { - return g.readPids(Procs) -} - -// AddTasks writes the given thread pids to the group. -func (g Group) AddTasks(pids ...string) error { - return g.writePids(Tasks, pids...) -} - -// AddProcesses writes the given process pids to the group. -func (g Group) AddProcesses(pids ...string) error { - return g.writePids(Procs, pids...) -} - -// Write writes the formatted data to the groups entry. -func (g Group) Write(entry, format string, args ...interface{}) error { - entryPath := path.Join(string(g), entry) - f, err := fsi.OpenFile(entryPath, os.O_WRONLY, 0644) - if err != nil { - return g.errorf("%q: failed to open for writing: %v", entry, err) - } - defer f.Close() - - data := fmt.Sprintf(format, args...) - if _, err := f.Write([]byte(data)); err != nil { - return g.errorf("%q: failed to write %q: %v", entry, data, err) - } - - return nil -} - -// Read the groups entry and return contents in a string -func (g Group) Read(entry string) (string, error) { - var buf bytes.Buffer - entryPath := path.Join(string(g), entry) - f, err := fsi.OpenFile(entryPath, os.O_RDONLY, 0644) - if err != nil { - return "", g.errorf("%q: failed to open for reading: %v", entry, err) - } - defer f.Close() - if _, err := buf.ReadFrom(f); err != nil { - return "", err - } - return buf.String(), nil -} - -// readPids reads pids from a cgroup's tasks or procs entry. -func (g Group) readPids(entry string) ([]string, error) { - var pids []string - - pidFile := path.Join(string(g), entry) - - f, err := fsi.OpenFile(pidFile, os.O_RDONLY, 0644) - if err != nil { - return nil, g.errorf("failed to open %q: %v", entry, err) - } - defer f.Close() - - s := bufio.NewScanner(f) - for s.Scan() { - pids = append(pids, s.Text()) - } - if s.Err() != nil { - return nil, g.errorf("failed to read %q: %v", entry, err) - } - - return pids, nil -} - -// writePids writes pids to a cgroup's tasks or procs entry. -func (g Group) writePids(entry string, pids ...string) error { - pidFile := path.Join(string(g), entry) - - f, err := fsi.OpenFile(pidFile, os.O_WRONLY, 0644) - if err != nil { - return g.errorf("failed to write pids to %q: %v", pidFile, err) - } - defer f.Close() - - for _, pid := range pids { - if _, err := f.Write([]byte(pid)); err != nil { - if !errors.Is(err, syscall.ESRCH) { - return g.errorf("failed to write pid %s to %q: %v", - pidFile, pid, err) - } - } - } - - return nil -} - -// error returns a formatted group-specific error. -func (g Group) errorf(format string, args ...interface{}) error { - name := strings.TrimPrefix(string(g), cgroupPath()+"/") - return fmt.Errorf("cgroup "+name+": "+format, args...) -} diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid.go deleted file mode 100644 index 920312943..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid.go +++ /dev/null @@ -1,65 +0,0 @@ -package cgroups - -import ( - "fmt" - "os" - "path/filepath" - "sync" -) - -// CgroupID implements mapping kernel cgroup IDs to cgroupfs paths with transparent caching. -type CgroupID struct { - root string - cache map[uint64]string - sync.Mutex -} - -// NewCgroupID creates a new CgroupID map/cache. -func NewCgroupID(root string) *CgroupID { - return &CgroupID{ - root: root, - cache: make(map[uint64]string), - } -} - -// Find finds the path for the given cgroup id. -func (cgid *CgroupID) Find(id uint64) (string, error) { - found := false - var p string - - cgid.Lock() - defer cgid.Unlock() - - if path, ok := cgid.cache[id]; ok { - return path, nil - } - - err := fsi.Walk(cgid.root, func(path string, info os.FileInfo, err error) error { - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - - if found { - return filepath.SkipDir - } - - if info.IsDir() && id == getID(path) { - found = true - p = path - return filepath.SkipDir - } - return nil - }) - - if err != nil { - return "", err - } else if !found { - return "", fmt.Errorf("cgroupid %v not found", id) - } else { - cgid.cache[id] = p - return p, nil - } -} diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid_linux.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid_linux.go deleted file mode 100644 index 6c27ff1e1..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid_linux.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build linux -// +build linux - -package cgroups - -import ( - "encoding/binary" - "golang.org/x/sys/unix" -) - -func getID(path string) uint64 { - h, _, err := unix.NameToHandleAt(unix.AT_FDCWD, path, 0) - if err != nil { - return 0 - } - - return binary.LittleEndian.Uint64(h.Bytes()) -} diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid_other.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid_other.go deleted file mode 100644 index 519450a3f..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgroupid_other.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !linux -// +build !linux - -package cgroups - -func getID(path string) uint64 { - return 0 -} diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgrouppath.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/cgrouppath.go deleted file mode 100644 index 619f20820..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/cgrouppath.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 Intel Corporation. All Rights Reserved. -// -// 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 cgroups - -import ( - goresctrlpath "github.com/intel/goresctrl/pkg/path" -) - -// nolint -const ( - // Tasks is a cgroup's "tasks" entry. - Tasks = "tasks" - // Procs is cgroup's "cgroup.procs" entry. - Procs = "cgroup.procs" - // CpuShares is the cpu controller's "cpu.shares" entry. - CpuShares = "cpu.shares" - // CpuPeriod is the cpu controller's "cpu.cfs_period_us" entry. - CpuPeriod = "cpu.cfs_period_us" - // CpuQuota is the cpu controller's "cpu.cfs_quota_us" entry. - CpuQuota = "cpu.cfs_quota_us" - // CpusetCpus is the cpuset controller's cpuset.cpus entry. - CpusetCpus = "cpuset.cpus" - // CpusetMems is the cpuset controller's cpuset.mems entry. - CpusetMems = "cpuset.mems" -) - -const cgroupBasePath = "sys/fs/cgroup" - -// GetMountDir returns the common mount point for cgroup v1 controllers. -func GetMountDir() string { - return cgroupPath() -} - -// GetV2Dir returns the cgroup v2 unified mount directory. -func GetV2Dir() string { - return cgroupPath("unified") -} - -func cgroupPath(elems ...string) string { - return goresctrlpath.Path(append([]string{cgroupBasePath}, elems...)...) -} diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/fsi.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/fsi.go deleted file mode 100644 index b5e32a2df..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/fsi.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2021 Intel Corporation. All Rights Reserved. -// -// 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. - -// This module defines filesystem interface (fsi) through which -// cgroups package accesses files. - -package cgroups - -import ( - "os" - "path/filepath" -) - -type fsiIface interface { - Open(name string) (fileIface, error) - OpenFile(name string, flag int, perm os.FileMode) (fileIface, error) - Walk(string, filepath.WalkFunc) error - Lstat(path string) (os.FileInfo, error) -} - -type fileIface interface { - Close() error - Read(p []byte) (n int, err error) - Write(b []byte) (n int, err error) -} - -// Set the default filesystem interface -var fsi fsiIface = newFsiOS() diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/fsimock.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/fsimock.go deleted file mode 100644 index 54bf47c40..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/fsimock.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2021 Intel Corporation. All Rights Reserved. -// -// 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. - -// This module implements a mock filesystem that can be used as a -// replacement for the native filesystem interface (fsi). - -package cgroups - -import ( - "fmt" - "io" - "os" - "path/filepath" - "strings" - "time" -) - -type fsMock struct { - files map[string]*mockFile // filesystem contents -} - -type mockFile struct { - // User-defined file properties - data []byte // contents of the file - - // User/fsimock-defined properties - info *mockFileInfo - - // File-specific user-overrides for the default file behavior - open func(string) (fileIface, error) - read func([]byte) (int, error) - write func([]byte) (int, error) - - // fsimock-defined properties - fs *fsMock - filename string - handle *mockFileHandle - writeHistory [][]byte -} - -type mockFileHandle struct { - pos int -} - -type mockFileInfo struct { - mode os.FileMode - name string - mf *mockFile -} - -func NewFsiMock(files map[string]mockFile) fsiIface { - mfs := fsMock{} - mfs.files = map[string]*mockFile{} - for filename, usermf := range files { - mf := usermf - if mf.info == nil { - mf.info = &mockFileInfo{} - } - if mf.info.name == "" { - mf.info.name = filepath.Base(filename) - } - mf.filename = filename - mf.info.mf = &mf - mf.fs = &mfs - mfs.files[filename] = &mf - } - return &mfs -} - -func (mfs fsMock) OpenFile(name string, flag int, perm os.FileMode) (fileIface, error) { - fsmockLog("OpenFile(%q, %d, %d)", name, flag, perm) - if mf, ok := mfs.files[name]; ok { - mf.handle = &mockFileHandle{} - if mf.open != nil { - return mf.open(name) - } - return *mf, nil - } - return nil, fsmockErrorf("%q: file not found", name) -} - -func (mfs fsMock) Open(name string) (fileIface, error) { - return mfs.OpenFile(name, 0, 0) -} - -func (mfs fsMock) Walk(path string, walkFn filepath.WalkFunc) error { - dirPath := strings.TrimSuffix(path, "/") - info, err := mfs.Lstat(dirPath) - if err != nil { - err = walkFn(path, nil, err) - return err - } - if !info.IsDir() { - return walkFn(path, info, nil) - } - err = walkFn(path, info, nil) - if err != nil { - return err - } - for _, name := range mfs.dirContents(dirPath) { - if err = mfs.Walk(dirPath+"/"+name, walkFn); err != nil && err != filepath.SkipDir { - return err - } - } - return nil -} - -func (mfs fsMock) dirContents(path string) []string { - dirPathS := strings.TrimSuffix(path, "/") + "/" - contentSet := map[string]struct{}{} - for filename := range mfs.files { - if !strings.HasPrefix(filename, dirPathS) { - continue - } - relToDirPath := strings.TrimPrefix(filename, dirPathS) - names := strings.SplitN(relToDirPath, "/", 2) - contentSet[names[0]] = struct{}{} - } - contents := make([]string, 0, len(contentSet)) - for name := range contentSet { - contents = append(contents, name) - } - return contents -} - -func (mfs fsMock) Lstat(path string) (os.FileInfo, error) { - if mf, ok := mfs.files[path]; ok { - return *mf.info, nil - } - if len(mfs.dirContents(path)) > 0 { - return mockFileInfo{ - name: filepath.Base(path), - mode: os.ModeDir, - }, nil - } - return mockFileInfo{}, fsmockErrorf("%q: file not found", path) -} - -func (mfi mockFileInfo) Name() string { - return mfi.name -} -func (mfi mockFileInfo) Size() int64 { - if mfi.mf != nil { - return int64(len(mfi.mf.data)) - } - return 0 -} -func (mfi mockFileInfo) Mode() os.FileMode { - return mfi.mode -} - -func (mfi mockFileInfo) ModTime() time.Time { - return time.Time{} -} - -func (mfi mockFileInfo) IsDir() bool { - return mfi.mode&os.ModeDir != 0 -} - -func (mfi mockFileInfo) Sys() interface{} { - return nil -} - -func (mf mockFile) Write(b []byte) (n int, err error) { - pos := mf.handle.pos - if mf.write != nil { - n, err = mf.write(b) - if err == nil { - mf.fs.files[mf.filename].writeHistory = append(mf.fs.files[mf.filename].writeHistory, b) - } - } else { - newpos := pos + len(b) - if newpos > cap(mf.data) { - newdata := make([]byte, newpos) - copy(newdata, mf.data) - mf.data = newdata - } - copy(mf.data[pos:newpos], b) - mf.handle.pos = newpos - if f, ok := mf.fs.files[mf.filename]; ok { - f.data = mf.data - } - mf.fs.files[mf.filename].writeHistory = append(mf.fs.files[mf.filename].writeHistory, b) - } - fsmockLog("{%q, pos=%d}.Write([%d]byte(%q)) = (%d, %v) %q", mf.filename, pos, len(b), string(b), n, err, mf.fs.files[mf.filename].data) - return n, err -} - -func (mf mockFile) Read(b []byte) (n int, err error) { - pos := mf.handle.pos - if mf.read != nil { - n, err = mf.read(b) - } else { - n = len(mf.data) - pos - err = nil - if n <= 0 { - err = io.EOF - } - if n > cap(b) { - n = cap(b) - } - copy(b, mf.data[pos:pos+n]) - mf.handle.pos += n - } - fsmockLog("{%q, pos=%d}.Read([%d]byte) = (%d, %v)\n", mf.filename, pos, len(b), n, err) - return -} - -func (mf mockFile) Close() error { - return nil -} - -func fsmockLog(format string, args ...interface{}) { - fmt.Printf("fsmock: "+format+"\n", args...) -} - -func fsmockErrorf(format string, args ...interface{}) error { - return fmt.Errorf("fsmock: "+format, args...) -} diff --git a/vendor/github.com/intel/goresctrl/pkg/cgroups/fsios.go b/vendor/github.com/intel/goresctrl/pkg/cgroups/fsios.go deleted file mode 100644 index d1eb35178..000000000 --- a/vendor/github.com/intel/goresctrl/pkg/cgroups/fsios.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2021 Intel Corporation. All Rights Reserved. -// -// 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. - -// This module provides the native implementation of the filesystem -// interface (fsi). - -package cgroups - -import ( - "os" - "path/filepath" -) - -type fsOs struct{} - -type osFile struct { - file *os.File -} - -func newFsiOS() fsiIface { - return fsOs{} -} - -func (fsOs) OpenFile(name string, flag int, perm os.FileMode) (fileIface, error) { - f, err := os.OpenFile(name, flag, perm) - return osFile{f}, err -} - -func (fsOs) Open(name string) (fileIface, error) { - f, err := os.Open(name) - return osFile{f}, err -} - -func (fsOs) Lstat(name string) (os.FileInfo, error) { - return os.Lstat(name) -} - -func (fsOs) Walk(root string, walkFn filepath.WalkFunc) error { - return filepath.Walk(root, walkFn) -} - -func (osf osFile) Write(b []byte) (n int, err error) { - return osf.file.Write(b) -} - -func (osf osFile) Read(b []byte) (n int, err error) { - return osf.file.Read(b) -} - -func (osf osFile) Close() error { - return osf.file.Close() -} diff --git a/vendor/github.com/intel/goresctrl/pkg/rdt/rdt.go b/vendor/github.com/intel/goresctrl/pkg/rdt/rdt.go index 52384802f..a0991f8ab 100644 --- a/vendor/github.com/intel/goresctrl/pkg/rdt/rdt.go +++ b/vendor/github.com/intel/goresctrl/pkg/rdt/rdt.go @@ -234,7 +234,7 @@ func SetConfig(c *Config, force bool) error { // reconfigures the resctrl filesystem. func SetConfigFromData(data []byte, force bool) error { cfg := &Config{} - if err := yaml.Unmarshal(data, &cfg); err != nil { + if err := yaml.UnmarshalStrict(data, cfg); err != nil { return fmt.Errorf("failed to parse configuration data: %v", err) } diff --git a/vendor/github.com/intel/goresctrl/pkg/utils/idset.go b/vendor/github.com/intel/goresctrl/pkg/utils/idset.go index 16fb4d443..71d256a4e 100644 --- a/vendor/github.com/intel/goresctrl/pkg/utils/idset.go +++ b/vendor/github.com/intel/goresctrl/pkg/utils/idset.go @@ -169,7 +169,7 @@ func (s *IDSet) UnmarshalJSON(data []byte) error { } for _, idstr := range strings.Split(str, ",") { - id, err := strconv.ParseUint(idstr, 10, 0) + id, err := strconv.ParseInt(idstr, 10, 0) if err != nil { return fmt.Errorf("invalid IDSet entry '%s': %v", idstr, err) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 3cca7578a..09e037fa2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -256,10 +256,9 @@ github.com/grpc-ecosystem/go-grpc-prometheus github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/utilities -# github.com/intel/goresctrl v0.5.0 +# github.com/intel/goresctrl v0.6.0 ## explicit; go 1.20 github.com/intel/goresctrl/pkg/blockio -github.com/intel/goresctrl/pkg/cgroups github.com/intel/goresctrl/pkg/kubernetes github.com/intel/goresctrl/pkg/log github.com/intel/goresctrl/pkg/path