Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libct/cg/sd: write rounded CPU quota to cgroupfs #4639

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions libcontainer/cgroups/systemd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,26 @@ func addCpuQuota(cm *dbusConnManager, properties *[]systemdDbus.Property, quota
}
}

func getCPUQuotaFromProperties(properties []systemdDbus.Property, period uint64) (int64, error) {
var cpuQuotaPerSecUsec int64

for _, prop := range properties {
if prop.Name == "CPUQuotaPerSecUSec" {
if err := prop.Value.Store(&cpuQuotaPerSecUsec); err != nil {
return 0, fmt.Errorf("can't parse CPUQuotaPerSecUSec %v: %w", prop.Value, err)
}
break
}
}
if cpuQuotaPerSecUsec == 0 {
return 0, nil
}
if period == 0 {
period = defCPUQuotaPeriod
}
return cpuQuotaPerSecUsec * int64(period) / 1000000, nil
}

func addCpuset(cm *dbusConnManager, props *[]systemdDbus.Property, cpus, mems string) error {
if cpus == "" && mems == "" {
return nil
Expand Down
61 changes: 61 additions & 0 deletions libcontainer/cgroups/systemd/systemd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,64 @@ func TestUnifiedResToSystemdProps(t *testing.T) {
})
}
}

func TestGetCPUQuotaFromProperties(t *testing.T) {
testCases := []struct {
name string
properties []systemdDbus.Property
cpuPeriod uint64
expectedCPUQuota int64
}{
{
name: "Update only CPU quota",
properties: []systemdDbus.Property{
newProp("CPUQuotaPerSecUSec", 1230000),
},
cpuPeriod: 0,
expectedCPUQuota: 123000,
},
{
name: "Update CPU Quota and CPU period",
properties: []systemdDbus.Property{
newProp("CPUQuotaPerSecUSec", 560000),
newProp("CPUQuotaPeriodUSec", 900000),
},
cpuPeriod: 900000,
expectedCPUQuota: 504000,
},
{
name: "Update CPU Quota and CPU period without supporting CPUQuotaPeriodUSec",
properties: []systemdDbus.Property{
newProp("CPUQuotaPerSecUSec", 560000),
},
cpuPeriod: 900000,
expectedCPUQuota: 504000,
},
{
name: "Update only CPU period",
properties: []systemdDbus.Property{
newProp("CPUQuotaPeriodUSec", 900000),
},
cpuPeriod: 900000,
expectedCPUQuota: 0,
},
{
name: "Update neither CPU quota nor CPU period",
properties: []systemdDbus.Property{
newProp("MemoryMax", 67108864),
},
cpuPeriod: 0,
expectedCPUQuota: 0,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if cpuQuota, err := getCPUQuotaFromProperties(tc.properties, tc.cpuPeriod); err != nil {
t.Errorf("getCPUQuotaFromProperties(%v); unexpected error %v", tc.properties, err)
} else if cpuQuota != tc.expectedCPUQuota {
t.Errorf("getCPUQuotaFromProperties(%v); want %d; got %d", tc.properties, tc.expectedCPUQuota, cpuQuota)
}
})
}
}
10 changes: 10 additions & 0 deletions libcontainer/cgroups/systemd/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,16 @@ func (m *LegacyManager) Set(r *cgroups.Resources) error {
return setErr
}

if cpuQuota, err := getCPUQuotaFromProperties(properties, r.CpuPeriod); err != nil {
return err
} else if cpuQuota > 0 {
// CPU Quota is rounded up to the nearest 10ms in properties.
// Get the rounded value in order to write the same value to the file.
rCopy := *r
r = &rCopy
r.CpuQuota = cpuQuota
}

for _, sys := range legacySubsystems {
// Get the subsystem path, but don't error out for not found cgroups.
path, ok := m.paths[sys.Name()]
Expand Down
10 changes: 10 additions & 0 deletions libcontainer/cgroups/systemd/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,16 @@ func (m *UnifiedManager) Set(r *cgroups.Resources) error {
return fmt.Errorf("unable to set unit properties: %w", err)
}

if cpuQuota, err := getCPUQuotaFromProperties(properties, r.CpuPeriod); err != nil {
return err
} else if cpuQuota > 0 {
// CPU Quota is rounded up to the nearest 10ms in properties.
// Get the rounded value in order to write the same value to the file.
rCopy := *r
r = &rCopy
r.CpuQuota = cpuQuota
}

return m.fsMgr.Set(r)
}

Expand Down
32 changes: 29 additions & 3 deletions tests/integration/update.bats
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,37 @@ EOF
check_cpu_quota 500000 1000000 "500ms"
check_cpu_shares 100

# update cpu quota with fraction
runc update test_update --cpu-quota 123456
[ "$status" -eq 0 ]
expected_quota=123456
if [ -v RUNC_USE_SYSTEMD ]; then
expected_quota=130000
fi
check_cpu_quota $expected_quota 1000000 "130ms"

# update cpu quota to original value
runc update test_update --cpu-quota 500000
[ "$status" -eq 0 ]
check_cpu_quota 500000 1000000 "500ms"

# update cpu period
runc update test_update --cpu-period 900000
[ "$status" -eq 0 ]
check_cpu_quota 500000 900000 "560ms"
expected_quota=500000
if [ -v RUNC_USE_SYSTEMD ]; then
expected_quota=504000
fi
check_cpu_quota $expected_quota 900000 "560ms"

# update cpu quota
runc update test_update --cpu-quota 600000
[ "$status" -eq 0 ]
check_cpu_quota 600000 900000 "670ms"
expected_quota=600000
if [ -v RUNC_USE_SYSTEMD ]; then
expected_quota=603000
fi
check_cpu_quota $expected_quota 900000 "670ms"

# remove cpu quota
runc update test_update --cpu-quota -1
Expand Down Expand Up @@ -304,7 +326,11 @@ EOF
runc update test_update \
--cpu-period 900000 --cpu-quota 600000 --cpu-share 200
[ "$status" -eq 0 ]
check_cpu_quota 600000 900000 "670ms"
expected_quota=600000
if [ -v RUNC_USE_SYSTEMD ]; then
expected_quota=603000
fi
check_cpu_quota $expected_quota 900000 "670ms"
check_cpu_shares 200

# remove cpu quota and reset the period
Expand Down