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

Commit

Permalink
don't fail when subsystem not mounted
Browse files Browse the repository at this point in the history
We do this aim two goals:
 - don't fail when some subsystems are not mounted (devices cgroup
   is an exception because it will cause secirity issues).
 - fail hard instead of ignoring the error when a user specifies
   an option and we are unable to fulfill the request.

Devices cgroup is an exception, because there are secirity issues
if we don't have devices cgroup, so it is hard requirement.

Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
  • Loading branch information
hqhq committed Apr 1, 2015
1 parent 1a246dd commit e10bc4b
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 12 deletions.
6 changes: 6 additions & 0 deletions cgroups/fs/apply_raw.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fs

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
Expand Down Expand Up @@ -263,6 +264,11 @@ func (raw *data) join(subsystem string) (string, error) {
}

func writeFile(dir, file, data string) error {
// Normally dir should not be empty, one case is that cgroup subsystem
// is not mounted, we will get empty dir, and we want it fail here.
if dir == "" {
return fmt.Errorf("no such directory for %s.", file)
}
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
}

Expand Down
2 changes: 1 addition & 1 deletion cgroups/fs/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (s *CpuGroup) Apply(d *data) error {
// We always want to join the cpu group, to allow fair cpu scheduling
// on a container basis
dir, err := d.join("cpu")
if err != nil {
if err != nil && !cgroups.IsNotFound(err) {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion cgroups/fs/cpuset.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type CpusetGroup struct {

func (s *CpusetGroup) Apply(d *data) error {
dir, err := d.path("cpuset")
if err != nil {
if err != nil && !cgroups.IsNotFound(err) {
return err
}

Expand Down
2 changes: 2 additions & 0 deletions cgroups/fs/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type DevicesGroup struct {
func (s *DevicesGroup) Apply(d *data) error {
dir, err := d.join("devices")
if err != nil {
// We will return error even it's `not found` error, devices
// cgroup is hard requirement for container's security.
return err
}

Expand Down
3 changes: 1 addition & 2 deletions cgroups/fs/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ type MemoryGroup struct {

func (s *MemoryGroup) Apply(d *data) error {
dir, err := d.join("memory")
// only return an error for memory if it was specified
if err != nil && (d.c.Memory != 0 || d.c.MemoryReservation != 0 || d.c.MemorySwap != 0) {
if err != nil && !cgroups.IsNotFound(err) {
return err
}
defer func() {
Expand Down
37 changes: 29 additions & 8 deletions cgroups/systemd/apply_systemd.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,21 +253,26 @@ func (m *Manager) GetPaths() map[string]string {
}

func writeFile(dir, file, data string) error {
// Normally dir should not be empty, one case is that cgroup subsystem
// is not mounted, we will get empty dir, and we want it fail here.
if dir == "" {
return fmt.Errorf("no such directory for %s.", file)
}
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
}

func joinCpu(c *configs.Cgroup, pid int) error {
path, err := getSubsystemPath(c, "cpu")
if err != nil {
if err != nil && !cgroups.IsNotFound(err) {
return err
}
if c.CpuQuota != 0 {
if err = ioutil.WriteFile(filepath.Join(path, "cpu.cfs_quota_us"), []byte(strconv.FormatInt(c.CpuQuota, 10)), 0700); err != nil {
if err = writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(c.CpuQuota, 10)); err != nil {
return err
}
}
if c.CpuPeriod != 0 {
if err = ioutil.WriteFile(filepath.Join(path, "cpu.cfs_period_us"), []byte(strconv.FormatInt(c.CpuPeriod, 10)), 0700); err != nil {
if err = writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(c.CpuPeriod, 10)); err != nil {
return err
}
}
Expand All @@ -276,15 +281,19 @@ func joinCpu(c *configs.Cgroup, pid int) error {

func joinFreezer(c *configs.Cgroup, pid int) error {
path, err := getSubsystemPath(c, "freezer")
if err != nil {
if err != nil && !cgroups.IsNotFound(err) {
return err
}

if path == "" {
return nil
}

if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
return err
}

return ioutil.WriteFile(filepath.Join(path, "cgroup.procs"), []byte(strconv.Itoa(pid)), 0700)
return writeFile(path, "cgroup.procs", strconv.Itoa(pid))
}

func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
Expand Down Expand Up @@ -376,6 +385,8 @@ func getUnitName(c *configs.Cgroup) string {
// This happens at least for v208 when any sibling unit is started.
func joinDevices(c *configs.Cgroup, pid int) error {
path, err := getSubsystemPath(c, "devices")
// Even if it's `not found` error, we'll return err because devices cgroup
// is hard requirement for container security.
if err != nil {
return err
}
Expand Down Expand Up @@ -416,22 +427,32 @@ func joinMemory(c *configs.Cgroup, pid int) error {
}

path, err := getSubsystemPath(c, "memory")
if err != nil {
if err != nil && !cgroups.IsNotFound(err) {
return err
}

return ioutil.WriteFile(filepath.Join(path, "memory.memsw.limit_in_bytes"), []byte(strconv.FormatInt(memorySwap, 10)), 0700)
if memorySwap != 0 {
if err := writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(memorySwap, 10)); err != nil {
return err
}
}

return nil
}

// systemd does not atm set up the cpuset controller, so we must manually
// join it. Additionally that is a very finicky controller where each
// level must have a full setup as the default for a new directory is "no cpus"
func joinCpuset(c *configs.Cgroup, pid int) error {
path, err := getSubsystemPath(c, "cpuset")
if err != nil {
if err != nil && !cgroups.IsNotFound(err) {
return err
}

if path == "" {
return nil
}

s := &fs.CpusetGroup{}

return s.ApplyDir(path, c, pid)
Expand Down

0 comments on commit e10bc4b

Please sign in to comment.