mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-29 20:24:31 +00:00
cpuset: support setting mems for sandbox
CPUSet cgroup allows for pinning the memory associated with a cpuset to a given numa node. Similar to cpuset.cpus, we should take cpuset.mems into account for the sandbox-cgroup that Kata creates. Signed-off-by: Eric Ernst <eric.g.ernst@gmail.com>
This commit is contained in:
parent
2d690536b8
commit
77a463e57a
@ -332,7 +332,7 @@ func (m *Manager) RemoveDevice(device string) error {
|
||||
return fmt.Errorf("device %v not found in the cgroup", device)
|
||||
}
|
||||
|
||||
func (m *Manager) SetCPUSet(cpuset string) error {
|
||||
func (m *Manager) SetCPUSet(cpuset, memset string) error {
|
||||
cgroups, err := m.GetCgroups()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -340,6 +340,7 @@ func (m *Manager) SetCPUSet(cpuset string) error {
|
||||
|
||||
m.Lock()
|
||||
cgroups.CpusetCpus = cpuset
|
||||
cgroups.CpusetMems = memset
|
||||
m.Unlock()
|
||||
|
||||
return m.Apply()
|
||||
|
@ -1995,15 +1995,13 @@ func (s *Sandbox) cgroupsUpdate() error {
|
||||
// in the Kata sandbox cgroup (inherited). Check to see if sandbox cpuset needs to be
|
||||
// updated.
|
||||
if s.config.SandboxCgroupOnly {
|
||||
cpuset, err := s.getSandboxCPUSet()
|
||||
cpuset, memset, err := s.getSandboxCPUSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cpuset != "" {
|
||||
if err := s.cgroupMgr.SetCPUSet(cpuset); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.cgroupMgr.SetCPUSet(cpuset, memset); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -2304,23 +2302,30 @@ func (s *Sandbox) GetAgentURL() (string, error) {
|
||||
return s.agent.getAgentURL()
|
||||
}
|
||||
|
||||
// getSandboxCPUSet returns the union of each of the sandbox's containers' CPU sets
|
||||
// as a string in canonical linux CPU list format
|
||||
func (s *Sandbox) getSandboxCPUSet() (string, error) {
|
||||
// getSandboxCPUSet returns the union of each of the sandbox's containers' CPU sets'
|
||||
// cpus and mems as a string in canonical linux CPU/mems list format
|
||||
func (s *Sandbox) getSandboxCPUSet() (string, string, error) {
|
||||
if s.config == nil {
|
||||
return "", nil
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
result := cpuset.NewCPUSet()
|
||||
cpuResult := cpuset.NewCPUSet()
|
||||
memResult := cpuset.NewCPUSet()
|
||||
for _, ctr := range s.config.Containers {
|
||||
if ctr.Resources.CPU != nil {
|
||||
currSet, err := cpuset.Parse(ctr.Resources.CPU.Cpus)
|
||||
currCpuSet, err := cpuset.Parse(ctr.Resources.CPU.Cpus)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to parse CPUset for container %s", ctr.ID)
|
||||
return "", "", fmt.Errorf("unable to parse CPUset.cpus for container %s: %v", ctr.ID, err)
|
||||
}
|
||||
result = result.Union(currSet)
|
||||
cpuResult = cpuResult.Union(currCpuSet)
|
||||
|
||||
currMemSet, err := cpuset.Parse(ctr.Resources.CPU.Mems)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("unable to parse CPUset.mems for container %s: %v", ctr.ID, err)
|
||||
}
|
||||
memResult = memResult.Union(currMemSet)
|
||||
}
|
||||
}
|
||||
|
||||
return result.String(), nil
|
||||
return cpuResult.String(), memResult.String(), nil
|
||||
}
|
||||
|
@ -1420,24 +1420,25 @@ func TestSandbox_SetupSandboxCgroup(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getContainerConfigWithCPUSet(cpuset string) ContainerConfig {
|
||||
func getContainerConfigWithCPUSet(cpuset, memset string) ContainerConfig {
|
||||
return ContainerConfig{
|
||||
Resources: specs.LinuxResources{
|
||||
CPU: &specs.LinuxCPU{
|
||||
Cpus: cpuset,
|
||||
Mems: memset,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getSimpleSandbox(cpuset0, cpuset1, cpuset2 string) *Sandbox {
|
||||
func getSimpleSandbox(cpusets, memsets [3]string) *Sandbox {
|
||||
sandbox := Sandbox{}
|
||||
|
||||
sandbox.config = &SandboxConfig{
|
||||
Containers: []ContainerConfig{
|
||||
getContainerConfigWithCPUSet(cpuset0),
|
||||
getContainerConfigWithCPUSet(cpuset1),
|
||||
getContainerConfigWithCPUSet(cpuset2),
|
||||
getContainerConfigWithCPUSet(cpusets[0], memsets[0]),
|
||||
getContainerConfigWithCPUSet(cpusets[1], memsets[1]),
|
||||
getContainerConfigWithCPUSet(cpusets[2], memsets[2]),
|
||||
},
|
||||
}
|
||||
|
||||
@ -1447,80 +1448,97 @@ func getSimpleSandbox(cpuset0, cpuset1, cpuset2 string) *Sandbox {
|
||||
func TestGetSandboxCpuSet(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
cpuset0 string
|
||||
cpuset1 string
|
||||
cpuset2 string
|
||||
result string
|
||||
wantErr bool
|
||||
name string
|
||||
cpusets [3]string
|
||||
memsets [3]string
|
||||
cpuResult string
|
||||
memResult string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"single, no cpuset",
|
||||
"",
|
||||
"",
|
||||
[3]string{"", "", ""},
|
||||
[3]string{"", "", ""},
|
||||
"",
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"single cpuset",
|
||||
[3]string{"0", "", ""},
|
||||
[3]string{"", "", ""},
|
||||
"0",
|
||||
"",
|
||||
"",
|
||||
"0",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"two duplicate cpuset",
|
||||
"0",
|
||||
[3]string{"0", "0", ""},
|
||||
[3]string{"", "", ""},
|
||||
"0",
|
||||
"",
|
||||
"0",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"3 cpusets",
|
||||
"0-3",
|
||||
"5-7",
|
||||
"1",
|
||||
[3]string{"0-3", "5-7", "1"},
|
||||
[3]string{"", "", ""},
|
||||
"0-3,5-7",
|
||||
"",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
"weird, but should be okay",
|
||||
"0-3",
|
||||
"99999",
|
||||
"",
|
||||
[3]string{"0-3", "99999", ""},
|
||||
[3]string{"", "", ""},
|
||||
"0-3,99999",
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"two, overlapping cpuset",
|
||||
[3]string{"0-3", "1-2", ""},
|
||||
[3]string{"", "", ""},
|
||||
"0-3",
|
||||
"1-2",
|
||||
"",
|
||||
"0-3",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"garbage, should fail",
|
||||
"7 beard-seconds",
|
||||
"Audrey + 7",
|
||||
"Elliott - 17",
|
||||
[3]string{"7 beard-seconds", "Audrey + 7", "Elliott - 17"},
|
||||
[3]string{"", "", ""},
|
||||
"",
|
||||
"",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"cpuset and memset",
|
||||
[3]string{"0-3", "1-2", ""},
|
||||
[3]string{"0", "1", "0-1"},
|
||||
"0-3",
|
||||
"0-1",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"memset",
|
||||
[3]string{"0-3", "1-2", ""},
|
||||
[3]string{"0", "3", ""},
|
||||
"0-3",
|
||||
"0,3",
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := getSimpleSandbox(tt.cpuset0, tt.cpuset1, tt.cpuset2)
|
||||
res, err := s.getSandboxCPUSet()
|
||||
s := getSimpleSandbox(tt.cpusets, tt.memsets)
|
||||
res, _, err := s.getSandboxCPUSet()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("getSandboxCPUSet() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if res != tt.result {
|
||||
t.Errorf("getSandboxCPUSet() result = %s, wanted result %s", res, tt.result)
|
||||
if res != tt.cpuResult {
|
||||
t.Errorf("getSandboxCPUSet() result = %s, wanted result %s", res, tt.cpuResult)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user