Merge pull request #2248 from AkihiroSuda/fix-cgroupv2-conversion

cgroup2: fix conversion
This commit is contained in:
Akihiro Suda 2020-03-16 14:00:02 +09:00 committed by GitHub
commit 525b9f311c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 102 additions and 1 deletions

View File

@ -14,12 +14,14 @@ import (
)
func setCpu(dirPath string, cgroup *configs.Cgroup) error {
// NOTE: .CpuShares is not used here. Conversion is the caller's responsibility.
if cgroup.Resources.CpuWeight != 0 {
if err := fscommon.WriteFile(dirPath, "cpu.weight", strconv.FormatUint(cgroup.Resources.CpuWeight, 10)); err != nil {
return err
}
}
// NOTE: .CpuQuota and .CpuPeriod are not used here. Conversion is the caller's responsibility.
if cgroup.Resources.CpuMax != "" {
if err := fscommon.WriteFile(dirPath, "cpu.max", cgroup.Resources.CpuMax); err != nil {
return err

View File

@ -592,7 +592,10 @@ func isEINVAL(err error) bool {
// the formula for BlkIOWeight is y = (1 + (x - 10) * 9999 / 990)
// convert linearly from [10-1000] to [1-10000]
func ConvertBlkIOToCgroupV2Value(blkIoWeight uint16) uint64 {
return uint64(1 + (blkIoWeight-10)*9999/990)
if blkIoWeight == 0 {
return 0
}
return uint64(1 + (uint64(blkIoWeight)-10)*9999/990)
}
// Since the OCI spec is designed for cgroup v1, in some cases
@ -601,5 +604,23 @@ func ConvertBlkIOToCgroupV2Value(blkIoWeight uint16) uint64 {
// convert from [2-262144] to [1-10000]
// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)"
func ConvertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 {
if cpuShares == 0 {
return 0
}
return (1 + ((cpuShares-2)*9999)/262142)
}
// ConvertCPUQuotaCPUPeriodToCgroupV2Value generates cpu.max string.
func ConvertCPUQuotaCPUPeriodToCgroupV2Value(quota int64, period uint64) string {
if quota <= 0 && period == 0 {
return ""
}
if period == 0 {
// This default value is documented in https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
period = 100000
}
if quota <= 0 {
return fmt.Sprintf("max %d", period)
}
return fmt.Sprintf("%d %d", quota, period)
}

View File

@ -457,3 +457,76 @@ func TestGetHugePageSizeImpl(t *testing.T) {
}
}
}
func TestConvertBlkIOToCgroupV2Value(t *testing.T) {
cases := map[uint16]uint64{
0: 0,
10: 1,
1000: 10000,
}
for i, expected := range cases {
got := ConvertBlkIOToCgroupV2Value(i)
if got != expected {
t.Errorf("expected ConvertBlkIOToCgroupV2Value(%d) to be %d, got %d", i, expected, got)
}
}
}
func TestConvertCPUSharesToCgroupV2Value(t *testing.T) {
cases := map[uint64]uint64{
0: 0,
2: 1,
262144: 10000,
}
for i, expected := range cases {
got := ConvertCPUSharesToCgroupV2Value(i)
if got != expected {
t.Errorf("expected ConvertCPUSharesToCgroupV2Value(%d) to be %d, got %d", i, expected, got)
}
}
}
func TestConvertCPUQuotaCPUPeriodToCgroupV2Value(t *testing.T) {
cases := []struct {
quota int64
period uint64
expected string
}{
{
quota: 0,
period: 0,
expected: "",
},
{
quota: -1,
period: 0,
expected: "",
},
{
quota: 1000,
period: 5000,
expected: "1000 5000",
},
{
quota: 0,
period: 5000,
expected: "max 5000",
},
{
quota: -1,
period: 5000,
expected: "max 5000",
},
{
quota: 1000,
period: 0,
expected: "1000 100000",
},
}
for _, c := range cases {
got := ConvertCPUQuotaCPUPeriodToCgroupV2Value(c.quota, c.period)
if got != c.expected {
t.Errorf("expected ConvertCPUQuotaCPUPeriodToCgroupV2Value(%d, %d) to be %s, got %s", c.quota, c.period, c.expected, got)
}
}
}

View File

@ -492,6 +492,9 @@ func CreateCgroupConfig(opts *CreateOpts) (*configs.Cgroup, error) {
if r.CPU.Period != nil {
c.Resources.CpuPeriod = *r.CPU.Period
}
//CpuMax is used for cgroupv2 and should be converted
c.Resources.CpuMax = cgroups.ConvertCPUQuotaCPUPeriodToCgroupV2Value(c.Resources.CpuQuota, c.Resources.CpuPeriod)
if r.CPU.RealtimeRuntime != nil {
c.Resources.CpuRtRuntime = *r.CPU.RealtimeRuntime
}

View File

@ -257,6 +257,8 @@ other options are ignored.
config.Cgroups.Resources.CpuShares = *r.CPU.Shares
//CpuWeight is used for cgroupv2 and should be converted
config.Cgroups.Resources.CpuWeight = cgroups.ConvertCPUSharesToCgroupV2Value(*r.CPU.Shares)
//CpuMax is used for cgroupv2 and should be converted
config.Cgroups.Resources.CpuMax = cgroups.ConvertCPUQuotaCPUPeriodToCgroupV2Value(*r.CPU.Quota, *r.CPU.Period)
config.Cgroups.Resources.CpuRtPeriod = *r.CPU.RealtimePeriod
config.Cgroups.Resources.CpuRtRuntime = *r.CPU.RealtimeRuntime
config.Cgroups.Resources.CpusetCpus = r.CPU.Cpus