runc update: support per-device weight and iops

This support was missing from runc, and thus the example from the
podman-update wasn't working.

To fix, introduce a function to either update or insert new weights and iops.

Add integration tests.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin
2025-05-30 15:08:21 -07:00
parent 178a58d654
commit 7696402dac
4 changed files with 156 additions and 6 deletions
+57
View File
@@ -273,6 +273,25 @@ other options are ignored.
if r.BlockIO.Weight != nil {
config.Cgroups.Resources.BlkioWeight = *r.BlockIO.Weight
}
if r.BlockIO.LeafWeight != nil {
config.Cgroups.Resources.BlkioLeafWeight = *r.BlockIO.LeafWeight
}
// For devices, we either update an existing one, or insert a new one.
for _, wd := range r.BlockIO.WeightDevice {
config.Cgroups.Resources.BlkioWeightDevice = upsertWeightDevice(config.Cgroups.Resources.BlkioWeightDevice, wd)
}
for _, td := range r.BlockIO.ThrottleReadBpsDevice {
config.Cgroups.Resources.BlkioThrottleReadBpsDevice = upsertThrottleDevice(config.Cgroups.Resources.BlkioThrottleReadBpsDevice, td)
}
for _, td := range r.BlockIO.ThrottleWriteBpsDevice {
config.Cgroups.Resources.BlkioThrottleWriteBpsDevice = upsertThrottleDevice(config.Cgroups.Resources.BlkioThrottleWriteBpsDevice, td)
}
for _, td := range r.BlockIO.ThrottleReadIOPSDevice {
config.Cgroups.Resources.BlkioThrottleReadIOPSDevice = upsertThrottleDevice(config.Cgroups.Resources.BlkioThrottleReadIOPSDevice, td)
}
for _, td := range r.BlockIO.ThrottleWriteIOPSDevice {
config.Cgroups.Resources.BlkioThrottleWriteIOPSDevice = upsertThrottleDevice(config.Cgroups.Resources.BlkioThrottleWriteIOPSDevice, td)
}
// Setting CPU quota and period independently does not make much sense,
// but historically runc allowed it and this needs to be supported
@@ -381,3 +400,41 @@ other options are ignored.
return container.Set(config)
},
}
func upsertWeightDevice(devices []*cgroups.WeightDevice, wd specs.LinuxWeightDevice) []*cgroups.WeightDevice {
for i, dev := range devices {
if dev.Major != wd.Major || dev.Minor != wd.Minor {
continue
}
// Update weights for existing device.
if wd.Weight != nil {
devices[i].Weight = *wd.Weight
}
if wd.LeafWeight != nil {
devices[i].LeafWeight = *wd.LeafWeight
}
return devices
}
// New device -- append it.
var weight, leafWeight uint16
if wd.Weight != nil {
weight = *wd.Weight
}
if wd.LeafWeight != nil {
leafWeight = *wd.LeafWeight
}
return append(devices, cgroups.NewWeightDevice(wd.Major, wd.Minor, weight, leafWeight))
}
func upsertThrottleDevice(devices []*cgroups.ThrottleDevice, td specs.LinuxThrottleDevice) []*cgroups.ThrottleDevice {
for i, dev := range devices {
if dev.Major == td.Major && dev.Minor == td.Minor {
devices[i].Rate = td.Rate
return devices
}
}
return append(devices, cgroups.NewThrottleDevice(td.Major, td.Minor, td.Rate))
}