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 <h.huangqiang@huawei.com>
This commit is contained in:
Qiang Huang
2015-06-18 15:44:30 +08:00
parent ca3ab4ba40
commit 39279b1762
3 changed files with 77 additions and 13 deletions
+15 -6
View File
@@ -18,20 +18,29 @@ type MemoryGroup struct {
}
func (s *MemoryGroup) Apply(d *data) error {
dir, err := d.join("memory")
path, err := d.path("memory")
if err != nil && !cgroups.IsNotFound(err) {
return err
}
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
return err
}
if err := s.Set(path, d.c); err != nil {
return err
}
// We need to join memory cgroup after set memory limits, because
// kmem.limit_in_bytes can only be set when the cgroup is empty.
_, err = d.join("memory")
if err != nil {
return err
}
defer func() {
if err != nil {
os.RemoveAll(dir)
os.RemoveAll(path)
}
}()
if err := s.Set(dir, d.c); err != nil {
return err
}
return nil
}
+30 -6
View File
@@ -188,6 +188,16 @@ func (m *Manager) Apply(pid int) error {
newProp("BlockIOWeight", uint64(c.BlkioWeight)))
}
// We need to set kernel memory before processes join cgroup because
// kmem.limit_in_bytes can only be set when the cgroup is empty.
// And swap memory limit needs to be set after memory limit, only
// memory limit is handled by systemd, so it's kind of ugly here.
if c.KernelMemory > 0 {
if err := setKernelMemory(c); err != nil {
return err
}
}
if _, err := theConn.StartTransientUnit(unitName, "replace", properties...); err != nil {
return err
}
@@ -462,6 +472,26 @@ func joinDevices(c *configs.Cgroup, pid int) error {
return devices.Set(path, c)
}
func setKernelMemory(c *configs.Cgroup) error {
path, err := getSubsystemPath(c, "memory")
if err != nil && !cgroups.IsNotFound(err) {
return err
}
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
return err
}
if c.KernelMemory > 0 {
err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.KernelMemory, 10))
if err != nil {
return err
}
}
return nil
}
func joinMemory(c *configs.Cgroup, pid int) error {
path, err := getSubsystemPath(c, "memory")
if err != nil && !cgroups.IsNotFound(err) {
@@ -476,12 +506,6 @@ func joinMemory(c *configs.Cgroup, pid int) error {
}
}
if c.KernelMemory > 0 {
err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.KernelMemory, 10))
if err != nil {
return err
}
}
if c.MemorySwappiness >= 0 && c.MemorySwappiness <= 100 {
err = writeFile(path, "memory.swappiness", strconv.FormatInt(c.MemorySwappiness, 10))
if err != nil {
+32 -1
View File
@@ -497,7 +497,7 @@ func TestCpuShares(t *testing.T) {
testCpuShares(t, false)
}
func TestSystemdCpuShares(t *testing.T) {
func TestCpuSharesSystemd(t *testing.T) {
if !systemd.UseSystemd() {
t.Skip("Systemd is unsupported")
}
@@ -524,6 +524,37 @@ func testCpuShares(t *testing.T, systemd bool) {
}
}
func TestRunWithKernelMemory(t *testing.T) {
testRunWithKernelMemory(t, false)
}
func TestRunWithKernelMemorySystemd(t *testing.T) {
if !systemd.UseSystemd() {
t.Skip("Systemd is unsupported")
}
testRunWithKernelMemory(t, true)
}
func testRunWithKernelMemory(t *testing.T, systemd bool) {
if testing.Short() {
return
}
rootfs, err := newRootfs()
ok(t, err)
defer remove(rootfs)
config := newTemplateConfig(rootfs)
if systemd {
config.Cgroups.Slice = "system.slice"
}
config.Cgroups.KernelMemory = 52428800
_, _, err = runContainer(config, "", "ps")
if err != nil {
t.Fatalf("runContainer failed with kernel memory limit: %v", err)
}
}
func TestContainerState(t *testing.T) {
if testing.Short() {
return