diff --git a/userns.go b/userns.go index 5ba8cc418..49ec544a3 100644 --- a/userns.go +++ b/userns.go @@ -221,94 +221,71 @@ outer: return size, nil } +func minInt(a, b int) int { + if a < b { + return a + } + return b +} + +func maxInt(a, b int) int { + if a < b { + return b + } + return a +} + // subtractHostIDs return the subtraction of the range USED from AVAIL. The range is specified // by [HostID, HostID+Size). // ContainerID is ignored. func subtractHostIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDMap { - switch { - case used.HostID <= avail.HostID && used.HostID+used.Size >= avail.HostID+avail.Size: - return nil - case used.HostID <= avail.HostID && used.HostID+used.Size > avail.HostID && used.HostID+used.Size < avail.HostID+avail.Size: - newContainerID := avail.ContainerID + used.Size - newHostID := used.HostID + used.Size - r := idtools.IDMap{ - ContainerID: newContainerID, - HostID: newHostID, - Size: avail.Size + avail.HostID - newHostID, - } - return []idtools.IDMap{r} - case used.HostID > avail.HostID && used.HostID < avail.HostID+avail.Size && used.HostID+used.Size >= avail.HostID+avail.Size: - r := idtools.IDMap{ + var out []idtools.IDMap + availEnd := avail.HostID + avail.Size + usedEnd := used.HostID + used.Size + // Intersection of [avail.HostID, availEnd) and (-inf, used.HostID) is [avail.HostID, newEnd). + if newEnd := minInt(availEnd, used.HostID); newEnd > avail.HostID { + out = append(out, idtools.IDMap{ ContainerID: avail.ContainerID, HostID: avail.HostID, - Size: used.HostID - avail.HostID, - } - return []idtools.IDMap{r} - case used.HostID > avail.HostID && used.HostID < avail.HostID+avail.Size && used.HostID+used.Size < avail.HostID+avail.Size: - r1 := idtools.IDMap{ - ContainerID: avail.ContainerID, - HostID: avail.HostID, - Size: used.HostID - avail.HostID, - } - r2 := idtools.IDMap{ - ContainerID: used.ContainerID + used.Size, - HostID: avail.HostID + (used.HostID - avail.HostID), - Size: avail.HostID + avail.Size - used.HostID - used.Size, - } - return []idtools.IDMap{r1, r2} - default: - r := idtools.IDMap{ - ContainerID: 0, - HostID: avail.HostID, - Size: avail.Size, - } - return []idtools.IDMap{r} + Size: newEnd - avail.HostID, + }) } + // Intersection of [avail.HostID, availEnd) and [usedEnd, +inf) is [newStart, availEnd). + if newStart := maxInt(avail.HostID, usedEnd); newStart < availEnd { + out = append(out, idtools.IDMap{ + ContainerID: newStart + avail.ContainerID - avail.HostID, + HostID: newStart, + Size: availEnd - newStart, + }) + } + return out } // subtractContainerIDs return the subtraction of the range USED from AVAIL. The range is specified // by [ContainerID, ContainerID+Size). // HostID is ignored. func subtractContainerIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDMap { - switch { - case used.ContainerID <= avail.ContainerID && used.ContainerID+used.Size >= avail.ContainerID+avail.Size: - return nil - case used.ContainerID <= avail.ContainerID && used.ContainerID+used.Size > avail.ContainerID && used.ContainerID+used.Size < avail.ContainerID+avail.Size: - newContainerID := used.ContainerID + used.Size - newHostID := avail.HostID + used.Size - r := idtools.IDMap{ - ContainerID: newContainerID, - HostID: newHostID, - Size: avail.Size + avail.ContainerID - newContainerID, - } - return []idtools.IDMap{r} - case used.ContainerID > avail.ContainerID && used.ContainerID < avail.ContainerID+avail.Size && used.ContainerID+used.Size >= avail.ContainerID+avail.Size: - r := idtools.IDMap{ + var out []idtools.IDMap + availEnd := avail.ContainerID + avail.Size + usedEnd := used.ContainerID + used.Size + // Intersection of [avail.ContainerID, availEnd) and (-inf, used.ContainerID) is + // [avail.ContainerID, newEnd). + if newEnd := minInt(availEnd, used.ContainerID); newEnd > avail.ContainerID { + out = append(out, idtools.IDMap{ ContainerID: avail.ContainerID, HostID: avail.HostID, - Size: used.ContainerID - avail.ContainerID, - } - return []idtools.IDMap{r} - case used.ContainerID > avail.ContainerID && used.ContainerID < avail.ContainerID+avail.Size && used.ContainerID+used.Size < avail.ContainerID+avail.Size: - r1 := idtools.IDMap{ - ContainerID: avail.ContainerID, - HostID: avail.HostID, - Size: used.ContainerID - avail.ContainerID, - } - r2 := idtools.IDMap{ - ContainerID: used.ContainerID + used.Size, - HostID: avail.HostID + (used.ContainerID - avail.ContainerID), - Size: avail.ContainerID + avail.Size - used.ContainerID - used.Size, - } - return []idtools.IDMap{r1, r2} - default: - r := idtools.IDMap{ - ContainerID: avail.ContainerID, - HostID: avail.HostID, - Size: avail.Size, - } - return []idtools.IDMap{r} + Size: newEnd - avail.ContainerID, + }) } + // Intersection of [avail.ContainerID, availEnd) and [usedEnd, +inf) is [newStart, availEnd). + if newStart := maxInt(avail.ContainerID, usedEnd); newStart < availEnd { + out = append(out, idtools.IDMap{ + ContainerID: newStart, + HostID: newStart + avail.HostID - avail.ContainerID, + Size: availEnd - newStart, + }) + } + return out } // subtractAll subtracts all usedIDs from the available IDs. diff --git a/userns_test.go b/userns_test.go index c51d2e5c9..296922fd5 100644 --- a/userns_test.go +++ b/userns_test.go @@ -72,7 +72,7 @@ func TestSubtractHostID(t *testing.T) { assert.Equal(t, len(ret), 2) assert.Equal(t, ret[0].HostID, avail.HostID) assert.Equal(t, ret[0].Size, 32768) - assert.Equal(t, ret[1].HostID, avail.HostID+32768) + assert.Equal(t, ret[1].HostID, avail.HostID+32768+4096) assert.Equal(t, ret[1].Size, 32768-4096) used = idtools.IDMap{ @@ -211,7 +211,7 @@ func TestSubtractContainerID(t *testing.T) { assert.Equal(t, ret[0].HostID, 1000) assert.Equal(t, ret[0].Size, 10) assert.Equal(t, ret[1].ContainerID, 11) - assert.Equal(t, ret[1].HostID, 1010) + assert.Equal(t, ret[1].HostID, 1011) assert.Equal(t, ret[1].Size, 65525) } @@ -268,5 +268,5 @@ func TestFindAvailableIDRange(t *testing.T) { assert.Nil(t, err) assert.Equal(t, len(ret), 2) assert.Equal(t, ret[0].HostID, 100000) - assert.Equal(t, ret[1].HostID, 100010) + assert.Equal(t, ret[1].HostID, 100020) }