Skip to content

Commit 8f22a0c

Browse files
Merge pull request #26022 from giuseppe/test-do-not-set-limits-on-dev-zero
test: use block devices for I/O limit tests
2 parents 9ce7087 + 80065f7 commit 8f22a0c

File tree

11 files changed

+72
-35
lines changed

11 files changed

+72
-35
lines changed

contrib/cirrus/setup_environment.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ mount -t tmpfs -o size=75%,mode=0700 none /var/lib/containers
209209
showrun echo "Setting CI_DESIRED_STORAGE [=$CI_DESIRED_STORAGE] for *e2e* tests"
210210
echo "STORAGE_FS=$CI_DESIRED_STORAGE" >>/etc/ci_environment
211211

212+
if ((CONTAINER==0)); then # not yet inside a container
213+
# Load null_blk to use /dev/nullb0 for testing block
214+
# devices limits
215+
modprobe null_blk nr_devices=1 || :
216+
fi
217+
212218
# Required to be defined by caller: The environment where primary testing happens
213219
# shellcheck disable=SC2154
214220
showrun echo "about to set up for TEST_ENVIRON [=$TEST_ENVIRON]"

libpod/container_inspect.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ func (c *Container) GetDevices(priv bool, ctrSpec spec.Spec, deviceNodes map[str
653653
for _, dev := range ctrSpec.Linux.Devices {
654654
key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
655655
if deviceNodes == nil {
656-
nodes, err := util.FindDeviceNodes()
656+
nodes, err := util.FindDeviceNodes(false)
657657
if err != nil {
658658
return nil, err
659659
}
@@ -678,7 +678,7 @@ func blkioDeviceThrottle(deviceNodes map[string]string, devs []spec.LinuxThrottl
678678
for _, dev := range devs {
679679
key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
680680
if deviceNodes == nil {
681-
nodes, err := util.FindDeviceNodes()
681+
nodes, err := util.FindDeviceNodes(true)
682682
if err != nil {
683683
return nil, err
684684
}

libpod/container_inspect_linux.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func (c *Container) platformInspectContainerHostConfig(ctrSpec *spec.Spec, hostC
8989
continue
9090
}
9191
if deviceNodes == nil {
92-
nodes, err := util.FindDeviceNodes()
92+
nodes, err := util.FindDeviceNodes(true)
9393
if err != nil {
9494
return err
9595
}

pkg/util/utils_linux.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ func GetContainerPidInformationDescriptors() ([]string, error) {
3333
// [major:minor] is the device's major and minor numbers formatted as, for
3434
// example, 2:0 and path is the path to the device node.
3535
// Symlinks to nodes are ignored.
36-
func FindDeviceNodes() (map[string]string, error) {
36+
// If onlyBlockDevices is specified, character devices are ignored.
37+
func FindDeviceNodes(onlyBlockDevices bool) (map[string]string, error) {
3738
nodes := make(map[string]string)
3839
err := filepath.WalkDir("/dev", func(path string, d fs.DirEntry, err error) error {
3940
if err != nil {
@@ -44,7 +45,13 @@ func FindDeviceNodes() (map[string]string, error) {
4445
}
4546

4647
// If we aren't a device node, do nothing.
47-
if d.Type()&(os.ModeDevice|os.ModeCharDevice) == 0 {
48+
if d.Type()&os.ModeDevice == 0 {
49+
return nil
50+
}
51+
52+
// Ignore character devices, because it is not possible to set limits on them.
53+
// os.ModeCharDevice is usable only when os.ModeDevice is set.
54+
if onlyBlockDevices && d.Type()&os.ModeCharDevice != 0 {
4855
return nil
4956
}
5057

pkg/util/utils_unsupported.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ package util
55
import "errors"
66

77
// FindDeviceNodes is not implemented anywhere except Linux.
8-
func FindDeviceNodes() (map[string]string, error) {
8+
func FindDeviceNodes(onlyBlockDevices bool) (map[string]string, error) {
99
return nil, errors.New("not supported on non-Linux OSes")
1010
}

test/apiv2/20-containers.at

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -710,15 +710,15 @@ t GET libpod/containers/$cname/json 200 \
710710
.ImageName=$IMAGE \
711711
.Name=$cname
712712

713-
if root; then
713+
if root && test -e /dev/nullb0; then
714714
podman run -dt --name=updateCtr alpine
715715
echo '{
716716
"Memory":{"Limit":500000},
717717
"CPU":{"Shares":123},
718-
"DeviceReadBPs": [{ "Path": "/dev/zero", "Rate": 10485760 }],
719-
"DeviceWriteBPs": [{ "Path": "/dev/zero", "Rate": 31457280 }],
720-
"DeviceReadIOPs": [{ "Path": "/dev/zero", "Rate": 2000 }],
721-
"DeviceWriteIOPs": [{ "Path": "/dev/zero", "Rate": 4000 }]
718+
"DeviceReadBPs": [{ "Path": "/dev/nullb0", "Rate": 10485760 }],
719+
"DeviceWriteBPs": [{ "Path": "/dev/nullb0", "Rate": 31457280 }],
720+
"DeviceReadIOPs": [{ "Path": "/dev/nullb0", "Rate": 2000 }],
721+
"DeviceWriteIOPs": [{ "Path": "/dev/nullb0", "Rate": 4000 }]
722722
}' >${TMPD}/update.json
723723
t POST libpod/containers/updateCtr/update ${TMPD}/update.json 201
724724

@@ -734,25 +734,25 @@ if root; then
734734

735735
BlkioDeviceReadBps_expected='[
736736
{
737-
"Path": "/dev/zero",
737+
"Path": "/dev/nullb0",
738738
"Rate": 10485760
739739
}
740740
]'
741741
BlkioDeviceWriteBPs_expected='[
742742
{
743-
"Path": "/dev/zero",
743+
"Path": "/dev/nullb0",
744744
"Rate": 31457280
745745
}
746746
]'
747747
BlkioDeviceReadIOPs_expected='[
748748
{
749-
"Path": "/dev/zero",
749+
"Path": "/dev/nullb0",
750750
"Rate": 2000
751751
}
752752
]'
753753
BlkioDeviceWriteIOPs_expected='[
754754
{
755-
"Path": "/dev/zero",
755+
"Path": "/dev/nullb0",
756756
"Rate": 4000
757757
}
758758
]'

test/e2e/common_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,13 @@ func SkipIfNotRootless(reason string) {
942942
}
943943
}
944944

945+
func SkipIfNotExist(reason, path string) {
946+
checkReason(reason)
947+
if _, err := os.Stat(path); err != nil {
948+
Skip("[doesNotExist]: " + path + " does not exist: " + reason)
949+
}
950+
}
951+
945952
func SkipIfSystemdNotRunning(reason string) {
946953
checkReason(reason)
947954

@@ -1648,3 +1655,7 @@ func makeTempDirInDir(dir string) string {
16481655
Expect(err).ToNot(HaveOccurred())
16491656
return path
16501657
}
1658+
1659+
func skipWithoutDevNullb0() {
1660+
SkipIfNotExist("use modprobe null_blk nr_devices=1 to create it", "/dev/nullb0")
1661+
}

test/e2e/run_test.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -848,13 +848,14 @@ USER bin`, BB)
848848

849849
It("podman run device-read-bps test", func() {
850850
SkipIfRootless("Setting device-read-bps not supported for rootless users")
851+
skipWithoutDevNullb0()
851852

852853
var session *PodmanSessionIntegration
853854

854855
if CGROUPSV2 {
855-
session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
856+
session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/nullb0:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
856857
} else {
857-
session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"})
858+
session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/nullb0:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"})
858859
}
859860

860861
session.WaitWithDefaultTimeout()
@@ -866,13 +867,14 @@ USER bin`, BB)
866867

867868
It("podman run device-write-bps test", func() {
868869
SkipIfRootless("Setting device-write-bps not supported for rootless users")
870+
skipWithoutDevNullb0()
869871

870872
var session *PodmanSessionIntegration
871873

872874
if CGROUPSV2 {
873-
session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
875+
session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/nullb0:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
874876
} else {
875-
session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"})
877+
session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/nullb0:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"})
876878
}
877879
session.WaitWithDefaultTimeout()
878880
Expect(session).Should(ExitCleanly())
@@ -883,12 +885,14 @@ USER bin`, BB)
883885

884886
It("podman run device-read-iops test", func() {
885887
SkipIfRootless("Setting device-read-iops not supported for rootless users")
888+
skipWithoutDevNullb0()
889+
886890
var session *PodmanSessionIntegration
887891

888892
if CGROUPSV2 {
889-
session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
893+
session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/nullb0:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
890894
} else {
891-
session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"})
895+
session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/nullb0:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"})
892896
}
893897

894898
session.WaitWithDefaultTimeout()
@@ -900,12 +904,14 @@ USER bin`, BB)
900904

901905
It("podman run device-write-iops test", func() {
902906
SkipIfRootless("Setting device-write-iops not supported for rootless users")
907+
skipWithoutDevNullb0()
908+
903909
var session *PodmanSessionIntegration
904910

905911
if CGROUPSV2 {
906-
session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
912+
session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/nullb0:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
907913
} else {
908-
session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"})
914+
session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/nullb0:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"})
909915
}
910916

911917
session.WaitWithDefaultTimeout()

test/e2e/update_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ var _ = Describe("Podman update", func() {
8787
It("podman update container all options v2", func() {
8888
SkipIfCgroupV1("testing flags that only work in cgroup v2")
8989
SkipIfRootless("many of these handlers are not enabled while rootless in CI")
90+
skipWithoutDevNullb0()
9091
session := podmanTest.Podman([]string{"run", "-dt", ALPINE})
9192
session.WaitWithDefaultTimeout()
9293
Expect(session).Should(ExitCleanly())
@@ -103,10 +104,10 @@ var _ = Describe("Podman update", func() {
103104
"--memory-swap", "2G",
104105
"--memory-reservation", "2G",
105106
"--blkio-weight", "123",
106-
"--device-read-bps", "/dev/zero:10mb",
107-
"--device-write-bps", "/dev/zero:10mb",
108-
"--device-read-iops", "/dev/zero:1000",
109-
"--device-write-iops", "/dev/zero:1000",
107+
"--device-read-bps", "/dev/nullb0:10mb",
108+
"--device-write-bps", "/dev/nullb0:10mb",
109+
"--device-read-iops", "/dev/nullb0:1000",
110+
"--device-write-iops", "/dev/nullb0:1000",
110111
"--pids-limit", "123",
111112
ctrID}
112113

test/system/030-run.bats

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,18 +1123,24 @@ EOF
11231123
@test "podman run --device-read-bps" {
11241124
skip_if_rootless "cannot use this flag in rootless mode"
11251125

1126+
if test \! -e /dev/nullb0; then
1127+
skip "/dev/nullb0 not present, use 'modprobe null_blk nr_devices=1' to create it"
1128+
fi
1129+
11261130
local cid
1131+
local dev_maj_min=$(stat -c %Hr:%Lr /dev/nullb0)
1132+
11271133
# this test is a triple check on blkio flags since they seem to sneak by the tests
11281134
if is_cgroupsv2; then
1129-
run_podman run -dt --device-read-bps=/dev/zero:1M $IMAGE top
1135+
run_podman run -dt --device-read-bps=/dev/nullb0:1M $IMAGE top
11301136
cid=$output
11311137
run_podman exec -it $output cat /sys/fs/cgroup/io.max
1132-
is "$output" ".*1:5 rbps=1048576 wbps=max riops=max wiops=max" "throttle devices passed successfully.*"
1138+
is "$output" ".*$dev_maj_min rbps=1048576 wbps=max riops=max wiops=max" "throttle devices passed successfully.*"
11331139
else
1134-
run_podman run -dt --device-read-bps=/dev/zero:1M $IMAGE top
1140+
run_podman run -dt --device-read-bps=/dev/nullb0:1M $IMAGE top
11351141
cid=$output
11361142
run_podman exec -it $output cat /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device
1137-
is "$output" ".*1:5 1048576" "throttle devices passed successfully.*"
1143+
is "$output" ".*$dev_maj_min 1048576" "throttle devices passed successfully.*"
11381144
fi
11391145
run_podman container rm -f -t0 $cid
11401146
}

0 commit comments

Comments
 (0)