Commit 692d9bbe authored by Mark Karpeles's avatar Mark Karpeles Committed by Han-Wen Nienhuys

attempt to mount directly using syscall if running as root

Fixes issue #314

Change-Id: I6bf2d64d0e62c4881b7010c5c0421a16bd8d7db2
parent 152e6ac3
......@@ -158,6 +158,15 @@ type MountOptions struct {
// If set, ask kernel not to do automatic data cache invalidation.
// The filesystem is fully responsible for invalidating data cache.
ExplicitDataCacheControl bool
// If set, fuse will first attempt to use syscall.Mount instead of
// fusermount to mount the filesystem. This will not update /etc/mtab
// but might be needed if fusermount is not available.
DirectMount bool
// Options passed to syscall.Mount, the default value used by fusermount
// is syscall.MS_NOSUID|syscall.MS_NODEV
DirectMountFlags uintptr
}
// RawFileSystem is an interface close to the FUSE wire protocol.
......
......@@ -92,6 +92,6 @@ func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, e
return syscall.Dup(int(f.Fd()))
}
func unmount(dir string) error {
func unmount(dir string, opts *MountOptions) error {
return syscall.Unmount(dir, 0)
}
......@@ -7,6 +7,7 @@ package fuse
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
"path"
......@@ -26,9 +27,59 @@ func unixgramSocketpair() (l, r *os.File, err error) {
return
}
// Create a FUSE FS on the specified mount point without using
// fusermount.
func mountDirect(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) {
fd, err = syscall.Open("/dev/fuse", os.O_RDWR, 0) // use syscall.Open since we want an int fd
if err != nil {
return
}
// managed to open dev/fuse, attempt to mount
source := opts.FsName
if source == "" {
source = opts.Name
}
var flags uintptr
flags |= syscall.MS_NOSUID | syscall.MS_NODEV
// some values we need to pass to mount, but override possible since opts.Options comes after
var r = []string{
fmt.Sprintf("fd=%d", fd),
"rootmode=40000",
"user_id=0",
"group_id=0",
}
r = append(r, opts.Options...)
if opts.AllowOther {
r = append(r, "allow_other")
}
err = syscall.Mount(opts.FsName, mountPoint, "fuse."+opts.Name, opts.DirectMountFlags, strings.Join(r, ","))
if err != nil {
syscall.Close(fd)
return
}
// success
close(ready)
return
}
// Create a FUSE FS on the specified mount point. The returned
// mount point is always absolute.
func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) {
if opts.DirectMount {
fd, err := mountDirect(mountPoint, opts, ready)
if err == nil {
return fd, nil
} else if opts.Debug {
log.Printf("mount: failed to do direct mount: %s", err)
}
}
local, remote, err := unixgramSocketpair()
if err != nil {
return
......@@ -79,7 +130,15 @@ func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, e
return fd, err
}
func unmount(mountPoint string) (err error) {
func unmount(mountPoint string, opts *MountOptions) (err error) {
if opts.DirectMount {
// Attempt to directly unmount, if fails fallback to fusermount method
err := syscall.Unmount(mountPoint, 0)
if err == nil {
return nil
}
}
bin, err := fusermountBinary()
if err != nil {
return err
......
......@@ -108,7 +108,7 @@ func (ms *Server) Unmount() (err error) {
}
delay := time.Duration(0)
for try := 0; try < 5; try++ {
err = unmount(ms.mountPoint)
err = unmount(ms.mountPoint, ms.opts)
if err == nil {
break
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment