Skip to content

runsc Doesn't Skip Empty BlockIO #14738

Description

@colin240215

Description

Symptom

runsc fails on a kernel with

  • cgroup v1, and
  • CONFIG_BLK_CGROUP disabled

Root Cause

992a840889 intends to make cgroup blkio optional. But it skips iff the BlockIO struct is nil.

Docker always populates that struct, even when no I/O limit was requested.

Inspect Container Config
docker run --rm -v /run:/rc:ro alpine sh -c 'grep -o "\"blockIO\":{[^}]*}" $(find /rc -path "*/io.containerd.runtime.v2.task/moby/$(hostname)*/config.json")'

Output

// Docker v24.0.2
"blockIO":{"weight":0}

// Newer Docker
"blockIO":{}

Proposal

In addition to nil check, blockIO.skip() checks whether all fields of LinuxBlockIO are default.

func (*blockIO) skip(spec *specs.LinuxResources) error {
	if spec == nil || spec.BlockIO == nil {
		return nil
	}

	b := spec.BlockIO
	if (b.Weight != nil && *b.Weight != 0) ||
		(b.LeafWeight != nil && *b.LeafWeight != 0) ||
		len(b.WeightDevice) > 0 ||
		len(b.ThrottleReadBpsDevice) > 0 ||
		len(b.ThrottleWriteBpsDevice) > 0 ||
		len(b.ThrottleReadIOPSDevice) > 0 ||
		len(b.ThrottleWriteIOPSDevice) > 0 {
		return fmt.Errorf("blkio controller is missing but limits are set in OCI spec")
	}
	return nil
}

Steps to reproduce

Docker Runtime Failure

Requirements (if infeasible, try Unit Test Failure instead)

  • cgroup v1
  • CONFIG_BLK_CGROUP disabled. i.e. build the kernel with CONFIG_BLK_CGROUP=n

Command

docker run --rm --runtime runsc alpine true

Error

docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: creating container: cannot set up cgroup for root: configuring cgroup: stat /sys/fs/cgroup/blkio: no such file or directory: unknown.

Unit Test Failure

Add extraValid to TestOptional

		{
			name:  "blkio",
			ctrlr: &blockIO{},
			extraValid: []*specs.LinuxResources{
				{BlockIO: &specs.LinuxBlockIO{}},                     // Docker 29
				{BlockIO: &specs.LinuxBlockIO{Weight: uint16Ptr(0)}}, // Docker ≤ 24
			},
			invalid: []struct {
				name string
				spec *specs.LinuxResources
				err  string
			}{
				{
					name: "weight",
					spec: &specs.LinuxResources{BlockIO: &specs.LinuxBlockIO{Weight: uint16Ptr(1)}},
					err:  "blkio controller is missing but limits are set in OCI spec",
				},
			},
		},

The test fails with the current skip().

The proposal fixes it.

Combined with Inspect Container Config, this shows that the current implementation does not skip BlockIO as expected.

runsc version

runsc version VERSION_MISSING
spec: 1.2.1

Built from source at release-20260817.0-43-g80336ad54

docker version (if using docker)

Client:
 Version:           24.0.2
 API version:       1.43
 Go version:        go1.20.4
 Git commit:        610b8d0
 Built:             Thu Sep 25 10:08:01 2025
 OS/Arch:           linux/amd64
 Context:           default

Server:
 Engine:
  Version:          24.0.2
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.4
  Git commit:       bd0a34d
  Built:            Thu Sep 25 10:09:08 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.7.1
  GitCommit:        fea6458b8abe502f6228eab2e5a6678fcb5c3fb0
 runc:
  Version:          v1.1.7
  GitCommit:        0320c58
 docker-init:
  Version:          0.19.0
  GitCommit:        ed96d00

uname

Linux 5.10.55+ SMP x86_64 GNU/Linux

kubectl (if using Kubernetes)

repo state (if built from source)

fatal: No names found, cannot describe anything.

runsc debug logs (if available)

Not applicable: the failure happens in runsc create before the sandbox starts

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions