Copy parents cpus and mems for cpuset

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
Michael Crosby 2014-05-13 13:34:31 -07:00
parent 04ec76023a
commit 1cc1c05a55
2 changed files with 89 additions and 9 deletions

View file

@ -103,12 +103,20 @@ func GetStats(c *cgroups.Cgroup, subsystem string, pid int) (map[string]float64,
return sys.Stats(d) return sys.Stats(d)
} }
func (raw *data) path(subsystem string) (string, error) { func (raw *data) parent(subsystem string) (string, error) {
initPath, err := cgroups.GetInitCgroupDir(subsystem) initPath, err := cgroups.GetInitCgroupDir(subsystem)
if err != nil { if err != nil {
return "", err return "", err
} }
return filepath.Join(raw.root, subsystem, initPath, raw.cgroup), nil return filepath.Join(raw.root, subsystem, initPath), nil
}
func (raw *data) path(subsystem string) (string, error) {
parent, err := raw.parent(subsystem)
if err != nil {
return "", err
}
return filepath.Join(parent, raw.cgroup), nil
} }
func (raw *data) join(subsystem string) (string, error) { func (raw *data) join(subsystem string) (string, error) {

View file

@ -1,7 +1,11 @@
package fs package fs
import ( import (
"bytes"
"io/ioutil"
"os" "os"
"path/filepath"
"strconv"
) )
type cpusetGroup struct { type cpusetGroup struct {
@ -10,16 +14,19 @@ type cpusetGroup struct {
func (s *cpusetGroup) Set(d *data) error { func (s *cpusetGroup) Set(d *data) error {
// we don't want to join this cgroup unless it is specified // we don't want to join this cgroup unless it is specified
if d.c.CpusetCpus != "" { if d.c.CpusetCpus != "" {
dir, err := d.join("cpuset") dir, err := d.path("cpuset")
if err != nil && d.c.CpusetCpus != "" { if err != nil {
return err
}
if err := s.ensureParent(dir); err != nil {
return err return err
} }
defer func() {
if err != nil {
os.RemoveAll(dir)
}
}()
// because we are not using d.join we need to place the pid into the procs file
// unlike the other subsystems
if err := writeFile(dir, "cgroup.procs", strconv.Itoa(d.pid)); err != nil {
return err
}
if err := writeFile(dir, "cpuset.cpus", d.c.CpusetCpus); err != nil { if err := writeFile(dir, "cpuset.cpus", d.c.CpusetCpus); err != nil {
return err return err
} }
@ -34,3 +41,68 @@ func (s *cpusetGroup) Remove(d *data) error {
func (s *cpusetGroup) Stats(d *data) (map[string]float64, error) { func (s *cpusetGroup) Stats(d *data) (map[string]float64, error) {
return nil, ErrNotSupportStat return nil, ErrNotSupportStat
} }
func (s *cpusetGroup) getSubsystemSettings(parent string) (cpus []byte, mems []byte, err error) {
if cpus, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.cpus")); err != nil {
return
}
if mems, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.mems")); err != nil {
return
}
return cpus, mems, nil
}
// ensureParent ensures that the parent directory of current is created
// with the proper cpus and mems files copied from it's parent if the values
// are a file with a new line char
func (s *cpusetGroup) ensureParent(current string) error {
parent := filepath.Dir(current)
if _, err := os.Stat(parent); err != nil {
if !os.IsNotExist(err) {
return err
}
if err := s.ensureParent(parent); err != nil {
return err
}
}
if err := os.MkdirAll(current, 0755); err != nil && !os.IsExist(err) {
return err
}
return s.copyIfNeeded(current, parent)
}
// copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent
// directory to the current directory if the file's contents are 0
func (s *cpusetGroup) copyIfNeeded(current, parent string) error {
var (
err error
currentCpus, currentMems []byte
parentCpus, parentMems []byte
)
if currentCpus, currentMems, err = s.getSubsystemSettings(current); err != nil {
return err
}
if parentCpus, parentMems, err = s.getSubsystemSettings(parent); err != nil {
return err
}
if s.isEmpty(currentCpus) {
if err := writeFile(current, "cpuset.cpus", string(parentCpus)); err != nil {
return err
}
}
if s.isEmpty(currentMems) {
if err := writeFile(current, "cpuset.mems", string(parentMems)); err != nil {
return err
}
}
return nil
}
func (s *cpusetGroup) isEmpty(b []byte) bool {
return len(bytes.Trim(b, "\n")) == 0
}