func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err error) { defer func() { if err != nil { Unmount(target) } }() // Mount options are clipped to page size(4096 bytes). If there are more // layers then these are remounted individually using append. b := make([]byte, syscall.Getpagesize()-len(mountLabel)-54) // room for xino & mountLabel bp := copy(b, fmt.Sprintf("br:%s=rw", rw)) firstMount := true i := 0 for { for ; i < len(ro); i++ { layer := fmt.Sprintf(":%s=ro+wh", ro[i]) if firstMount { if bp+len(layer) > len(b) { break } bp += copy(b[bp:], layer) } else { data := label.FormatMountLabel(fmt.Sprintf("append%s", layer), mountLabel) if err = mount("none", target, "aufs", MsRemount, data); err != nil { return } } } if firstMount { data := label.FormatMountLabel(fmt.Sprintf("%s,dio,xino=/dev/shm/aufs.xino", string(b[:bp])), mountLabel) if err = mount("none", target, "aufs", 0, data); err != nil { return } firstMount = false } if i == len(ro) { break } } return }
// Try to mount using the aufs fast path, if this fails then // append ro layers. func (a *Driver) tryMount(ro []string, rw, target, mountLabel string) (err error) { var ( rwBranch = fmt.Sprintf("%s=rw", rw) roBranches = fmt.Sprintf("%s=ro+wh:", strings.Join(ro, "=ro+wh:")) data = label.FormatMountLabel(fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches), mountLabel) ) return mount("none", target, "aufs", 0, data) }
func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { info, err := devices.lookupDevice(hash) if err != nil { return err } info.lock.Lock() defer info.lock.Unlock() devices.Lock() defer devices.Unlock() if info.mountCount > 0 { if path != info.mountPath { return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path) } info.mountCount++ return nil } if err := devices.activateDeviceIfNeeded(info); err != nil { return fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err) } var flags uintptr = syscall.MS_MGC_VAL fstype, err := ProbeFsType(info.DevName()) if err != nil { return err } options := "" if fstype == "xfs" { // XFS needs nouuid or it can't mount filesystems with the same fs options = joinMountOptions(options, "nouuid") } options = joinMountOptions(options, devices.mountOptions) options = joinMountOptions(options, label.FormatMountLabel("", mountLabel)) err = syscall.Mount(info.DevName(), path, fstype, flags, joinMountOptions("discard", options)) if err != nil && err == syscall.EINVAL { err = syscall.Mount(info.DevName(), path, fstype, flags, options) } if err != nil { return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err) } info.mountCount = 1 info.mountPath = path return nil }
func (d *Driver) Get(id string, mountLabel string) (string, error) { // Protect the d.active from concurrent access d.Lock() defer d.Unlock() mount := d.active[id] if mount != nil { mount.count++ return mount.path, nil } mount = &ActiveMount{count: 1} dir := d.dir(id) if _, err := os.Stat(dir); err != nil { return "", err } // If id has a root, just return it rootDir := path.Join(dir, "root") if _, err := os.Stat(rootDir); err == nil { mount.path = rootDir d.active[id] = mount return mount.path, nil } lowerId, err := ioutil.ReadFile(path.Join(dir, "lower-id")) if err != nil { return "", err } lowerDir := path.Join(d.dir(string(lowerId)), "root") upperDir := path.Join(dir, "upper") workDir := path.Join(dir, "work") mergedDir := path.Join(dir, "merged") opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, upperDir, workDir) if err := syscall.Mount("overlay", mergedDir, "overlay", 0, label.FormatMountLabel(opts, mountLabel)); err != nil { return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err) } mount.path = mergedDir mount.mounted = true d.active[id] = mount return mount.path, nil }
func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err error) { defer func() { if err != nil { Unmount(target) } }() if err = a.tryMount(ro, rw, target, mountLabel); err != nil { if err = a.mountRw(rw, target, mountLabel); err != nil { return } for _, layer := range ro { data := label.FormatMountLabel(fmt.Sprintf("append:%s=ro+wh", layer), mountLabel) if err = mount("none", target, "aufs", MsRemount, data); err != nil { return } } } return }
func (a *Driver) mountRw(rw, target, mountLabel string) error { data := label.FormatMountLabel(fmt.Sprintf("br:%s,xino=/dev/shm/aufs.xino", rw), mountLabel) return mount("none", target, "aufs", 0, data) }