inspect: Ignore character devices for IO limits

Cgroup block I/O limits cannot be applied to character devices.

Ignore character devices in the inspect output.

Update the API tests to use the null block device `/dev/nullb0` (if
available) instead of `/dev/zero` for testing I/O limits.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2025-04-30 11:06:00 +02:00
committed by openshift-cherrypick-robot
parent 52eb2dcca2
commit 6bc2393df0
5 changed files with 22 additions and 15 deletions

View File

@ -653,7 +653,7 @@ func (c *Container) GetDevices(priv bool, ctrSpec spec.Spec, deviceNodes map[str
for _, dev := range ctrSpec.Linux.Devices { for _, dev := range ctrSpec.Linux.Devices {
key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor) key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
if deviceNodes == nil { if deviceNodes == nil {
nodes, err := util.FindDeviceNodes() nodes, err := util.FindDeviceNodes(false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -678,7 +678,7 @@ func blkioDeviceThrottle(deviceNodes map[string]string, devs []spec.LinuxThrottl
for _, dev := range devs { for _, dev := range devs {
key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor) key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
if deviceNodes == nil { if deviceNodes == nil {
nodes, err := util.FindDeviceNodes() nodes, err := util.FindDeviceNodes(true)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -89,7 +89,7 @@ func (c *Container) platformInspectContainerHostConfig(ctrSpec *spec.Spec, hostC
continue continue
} }
if deviceNodes == nil { if deviceNodes == nil {
nodes, err := util.FindDeviceNodes() nodes, err := util.FindDeviceNodes(true)
if err != nil { if err != nil {
return err return err
} }

View File

@ -33,7 +33,8 @@ func GetContainerPidInformationDescriptors() ([]string, error) {
// [major:minor] is the device's major and minor numbers formatted as, for // [major:minor] is the device's major and minor numbers formatted as, for
// example, 2:0 and path is the path to the device node. // example, 2:0 and path is the path to the device node.
// Symlinks to nodes are ignored. // Symlinks to nodes are ignored.
func FindDeviceNodes() (map[string]string, error) { // If onlyBlockDevices is specified, character devices are ignored.
func FindDeviceNodes(onlyBlockDevices bool) (map[string]string, error) {
nodes := make(map[string]string) nodes := make(map[string]string)
err := filepath.WalkDir("/dev", func(path string, d fs.DirEntry, err error) error { err := filepath.WalkDir("/dev", func(path string, d fs.DirEntry, err error) error {
if err != nil { if err != nil {
@ -44,7 +45,13 @@ func FindDeviceNodes() (map[string]string, error) {
} }
// If we aren't a device node, do nothing. // If we aren't a device node, do nothing.
if d.Type()&(os.ModeDevice|os.ModeCharDevice) == 0 { if d.Type()&os.ModeDevice == 0 {
return nil
}
// Ignore character devices, because it is not possible to set limits on them.
// os.ModeCharDevice is usable only when os.ModeDevice is set.
if onlyBlockDevices && d.Type()&os.ModeCharDevice != 0 {
return nil return nil
} }

View File

@ -5,6 +5,6 @@ package util
import "errors" import "errors"
// FindDeviceNodes is not implemented anywhere except Linux. // FindDeviceNodes is not implemented anywhere except Linux.
func FindDeviceNodes() (map[string]string, error) { func FindDeviceNodes(onlyBlockDevices bool) (map[string]string, error) {
return nil, errors.New("not supported on non-Linux OSes") return nil, errors.New("not supported on non-Linux OSes")
} }

View File

@ -710,15 +710,15 @@ t GET libpod/containers/$cname/json 200 \
.ImageName=$IMAGE \ .ImageName=$IMAGE \
.Name=$cname .Name=$cname
if root; then if root && test -e /dev/nullb0; then
podman run -dt --name=updateCtr alpine podman run -dt --name=updateCtr alpine
echo '{ echo '{
"Memory":{"Limit":500000}, "Memory":{"Limit":500000},
"CPU":{"Shares":123}, "CPU":{"Shares":123},
"DeviceReadBPs": [{ "Path": "/dev/zero", "Rate": 10485760 }], "DeviceReadBPs": [{ "Path": "/dev/nullb0", "Rate": 10485760 }],
"DeviceWriteBPs": [{ "Path": "/dev/zero", "Rate": 31457280 }], "DeviceWriteBPs": [{ "Path": "/dev/nullb0", "Rate": 31457280 }],
"DeviceReadIOPs": [{ "Path": "/dev/zero", "Rate": 2000 }], "DeviceReadIOPs": [{ "Path": "/dev/nullb0", "Rate": 2000 }],
"DeviceWriteIOPs": [{ "Path": "/dev/zero", "Rate": 4000 }] "DeviceWriteIOPs": [{ "Path": "/dev/nullb0", "Rate": 4000 }]
}' >${TMPD}/update.json }' >${TMPD}/update.json
t POST libpod/containers/updateCtr/update ${TMPD}/update.json 201 t POST libpod/containers/updateCtr/update ${TMPD}/update.json 201
@ -734,25 +734,25 @@ if root; then
BlkioDeviceReadBps_expected='[ BlkioDeviceReadBps_expected='[
{ {
"Path": "/dev/zero", "Path": "/dev/nullb0",
"Rate": 10485760 "Rate": 10485760
} }
]' ]'
BlkioDeviceWriteBPs_expected='[ BlkioDeviceWriteBPs_expected='[
{ {
"Path": "/dev/zero", "Path": "/dev/nullb0",
"Rate": 31457280 "Rate": 31457280
} }
]' ]'
BlkioDeviceReadIOPs_expected='[ BlkioDeviceReadIOPs_expected='[
{ {
"Path": "/dev/zero", "Path": "/dev/nullb0",
"Rate": 2000 "Rate": 2000
} }
]' ]'
BlkioDeviceWriteIOPs_expected='[ BlkioDeviceWriteIOPs_expected='[
{ {
"Path": "/dev/zero", "Path": "/dev/nullb0",
"Rate": 4000 "Rate": 4000
} }
]' ]'