Store all the cgroups paths as part of the state. This simplifies entering cgroups and will be useful for

cleanups too in the future.
Docker-DCO-1.1-Signed-off-by: Vishnu Kannan <vishnuk@google.com> (github: vishh)
This commit is contained in:
Vishnu Kannan
2014-08-13 06:18:55 +00:00
parent ae08910fde
commit ad16526d7f
8 changed files with 56 additions and 69 deletions
+1
View File
@@ -37,4 +37,5 @@ type Cgroup struct {
type ActiveCgroup interface {
Cleanup() error
Paths() ([]string, error)
}
+12 -27
View File
@@ -120,33 +120,6 @@ func GetPids(c *cgroups.Cgroup) ([]int, error) {
return cgroups.ReadProcsFile(dir)
}
func EnterPid(c *cgroups.Cgroup, pid int) error {
d, err := getCgroupData(c, pid)
if err != nil {
return err
}
for sysname := range subsystems {
path, err := d.path(sysname)
if err != nil {
// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
if err == cgroups.ErrNotFound {
continue
}
return err
}
if PathExists(path) {
if _, err := d.join(sysname); err != nil {
return err
}
}
}
return nil
}
func getCgroupData(c *cgroups.Cgroup, pid int) (*data, error) {
// we can pick any subsystem to find the root
cgroupRoot, err := cgroups.FindCgroupMountpoint("cpu")
@@ -180,6 +153,18 @@ func (raw *data) parent(subsystem string) (string, error) {
return filepath.Join(raw.root, subsystem, initPath), nil
}
func (raw *data) Paths() ([]string, error) {
var paths []string
for sysname := range subsystems {
path, err := raw.path(sysname)
if err != nil {
return nil, err
}
paths = append(paths, path)
}
return paths, nil
}
func (raw *data) path(subsystem string) (string, error) {
// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
if filepath.IsAbs(raw.cgroup) {
-8
View File
@@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
@@ -39,10 +38,3 @@ func getCgroupParamInt(cgroupPath, cgroupFile string) (uint64, error) {
}
return strconv.ParseUint(strings.TrimSpace(string(contents)), 10, 64)
}
func PathExists(path string) bool {
if _, err := os.Stat(path); err != nil {
return false
}
return true
}
+4 -23
View File
@@ -320,6 +320,10 @@ func writeFile(dir, file, data string) error {
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
}
func (c *systemdCgroup) Paths() ([]string, error) {
return c.cleanupDirs, nil
}
func (c *systemdCgroup) Cleanup() error {
// systemd cleans up, we don't need to do much
@@ -437,26 +441,3 @@ func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) {
return stats, nil
}
func EnterPid(c *cgroups.Cgroup, pid int) error {
for sysname := range subsystems {
subsystemPath, err := getSubsystemPath(c, sysname)
if err != nil {
// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
if err == cgroups.ErrNotFound {
continue
}
return err
}
if fs.PathExists(subsystemPath) {
if err := ioutil.WriteFile(filepath.Join(subsystemPath, fs.CgroupProcesses),
[]byte(strconv.Itoa(pid)), 0700); err != nil {
return err
}
}
}
return nil
}
+21
View File
@@ -4,6 +4,7 @@ import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -166,3 +167,23 @@ func parseCgroupFile(subsystem string, r io.Reader) (string, error) {
}
return "", ErrNotFound
}
func pathExists(path string) bool {
if _, err := os.Stat(path); err != nil {
return false
}
return true
}
func EnterPid(cgroupPaths []string, pid int) error {
for _, path := range cgroupPaths {
if pathExists(path) {
if err := ioutil.WriteFile(filepath.Join(path, "cgroup.procs"),
[]byte(strconv.Itoa(pid)), 0700); err != nil {
return err
}
}
}
return nil
}
+11 -3
View File
@@ -56,14 +56,21 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
// Do this before syncing with child so that no children
// can escape the cgroup
cleaner, err := SetupCgroups(container, command.Process.Pid)
cgroupRef, err := SetupCgroups(container, command.Process.Pid)
if err != nil {
command.Process.Kill()
command.Wait()
return -1, err
}
if cleaner != nil {
defer cleaner.Cleanup()
if cgroupRef != nil {
defer cgroupRef.Cleanup()
}
cgroupPaths, err := cgroupRef.Paths()
if err != nil {
command.Process.Kill()
command.Wait()
return -1, err
}
var networkState network.NetworkState
@@ -77,6 +84,7 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
InitPid: command.Process.Pid,
InitStartTime: started,
NetworkState: networkState,
CgroupPaths: cgroupPaths,
}
if err := libcontainer.SaveState(dataPath, state); err != nil {
+4 -8
View File
@@ -12,8 +12,7 @@ import (
"syscall"
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/cgroups/fs"
"github.com/docker/libcontainer/cgroups/systemd"
"github.com/docker/libcontainer/cgroups"
"github.com/docker/libcontainer/label"
"github.com/docker/libcontainer/syncpipe"
"github.com/docker/libcontainer/system"
@@ -62,7 +61,7 @@ func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs
pipe.CloseChild()
// Enter cgroups.
if err := EnterCgroups(container, cmd.Process.Pid); err != nil {
if err := EnterCgroups(state, cmd.Process.Pid); err != nil {
return -1, err
}
@@ -110,9 +109,6 @@ func FinalizeSetns(container *libcontainer.Config, args []string) error {
panic("unreachable")
}
func EnterCgroups(container *libcontainer.Config, pid int) error {
if systemd.UseSystemd() {
return systemd.EnterPid(container.Cgroups, pid)
}
return fs.EnterPid(container.Cgroups, pid)
func EnterCgroups(state *libcontainer.State, pid int) error {
return cgroups.EnterPid(state.CgroupPaths, pid)
}
+3
View File
@@ -18,6 +18,9 @@ type State struct {
// Network runtime state.
NetworkState network.NetworkState `json:"network_state,omitempty"`
// Path to all the cgroup dirs.
CgroupPaths []string `json:"cgroup_paths,omitempty"`
}
// The running state of the container.