runc update: handle duplicated devs properly

In case there's a duplicate in the device list, the latter entry
overrides the former one.

So, we need to modify the last entry, not the first one. To do that,
use slices.Backward.

Amend the test case to test the fix.

Reported-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin
2025-06-12 13:52:17 -07:00
parent 7696402dac
commit 0b01dccfbb
2 changed files with 15 additions and 2 deletions

View File

@@ -905,6 +905,14 @@ EOF
echo "==="
skip "can't get device major number from /proc/partitions (got $major)"
fi
# Add an entry to check that
# - existing devices can be updated;
# - duplicates are handled properly;
# (see func upsert* in update.go).
update_config ' .linux.resources.blockIO.throttleReadBpsDevice |= [
{ major: '"$major"', minor: 0, rate: 485760 },
{ major: '"$major"', minor: 0, rate: 485760 }
]'
runc run -d --console-socket "$CONSOLE_SOCKET" test_update
[ "$status" -eq 0 ]

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"os"
"slices"
"strconv"
"github.com/opencontainers/cgroups"
@@ -402,7 +403,9 @@ other options are ignored.
}
func upsertWeightDevice(devices []*cgroups.WeightDevice, wd specs.LinuxWeightDevice) []*cgroups.WeightDevice {
for i, dev := range devices {
// Iterate backwards because in case of a duplicate
// the last one will be used.
for i, dev := range slices.Backward(devices) {
if dev.Major != wd.Major || dev.Minor != wd.Minor {
continue
}
@@ -429,7 +432,9 @@ func upsertWeightDevice(devices []*cgroups.WeightDevice, wd specs.LinuxWeightDev
}
func upsertThrottleDevice(devices []*cgroups.ThrottleDevice, td specs.LinuxThrottleDevice) []*cgroups.ThrottleDevice {
for i, dev := range devices {
// Iterate backwards because in case of a duplicate
// the last one will be used.
for i, dev := range slices.Backward(devices) {
if dev.Major == td.Major && dev.Minor == td.Minor {
devices[i].Rate = td.Rate
return devices