Merge pull request #3377 from wineway/main

libct/cg: support SCHED_IDLE for runc cgroupfs
This commit is contained in:
Kir Kolyshkin
2023-01-31 19:19:03 -08:00
committed by GitHub
9 changed files with 90 additions and 2 deletions

View File

@@ -743,6 +743,7 @@ _runc_update() {
--pids-limit
--l3-cache-schema
--mem-bw-schema
--cpu-idle
"
case "$prev" in

View File

@@ -94,6 +94,14 @@ func (s *CpuGroup) Set(path string, r *configs.Resources) error {
}
}
}
if r.CPUIdle != nil {
idle := strconv.FormatInt(*r.CPUIdle, 10)
if err := cgroups.WriteFile(path, "cpu.idle", idle); err != nil {
return err
}
}
return s.SetRtSched(path, r)
}

View File

@@ -11,7 +11,7 @@ import (
)
func isCpuSet(r *configs.Resources) bool {
return r.CpuWeight != 0 || r.CpuQuota != 0 || r.CpuPeriod != 0
return r.CpuWeight != 0 || r.CpuQuota != 0 || r.CpuPeriod != 0 || r.CPUIdle != nil
}
func setCpu(dirPath string, r *configs.Resources) error {
@@ -19,6 +19,12 @@ func setCpu(dirPath string, r *configs.Resources) error {
return nil
}
if r.CPUIdle != nil {
if err := cgroups.WriteFile(dirPath, "cpu.idle", strconv.FormatInt(*r.CPUIdle, 10)); err != nil {
return err
}
}
// NOTE: .CpuShares is not used here. Conversion is the caller's responsibility.
if r.CpuWeight != 0 {
if err := cgroups.WriteFile(dirPath, "cpu.weight", strconv.FormatUint(r.CpuWeight, 10)); err != nil {

View File

@@ -84,6 +84,9 @@ type Resources struct {
// MEM to use
CpusetMems string `json:"cpuset_mems"`
// cgroup SCHED_IDLE
CPUIdle *int64 `json:"cpu_idle,omitempty"`
// Process limit; set <= `0' to disable limit.
PidsLimit int64 `json:"pids_limit"`

View File

@@ -748,6 +748,7 @@ func CreateCgroupConfig(opts *CreateOpts, defaultDevs []*devices.Device) (*confi
}
c.Resources.CpusetCpus = r.CPU.Cpus
c.Resources.CpusetMems = r.CPU.Mems
c.Resources.CPUIdle = r.CPU.Idle
}
if r.Pids != nil {
c.Resources.PidsLimit = r.Pids.Limit

View File

@@ -187,6 +187,18 @@ function setup() {
[[ "$weights" == *"$major:$minor 444"* ]]
}
@test "runc run (cpu.idle)" {
requires cgroups_cpu_idle
[ $EUID -ne 0 ] && requires rootless_cgroup
set_cgroups_path
update_config '.linux.resources.cpu.idle = 1'
runc run -d --console-socket "$CONSOLE_SOCKET" test_cgroups_unified
[ "$status" -eq 0 ]
check_cgroup_value "cpu.idle" "1"
}
@test "runc run (cgroup v2 resources.unified only)" {
requires root cgroups_v2

View File

@@ -413,6 +413,15 @@ function requires() {
skip_me=1
fi
;;
cgroups_cpu_idle)
local p
init_cgroup_paths
[ -v CGROUP_V1 ] && p="$CGROUP_CPU_BASE_PATH"
[ -v CGROUP_V2 ] && p="$CGROUP_BASE_PATH"
if [ -z "$(find "$p" -name cpu.idle -print -quit)" ]; then
skip_me=1
fi
;;
cgroupns)
if [ ! -e "/proc/self/ns/cgroup" ]; then
skip_me=1

View File

@@ -425,6 +425,41 @@ EOF
check_cpu_quota 3000 10000 "300ms"
}
@test "update cgroup cpu.idle" {
requires cgroups_cpu_idle
[ $EUID -ne 0 ] && requires rootless_cgroup
runc run -d --console-socket "$CONSOLE_SOCKET" test_update
[ "$status" -eq 0 ]
check_cgroup_value "cpu.idle" "0"
local val
for val in 1 0 1; do
runc update -r - test_update <<EOF
{
"cpu": {
"idle": $val
}
}
EOF
[ "$status" -eq 0 ]
check_cgroup_value "cpu.idle" "$val"
done
for val in 1 0 1; do
runc update --cpu-idle "$val" test_update
[ "$status" -eq 0 ]
check_cgroup_value "cpu.idle" "$val"
done
# test update other option won't impact on cpu.idle
runc update --cpu-period 10000 test_update
[ "$status" -eq 0 ]
check_cgroup_value "cpu.idle" "1"
}
@test "update cgroup v2 resources via unified map" {
[ $EUID -ne 0 ] && requires rootless_cgroup
requires cgroups_v2

View File

@@ -48,7 +48,8 @@ The accepted format is as follow (unchanged values can be omitted):
"realtimeRuntime": 0,
"realtimePeriod": 0,
"cpus": "",
"mems": ""
"mems": "",
"idle": 0
},
"blockIO": {
"weight": 0
@@ -106,6 +107,10 @@ other options are ignored.
Name: "memory",
Usage: "Memory limit (in bytes)",
},
cli.StringFlag{
Name: "cpu-idle",
Usage: "set cgroup SCHED_IDLE or not, 0: default behavior, 1: SCHED_IDLE",
},
cli.StringFlag{
Name: "memory-reservation",
Usage: "Memory reservation or soft_limit (in bytes)",
@@ -192,6 +197,13 @@ other options are ignored.
if val := context.String("cpuset-mems"); val != "" {
r.CPU.Mems = val
}
if val := context.String("cpu-idle"); val != "" {
idle, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return fmt.Errorf("invalid value for cpu-idle: %w", err)
}
r.CPU.Idle = i64Ptr(idle)
}
for _, pair := range []struct {
opt string
@@ -294,6 +306,7 @@ other options are ignored.
config.Cgroups.Resources.CpusetCpus = r.CPU.Cpus
config.Cgroups.Resources.CpusetMems = r.CPU.Mems
config.Cgroups.Resources.Memory = *r.Memory.Limit
config.Cgroups.Resources.CPUIdle = r.CPU.Idle
config.Cgroups.Resources.MemoryReservation = *r.Memory.Reservation
config.Cgroups.Resources.MemorySwap = *r.Memory.Swap
config.Cgroups.Resources.MemoryCheckBeforeUpdate = *r.Memory.CheckBeforeUpdate