diff --git a/hack/vendor.sh b/hack/vendor.sh index b175918a3b..490184a80c 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -62,7 +62,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 db65c35051d05f3fb218a0e84a11267e0894fe0a +clone git github.com/docker/libcontainer 55430d0db7c6bb1198c0bb573a9700a859d5ec26 # 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/Makefile b/vendor/src/github.com/docker/libcontainer/Makefile index d6852b24ab..4744c5efcc 100644 --- a/vendor/src/github.com/docker/libcontainer/Makefile +++ b/vendor/src/github.com/docker/libcontainer/Makefile @@ -4,10 +4,10 @@ all: test: # we need NET_ADMIN for the netlink tests and SYS_ADMIN for mounting - docker run --rm -it --cap-add NET_ADMIN --cap-add SYS_ADMIN docker/libcontainer + docker run --rm -it --privileged docker/libcontainer sh: - docker run --rm -it --cap-add NET_ADMIN --cap-add SYS_ADMIN -w /busybox docker/libcontainer nsinit exec sh + docker run --rm -it --privileged -w /busybox docker/libcontainer nsinit exec sh GO_PACKAGES = $(shell find . -not \( -wholename ./vendor -prune \) -name '*.go' -print0 | xargs -0n1 dirname | sort -u) 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 f784d01151..261a97ff23 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio.go @@ -115,6 +115,14 @@ func getBlkioStat(path string) ([]cgroups.BlkioStatEntry, error) { } func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { + // Try to read CFQ stats available on all CFQ enabled kernels first + if blkioStats, err := getBlkioStat(filepath.Join(path, "blkio.io_serviced_recursive")); err == nil && blkioStats != nil { + return getCFQStats(path, stats) + } + return getStats(path, stats) // Use generic stats as fallback +} + +func getCFQStats(path string, stats *cgroups.Stats) error { var blkioStats []cgroups.BlkioStatEntry var err error @@ -140,3 +148,20 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { return nil } + +func getStats(path string, stats *cgroups.Stats) error { + var blkioStats []cgroups.BlkioStatEntry + var err error + + if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.throttle.io_service_bytes")); err != nil { + return err + } + stats.BlkioStats.IoServiceBytesRecursive = blkioStats + + if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.throttle.io_serviced")); err != nil { + return err + } + stats.BlkioStats.IoServicedRecursive = blkioStats + + return nil +} diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio_test.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio_test.go index db6f8d5214..2a79d260f6 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio_test.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio_test.go @@ -26,10 +26,30 @@ Total 50` 8:0 Async 3 8:0 Total 5 Total 5` + throttleServiceBytes = `8:0 Read 11030528 +8:0 Write 23 +8:0 Sync 42 +8:0 Async 11030528 +8:0 Total 11030528 +252:0 Read 11030528 +252:0 Write 23 +252:0 Sync 42 +252:0 Async 11030528 +252:0 Total 11030528 +Total 22061056` + throttleServiced = `8:0 Read 164 +8:0 Write 23 +8:0 Sync 42 +8:0 Async 164 +8:0 Total 164 +252:0 Read 164 +252:0 Write 23 +252:0 Sync 42 +252:0 Async 164 +252:0 Total 164 +Total 328` ) -var actualStats = *cgroups.NewStats() - func appendBlkioStatEntry(blkioStatEntries *[]cgroups.BlkioStatEntry, major, minor, value uint64, op string) { *blkioStatEntries = append(*blkioStatEntries, cgroups.BlkioStatEntry{Major: major, Minor: minor, Value: value, Op: op}) } @@ -45,6 +65,7 @@ func TestBlkioStats(t *testing.T) { }) blkio := &BlkioGroup{} + actualStats := *cgroups.NewStats() err := blkio.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatal(err) @@ -85,6 +106,7 @@ func TestBlkioStatsNoSectorsFile(t *testing.T) { }) blkio := &BlkioGroup{} + actualStats := *cgroups.NewStats() err := blkio.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatalf("Failed unexpectedly: %s", err) @@ -101,6 +123,7 @@ func TestBlkioStatsNoServiceBytesFile(t *testing.T) { }) blkio := &BlkioGroup{} + actualStats := *cgroups.NewStats() err := blkio.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatalf("Failed unexpectedly: %s", err) @@ -117,6 +140,7 @@ func TestBlkioStatsNoServicedFile(t *testing.T) { }) blkio := &BlkioGroup{} + actualStats := *cgroups.NewStats() err := blkio.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatalf("Failed unexpectedly: %s", err) @@ -133,6 +157,7 @@ func TestBlkioStatsNoQueuedFile(t *testing.T) { }) blkio := &BlkioGroup{} + actualStats := *cgroups.NewStats() err := blkio.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatalf("Failed unexpectedly: %s", err) @@ -150,6 +175,7 @@ func TestBlkioStatsUnexpectedNumberOfFields(t *testing.T) { }) blkio := &BlkioGroup{} + actualStats := *cgroups.NewStats() err := blkio.GetStats(helper.CgroupPath, &actualStats) if err == nil { t.Fatal("Expected to fail, but did not") @@ -167,8 +193,56 @@ func TestBlkioStatsUnexpectedFieldType(t *testing.T) { }) blkio := &BlkioGroup{} + actualStats := *cgroups.NewStats() err := blkio.GetStats(helper.CgroupPath, &actualStats) if err == nil { t.Fatal("Expected to fail, but did not") } } + +func TestNonCFQBlkioStats(t *testing.T) { + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + helper.writeFileContents(map[string]string{ + "blkio.io_service_bytes_recursive": "", + "blkio.io_serviced_recursive": "", + "blkio.io_queued_recursive": "", + "blkio.sectors_recursive": "", + "blkio.throttle.io_service_bytes": throttleServiceBytes, + "blkio.throttle.io_serviced": throttleServiced, + }) + + blkio := &BlkioGroup{} + actualStats := *cgroups.NewStats() + err := blkio.GetStats(helper.CgroupPath, &actualStats) + if err != nil { + t.Fatal(err) + } + + // Verify expected stats. + expectedStats := cgroups.BlkioStats{} + + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Read") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 23, "Write") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 42, "Sync") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Async") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Total") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Read") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 23, "Write") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 42, "Sync") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Async") + appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Total") + + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Read") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 23, "Write") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 42, "Sync") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Async") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Total") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Read") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 23, "Write") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 42, "Sync") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Async") + appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Total") + + expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) +} diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu_test.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu_test.go index 017a1f4b8e..2470e68956 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu_test.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu_test.go @@ -24,6 +24,7 @@ func TestCpuStats(t *testing.T) { }) cpu := &CpuGroup{} + actualStats := *cgroups.NewStats() err := cpu.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatal(err) @@ -42,6 +43,7 @@ func TestNoCpuStatFile(t *testing.T) { defer helper.cleanup() cpu := &CpuGroup{} + actualStats := *cgroups.NewStats() err := cpu.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatal("Expected not to fail, but did") @@ -59,6 +61,7 @@ func TestInvalidCpuStat(t *testing.T) { }) cpu := &CpuGroup{} + actualStats := *cgroups.NewStats() err := cpu.GetStats(helper.CgroupPath, &actualStats) if err == nil { t.Fatal("Expected failed stat parsing.") 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 e92f1dafe6..a21cec75c0 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 @@ -25,6 +25,7 @@ func TestMemoryStats(t *testing.T) { }) memory := &MemoryGroup{} + actualStats := *cgroups.NewStats() err := memory.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatal(err) @@ -42,6 +43,7 @@ func TestMemoryStatsNoStatFile(t *testing.T) { }) memory := &MemoryGroup{} + actualStats := *cgroups.NewStats() err := memory.GetStats(helper.CgroupPath, &actualStats) if err != nil { t.Fatal(err) @@ -57,6 +59,7 @@ func TestMemoryStatsNoUsageFile(t *testing.T) { }) memory := &MemoryGroup{} + actualStats := *cgroups.NewStats() err := memory.GetStats(helper.CgroupPath, &actualStats) if err == nil { t.Fatal("Expected failure") @@ -72,6 +75,7 @@ func TestMemoryStatsNoMaxUsageFile(t *testing.T) { }) memory := &MemoryGroup{} + actualStats := *cgroups.NewStats() err := memory.GetStats(helper.CgroupPath, &actualStats) if err == nil { t.Fatal("Expected failure") @@ -88,6 +92,7 @@ func TestMemoryStatsBadStatFile(t *testing.T) { }) memory := &MemoryGroup{} + actualStats := *cgroups.NewStats() err := memory.GetStats(helper.CgroupPath, &actualStats) if err == nil { t.Fatal("Expected failure") @@ -104,6 +109,7 @@ func TestMemoryStatsBadUsageFile(t *testing.T) { }) memory := &MemoryGroup{} + actualStats := *cgroups.NewStats() err := memory.GetStats(helper.CgroupPath, &actualStats) if err == nil { t.Fatal("Expected failure") @@ -120,6 +126,7 @@ func TestMemoryStatsBadMaxUsageFile(t *testing.T) { }) memory := &MemoryGroup{} + actualStats := *cgroups.NewStats() err := memory.GetStats(helper.CgroupPath, &actualStats) if err == nil { t.Fatal("Expected failure") diff --git a/vendor/src/github.com/docker/libcontainer/container.go b/vendor/src/github.com/docker/libcontainer/container.go index c4d372ce35..ace997b77c 100644 --- a/vendor/src/github.com/docker/libcontainer/container.go +++ b/vendor/src/github.com/docker/libcontainer/container.go @@ -9,8 +9,8 @@ package libcontainer // be destroyed by a separate process, any function may return that the container // was not found. type Container interface { - // Returns the path to the container which contains the state - Path() string + // Returns the ID of the container + ID() string // Returns the current run state of the container. // diff --git a/vendor/src/github.com/docker/libcontainer/factory.go b/vendor/src/github.com/docker/libcontainer/factory.go index 9161ff05f3..b744933597 100644 --- a/vendor/src/github.com/docker/libcontainer/factory.go +++ b/vendor/src/github.com/docker/libcontainer/factory.go @@ -12,14 +12,14 @@ type Factory interface { // System error // // On error, any partially created container parts are cleaned up (the operation is atomic). - Create(path string, config *Config) (Container, error) + Create(id string, config *Config) (Container, error) - // Load takes the path for an existing container and reconstructs the container + // Load takes an ID for an existing container and reconstructs the container // from the state. // // Errors: // Path does not exist // Container is stopped // System error - Load(path string) (Container, error) + Load(id string) (Container, error) } diff --git a/vendor/src/github.com/docker/libcontainer/label/label.go b/vendor/src/github.com/docker/libcontainer/label/label.go index 73869b36cf..ce60296ea1 100644 --- a/vendor/src/github.com/docker/libcontainer/label/label.go +++ b/vendor/src/github.com/docker/libcontainer/label/label.go @@ -39,3 +39,7 @@ func Init() { func ReserveLabel(label string) error { return nil } + +func UnreserveLabel(label string) error { + return nil +} diff --git a/vendor/src/github.com/docker/libcontainer/label/label_selinux.go b/vendor/src/github.com/docker/libcontainer/label/label_selinux.go index 5b1380a2be..0a9a82052c 100644 --- a/vendor/src/github.com/docker/libcontainer/label/label_selinux.go +++ b/vendor/src/github.com/docker/libcontainer/label/label_selinux.go @@ -128,3 +128,11 @@ func ReserveLabel(label string) error { selinux.ReserveLabel(label) return nil } + +// UnreserveLabel will remove the reservation of the MCS label. +// This will allow InitLabels to use the MCS label in a newly created +// containers +func UnreserveLabel(label string) error { + selinux.FreeLxcContexts(label) + return nil +} diff --git a/vendor/src/github.com/docker/libcontainer/mount/init.go b/vendor/src/github.com/docker/libcontainer/mount/init.go index 05ab334c36..ea2b732737 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/init.go +++ b/vendor/src/github.com/docker/libcontainer/mount/init.go @@ -8,7 +8,6 @@ import ( "path/filepath" "syscall" - "github.com/docker/docker/pkg/symlink" "github.com/docker/libcontainer/label" "github.com/docker/libcontainer/mount/nodes" ) @@ -31,24 +30,34 @@ func InitializeMountNamespace(rootfs, console string, sysReadonly bool, mountCon err error flag = syscall.MS_PRIVATE ) + if mountConfig.NoPivotRoot { flag = syscall.MS_SLAVE } + if err := syscall.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil { return fmt.Errorf("mounting / with flags %X %s", (flag | syscall.MS_REC), err) } + if err := syscall.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mouting %s as bind %s", rootfs, err) } + if err := mountSystem(rootfs, sysReadonly, mountConfig); err != nil { return fmt.Errorf("mount system %s", err) } - if err := setupBindmounts(rootfs, mountConfig); err != nil { - return fmt.Errorf("bind mounts %s", err) + + // apply any user specified mounts within the new mount namespace + for _, m := range mountConfig.Mounts { + if err := m.Mount(rootfs, mountConfig.MountLabel); err != nil { + return err + } } + if err := nodes.CreateDeviceNodes(rootfs, mountConfig.DeviceNodes); err != nil { return fmt.Errorf("create device nodes %s", err) } + if err := SetupPtmx(rootfs, console, mountConfig.MountLabel); err != nil { return err } @@ -72,6 +81,7 @@ func InitializeMountNamespace(rootfs, console string, sysReadonly bool, mountCon } else { err = PivotRoot(rootfs) } + if err != nil { return err } @@ -90,7 +100,7 @@ func InitializeMountNamespace(rootfs, console string, sysReadonly bool, mountCon // mountSystem sets up linux specific system mounts like sys, proc, shm, and devpts // inside the mount namespace func mountSystem(rootfs string, sysReadonly bool, mountConfig *MountConfig) error { - for _, m := range newSystemMounts(rootfs, mountConfig.MountLabel, sysReadonly, mountConfig.Mounts) { + for _, m := range newSystemMounts(rootfs, mountConfig.MountLabel, sysReadonly) { if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) { return fmt.Errorf("mkdirall %s %s", m.path, err) } @@ -151,56 +161,9 @@ func setupDevSymlinks(rootfs string) error { return nil } -func setupBindmounts(rootfs string, mountConfig *MountConfig) error { - bindMounts := mountConfig.Mounts - for _, m := range bindMounts.OfType("bind") { - var ( - flags = syscall.MS_BIND | syscall.MS_REC - dest = filepath.Join(rootfs, m.Destination) - ) - if !m.Writable { - flags = flags | syscall.MS_RDONLY - } - - stat, err := os.Stat(m.Source) - if err != nil { - return err - } - - dest, err = symlink.FollowSymlinkInScope(dest, rootfs) - if err != nil { - return err - } - - if err := createIfNotExists(dest, stat.IsDir()); err != nil { - return fmt.Errorf("Creating new bind-mount target, %s", err) - } - - if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil { - return fmt.Errorf("mounting %s into %s %s", m.Source, dest, err) - } - if !m.Writable { - if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil { - return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err) - } - } - if m.Relabel != "" { - if err := label.Relabel(m.Source, mountConfig.MountLabel, m.Relabel); err != nil { - return fmt.Errorf("relabeling %s to %s %s", m.Source, mountConfig.MountLabel, err) - } - } - if m.Private { - if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil { - return fmt.Errorf("mounting %s private %s", dest, err) - } - } - } - return nil -} - // TODO: this is crappy right now and should be cleaned up with a better way of handling system and // standard bind mounts allowing them to be more dynamic -func newSystemMounts(rootfs, mountLabel string, sysReadonly bool, mounts Mounts) []mount { +func newSystemMounts(rootfs, mountLabel string, sysReadonly bool) []mount { systemMounts := []mount{ {source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags}, {source: "tmpfs", path: filepath.Join(rootfs, "dev"), device: "tmpfs", flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, data: label.FormatMountLabel("mode=755", mountLabel)}, @@ -212,6 +175,7 @@ func newSystemMounts(rootfs, mountLabel string, sysReadonly bool, mounts Mounts) if sysReadonly { sysMountFlags |= syscall.MS_RDONLY } + systemMounts = append(systemMounts, mount{source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: sysMountFlags}) return systemMounts diff --git a/vendor/src/github.com/docker/libcontainer/mount/mount.go b/vendor/src/github.com/docker/libcontainer/mount/mount.go new file mode 100644 index 0000000000..c7865b3c8e --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/mount/mount.go @@ -0,0 +1,104 @@ +package mount + +import ( + "fmt" + "os" + "path/filepath" + "syscall" + + "github.com/docker/docker/pkg/symlink" + "github.com/docker/libcontainer/label" +) + +type Mount struct { + Type string `json:"type,omitempty"` + Source string `json:"source,omitempty"` // Source path, in the host namespace + Destination string `json:"destination,omitempty"` // Destination path, in the container + Writable bool `json:"writable,omitempty"` + Relabel string `json:"relabel,omitempty"` // Relabel source if set, "z" indicates shared, "Z" indicates unshared + Private bool `json:"private,omitempty"` +} + +func (m *Mount) Mount(rootfs, mountLabel string) error { + switch m.Type { + case "bind": + return m.bindMount(rootfs, mountLabel) + case "tmpfs": + return m.tmpfsMount(rootfs, mountLabel) + default: + return fmt.Errorf("unsupported mount type %s for %s", m.Type, m.Destination) + } +} + +func (m *Mount) bindMount(rootfs, mountLabel string) error { + var ( + flags = syscall.MS_BIND | syscall.MS_REC + dest = filepath.Join(rootfs, m.Destination) + ) + + if !m.Writable { + flags = flags | syscall.MS_RDONLY + } + + stat, err := os.Stat(m.Source) + if err != nil { + return err + } + + // FIXME: (crosbymichael) This does not belong here and should be done a layer above + dest, err = symlink.FollowSymlinkInScope(dest, rootfs) + if err != nil { + return err + } + + if err := createIfNotExists(dest, stat.IsDir()); err != nil { + return fmt.Errorf("creating new bind mount target %s", err) + } + + if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil { + return fmt.Errorf("mounting %s into %s %s", m.Source, dest, err) + } + + if !m.Writable { + if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil { + return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err) + } + } + + if m.Relabel != "" { + if err := label.Relabel(m.Source, mountLabel, m.Relabel); err != nil { + return fmt.Errorf("relabeling %s to %s %s", m.Source, mountLabel, err) + } + } + + if m.Private { + if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil { + return fmt.Errorf("mounting %s private %s", dest, err) + } + } + + return nil +} + +func (m *Mount) tmpfsMount(rootfs, mountLabel string) error { + var ( + err error + l = label.FormatMountLabel("", mountLabel) + dest = filepath.Join(rootfs, m.Destination) + ) + + // FIXME: (crosbymichael) This does not belong here and should be done a layer above + if dest, err = symlink.FollowSymlinkInScope(dest, rootfs); err != nil { + return err + } + + if err := createIfNotExists(dest, true); err != nil { + return fmt.Errorf("creating new tmpfs mount target %s", err) + } + + if err := syscall.Mount("tmpfs", dest, "tmpfs", uintptr(defaultMountFlags), l); err != nil { + return fmt.Errorf("%s mounting %s in tmpfs", err, dest) + } + + return nil +} diff --git a/vendor/src/github.com/docker/libcontainer/mount/types.go b/vendor/src/github.com/docker/libcontainer/mount/mount_config.go similarity index 59% rename from vendor/src/github.com/docker/libcontainer/mount/types.go rename to vendor/src/github.com/docker/libcontainer/mount/mount_config.go index 063bbac1c5..eef9b8ce4d 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/types.go +++ b/vendor/src/github.com/docker/libcontainer/mount/mount_config.go @@ -6,6 +6,8 @@ import ( "github.com/docker/libcontainer/devices" ) +var ErrUnsupported = errors.New("Unsupported method") + type MountConfig struct { // NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs // This is a common option when the container is running in ramdisk @@ -17,33 +19,10 @@ type MountConfig struct { // Mounts specify additional source and destination paths that will be mounted inside the container's // rootfs and mount namespace if specified - Mounts Mounts `json:"mounts,omitempty"` + Mounts []*Mount `json:"mounts,omitempty"` // The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well! DeviceNodes []*devices.Device `json:"device_nodes,omitempty"` MountLabel string `json:"mount_label,omitempty"` } - -type Mount struct { - Type string `json:"type,omitempty"` - Source string `json:"source,omitempty"` // Source path, in the host namespace - Destination string `json:"destination,omitempty"` // Destination path, in the container - Writable bool `json:"writable,omitempty"` - Relabel string `json:"relabel,omitempty"` // Relabel source if set, "z" indicates shared, "Z" indicates unshared - Private bool `json:"private,omitempty"` -} - -type Mounts []Mount - -var ErrUnsupported = errors.New("Unsupported method") - -func (s Mounts) OfType(t string) Mounts { - out := Mounts{} - for _, m := range s { - if m.Type == t { - out = append(out, m) - } - } - return out -} diff --git a/vendor/src/github.com/docker/libcontainer/sample_configs/minimal.json b/vendor/src/github.com/docker/libcontainer/sample_configs/minimal.json index c08c996797..8d85ddf7da 100644 --- a/vendor/src/github.com/docker/libcontainer/sample_configs/minimal.json +++ b/vendor/src/github.com/docker/libcontainer/sample_configs/minimal.json @@ -166,6 +166,12 @@ "path": "/dev/random", "type": 99 } + ], + "mounts": [ + { + "type": "tmpfs", + "destination": "/tmp" + } ] }, "environment": [