Skip to content

Commit 284a680

Browse files
committed
fix:cpu affinity
Signed-off-by: ningmingxiao <[email protected]>
1 parent a85b5fc commit 284a680

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

libcontainer/process_linux.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ func (p *setnsProcess) start() (retErr error) {
254254
}
255255
}
256256
}
257+
if err := setAffinityAll(p.pid()); err != nil {
258+
return err
259+
}
257260
// Set final CPU affinity right after the process is moved into container's cgroup.
258261
if err := p.setFinalCPUAffinity(); err != nil {
259262
return err
@@ -615,6 +618,11 @@ func (p *initProcess) start() (retErr error) {
615618
return fmt.Errorf("unable to apply cgroup configuration: %w", err)
616619
}
617620
}
621+
622+
if err := setAffinityAll(p.pid()); err != nil {
623+
return err
624+
}
625+
618626
if p.intelRdtManager != nil {
619627
if err := p.intelRdtManager.Apply(p.pid()); err != nil {
620628
return fmt.Errorf("unable to apply Intel RDT configuration: %w", err)
@@ -981,3 +989,24 @@ func (p *Process) InitializeIO(rootuid, rootgid int) (i *IO, err error) {
981989
}
982990
return i, nil
983991
}
992+
993+
// Set all inherited cpu affinity. Old kernels do that automatically, but
994+
// new kernels remember the affinity that was set before the cgroup move.
995+
// This is undesirable, because it inherits the systemd affinity when the container
996+
// should really move to the container space cpus.
997+
// here we can't use runtime.NumCPU() to get cpu counts because it call sched_getaffinity to get cpu counts.
998+
// If systemd set CPUAffinity then use runtime.NumCPU() can't get real cpu counts.
999+
func setAffinityAll(pid int) error {
1000+
cpus, err := utils.SystemCPUCores()
1001+
if err != nil {
1002+
return err
1003+
}
1004+
cpuset := unix.CPUSet{}
1005+
for i := 0; i < int(cpus); i++ {
1006+
cpuset.Set(i)
1007+
}
1008+
if err := unix.SchedSetaffinity(pid, &cpuset); err != nil {
1009+
return fmt.Errorf("error resetting pid %d affinity: %w", pid, err)
1010+
}
1011+
return nil
1012+
}

libcontainer/utils/utils.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package utils
22

33
import (
4+
"bufio"
45
"encoding/json"
6+
"fmt"
57
"io"
68
"os"
79
"path/filepath"
@@ -113,3 +115,37 @@ func Annotations(labels []string) (bundle string, userAnnotations map[string]str
113115
}
114116
return
115117
}
118+
119+
// SystemCPUCores parses CPU usage information from a reader providing
120+
// /proc/stat format data. It returns the number of CPUs.
121+
func SystemCPUCores() (cpuNum uint32, _ error) {
122+
f, err := os.Open("/proc/stat")
123+
if err != nil {
124+
return 0, err
125+
}
126+
defer f.Close()
127+
return readSystemCPU(f)
128+
}
129+
130+
func readSystemCPU(r io.Reader) (cpuNum uint32, _ error) {
131+
rdr := bufio.NewReaderSize(r, 1024)
132+
for {
133+
data, isPartial, err := rdr.ReadLine()
134+
if err != nil {
135+
return 0, fmt.Errorf("error scanning /proc/stat file: %w", err)
136+
}
137+
// Assume all cpu* records are at the start of the file, like glibc:
138+
// https://github.com/bminor/glibc/blob/5d00c201b9a2da768a79ea8d5311f257871c0b43/sysdeps/unix/sysv/linux/getsysstats.c#L108-L135
139+
if isPartial || len(data) < 4 {
140+
break
141+
}
142+
line := string(data)
143+
if line[:3] != "cpu" {
144+
break
145+
}
146+
if '0' <= line[3] && line[3] <= '9' {
147+
cpuNum++
148+
}
149+
}
150+
return cpuNum, nil
151+
}

libcontainer/utils/utils_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,13 @@ func TestStripRoot(t *testing.T) {
137137
}
138138
}
139139
}
140+
141+
func TestSystemCPUCores(t *testing.T) {
142+
numCpusNew, err := SystemCPUCores()
143+
if err != nil {
144+
t.Errorf("failed to run SystemCPUCores err:%v", err)
145+
}
146+
if numCpusNew == 0 {
147+
t.Errorf("numCpusNew can't equal 0")
148+
}
149+
}

0 commit comments

Comments
 (0)