Skip to content

Commit 1da08ce

Browse files
committed
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>
1 parent b04031d commit 1da08ce

File tree

3 files changed

+133
-6
lines changed

3 files changed

+133
-6
lines changed

tests/integration/cgroups.bats

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,17 +174,40 @@ function setup() {
174174
runc run -d --console-socket "$CONSOLE_SOCKET" test_dev_weight
175175
[ "$status" -eq 0 ]
176176

177-
# The loop device itself is no longer needed.
178-
losetup -d "$dev"
179-
180177
if [ -v CGROUP_V2 ]; then
181178
file="io.bfq.weight"
182179
else
183180
file="blkio.bfq.weight_device"
184181
fi
185-
weights=$(get_cgroup_value $file)
186-
[[ "$weights" == *"default 333"* ]]
187-
[[ "$weights" == *"$major:$minor 444"* ]]
182+
weights1=$(get_cgroup_value $file)
183+
184+
# Check that runc update works.
185+
runc update -r - test_dev_weight <<EOF
186+
{
187+
"blockIO": {
188+
"weight": 111,
189+
"weightDevice": [
190+
{
191+
"major": $major,
192+
"minor": $minor,
193+
"weight": 222
194+
}
195+
]
196+
}
197+
}
198+
EOF
199+
weights2=$(get_cgroup_value $file)
200+
201+
# The loop device itself is no longer needed.
202+
losetup -d "$dev"
203+
204+
# Check original values.
205+
[[ "$weights1" == *"default 333"* ]]
206+
[[ "$weights1" == *"$major:$minor 444"* ]]
207+
# Check updated values.
208+
[[ "$weights2" == *"default 111"* ]]
209+
[[ "$weights2" == *"$major:$minor 222"* ]]
210+
188211
}
189212

190213
@test "runc run (per-device multiple iops via unified)" {

tests/integration/update.bats

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,3 +892,57 @@ EOF
892892
runc update test_update --memory 1024
893893
wait_for_container 10 1 test_update stopped
894894
}
895+
896+
@test "update per-device iops values" {
897+
[ $EUID -ne 0 ] && requires rootless_cgroup
898+
899+
runc run -d --console-socket "$CONSOLE_SOCKET" test_update
900+
[ "$status" -eq 0 ]
901+
902+
runc update -r - test_update <<EOF
903+
{
904+
"blockIO": {
905+
"throttleReadBpsDevice": [
906+
{
907+
"major": 1,
908+
"minor": 5,
909+
"rate": 10485760
910+
}
911+
],
912+
"throttleWriteBpsDevice": [
913+
{
914+
"major": 1,
915+
"minor": 5,
916+
"rate": 10485760
917+
}
918+
],
919+
"throttleReadIOPSDevice": [
920+
{
921+
"major": 1,
922+
"minor": 5,
923+
"rate": 1000
924+
}
925+
],
926+
"throttleWriteIOPSDevice": [
927+
{
928+
"major": 1,
929+
"minor": 5,
930+
"rate": 1000
931+
}
932+
]
933+
}
934+
}
935+
EOF
936+
[ "$status" -eq 0 ]
937+
938+
if [ -v CGROUP_V2 ]; then
939+
iops=$(get_cgroup_value "io.max")
940+
printf "== io.max --\n%s\n" "$iops"
941+
grep "^1:5 rbps=10485760 wbps=10485760 riops=1000 wiops=1000$" <<<"$iops"
942+
else
943+
grep "^1:5 10485760$" <<<"$(get_cgroup_value blkio.throttle.read_bps_device)"
944+
grep "^1:5 10485760$" <<<"$(get_cgroup_value blkio.throttle.write_bps_device)"
945+
grep "^1:5 1000$" <<<"$(get_cgroup_value blkio.throttle.read_iops_device)"
946+
grep "^1:5 1000$" <<<"$(get_cgroup_value blkio.throttle.write_iops_device)"
947+
fi
948+
}

update.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,25 @@ other options are ignored.
273273
if r.BlockIO.Weight != nil {
274274
config.Cgroups.Resources.BlkioWeight = *r.BlockIO.Weight
275275
}
276+
if r.BlockIO.LeafWeight != nil {
277+
config.Cgroups.Resources.BlkioLeafWeight = *r.BlockIO.LeafWeight
278+
}
279+
// For devices, we either update an existing one, or insert a new one.
280+
for _, wd := range r.BlockIO.WeightDevice {
281+
config.Cgroups.Resources.BlkioWeightDevice = upsertWeightDevice(config.Cgroups.Resources.BlkioWeightDevice, wd)
282+
}
283+
for _, td := range r.BlockIO.ThrottleReadBpsDevice {
284+
config.Cgroups.Resources.BlkioThrottleReadBpsDevice = upsertThrottleDevice(config.Cgroups.Resources.BlkioThrottleReadBpsDevice, td)
285+
}
286+
for _, td := range r.BlockIO.ThrottleWriteBpsDevice {
287+
config.Cgroups.Resources.BlkioThrottleWriteBpsDevice = upsertThrottleDevice(config.Cgroups.Resources.BlkioThrottleWriteBpsDevice, td)
288+
}
289+
for _, td := range r.BlockIO.ThrottleReadIOPSDevice {
290+
config.Cgroups.Resources.BlkioThrottleReadIOPSDevice = upsertThrottleDevice(config.Cgroups.Resources.BlkioThrottleReadIOPSDevice, td)
291+
}
292+
for _, td := range r.BlockIO.ThrottleWriteIOPSDevice {
293+
config.Cgroups.Resources.BlkioThrottleWriteIOPSDevice = upsertThrottleDevice(config.Cgroups.Resources.BlkioThrottleWriteIOPSDevice, td)
294+
}
276295

277296
// Setting CPU quota and period independently does not make much sense,
278297
// but historically runc allowed it and this needs to be supported
@@ -381,3 +400,34 @@ other options are ignored.
381400
return container.Set(config)
382401
},
383402
}
403+
404+
func upsertWeightDevice(slice []*cgroups.WeightDevice, wd specs.LinuxWeightDevice) []*cgroups.WeightDevice {
405+
var weight, leafWeight uint16
406+
if wd.Weight != nil {
407+
weight = *wd.Weight
408+
}
409+
if wd.LeafWeight != nil {
410+
leafWeight = *wd.LeafWeight
411+
}
412+
413+
for i, dev := range slice {
414+
if dev.Major == wd.Major && dev.Minor == wd.Minor {
415+
slice[i].Weight = weight
416+
slice[i].LeafWeight = leafWeight
417+
return slice
418+
}
419+
}
420+
421+
return append(slice, cgroups.NewWeightDevice(wd.Major, wd.Minor, weight, leafWeight))
422+
}
423+
424+
func upsertThrottleDevice(slice []*cgroups.ThrottleDevice, td specs.LinuxThrottleDevice) []*cgroups.ThrottleDevice {
425+
for i, dev := range slice {
426+
if dev.Major == td.Major && dev.Minor == td.Minor {
427+
slice[i].Rate = td.Rate
428+
return slice
429+
}
430+
}
431+
432+
return append(slice, cgroups.NewThrottleDevice(td.Major, td.Minor, td.Rate))
433+
}

0 commit comments

Comments
 (0)