Handle external mounts outside of lxc

This commit is contained in:
Michael Crosby
2013-12-18 13:46:02 -08:00
parent f768c6adb7
commit 45d7dcfea2
4 changed files with 209 additions and 33 deletions
+97
View File
@@ -6,6 +6,8 @@ import (
"github.com/dotcloud/docker/utils"
"os"
"path"
"strings"
"syscall"
)
type InitFunc func(root string) (Driver, error)
@@ -31,6 +33,13 @@ type Differ interface {
DiffSize(id string) (bytes int64, err error)
}
type Mount struct {
Device string
Target string
Type string
Options string
}
var (
DefaultDriver string
// All registred drivers
@@ -88,3 +97,91 @@ func New(root string) (driver Driver, err error) {
}
return nil, err
}
func (m *Mount) Mount(root string) error {
var (
flag int
data []string
target = path.Join(root, m.Target)
)
if mounted, err := Mounted(target); err != nil || mounted {
return err
}
flags := map[string]struct {
clear bool
flag int
}{
"defaults": {false, 0},
"ro": {false, syscall.MS_RDONLY},
"rw": {true, syscall.MS_RDONLY},
"suid": {true, syscall.MS_NOSUID},
"nosuid": {false, syscall.MS_NOSUID},
"dev": {true, syscall.MS_NODEV},
"nodev": {false, syscall.MS_NODEV},
"exec": {true, syscall.MS_NOEXEC},
"noexec": {false, syscall.MS_NOEXEC},
"sync": {false, syscall.MS_SYNCHRONOUS},
"async": {true, syscall.MS_SYNCHRONOUS},
"dirsync": {false, syscall.MS_DIRSYNC},
"remount": {false, syscall.MS_REMOUNT},
"mand": {false, syscall.MS_MANDLOCK},
"nomand": {true, syscall.MS_MANDLOCK},
"atime": {true, syscall.MS_NOATIME},
"noatime": {false, syscall.MS_NOATIME},
"diratime": {true, syscall.MS_NODIRATIME},
"nodiratime": {false, syscall.MS_NODIRATIME},
"bind": {false, syscall.MS_BIND},
"rbind": {false, syscall.MS_BIND | syscall.MS_REC},
"relatime": {false, syscall.MS_RELATIME},
"norelatime": {true, syscall.MS_RELATIME},
"strictatime": {false, syscall.MS_STRICTATIME},
"nostrictatime": {true, syscall.MS_STRICTATIME},
}
for _, o := range strings.Split(m.Options, ",") {
// If the option does not exist in the flags table then it is a
// data value for a specific fs type
if f, exists := flags[o]; exists {
if f.clear {
flag &= ^f.flag
} else {
flag |= f.flag
}
} else {
data = append(data, o)
}
}
if err := syscall.Mount(m.Device, target, m.Type, uintptr(flag), strings.Join(data, ",")); err != nil {
panic(err)
}
return nil
}
func (m *Mount) Unmount(root string) error {
target := path.Join(root, m.Target)
if mounted, err := Mounted(target); err != nil || !mounted {
return err
}
return syscall.Unmount(target, 0)
}
func Mounted(mountpoint string) (bool, error) {
mntpoint, err := os.Stat(mountpoint)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
parent, err := os.Stat(path.Join(mountpoint, ".."))
if err != nil {
return false, err
}
mntpointSt := mntpoint.Sys().(*syscall.Stat_t)
parentSt := parent.Sys().(*syscall.Stat_t)
return mntpointSt.Dev != parentSt.Dev, nil
}