From bc34662c2c1497976eed404962015f4c73c14a5e Mon Sep 17 00:00:00 2001 From: eabdullin Date: Tue, 11 Mar 2025 08:09:35 +0000 Subject: [PATCH] import CS runc-1.2.4-2.el9 --- .gitignore | 2 +- .runc.metadata | 2 +- ...Bump-runtime-spec-to-latest-git-HEAD.patch | 103 ++++ ...002-runc-exec-implement-CPU-affinity.patch | 521 ++++++++++++++++++ SPECS/runc.spec | 30 +- 5 files changed, 654 insertions(+), 4 deletions(-) create mode 100644 SOURCES/0001-Bump-runtime-spec-to-latest-git-HEAD.patch create mode 100644 SOURCES/0002-runc-exec-implement-CPU-affinity.patch diff --git a/.gitignore b/.gitignore index aa46d22..eb6c2df 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/v1.1.13.tar.gz +SOURCES/v1.2.4.tar.gz diff --git a/.runc.metadata b/.runc.metadata index 394b328..e5c8864 100644 --- a/.runc.metadata +++ b/.runc.metadata @@ -1 +1 @@ -d02f66428909c9d4fdf5333d6a23c218f5bb8c7d SOURCES/v1.1.13.tar.gz +14c6119053012f4072aed8dbb9fd47b57c47279b SOURCES/v1.2.4.tar.gz diff --git a/SOURCES/0001-Bump-runtime-spec-to-latest-git-HEAD.patch b/SOURCES/0001-Bump-runtime-spec-to-latest-git-HEAD.patch new file mode 100644 index 0000000..8268405 --- /dev/null +++ b/SOURCES/0001-Bump-runtime-spec-to-latest-git-HEAD.patch @@ -0,0 +1,103 @@ +From c6dad73d617864f3a281ac1fdaacd5ed971fa317 Mon Sep 17 00:00:00 2001 +From: Kir Kolyshkin +Date: Thu, 27 Jun 2024 09:00:51 -0700 +Subject: [PATCH 1/2] Bump runtime-spec to latest git HEAD + +This is to include + - https://github.com/opencontainers/runtime-spec/pull/1261 + - https://github.com/opencontainers/runtime-spec/pull/1253 + +Signed-off-by: Kir Kolyshkin +(cherry picked from commit 2cac22b1e29e6be4c004f35ce582aa2b7e1c2fda) +Signed-off-by: Kir Kolyshkin +--- + go.mod | 2 +- + go.sum | 4 ++-- + .../opencontainers/runtime-spec/specs-go/config.go | 8 ++++++++ + .../opencontainers/runtime-spec/specs-go/version.go | 2 +- + vendor/modules.txt | 2 +- + 5 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/go.mod b/go.mod +index 348bc9c6..db2d7ef1 100644 +--- a/go.mod ++++ b/go.mod +@@ -19,7 +19,7 @@ require ( + github.com/moby/sys/user v0.3.0 + github.com/moby/sys/userns v0.1.0 + github.com/mrunalp/fileutils v0.5.1 +- github.com/opencontainers/runtime-spec v1.2.0 ++ github.com/opencontainers/runtime-spec v1.2.1-0.20240625190033-701738418b95 + github.com/opencontainers/selinux v1.11.0 + github.com/seccomp/libseccomp-golang v0.10.0 + github.com/sirupsen/logrus v1.9.3 +diff --git a/go.sum b/go.sum +index 225d5860..4c863cc9 100644 +--- a/go.sum ++++ b/go.sum +@@ -46,8 +46,8 @@ github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g + github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= + github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= + github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +-github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= +-github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= ++github.com/opencontainers/runtime-spec v1.2.1-0.20240625190033-701738418b95 h1:Ghl8Z3l+yPQUDSxAp7Kg7fJLRNNXjOsR6ooDcca7PjU= ++github.com/opencontainers/runtime-spec v1.2.1-0.20240625190033-701738418b95/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= + github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= + github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= + github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go +index d1236ba7..671f0d01 100644 +--- a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go ++++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go +@@ -94,6 +94,8 @@ type Process struct { + SelinuxLabel string `json:"selinuxLabel,omitempty" platform:"linux"` + // IOPriority contains the I/O priority settings for the cgroup. + IOPriority *LinuxIOPriority `json:"ioPriority,omitempty" platform:"linux"` ++ // ExecCPUAffinity specifies CPU affinity for exec processes. ++ ExecCPUAffinity *CPUAffinity `json:"execCPUAffinity,omitempty" platform:"linux"` + } + + // LinuxCapabilities specifies the list of allowed capabilities that are kept for a process. +@@ -127,6 +129,12 @@ const ( + IOPRIO_CLASS_IDLE IOPriorityClass = "IOPRIO_CLASS_IDLE" + ) + ++// CPUAffinity specifies process' CPU affinity. ++type CPUAffinity struct { ++ Initial string `json:"initial,omitempty"` ++ Final string `json:"final,omitempty"` ++} ++ + // Box specifies dimensions of a rectangle. Used for specifying the size of a console. + type Box struct { + // Height is the vertical dimension of a box. +diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go +index 503971e0..f6c15f6c 100644 +--- a/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go ++++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go +@@ -11,7 +11,7 @@ const ( + VersionPatch = 0 + + // VersionDev indicates development branch. Releases will be empty string. +- VersionDev = "" ++ VersionDev = "+dev" + ) + + // Version is the specification version that the package types support. +diff --git a/vendor/modules.txt b/vendor/modules.txt +index 3b245e0d..df520923 100644 +--- a/vendor/modules.txt ++++ b/vendor/modules.txt +@@ -46,7 +46,7 @@ github.com/moby/sys/userns + # github.com/mrunalp/fileutils v0.5.1 + ## explicit; go 1.13 + github.com/mrunalp/fileutils +-# github.com/opencontainers/runtime-spec v1.2.0 ++# github.com/opencontainers/runtime-spec v1.2.1-0.20240625190033-701738418b95 + ## explicit + github.com/opencontainers/runtime-spec/specs-go + github.com/opencontainers/runtime-spec/specs-go/features +-- +2.47.1 + diff --git a/SOURCES/0002-runc-exec-implement-CPU-affinity.patch b/SOURCES/0002-runc-exec-implement-CPU-affinity.patch new file mode 100644 index 0000000..90de1a6 --- /dev/null +++ b/SOURCES/0002-runc-exec-implement-CPU-affinity.patch @@ -0,0 +1,521 @@ +From 73786942b7176eae1e676cf2f78af548f090e418 Mon Sep 17 00:00:00 2001 +From: Kir Kolyshkin +Date: Mon, 21 Oct 2024 15:50:38 -0700 +Subject: [PATCH 2/2] runc exec: implement CPU affinity + +As per +- https://github.com/opencontainers/runtime-spec/pull/1253 +- https://github.com/opencontainers/runtime-spec/pull/1261 + +CPU affinity can be set in two ways: +1. When creating/starting a container, in config.json's + Process.ExecCPUAffinity, which is when applied to all execs. +2. When running an exec, in process.json's CPUAffinity, which + applied to a given exec and overrides the value from (1). + +Add some basic tests. + +Note that older kernels (RHEL8, Ubuntu 20.04) change CPU affinity of a +process to that of a container's cgroup, as soon as it is moved to that +cgroup, while newer kernels (Ubuntu 24.04, Fedora 41) don't do that. + +Because of the above, + - it's impossible to really test initial CPU affinity without adding + debug logging to libcontainer/nsenter; + - for older kernels, there can be a brief moment when exec's affinity + is different than either initial or final affinity being set; + - exec's final CPU affinity, if not specified, can be different + depending on the kernel, therefore we don't test it. + +Signed-off-by: Kir Kolyshkin +(cherry picked from commit 57237b31de367a722c5d49088912d57c28c6fb46) +Signed-off-by: Kir Kolyshkin +--- + libcontainer/configs/config.go | 72 ++++++++++++++++++++ + libcontainer/container_linux.go | 4 ++ + libcontainer/init_linux.go | 3 +- + libcontainer/nsenter/log.c | 9 ++- + libcontainer/nsenter/log.h | 3 + + libcontainer/nsenter/nsexec.c | 29 ++++++++ + libcontainer/process.go | 2 + + libcontainer/process_linux.go | 49 +++++++++++++- + libcontainer/specconv/spec_linux.go | 5 ++ + tests/integration/cpu_affinity.bats | 101 ++++++++++++++++++++++++++++ + utils_linux.go | 6 ++ + 11 files changed, 277 insertions(+), 6 deletions(-) + create mode 100644 tests/integration/cpu_affinity.bats + +diff --git a/libcontainer/configs/config.go b/libcontainer/configs/config.go +index 22fe0f9b..daffd130 100644 +--- a/libcontainer/configs/config.go ++++ b/libcontainer/configs/config.go +@@ -3,8 +3,11 @@ package configs + import ( + "bytes" + "encoding/json" ++ "errors" + "fmt" + "os/exec" ++ "strconv" ++ "strings" + "time" + + "github.com/sirupsen/logrus" +@@ -225,6 +228,9 @@ type Config struct { + + // IOPriority is the container's I/O priority. + IOPriority *IOPriority `json:"io_priority,omitempty"` ++ ++ // ExecCPUAffinity is CPU affinity for a non-init process to be run in the container. ++ ExecCPUAffinity *CPUAffinity `json:"exec_cpu_affinity,omitempty"` + } + + // Scheduler is based on the Linux sched_setattr(2) syscall. +@@ -294,6 +300,72 @@ var IOPrioClassMapping = map[specs.IOPriorityClass]int{ + + type IOPriority = specs.LinuxIOPriority + ++type CPUAffinity struct { ++ Initial, Final *unix.CPUSet ++} ++ ++func toCPUSet(str string) (*unix.CPUSet, error) { ++ if str == "" { ++ return nil, nil ++ } ++ s := new(unix.CPUSet) ++ for _, r := range strings.Split(str, ",") { ++ // Allow extra spaces around. ++ r = strings.TrimSpace(r) ++ // Allow empty elements (extra commas). ++ if r == "" { ++ continue ++ } ++ if r0, r1, found := strings.Cut(r, "-"); found { ++ start, err := strconv.ParseUint(r0, 10, 32) ++ if err != nil { ++ return nil, err ++ } ++ end, err := strconv.ParseUint(r1, 10, 32) ++ if err != nil { ++ return nil, err ++ } ++ if start > end { ++ return nil, errors.New("invalid range: " + r) ++ } ++ for i := int(start); i <= int(end); i++ { ++ s.Set(i) ++ } ++ } else { ++ val, err := strconv.ParseUint(r, 10, 32) ++ if err != nil { ++ return nil, err ++ } ++ s.Set(int(val)) ++ } ++ } ++ ++ return s, nil ++} ++ ++// ConvertCPUAffinity converts [specs.CPUAffinity] to [CPUAffinity]. ++func ConvertCPUAffinity(sa *specs.CPUAffinity) (*CPUAffinity, error) { ++ if sa == nil { ++ return nil, nil ++ } ++ initial, err := toCPUSet(sa.Initial) ++ if err != nil { ++ return nil, fmt.Errorf("bad CPUAffinity.Initial: %w", err) ++ } ++ final, err := toCPUSet(sa.Final) ++ if err != nil { ++ return nil, fmt.Errorf("bad CPUAffinity.Final: %w", err) ++ } ++ if initial == nil && final == nil { ++ return nil, nil ++ } ++ ++ return &CPUAffinity{ ++ Initial: initial, ++ Final: final, ++ }, nil ++} ++ + type ( + HookName string + HookList []Hook +diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go +index c0211617..1fc590a5 100644 +--- a/libcontainer/container_linux.go ++++ b/libcontainer/container_linux.go +@@ -692,6 +692,7 @@ func (c *Container) newInitConfig(process *Process) *initConfig { + AppArmorProfile: c.config.AppArmorProfile, + ProcessLabel: c.config.ProcessLabel, + Rlimits: c.config.Rlimits, ++ CPUAffinity: c.config.ExecCPUAffinity, + CreateConsole: process.ConsoleSocket != nil, + ConsoleWidth: process.ConsoleWidth, + ConsoleHeight: process.ConsoleHeight, +@@ -708,6 +709,9 @@ func (c *Container) newInitConfig(process *Process) *initConfig { + if len(process.Rlimits) > 0 { + cfg.Rlimits = process.Rlimits + } ++ if process.CPUAffinity != nil { ++ cfg.CPUAffinity = process.CPUAffinity ++ } + if cgroups.IsCgroup2UnifiedMode() { + cfg.Cgroup2Path = c.cgroupManager.Path("") + } +diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go +index 1eb0279d..eddbfba6 100644 +--- a/libcontainer/init_linux.go ++++ b/libcontainer/init_linux.go +@@ -72,6 +72,7 @@ type initConfig struct { + RootlessCgroups bool `json:"rootless_cgroups,omitempty"` + SpecState *specs.State `json:"spec_state,omitempty"` + Cgroup2Path string `json:"cgroup2_path,omitempty"` ++ CPUAffinity *configs.CPUAffinity `json:"cpu_affinity,omitempty"` + } + + // Init is part of "runc init" implementation. +@@ -151,7 +152,7 @@ func startInitialization() (retErr error) { + + logrus.SetOutput(logPipe) + logrus.SetFormatter(new(logrus.JSONFormatter)) +- logrus.Debug("child process in init()") ++ logrus.Debugf("child process in init()") + + // Only init processes have FIFOFD. + var fifoFile *os.File +diff --git a/libcontainer/nsenter/log.c b/libcontainer/nsenter/log.c +index 086b5398..72774cb0 100644 +--- a/libcontainer/nsenter/log.c ++++ b/libcontainer/nsenter/log.c +@@ -31,6 +31,11 @@ void setup_logpipe(void) + loglevel = i; + } + ++bool log_enabled_for(int level) ++{ ++ return (logfd >= 0 && level <= loglevel); ++} ++ + /* Defined in nsexec.c */ + extern int current_stage; + +@@ -40,8 +45,8 @@ void write_log(int level, const char *format, ...) + va_list args; + int ret; + +- if (logfd < 0 || level > loglevel) +- goto out; ++ if (!log_enabled_for(level)) ++ return; + + va_start(args, format); + ret = vasprintf(&message, format, args); +diff --git a/libcontainer/nsenter/log.h b/libcontainer/nsenter/log.h +index 1fe95a11..3e18de68 100644 +--- a/libcontainer/nsenter/log.h ++++ b/libcontainer/nsenter/log.h +@@ -1,6 +1,7 @@ + #ifndef NSENTER_LOG_H + #define NSENTER_LOG_H + ++#include + #include + + /* +@@ -20,6 +21,8 @@ + */ + void setup_logpipe(void); + ++bool log_enabled_for(int level); ++ + void write_log(int level, const char *format, ...) __attribute__((format(printf, 2, 3))); + + extern int logfd; +diff --git a/libcontainer/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c +index 565b2ca2..aa4976d6 100644 +--- a/libcontainer/nsenter/nsexec.c ++++ b/libcontainer/nsenter/nsexec.c +@@ -558,6 +558,25 @@ static void update_timens_offsets(pid_t pid, char *map, size_t map_len) + bail("failed to update /proc/%d/timens_offsets", pid); + } + ++void print_cpu_affinity() ++{ ++ cpu_set_t cpus = { }; ++ size_t i, mask = 0; ++ ++ if (sched_getaffinity(0, sizeof(cpus), &cpus) < 0) { ++ write_log(WARNING, "sched_getaffinity: %m"); ++ return; ++ } ++ ++ /* Do not print the complete mask, we only need a few first CPUs. */ ++ for (i = 0; i < sizeof(mask) * 8; i++) { ++ if (CPU_ISSET(i, &cpus)) ++ mask |= 1 << i; ++ } ++ ++ write_log(DEBUG, "affinity: 0x%zx", mask); ++} ++ + void nsexec(void) + { + int pipenum; +@@ -584,6 +603,16 @@ void nsexec(void) + + write_log(DEBUG, "=> nsexec container setup"); + ++ /* This is for ../../tests/integration/cpu_affinity.bats test only. ++ * ++ * Printing this from Go code might be too late as some kernels ++ * change the process' CPU affinity to that of container's cpuset ++ * as soon as the process is moved into container's cgroup. ++ */ ++ if (log_enabled_for(DEBUG)) { ++ print_cpu_affinity(); ++ } ++ + /* Parse all of the netlink configuration. */ + nl_parse(pipenum, &config); + +diff --git a/libcontainer/process.go b/libcontainer/process.go +index 114b3f2b..5339583f 100644 +--- a/libcontainer/process.go ++++ b/libcontainer/process.go +@@ -102,6 +102,8 @@ type Process struct { + Scheduler *configs.Scheduler + + IOPriority *configs.IOPriority ++ ++ CPUAffinity *configs.CPUAffinity + } + + // Wait waits for the process to exit. +diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go +index fcbb54a3..477c8a77 100644 +--- a/libcontainer/process_linux.go ++++ b/libcontainer/process_linux.go +@@ -122,6 +122,46 @@ func (p *setnsProcess) signal(sig os.Signal) error { + return unix.Kill(p.pid(), s) + } + ++// Starts setns process with specified initial CPU affinity. ++func (p *setnsProcess) startWithCPUAffinity() error { ++ aff := p.config.CPUAffinity ++ if aff == nil || aff.Initial == nil { ++ return p.cmd.Start() ++ } ++ errCh := make(chan error) ++ defer close(errCh) ++ ++ // Use a goroutine to dedicate an OS thread. ++ go func() { ++ runtime.LockOSThread() ++ // Command inherits the CPU affinity. ++ if err := unix.SchedSetaffinity(unix.Gettid(), aff.Initial); err != nil { ++ runtime.UnlockOSThread() ++ errCh <- fmt.Errorf("error setting initial CPU affinity: %w", err) ++ return ++ } ++ ++ errCh <- p.cmd.Start() ++ // Deliberately omit runtime.UnlockOSThread here. ++ // https://pkg.go.dev/runtime#LockOSThread says: ++ // "If the calling goroutine exits without unlocking the ++ // thread, the thread will be terminated". ++ }() ++ ++ return <-errCh ++} ++ ++func (p *setnsProcess) setFinalCPUAffinity() error { ++ aff := p.config.CPUAffinity ++ if aff == nil || aff.Final == nil { ++ return nil ++ } ++ if err := unix.SchedSetaffinity(p.pid(), aff.Final); err != nil { ++ return fmt.Errorf("error setting final CPU affinity: %w", err) ++ } ++ return nil ++} ++ + func (p *setnsProcess) start() (retErr error) { + defer p.comm.closeParent() + +@@ -133,8 +173,8 @@ func (p *setnsProcess) start() (retErr error) { + + // get the "before" value of oom kill count + oom, _ := p.manager.OOMKillCount() +- err := p.cmd.Start() +- // close the child-side of the pipes (controlled by child) ++ err := p.startWithCPUAffinity() ++ // Close the child-side of the pipes (controlled by child). + p.comm.closeChild() + if err != nil { + return fmt.Errorf("error starting setns process: %w", err) +@@ -184,6 +224,10 @@ func (p *setnsProcess) start() (retErr error) { + } + } + } ++ // Set final CPU affinity right after the process is moved into container's cgroup. ++ if err := p.setFinalCPUAffinity(); err != nil { ++ return err ++ } + if p.intelRdtPath != "" { + // if Intel RDT "resource control" filesystem path exists + _, err := os.Stat(p.intelRdtPath) +@@ -193,7 +237,6 @@ func (p *setnsProcess) start() (retErr error) { + } + } + } +- + if err := utils.WriteJSON(p.comm.initSockParent, p.config); err != nil { + return fmt.Errorf("error writing config to pipe: %w", err) + } +diff --git a/libcontainer/specconv/spec_linux.go b/libcontainer/specconv/spec_linux.go +index 95ada499..2d0db342 100644 +--- a/libcontainer/specconv/spec_linux.go ++++ b/libcontainer/specconv/spec_linux.go +@@ -556,6 +556,11 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) { + ioPriority := *spec.Process.IOPriority + config.IOPriority = &ioPriority + } ++ config.ExecCPUAffinity, err = configs.ConvertCPUAffinity(spec.Process.ExecCPUAffinity) ++ if err != nil { ++ return nil, err ++ } ++ + } + createHooks(spec, config) + config.Version = specs.Version +diff --git a/tests/integration/cpu_affinity.bats b/tests/integration/cpu_affinity.bats +new file mode 100644 +index 00000000..f6adfa2a +--- /dev/null ++++ b/tests/integration/cpu_affinity.bats +@@ -0,0 +1,101 @@ ++#!/usr/bin/env bats ++# Exec CPU affinity tests. For more details, see: ++# - https://github.com/opencontainers/runtime-spec/pull/1253 ++ ++load helpers ++ ++function setup() { ++ requires smp cgroups_cpuset ++ setup_busybox ++} ++ ++function teardown() { ++ teardown_bundle ++} ++ ++function first_cpu() { ++ sed 's/[-,].*//g' "-". ++ cpus=${cpus//-/ } # 2. "-" --> " ". ++ ++ for c in $cpus; do ++ mask=$((mask | 1 << c)) ++ done ++ ++ printf "0x%x" $mask ++} ++ ++@test "runc exec [CPU affinity, only initial set from process.json]" { ++ first="$(first_cpu)" ++ second=$((first + 1)) # Hacky; might not work in all environments. ++ ++ runc run -d --console-socket "$CONSOLE_SOCKET" ct1 ++ [ "$status" -eq 0 ] ++ ++ for cpus in "$second" "$first-$second" "$first,$second" "$first"; do ++ proc=' ++{ ++ "terminal": false, ++ "execCPUAffinity": { ++ "initial": "'$cpus'" ++ }, ++ "args": [ "/bin/true" ], ++ "cwd": "/" ++}' ++ mask=$(cpus_to_mask "$cpus") ++ echo "CPUS: $cpus, mask: $mask" ++ runc --debug exec --process <(echo "$proc") ct1 ++ [[ "$output" == *"nsexec"*": affinity: $mask"* ]] ++ done ++} ++ ++@test "runc exec [CPU affinity, initial and final set from process.json]" { ++ first="$(first_cpu)" ++ second=$((first + 1)) # Hacky; might not work in all environments. ++ ++ runc run -d --console-socket "$CONSOLE_SOCKET" ct1 ++ [ "$status" -eq 0 ] ++ ++ for cpus in "$second" "$first-$second" "$first,$second" "$first"; do ++ proc=' ++{ ++ "terminal": false, ++ "execCPUAffinity": { ++ "initial": "'$cpus'", ++ "final": "'$cpus'" ++ }, ++ "args": [ "/bin/grep", "-F", "Cpus_allowed_list:", "/proc/self/status" ], ++ "cwd": "/" ++}' ++ mask=$(cpus_to_mask "$cpus") ++ exp=${cpus//,/-} # "," --> "-". ++ echo "CPUS: $cpus, mask: $mask, final: $exp" ++ runc --debug exec --process <(echo "$proc") ct1 ++ [[ "$output" == *"nsexec"*": affinity: $mask"* ]] ++ [[ "$output" == *"Cpus_allowed_list: $exp"* ]] # Mind the literal tab. ++ done ++} ++ ++@test "runc exec [CPU affinity, initial and final set from config.json]" { ++ initial="$(first_cpu)" ++ final=$((initial + 1)) # Hacky; might not work in all environments. ++ ++ update_config " .process.execCPUAffinity.initial = \"$initial\" ++ | .process.execCPUAffinity.final = \"$final\"" ++ ++ runc run -d --console-socket "$CONSOLE_SOCKET" ct1 ++ [ "$status" -eq 0 ] ++ ++ runc --debug exec ct1 grep "Cpus_allowed_list:" /proc/self/status ++ [ "$status" -eq 0 ] ++ mask=$(cpus_to_mask "$initial") ++ [[ "$output" == *"nsexec"*": affinity: $mask"* ]] ++ [[ "$output" == *"Cpus_allowed_list: $final"* ]] # Mind the literal tab. ++} +diff --git a/utils_linux.go b/utils_linux.go +index feb6ef80..013dbcf4 100644 +--- a/utils_linux.go ++++ b/utils_linux.go +@@ -90,6 +90,12 @@ func newProcess(p specs.Process) (*libcontainer.Process, error) { + } + lp.Rlimits = append(lp.Rlimits, rl) + } ++ aff, err := configs.ConvertCPUAffinity(p.ExecCPUAffinity) ++ if err != nil { ++ return nil, err ++ } ++ lp.CPUAffinity = aff ++ + return lp, nil + } + +-- +2.47.1 + diff --git a/SPECS/runc.spec b/SPECS/runc.spec index 6b595bf..4c391e5 100644 --- a/SPECS/runc.spec +++ b/SPECS/runc.spec @@ -19,8 +19,8 @@ go build -buildmode pie -compiler gc -tags="rpm_crashtraceback libtrust_openssl Epoch: 4 Name: %{repo} -Version: 1.1.13 -Release: 4%{?dist} +Version: 1.2.4 +Release: 2%{?dist} Summary: CLI for running Open Containers # https://fedoraproject.org/wiki/PackagingDrafts/Go#Go_Language_Architectures #ExclusiveArch: %%{go_arches} @@ -30,6 +30,8 @@ ExcludeArch: %{ix86} License: ASL 2.0 URL: %{git0} Source0: %{git0}/archive/v%{version}.tar.gz +Patch0: 0001-Bump-runtime-spec-to-latest-git-HEAD.patch +Patch1: 0002-runc-exec-implement-CPU-affinity.patch Provides: oci-runtime BuildRequires: golang >= 1.22.4 BuildRequires: git @@ -84,6 +86,30 @@ make install install-man install-bash DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} %{_datadir}/bash-completion/completions/%{name} %changelog +* Fri Jan 24 2025 Jindrich Novy - 4:1.2.4-2 +- Implement CPU affinity patch from Kir Kolishkin +- Related: RHEL-60277 + +* Fri Jan 10 2025 Jindrich Novy - 4:1.2.4-1 +- update to https://github.com/opencontainers/runc/releases/tag/v1.2.4 +- Related: RHEL-60277 + +* Wed Dec 11 2024 Jindrich Novy - 4:1.2.3-1 +- update to https://github.com/opencontainers/runc/releases/tag/v1.2.3 +- Related: RHEL-60277 + +* Wed Nov 27 2024 Jindrich Novy - 4:1.2.2-1 +- update to https://github.com/opencontainers/runc/releases/tag/v1.2.2 +- Resolves: RHEL-69142 + +* Tue Oct 08 2024 Jindrich Novy - 4:1.1.15-1 +- update to https://github.com/opencontainers/runc/releases/tag/v1.1.15 +- Related: RHEL-61725 + +* Wed Sep 04 2024 Jindrich Novy - 4:1.1.14-1 +- update to https://github.com/opencontainers/runc/releases/tag/v1.1.14 +- Related: RHEL-27608 + * Mon Jul 15 2024 Jindrich Novy - 4:1.1.13-4 - rebuild against new golang - Resolves: RHEL-46380