Merge pull request #5025 from askervin/5eA-workaround-max-1kcpus

libct: fix resetting CPU affinity
This commit is contained in:
Kir Kolyshkin
2026-03-04 13:26:42 -08:00
committed by GitHub
2 changed files with 41 additions and 22 deletions
+17
View File
@@ -2,6 +2,7 @@ package linux
import (
"os"
"unsafe"
"golang.org/x/sys/unix"
)
@@ -65,6 +66,22 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from unix.Sockaddr, err error
return n, from, err
}
// SchedSetaffinity wraps sched_setaffinity syscall without unix.CPUSet size limitation.
func SchedSetaffinity(pid int, buf []byte) error {
err := retryOnEINTR(func() error {
_, _, errno := unix.Syscall(
unix.SYS_SCHED_SETAFFINITY,
uintptr(pid),
uintptr(len(buf)),
uintptr((unsafe.Pointer)(&buf[0])))
if errno != 0 {
return errno
}
return nil
})
return os.NewSyscallError("sched_setaffinity", err)
}
// Sendmsg wraps [unix.Sendmsg].
func Sendmsg(fd int, p, oob []byte, to unix.Sockaddr, flags int) error {
err := retryOnEINTR(func() error {
+24 -22
View File
@@ -1,6 +1,7 @@
package libcontainer
import (
"bytes"
"context"
"encoding/json"
"errors"
@@ -25,6 +26,7 @@ import (
"github.com/opencontainers/cgroups"
"github.com/opencontainers/cgroups/fs2"
"github.com/opencontainers/runc/internal/linux"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/intelrdt"
"github.com/opencontainers/runc/libcontainer/internal/userns"
@@ -178,33 +180,33 @@ type setnsProcess struct {
// tryResetCPUAffinity tries to reset the CPU affinity of the process
// identified by pid to include all possible CPUs (notwithstanding cgroup
// cpuset restrictions and isolated CPUs).
// cpuset restrictions, isolated CPUs and CPU online status).
func tryResetCPUAffinity(pid int) {
// When resetting the CPU affinity, we want to match the configured cgroup
// cpuset (or the default set of all CPUs, if no cpuset is configured)
// rather than some more restrictive affinity we were spawned in (such as
// one that may have been inherited from systemd). The cpuset cgroup used
// to reconfigure the cpumask automatically for joining processes, but
// kcommit da019032819a ("sched: Enforce user requested affinity") changed
// this behaviour in Linux 6.2.
// When resetting the CPU affinity, we want to allow all
// possible CPUs in the system, including those not in
// cpuset.cpus, online or even present (hot-plugged) at call
// time. Using a cpumask any tighter this that may disallow
// using those CPUs if they are added to cpuset.cpus later.
//
// Parsing cpuset.cpus.effective is quite inefficient (and looking at
// things like /proc/stat would be wrong for most nested containers), but
// luckily sched_setaffinity(2) will implicitly:
// Note that sched_setaffinity(2) will implicitly:
//
// * Clamp the cpumask so that it matches the number of CPUs
// supported by the kernel.
//
// * Clamp the cpumask so that it matches the current number of CPUs on
// the system.
// * Mask out any CPUs that are not a member of the target task's
// configured cgroup cpuset.
// configured cgroup cpuset. This is for task's effective affinity,
// without forgetting masked-out CPUs should the cgroup cpuset
// change later.
//
// So we can just pass a very large array of set cpumask bits and the
// kernel will silently convert that to the correct value very cheaply.
var cpuset unix.CPUSet
cpuset.Fill() // set all bits
if err := unix.SchedSetaffinity(pid, &cpuset); err != nil {
logrus.WithError(
os.NewSyscallError("sched_setaffinity", err),
).Warnf("resetting the CPU affinity of pid %d failed -- the container process may inherit runc's CPU affinity", pid)
// Therefore, preparing the cpumask, we can avoid reading
// /sys/devices/system/cpu/possible and kernel_max.
// Instead, we use a huge buffer similarly to go 1.25 runtime in
// getCPUCount().
const maxCPUs = 64 * 1024
buf := bytes.Repeat([]byte{0xff}, maxCPUs/8)
if err := linux.SchedSetaffinity(pid, buf); err != nil {
logrus.WithError(err).Warnf("resetting the CPU affinity of pid %d failed -- the container process may inherit runc's CPU affinity", pid)
return
}
}