Skip to content

Commit

Permalink
Adding oom_score_adj as a container config param.
Browse files Browse the repository at this point in the history
Signed-off-by: Vishnu Kannan <vishnuk@google.com>
  • Loading branch information
vishh committed Aug 31, 2015
1 parent b1e7041 commit cc232c4
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 0 deletions.
6 changes: 6 additions & 0 deletions libcontainer/configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ type Config struct {
// If Rlimits are not set, the container will inherit rlimits from the parent process
Rlimits []Rlimit `json:"rlimits"`

// OomScoreAdj specifies the adjustment to be made by the kernel when calculating oom scores
// for a process. Valid values are between the range [-1000, '1000'], where processes with
// higher scores are preferred for being killed.
// More information about kernel oom score calculation here: https://lwn.net/Articles/317814/
OomScoreAdj int `json:"oom_score_adj"`

// AdditionalGroups specifies the gids that should be added to supplementary groups
// in addition to those that the user belongs to.
AdditionalGroups []string `json:"additional_groups"`
Expand Down
7 changes: 7 additions & 0 deletions libcontainer/init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ package libcontainer
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"syscall"

Expand Down Expand Up @@ -238,6 +240,11 @@ func setupRlimits(config *configs.Config) error {
return nil
}

func setOomScoreAdj(oomScoreAdj int) error {
path := "/proc/self/oom_score_adj"
return ioutil.WriteFile(path, []byte(strconv.Itoa(oomScoreAdj)), 0700)
}

// killCgroupProcesses freezes then iterates over all the processes inside the
// manager's cgroups sending a SIGKILL to each process then waiting for them to
// exit.
Expand Down
42 changes: 42 additions & 0 deletions libcontainer/integration/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -878,3 +878,45 @@ func TestMountCgroupRW(t *testing.T) {
}
}
}

func TestOomScoreAdj(t *testing.T) {
if testing.Short() {
return
}
root, err := newTestRoot()
ok(t, err)
defer os.RemoveAll(root)

rootfs, err := newRootfs()
ok(t, err)
defer remove(rootfs)

config := newTemplateConfig(rootfs)
config.OomScoreAdj = 200

factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
ok(t, err)

container, err := factory.Create("test", config)
ok(t, err)
defer container.Destroy()

var stdout bytes.Buffer
pconfig := libcontainer.Process{
Args: []string{"sh", "-c", "cat /proc/self/oom_score_adj"},
Env: standardEnvironment,
Stdin: nil,
Stdout: &stdout,
}
err = container.Start(&pconfig)
ok(t, err)

// Wait for process
waitProcess(&pconfig, t)
outputOomScoreAdj := strings.TrimSpace(string(stdout.Bytes()))

// Check that the oom_score_adj matches the value that was set as part of config.
if outputOomScoreAdj != strconv.Itoa(config.OomScoreAdj) {
t.Fatalf("Expected oom_score_adj %d; got %q", config.OomScoreAdj, outputOomScoreAdj)
}
}
47 changes: 47 additions & 0 deletions libcontainer/integration/execin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"io"
"os"
"strconv"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -332,3 +333,49 @@ func TestExecinPassExtraFiles(t *testing.T) {
t.Fatalf("expected second pipe to receive '2', got '%s'", out2)
}
}

func TestExecInOomScoreAdj(t *testing.T) {
if testing.Short() {
return
}
rootfs, err := newRootfs()
ok(t, err)
defer remove(rootfs)
config := newTemplateConfig(rootfs)
config.OomScoreAdj = 200
container, err := newContainer(config)
ok(t, err)
defer container.Destroy()

stdinR, stdinW, err := os.Pipe()
ok(t, err)
process := &libcontainer.Process{
Args: []string{"cat"},
Env: standardEnvironment,
Stdin: stdinR,
}
err = container.Start(process)
stdinR.Close()
defer stdinW.Close()
ok(t, err)

buffers := newStdBuffers()
ps := &libcontainer.Process{
Args: []string{"/bin/sh", "-c", "cat /proc/self/oom_score_adj"},
Env: standardEnvironment,
Stdin: buffers.Stdin,
Stdout: buffers.Stdout,
Stderr: buffers.Stderr,
}
err = container.Start(ps)
ok(t, err)
waitProcess(ps, t)

stdinW.Close()
waitProcess(process, t)

out := buffers.Stdout.String()
if oomScoreAdj := strings.TrimSpace(out); oomScoreAdj != strconv.Itoa(config.OomScoreAdj) {
t.Fatalf("expected oomScoreAdj to be %d, got %s", config.OomScoreAdj, oomScoreAdj)
}
}
3 changes: 3 additions & 0 deletions libcontainer/setns_init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ func (l *linuxSetnsInit) Init() error {
if err := setupRlimits(l.config.Config); err != nil {
return err
}
if err := setOomScoreAdj(l.config.Config.OomScoreAdj); err != nil {
return err
}
if l.config.Config.Seccomp != nil {
if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil {
return err
Expand Down
4 changes: 4 additions & 0 deletions libcontainer/standard_init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func (l *linuxStandardInit) Init() error {
if err := setupRlimits(l.config.Config); err != nil {
return err
}
if err := setOomScoreAdj(l.config.Config.OomScoreAdj); err != nil {
return err
}

label.Init()
// InitializeMountNamespace() can be executed only for a new mount namespace
if l.config.Config.Namespaces.Contains(configs.NEWNS) {
Expand Down

0 comments on commit cc232c4

Please sign in to comment.