Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit 39279b1

Browse files
committed
Fix kmem limit set
Currently we can't start container with kmem limit, because we set kmem limit after processes joined to cgroup, we'll get device busy error in this case. Fix it by moving set before join. Signed-off-by: Qiang Huang <[email protected]>
1 parent ca3ab4b commit 39279b1

File tree

3 files changed

+77
-13
lines changed

3 files changed

+77
-13
lines changed

Diff for: cgroups/fs/memory.go

+15-6
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,29 @@ type MemoryGroup struct {
1818
}
1919

2020
func (s *MemoryGroup) Apply(d *data) error {
21-
dir, err := d.join("memory")
21+
path, err := d.path("memory")
2222
if err != nil && !cgroups.IsNotFound(err) {
2323
return err
2424
}
25+
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
26+
return err
27+
}
28+
if err := s.Set(path, d.c); err != nil {
29+
return err
30+
}
31+
32+
// We need to join memory cgroup after set memory limits, because
33+
// kmem.limit_in_bytes can only be set when the cgroup is empty.
34+
_, err = d.join("memory")
35+
if err != nil {
36+
return err
37+
}
2538
defer func() {
2639
if err != nil {
27-
os.RemoveAll(dir)
40+
os.RemoveAll(path)
2841
}
2942
}()
3043

31-
if err := s.Set(dir, d.c); err != nil {
32-
return err
33-
}
34-
3544
return nil
3645
}
3746

Diff for: cgroups/systemd/apply_systemd.go

+30-6
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,16 @@ func (m *Manager) Apply(pid int) error {
188188
newProp("BlockIOWeight", uint64(c.BlkioWeight)))
189189
}
190190

191+
// We need to set kernel memory before processes join cgroup because
192+
// kmem.limit_in_bytes can only be set when the cgroup is empty.
193+
// And swap memory limit needs to be set after memory limit, only
194+
// memory limit is handled by systemd, so it's kind of ugly here.
195+
if c.KernelMemory > 0 {
196+
if err := setKernelMemory(c); err != nil {
197+
return err
198+
}
199+
}
200+
191201
if _, err := theConn.StartTransientUnit(unitName, "replace", properties...); err != nil {
192202
return err
193203
}
@@ -462,26 +472,40 @@ func joinDevices(c *configs.Cgroup, pid int) error {
462472
return devices.Set(path, c)
463473
}
464474

465-
func joinMemory(c *configs.Cgroup, pid int) error {
475+
func setKernelMemory(c *configs.Cgroup) error {
466476
path, err := getSubsystemPath(c, "memory")
467477
if err != nil && !cgroups.IsNotFound(err) {
468478
return err
469479
}
470480

471-
// -1 disables memoryswap
472-
if c.MemorySwap > 0 {
473-
err = writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(c.MemorySwap, 10))
481+
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
482+
return err
483+
}
484+
485+
if c.KernelMemory > 0 {
486+
err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.KernelMemory, 10))
474487
if err != nil {
475488
return err
476489
}
477490
}
478491

479-
if c.KernelMemory > 0 {
480-
err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.KernelMemory, 10))
492+
return nil
493+
}
494+
495+
func joinMemory(c *configs.Cgroup, pid int) error {
496+
path, err := getSubsystemPath(c, "memory")
497+
if err != nil && !cgroups.IsNotFound(err) {
498+
return err
499+
}
500+
501+
// -1 disables memoryswap
502+
if c.MemorySwap > 0 {
503+
err = writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(c.MemorySwap, 10))
481504
if err != nil {
482505
return err
483506
}
484507
}
508+
485509
if c.MemorySwappiness >= 0 && c.MemorySwappiness <= 100 {
486510
err = writeFile(path, "memory.swappiness", strconv.FormatInt(c.MemorySwappiness, 10))
487511
if err != nil {

Diff for: integration/exec_test.go

+32-1
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ func TestCpuShares(t *testing.T) {
497497
testCpuShares(t, false)
498498
}
499499

500-
func TestSystemdCpuShares(t *testing.T) {
500+
func TestCpuSharesSystemd(t *testing.T) {
501501
if !systemd.UseSystemd() {
502502
t.Skip("Systemd is unsupported")
503503
}
@@ -524,6 +524,37 @@ func testCpuShares(t *testing.T, systemd bool) {
524524
}
525525
}
526526

527+
func TestRunWithKernelMemory(t *testing.T) {
528+
testRunWithKernelMemory(t, false)
529+
}
530+
531+
func TestRunWithKernelMemorySystemd(t *testing.T) {
532+
if !systemd.UseSystemd() {
533+
t.Skip("Systemd is unsupported")
534+
}
535+
testRunWithKernelMemory(t, true)
536+
}
537+
538+
func testRunWithKernelMemory(t *testing.T, systemd bool) {
539+
if testing.Short() {
540+
return
541+
}
542+
rootfs, err := newRootfs()
543+
ok(t, err)
544+
defer remove(rootfs)
545+
546+
config := newTemplateConfig(rootfs)
547+
if systemd {
548+
config.Cgroups.Slice = "system.slice"
549+
}
550+
config.Cgroups.KernelMemory = 52428800
551+
552+
_, _, err = runContainer(config, "", "ps")
553+
if err != nil {
554+
t.Fatalf("runContainer failed with kernel memory limit: %v", err)
555+
}
556+
}
557+
527558
func TestContainerState(t *testing.T) {
528559
if testing.Short() {
529560
return

0 commit comments

Comments
 (0)