From c7406f707524f1df23d0fa75b8165573ff58ed97 Mon Sep 17 00:00:00 2001 From: Mrunal Patel Date: Thu, 26 May 2016 12:36:54 -0700 Subject: [PATCH] Support copyup mount extension for tmpfs mounts If copyup is specified for a tmpfs mount, then the contents of the underlying directory are copied into the tmpfs mounted over it. Signed-off-by: Mrunal Patel --- libcontainer/rootfs_linux.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index aeb43885..c913c168 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -16,6 +16,7 @@ import ( "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/symlink" + "github.com/mrunalp/fileutils" "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/label" @@ -152,15 +153,41 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { } return nil case "tmpfs": + copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP + tmpDir := "" stat, err := os.Stat(dest) if err != nil { if err := os.MkdirAll(dest, 0755); err != nil { return err } } + if copyUp { + tmpDir, err = ioutil.TempDir("/tmp", "runctmpdir") + if err != nil { + return newSystemErrorWithCause(err, "tmpcopyup: failed to create tmpdir") + } + defer os.RemoveAll(tmpDir) + m.Destination = tmpDir + } if err := mountPropagate(m, rootfs, mountLabel); err != nil { return err } + if copyUp { + if err := fileutils.CopyDirectory(dest, tmpDir); err != nil { + errMsg := fmt.Errorf("tmpcopyup: failed to copy %s to %s: %v", dest, tmpDir, err) + if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil { + return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg) + } + return errMsg + } + if err := syscall.Mount(tmpDir, dest, "", syscall.MS_MOVE, ""); err != nil { + errMsg := fmt.Errorf("tmpcopyup: failed to move mount %s to %s: %v", tmpDir, dest, err) + if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil { + return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg) + } + return errMsg + } + } if stat != nil { if err = os.Chmod(dest, stat.Mode()); err != nil { return err @@ -711,7 +738,9 @@ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error { if libcontainerUtils.CleanPath(dest) == "/dev" { flags &= ^syscall.MS_RDONLY } - if !strings.HasPrefix(dest, rootfs) { + + copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP + if !(copyUp || strings.HasPrefix(dest, rootfs)) { dest = filepath.Join(rootfs, dest) }