diff --git a/project/vendor.sh b/project/vendor.sh index 0849bc00c2..1623fbc0df 100755 --- a/project/vendor.sh +++ b/project/vendor.sh @@ -68,7 +68,7 @@ if [ "$1" = '--go' ]; then mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar fi -clone git github.com/docker/libcontainer dd3cb8822352fd4acc0b8b426bd86e47e98f6853 +clone git github.com/docker/libcontainer aa10040b570386c1ae311c6245b9e21295b2b83a # see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file) rm -rf src/github.com/docker/libcontainer/vendor eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli')" diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go index 4943b77529..7dc245595f 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go @@ -54,12 +54,10 @@ func getCgroupRoot() (string, error) { return cgroupRoot, nil } - // we can pick any subsystem to find the root - cpuRoot, err := cgroups.FindCgroupMountpoint("cpu") + root, err := cgroups.FindCgroupMountpointDir() if err != nil { return "", err } - root := filepath.Dir(cpuRoot) if _, err := os.Stat(root); err != nil { return "", err @@ -231,6 +229,12 @@ func (raw *data) parent(subsystem string) (string, error) { } func (raw *data) path(subsystem string) (string, error) { + _, err := cgroups.FindCgroupMountpoint(subsystem) + // If we didn't mount the subsystem, there is no point we make the path. + if err != nil { + return "", err + } + // If the cgroup name/path is absolute do not look relative to the cgroup of the init process. if filepath.IsAbs(raw.cgroup) { path := filepath.Join(raw.root, subsystem, raw.cgroup) diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio.go index 8e132643bb..01da5d7fc7 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio.go @@ -17,8 +17,12 @@ type BlkioGroup struct { func (s *BlkioGroup) Apply(d *data) error { dir, err := d.join("blkio") - if err != nil && !cgroups.IsNotFound(err) { - return err + if err != nil { + if cgroups.IsNotFound(err) { + return nil + } else { + return err + } } if err := s.Set(dir, d.c); err != nil { diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu.go index 1fbf7b1540..42386fd847 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu.go @@ -18,7 +18,11 @@ func (s *CpuGroup) Apply(d *data) error { // on a container basis dir, err := d.join("cpu") if err != nil { - return err + if cgroups.IsNotFound(err) { + return nil + } else { + return err + } } if err := s.Set(dir, d.c); err != nil { diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuset.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuset.go index 3ed2f67d59..75f38cd26b 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuset.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuset.go @@ -17,7 +17,11 @@ type CpusetGroup struct { func (s *CpusetGroup) Apply(d *data) error { dir, err := d.path("cpuset") if err != nil { - return err + if cgroups.IsNotFound(err) { + return nil + } else { + return err + } } return s.ApplyDir(dir, d.c, d.pid) } diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/devices.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/devices.go index 16e00b1c73..fab8323e93 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/devices.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/devices.go @@ -11,7 +11,11 @@ type DevicesGroup struct { func (s *DevicesGroup) Apply(d *data) error { dir, err := d.join("devices") if err != nil { - return err + if cgroups.IsNotFound(err) { + return nil + } else { + return err + } } if err := s.Set(dir, d.c); err != nil { diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/devices_test.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/devices_test.go index d87d092421..18bb127462 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/devices_test.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/devices_test.go @@ -25,7 +25,7 @@ func TestDevicesSetAllow(t *testing.T) { defer helper.cleanup() helper.writeFileContents(map[string]string{ - "device.deny": "a", + "devices.deny": "a", }) helper.CgroupData.c.AllowAllDevices = false @@ -35,8 +35,6 @@ func TestDevicesSetAllow(t *testing.T) { t.Fatal(err) } - // FIXME: this doesn't make sence, the file devices.allow under real cgroupfs - // is not allowed to read. Our test path don't have cgroupfs mounted. value, err := getCgroupParamString(helper.CgroupPath, "devices.allow") if err != nil { t.Fatalf("Failed to parse devices.allow - %s", err) diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go index fc8241d1bf..5e08e05302 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go @@ -13,8 +13,12 @@ type FreezerGroup struct { func (s *FreezerGroup) Apply(d *data) error { dir, err := d.join("freezer") - if err != nil && !cgroups.IsNotFound(err) { - return err + if err != nil { + if cgroups.IsNotFound(err) { + return nil + } else { + return err + } } if err := s.Set(dir, d.c); err != nil { diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go index b99f81687a..68e930fdc5 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go @@ -16,9 +16,12 @@ 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) { - return err + if err != nil { + if cgroups.IsNotFound(err) { + return nil + } else { + return err + } } defer func() { if err != nil { diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory_test.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory_test.go index f1c7dda8d8..1e939c4e88 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory_test.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory_test.go @@ -55,6 +55,63 @@ func TestMemorySetMemory(t *testing.T) { } } +func TestMemorySetMemoryswap(t *testing.T) { + helper := NewCgroupTestUtil("memory", t) + defer helper.cleanup() + + const ( + memoryswapBefore = 314572800 // 300M + memoryswapAfter = 524288000 // 500M + ) + + helper.writeFileContents(map[string]string{ + "memory.memsw.limit_in_bytes": strconv.Itoa(memoryswapBefore), + }) + + helper.CgroupData.c.MemorySwap = memoryswapAfter + memory := &MemoryGroup{} + if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { + t.Fatal(err) + } + + value, err := getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") + if err != nil { + t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err) + } + if value != memoryswapAfter { + t.Fatal("Got the wrong value, set memory.memsw.limit_in_bytes failed.") + } +} + +func TestMemorySetMemoryswapDefault(t *testing.T) { + helper := NewCgroupTestUtil("memory", t) + defer helper.cleanup() + + const ( + memoryBefore = 209715200 // 200M + memoryAfter = 314572800 // 300M + memoryswapAfter = 629145600 // 300M*2 + ) + + helper.writeFileContents(map[string]string{ + "memory.limit_in_bytes": strconv.Itoa(memoryBefore), + }) + + helper.CgroupData.c.Memory = memoryAfter + memory := &MemoryGroup{} + if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { + t.Fatal(err) + } + + value, err := getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") + if err != nil { + t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err) + } + if value != memoryswapAfter { + t.Fatal("Got the wrong value, set memory.memsw.limit_in_bytes failed.") + } +} + func TestMemoryStats(t *testing.T) { helper := NewCgroupTestUtil("memory", t) defer helper.cleanup() diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/util_test.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/util_test.go index e0c1262db2..37bf515781 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/util_test.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/util_test.go @@ -6,9 +6,9 @@ Creates a mock of the cgroup filesystem for the duration of the test. package fs import ( - "fmt" "io/ioutil" "os" + "path/filepath" "testing" "github.com/docker/libcontainer/configs" @@ -31,12 +31,12 @@ func NewCgroupTestUtil(subsystem string, t *testing.T) *cgroupTestUtil { d := &data{ c: &configs.Cgroup{}, } - tempDir, err := ioutil.TempDir("", fmt.Sprintf("%s_cgroup_test", subsystem)) + tempDir, err := ioutil.TempDir("", "cgroup_test") if err != nil { t.Fatal(err) } d.root = tempDir - testCgroupPath, err := d.path(subsystem) + testCgroupPath := filepath.Join(d.root, subsystem) if err != nil { t.Fatal(err) } diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/utils.go b/vendor/src/github.com/docker/libcontainer/cgroups/utils.go index a360904cce..c6c400c7d3 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/utils.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/utils.go @@ -34,6 +34,21 @@ func FindCgroupMountpoint(subsystem string) (string, error) { return "", NewNotFoundError(subsystem) } +func FindCgroupMountpointDir() (string, error) { + mounts, err := mount.GetMounts() + if err != nil { + return "", err + } + + for _, mount := range mounts { + if mount.Fstype == "cgroup" { + return filepath.Dir(mount.Mountpoint), nil + } + } + + return "", NewNotFoundError("cgroup") +} + type Mount struct { Mountpoint string Subsystems []string diff --git a/vendor/src/github.com/docker/libcontainer/nsenter/nsenter.go b/vendor/src/github.com/docker/libcontainer/nsenter/nsenter.go index 1c09c77e6e..07f4d63e43 100644 --- a/vendor/src/github.com/docker/libcontainer/nsenter/nsenter.go +++ b/vendor/src/github.com/docker/libcontainer/nsenter/nsenter.go @@ -1,25 +1,12 @@ -// +build linux +// +build linux,!gccgo package nsenter /* #cgo CFLAGS: -Wall extern void nsexec(); -void __attribute__((constructor)) init() { +void __attribute__((constructor)) init(void) { nsexec(); } */ import "C" - -// AlwaysFalse is here to stay false -// (and be exported so the compiler doesn't optimize out its reference) -var AlwaysFalse bool - -func init() { - if AlwaysFalse { - // by referencing this C init() in a noop test, it will ensure the compiler - // links in the C function. - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65134 - C.init() - } -} diff --git a/vendor/src/github.com/docker/libcontainer/nsenter/nsenter_gccgo.go b/vendor/src/github.com/docker/libcontainer/nsenter/nsenter_gccgo.go new file mode 100644 index 0000000000..63c7a3ec22 --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/nsenter/nsenter_gccgo.go @@ -0,0 +1,25 @@ +// +build linux,gccgo + +package nsenter + +/* +#cgo CFLAGS: -Wall +extern void nsexec(); +void __attribute__((constructor)) init(void) { + nsexec(); +} +*/ +import "C" + +// AlwaysFalse is here to stay false +// (and be exported so the compiler doesn't optimize out its reference) +var AlwaysFalse bool + +func init() { + if AlwaysFalse { + // by referencing this C init() in a noop test, it will ensure the compiler + // links in the C function. + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65134 + C.init() + } +} diff --git a/vendor/src/github.com/docker/libcontainer/rootfs_linux.go b/vendor/src/github.com/docker/libcontainer/rootfs_linux.go index 42d7d17cc7..a1fb8f490a 100644 --- a/vendor/src/github.com/docker/libcontainer/rootfs_linux.go +++ b/vendor/src/github.com/docker/libcontainer/rootfs_linux.go @@ -104,6 +104,10 @@ func mount(m *configs.Mount, rootfs, mountLabel string) error { if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) { return err } + if m.Device == "mqueue" { + // mqueue should not be labeled, otherwise the mount will fail + data = "" + } return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data) case "bind": stat, err := os.Stat(m.Source) diff --git a/vendor/src/github.com/docker/libcontainer/selinux/selinux.go b/vendor/src/github.com/docker/libcontainer/selinux/selinux.go index e5bd820980..b3a61d187a 100644 --- a/vendor/src/github.com/docker/libcontainer/selinux/selinux.go +++ b/vendor/src/github.com/docker/libcontainer/selinux/selinux.go @@ -37,8 +37,8 @@ var ( spaceRegex = regexp.MustCompile(`^([^=]+) (.*)$`) mcsList = make(map[string]bool) selinuxfs = "unknown" - selinuxEnabled = false - selinuxEnabledChecked = false + selinuxEnabled = false // Stores whether selinux is currently enabled + selinuxEnabledChecked = false // Stores whether selinux enablement has been checked or established yet ) type SELinuxContext map[string]string @@ -48,6 +48,11 @@ func SetDisabled() { selinuxEnabled, selinuxEnabledChecked = false, true } +// getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs +// filesystem or an empty string if no mountpoint is found. Selinuxfs is +// a proc-like pseudo-filesystem that exposes the selinux policy API to +// processes. The existence of an selinuxfs mount is used to determine +// whether selinux is currently enabled or not. func getSelinuxMountPoint() string { if selinuxfs != "unknown" { return selinuxfs @@ -74,6 +79,7 @@ func getSelinuxMountPoint() string { return selinuxfs } +// SelinuxEnabled returns whether selinux is currently enabled. func SelinuxEnabled() bool { if selinuxEnabledChecked { return selinuxEnabled @@ -145,11 +151,12 @@ func readCon(name string) (string, error) { return val, err } +// Setfilecon sets the SELinux label for this path or returns an error. func Setfilecon(path string, scon string) error { return system.Lsetxattr(path, xattrNameSelinux, []byte(scon), 0) } -// Return the SELinux label for this path +// Getfilecon returns the SELinux label for this path or returns an error. func Getfilecon(path string) (string, error) { con, err := system.Lgetxattr(path, xattrNameSelinux) return string(con), err @@ -163,11 +170,12 @@ func Getfscreatecon() (string, error) { return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid())) } -// Return the SELinux label of the current process thread. +// Getcon returns the SELinux label of the current process thread, or an error. func Getcon() (string, error) { return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid())) } +// Getpidcon returns the SELinux label of the given pid, or an error. func Getpidcon(pid int) (string, error) { return readCon(fmt.Sprintf("/proc/%d/attr/current", pid)) }