Commit 0f4e53e7 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Merge remote branch 'origin/master' into gcopt

parents 0b0f4ddb 9e57c957
*~ *~
*.6 *.6
8.out
.nfs* .nfs*
_* _*
...@@ -10,9 +10,6 @@ directory as a loopback: ...@@ -10,9 +10,6 @@ directory as a loopback:
./example/main -debug -threaded=false mountpoint /some/other/directory & ./example/main -debug -threaded=false mountpoint /some/other/directory &
(cd mountpoint ; ls) (cd mountpoint ; ls)
on my machine, compiles over loopback (threaded, without debug) are
about 2x slower compared to normal compiles.
Tested on: Tested on:
- x86 32bits (Fedora 14). - x86 32bits (Fedora 14).
...@@ -21,7 +18,22 @@ Tested on: ...@@ -21,7 +18,22 @@ Tested on:
LICENSE LICENSE
Like Go, this library is distributed under the new BSD. See accompanying LICENSE file. Like Go, this library is distributed under the new BSD license. See
accompanying LICENSE file.
BENCHMARKS
The speed of go-fuse is close to libfuse's speed (measurements on my
lenovo T60 laptop):
* 'find' in tree with 14k files. fs access: 0.06s, go-fuse: 3.5s, bbfs: 3.9
* 'ls -lR' in same tree: fs access: 0.5s, go-fuse: 9.5s, bbfs: 8.8s
* copying a 100 mb file: fs access: 200mb/s, go-fuse: 182mb/s, bbfs: 190mb/s
bbfs is a loopback filesystem written in C, see
http://www.cs.nmsu.edu/~pfeiffer/fuse-tutorial.tgz
CREDITS CREDITS
......
...@@ -23,9 +23,9 @@ func main() { ...@@ -23,9 +23,9 @@ func main() {
} }
orig := flag.Arg(0) orig := flag.Arg(0)
pt := examplelib.NewPassThroughFuse(orig) fs := examplelib.NewPassThroughFuse(orig)
fs := fuse.NewPathFileSystemConnector(pt) conn := fuse.NewPathFileSystemConnector(fs)
state := fuse.NewMountState(fs) state := fuse.NewMountState(conn)
state.Debug = *debug state.Debug = *debug
mountPoint := flag.Arg(1) mountPoint := flag.Arg(1)
......
...@@ -7,7 +7,8 @@ DEPS=../fuse ...@@ -7,7 +7,8 @@ DEPS=../fuse
GOFILES=dummyfuse.go\ GOFILES=dummyfuse.go\
passthrough.go\ passthrough.go\
stackfs.go stackfs.go\
misc.go
include $(GOROOT)/src/Make.pkg include $(GOROOT)/src/Make.pkg
...@@ -194,11 +194,11 @@ func (self *DummyPathFuse) OpenDir(name string) (dir fuse.RawFuseDir, code fuse. ...@@ -194,11 +194,11 @@ func (self *DummyPathFuse) OpenDir(name string) (dir fuse.RawFuseDir, code fuse.
return nil, fuse.ENOSYS return nil, fuse.ENOSYS
} }
func (self *DummyPathFuse) Init() (*fuse.InitOut, fuse.Status) { func (self *DummyPathFuse) Mount(conn *fuse.PathFileSystemConnector) (fuse.Status) {
return nil, fuse.ENOSYS return fuse.OK
} }
func (self *DummyPathFuse) Destroy() { func (self *DummyPathFuse) Unmount() {
} }
func (self *DummyPathFuse) Access(name string, mode uint32) (code fuse.Status) { func (self *DummyPathFuse) Access(name string, mode uint32) (code fuse.Status) {
...@@ -213,6 +213,3 @@ func (self *DummyPathFuse) Utimens(name string, AtimeNs uint64, CtimeNs uint64) ...@@ -213,6 +213,3 @@ func (self *DummyPathFuse) Utimens(name string, AtimeNs uint64, CtimeNs uint64)
return fuse.ENOSYS return fuse.ENOSYS
} }
func (self *DummyPathFuse) SetOptions(*fuse.PathFileSystemConnectorOptions) {
}
package examplelib
import "os"
////////////////
func IsDir(name string) bool {
fi, _ := os.Lstat(name)
return fi != nil && fi.IsDirectory()
}
func IsFile(name string) bool {
fi, _ := os.Lstat(name)
return fi != nil && fi.IsRegular()
}
func FileExists(name string) bool {
_, err := os.Lstat(name)
return err == nil
}
...@@ -25,11 +25,11 @@ func NewPassThroughFuse(root string) (out *PassThroughFuse) { ...@@ -25,11 +25,11 @@ func NewPassThroughFuse(root string) (out *PassThroughFuse) {
return out return out
} }
func (self *PassThroughFuse) Init() (*fuse.InitOut, fuse.Status) { func (self *PassThroughFuse) Mount(conn *fuse.PathFileSystemConnector) (fuse.Status) {
return new(fuse.InitOut), fuse.OK return fuse.OK
} }
func (self *PassThroughFuse) Destroy() { func (self *PassThroughFuse) Unmount() {
} }
......
...@@ -16,23 +16,6 @@ import ( ...@@ -16,23 +16,6 @@ import (
var _ = strings.Join var _ = strings.Join
var _ = log.Println var _ = log.Println
////////////////
func IsDir(name string) bool {
fi, _ := os.Lstat(name)
return fi != nil && fi.IsDirectory()
}
func IsFile(name string) bool {
fi, _ := os.Lstat(name)
return fi != nil && fi.IsRegular()
}
func FileExists(name string) bool {
_, err := os.Lstat(name)
return err == nil
}
//////////////// ////////////////
// state for our testcase, mostly constants // state for our testcase, mostly constants
...@@ -50,6 +33,7 @@ type testCase struct { ...@@ -50,6 +33,7 @@ type testCase struct {
origSubfile string origSubfile string
tester *testing.T tester *testing.T
state *fuse.MountState state *fuse.MountState
connector *fuse.PathFileSystemConnector
} }
// Create and mount filesystem. // Create and mount filesystem.
...@@ -68,10 +52,11 @@ func (self *testCase) Setup(t *testing.T) { ...@@ -68,10 +52,11 @@ func (self *testCase) Setup(t *testing.T) {
self.origFile = path.Join(self.origDir, name) self.origFile = path.Join(self.origDir, name)
self.origSubdir = path.Join(self.origDir, subdir) self.origSubdir = path.Join(self.origDir, subdir)
self.origSubfile = path.Join(self.origSubdir, "subfile") self.origSubfile = path.Join(self.origSubdir, "subfile")
fs := fuse.NewPathFileSystemConnector(NewPassThroughFuse(self.origDir)) pfs := NewPassThroughFuse(self.origDir)
self.connector = fuse.NewPathFileSystemConnector(pfs)
self.state = fuse.NewMountState(fs) self.connector.Debug = true
self.state = fuse.NewMountState(self.connector)
self.state.Mount(self.mountPoint) self.state.Mount(self.mountPoint)
//self.state.Debug = false //self.state.Debug = false
...@@ -610,3 +595,44 @@ func TestMount(t *testing.T) { ...@@ -610,3 +595,44 @@ func TestMount(t *testing.T) {
ts.testLargeDirRead() ts.testLargeDirRead()
ts.Cleanup() ts.Cleanup()
} }
func TestRecursiveMount(t *testing.T) {
ts := new(testCase)
ts.Setup(t)
f, err := os.Open(path.Join(ts.mountPoint, "hello.txt"),
os.O_WRONLY|os.O_CREATE, 0777)
if err != nil {
t.Errorf("open write err %v", err)
}
f.WriteString("bla")
f.Close()
pfs2 := NewPassThroughFuse(ts.origDir)
code := ts.connector.Mount("/hello.txt", pfs2)
if code != fuse.EINVAL {
t.Error("expect EINVAL", code)
}
submnt := path.Join(ts.mountPoint, "mnt")
err = os.Mkdir(submnt, 0777)
if err != nil {
t.Errorf("mkdir")
}
code = ts.connector.Mount("/mnt", pfs2)
if code != fuse.OK {
t.Errorf("mkdir")
}
_, err = os.Lstat(submnt)
if err != nil {
t.Error("lstat submount", err)
}
_, err = os.Lstat(path.Join(submnt, "hello.txt"))
if err != nil {
t.Error("lstat submount/file", err)
}
ts.Cleanup()
}
...@@ -43,7 +43,7 @@ func (self *stackFsTestCase) Setup(t *testing.T) { ...@@ -43,7 +43,7 @@ func (self *stackFsTestCase) Setup(t *testing.T) {
fs1 := fuse.NewPathFileSystemConnector(NewPassThroughFuse(self.origDir1)) fs1 := fuse.NewPathFileSystemConnector(NewPassThroughFuse(self.origDir1))
fs2 := fuse.NewPathFileSystemConnector(NewPassThroughFuse(self.origDir2)) fs2 := fuse.NewPathFileSystemConnector(NewPassThroughFuse(self.origDir2))
self.fs = NewSubmountFileSystem() self.fs = NewSubmountFileSystem()
attr := fuse.Attr{ attr := fuse.Attr{
......
...@@ -31,7 +31,7 @@ func (de *DirEntryList) Add(name []byte, inode uint64, mode uint32) bool { ...@@ -31,7 +31,7 @@ func (de *DirEntryList) Add(name []byte, inode uint64, mode uint32) bool {
dirent.Off = de.offset dirent.Off = de.offset
dirent.Ino = inode dirent.Ino = inode
dirent.NameLen = uint32(len(name)) dirent.NameLen = uint32(len(name))
dirent.Typ = (mode & 0170000) >> 12 dirent.Typ = ModeToType(mode)
err := binary.Write(&de.buf, binary.LittleEndian, dirent) err := binary.Write(&de.buf, binary.LittleEndian, dirent)
if err != nil { if err != nil {
......
...@@ -291,3 +291,7 @@ func NegativeEntry(time float64) *EntryOut { ...@@ -291,3 +291,7 @@ func NegativeEntry(time float64) *EntryOut {
SplitNs(time, &out.EntryValid, &out.EntryValidNsec) SplitNs(time, &out.EntryValid, &out.EntryValidNsec)
return out return out
} }
func ModeToType(mode uint32) uint32 {
return (mode & 0170000) >> 12
}
...@@ -96,10 +96,10 @@ func getFuseConn(local *os.File) (f *os.File, err os.Error) { ...@@ -96,10 +96,10 @@ func getFuseConn(local *os.File) (f *os.File, err os.Error) {
var data [4]byte var data [4]byte
control := make([]byte, 4*256) control := make([]byte, 4*256)
// n, oobn, recvflags - todo: error checking. // n, oobn, recvflags, from, errno - todo: error checking.
_, oobn, _, _, oobn, _, _,
errno := syscall.Recvmsg( errno := syscall.Recvmsg(
local.Fd(), data[:], control[:], nil, 0) local.Fd(), data[:], control[:], 0)
if errno != 0 { if errno != 0 {
return return
} }
......
This diff is collapsed.
...@@ -92,6 +92,9 @@ const ( ...@@ -92,6 +92,9 @@ const (
ENOTDIR = Status(syscall.ENOTDIR) ENOTDIR = Status(syscall.ENOTDIR)
EACCES = Status(syscall.EACCES) EACCES = Status(syscall.EACCES)
EPERM = Status(syscall.EPERM) EPERM = Status(syscall.EPERM)
EBUSY = Status(syscall.EBUSY)
EINVAL = Status(syscall.EINVAL)
EXDEV = Status(syscall.EXDEV)
) )
type Opcode int type Opcode int
...@@ -568,14 +571,12 @@ type PathFilesystem interface { ...@@ -568,14 +571,12 @@ type PathFilesystem interface {
OpenDir(name string) (dir RawFuseDir, code Status) OpenDir(name string) (dir RawFuseDir, code Status)
// TODO - what is a good interface? // TODO - what is a good interface?
Init() (*InitOut, Status) Mount(connector *PathFileSystemConnector) Status
Destroy() Unmount()
Access(name string, mode uint32) (code Status) Access(name string, mode uint32) (code Status)
Create(name string, flags uint32, mode uint32) (file RawFuseFile, code Status) Create(name string, flags uint32, mode uint32) (file RawFuseFile, code Status)
Utimens(name string, AtimeNs uint64, CtimeNs uint64) (code Status) Utimens(name string, AtimeNs uint64, CtimeNs uint64) (code Status)
// unimplemented: poll, ioctl, bmap. // unimplemented: poll, ioctl, bmap.
SetOptions(*PathFileSystemConnectorOptions)
} }
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