diff --git a/tests/integration/update.bats b/tests/integration/update.bats index 9e0c64bdf..9651ff93c 100644 --- a/tests/integration/update.bats +++ b/tests/integration/update.bats @@ -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 ] diff --git a/update.go b/update.go index 0a352b7b9..bc8ed1318 100644 --- a/update.go +++ b/update.go @@ -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