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 --pids-limit
--l3-cache-schema --l3-cache-schema
--mem-bw-schema --mem-bw-schema
--cpu-idle
" "
case "$prev" in 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) return s.SetRtSched(path, r)
} }

View File

@@ -11,7 +11,7 @@ import (
) )
func isCpuSet(r *configs.Resources) bool { 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 { func setCpu(dirPath string, r *configs.Resources) error {
@@ -19,6 +19,12 @@ func setCpu(dirPath string, r *configs.Resources) error {
return nil 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. // NOTE: .CpuShares is not used here. Conversion is the caller's responsibility.
if r.CpuWeight != 0 { if r.CpuWeight != 0 {
if err := cgroups.WriteFile(dirPath, "cpu.weight", strconv.FormatUint(r.CpuWeight, 10)); err != nil { 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 // MEM to use
CpusetMems string `json:"cpuset_mems"` CpusetMems string `json:"cpuset_mems"`
// cgroup SCHED_IDLE
CPUIdle *int64 `json:"cpu_idle,omitempty"`
// Process limit; set <= `0' to disable limit. // Process limit; set <= `0' to disable limit.
PidsLimit int64 `json:"pids_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.CpusetCpus = r.CPU.Cpus
c.Resources.CpusetMems = r.CPU.Mems c.Resources.CpusetMems = r.CPU.Mems
c.Resources.CPUIdle = r.CPU.Idle
} }
if r.Pids != nil { if r.Pids != nil {
c.Resources.PidsLimit = r.Pids.Limit c.Resources.PidsLimit = r.Pids.Limit

View File

@@ -187,6 +187,18 @@ function setup() {
[[ "$weights" == *"$major:$minor 444"* ]] [[ "$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)" { @test "runc run (cgroup v2 resources.unified only)" {
requires root cgroups_v2 requires root cgroups_v2

View File

@@ -413,6 +413,15 @@ function requires() {
skip_me=1 skip_me=1
fi 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) cgroupns)
if [ ! -e "/proc/self/ns/cgroup" ]; then if [ ! -e "/proc/self/ns/cgroup" ]; then
skip_me=1 skip_me=1

View File

@@ -425,6 +425,41 @@ EOF
check_cpu_quota 3000 10000 "300ms" 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" { @test "update cgroup v2 resources via unified map" {
[ $EUID -ne 0 ] && requires rootless_cgroup [ $EUID -ne 0 ] && requires rootless_cgroup
requires cgroups_v2 requires cgroups_v2

View File

@@ -48,7 +48,8 @@ The accepted format is as follow (unchanged values can be omitted):
"realtimeRuntime": 0, "realtimeRuntime": 0,
"realtimePeriod": 0, "realtimePeriod": 0,
"cpus": "", "cpus": "",
"mems": "" "mems": "",
"idle": 0
}, },
"blockIO": { "blockIO": {
"weight": 0 "weight": 0
@@ -106,6 +107,10 @@ other options are ignored.
Name: "memory", Name: "memory",
Usage: "Memory limit (in bytes)", 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{ cli.StringFlag{
Name: "memory-reservation", Name: "memory-reservation",
Usage: "Memory reservation or soft_limit (in bytes)", Usage: "Memory reservation or soft_limit (in bytes)",
@@ -192,6 +197,13 @@ other options are ignored.
if val := context.String("cpuset-mems"); val != "" { if val := context.String("cpuset-mems"); val != "" {
r.CPU.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 { for _, pair := range []struct {
opt string opt string
@@ -294,6 +306,7 @@ other options are ignored.
config.Cgroups.Resources.CpusetCpus = r.CPU.Cpus config.Cgroups.Resources.CpusetCpus = r.CPU.Cpus
config.Cgroups.Resources.CpusetMems = r.CPU.Mems config.Cgroups.Resources.CpusetMems = r.CPU.Mems
config.Cgroups.Resources.Memory = *r.Memory.Limit config.Cgroups.Resources.Memory = *r.Memory.Limit
config.Cgroups.Resources.CPUIdle = r.CPU.Idle
config.Cgroups.Resources.MemoryReservation = *r.Memory.Reservation config.Cgroups.Resources.MemoryReservation = *r.Memory.Reservation
config.Cgroups.Resources.MemorySwap = *r.Memory.Swap config.Cgroups.Resources.MemorySwap = *r.Memory.Swap
config.Cgroups.Resources.MemoryCheckBeforeUpdate = *r.Memory.CheckBeforeUpdate config.Cgroups.Resources.MemoryCheckBeforeUpdate = *r.Memory.CheckBeforeUpdate