Commit 41618631 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Rename MountState to Server and merge New and Mount functionality in NewServer.

gofmt -w -r 'MountState -> Server' $*
gofmt -w -r 'NewMountState -> NewServer' $*
gofmt -w -r 'x.Loop -> x.Serve' $*
parent 11af8051
......@@ -6,7 +6,7 @@ sh genversion.sh fuse/version.gen.go
for target in "clean" "install" ; do
for d in raw fuse fuse/pathfs fuse/test zipfs unionfs \
example/hello example/loopback example/zipfs \
example/multizip example/unionfs \
example/multizip example/unionfs example/memfs \
example/autounionfs ; \
do
go ${target} go-fuse/${d}
......
......@@ -32,7 +32,7 @@ func setupFs(fs pathfs.FileSystem) (string, func()) {
state.RecordLatencies(lmap)
// state.SetDebug(true)
go state.Loop()
go state.Serve()
return mountPoint, func() {
lc, lns := lmap.Get("LOOKUP")
......
......@@ -75,6 +75,6 @@ func main() {
gofs.SetMountState(state)
gofs.SetFileSystemConnector(conn)
state.Loop()
state.Serve()
time.Sleep(1 * time.Second)
}
......@@ -53,9 +53,9 @@ func main() {
log.Fatal("Usage:\n hello MOUNTPOINT")
}
nfs := pathfs.NewPathNodeFs(&HelloFs{FileSystem: pathfs.NewDefaultFileSystem()}, nil)
state, _, err := nodefs.MountFileSystem(flag.Arg(0), nfs, nil)
server, _, err := nodefs.MountFileSystem(flag.Arg(0), nfs, nil)
if err != nil {
log.Fatal("Mount fail: %v\n", err)
}
state.Loop()
server.Serve()
}
......@@ -44,21 +44,17 @@ func main() {
}
pathFs := pathfs.NewPathNodeFs(finalFs, nil)
conn := nodefs.NewFileSystemConnector(pathFs, opts)
state := fuse.NewMountState(conn.RawFS())
state.SetDebug(*debug)
mountPoint := flag.Arg(0)
fmt.Println("Mounting")
mOpts := &fuse.MountOptions{
AllowOther: *other,
}
err := state.Mount(mountPoint, mOpts)
state, err := fuse.NewServer(conn.RawFS(),mountPoint, mOpts)
if err != nil {
fmt.Printf("Mount fail: %v\n", err)
os.Exit(1)
}
state.SetDebug(*debug)
fmt.Println("Mounted!")
state.Loop()
state.Serve()
}
......@@ -25,16 +25,12 @@ func main() {
prefix := flag.Arg(1)
fs := nodefs.NewMemNodeFs(prefix)
conn := nodefs.NewFileSystemConnector(fs, nil)
state := fuse.NewMountState(conn.RawFS())
state.SetDebug(*debug)
fmt.Println("Mounting")
err := state.Mount(mountPoint, nil)
server, err := fuse.NewServer(conn.RawFS(),mountPoint, nil)
if err != nil {
fmt.Printf("Mount fail: %v\n", err)
os.Exit(1)
}
server.SetDebug(*debug)
fmt.Println("Mounted!")
state.Loop()
server.Serve()
}
......@@ -33,5 +33,5 @@ func main() {
}
state.SetDebug(*debug)
state.Loop()
state.Serve()
}
......@@ -54,5 +54,5 @@ func main() {
}
mountState.SetDebug(*debug)
mountState.Loop()
mountState.Serve()
}
......@@ -75,7 +75,7 @@ func main() {
cmd.Start()
}
state.Loop()
state.Serve()
if memProfFile != nil {
pprof.WriteHeapProfile(memProfFile)
}
......
......@@ -74,7 +74,7 @@ type RawFileSystem interface {
String() string
// If called, provide debug output through the log package.
SetDebug(debug bool)
SetDebug(debug bool)
Lookup(out *raw.EntryOut, context *Context, name string) (status Status)
Forget(nodeid, nlookup uint64)
......
......@@ -7,7 +7,6 @@ import (
"unsafe"
)
var paranoia bool
type BufferPool interface {
......
......@@ -14,7 +14,6 @@ func NewDefaultRawFileSystem() RawFileSystem {
type defaultRawFileSystem struct{}
func (fs *defaultRawFileSystem) Init(init *RawFsInit) {
}
......
......@@ -22,8 +22,8 @@ type DirEntry struct {
}
type DirEntryList struct {
buf []byte
size int
buf []byte
size int
// TODO - hide this again.
Offset uint64
......@@ -74,5 +74,3 @@ func (l *DirEntryList) Bytes() []byte {
}
////////////////////////////////////////////////////////////////
......@@ -33,7 +33,7 @@ type FileSystem interface {
String() string
// If called, provide debug output through the log package.
SetDebug(debug bool)
SetDebug(debug bool)
}
// The Node implements the basic functionality of inodes; this is
......@@ -128,7 +128,6 @@ type File interface {
Allocate(off uint64, size uint64, mode uint32) (code fuse.Status)
}
// Wrap a File return in this to set FUSE flags. Also used internally
// to store open file data.
type WithFlags struct {
......@@ -144,7 +143,6 @@ type WithFlags struct {
OpenFlags uint32
}
// Options contains time out options for a node FileSystem. The
// default copied from libfuse and set in NewMountOptions() is
// (1s,1s,0s).
......
......@@ -3,8 +3,8 @@ package nodefs
import (
"time"
"github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/raw"
)
type defaultFile struct{}
......
......@@ -2,7 +2,7 @@ package nodefs
import (
"time"
"github.com/hanwen/go-fuse/fuse"
)
......
......@@ -2,9 +2,9 @@ package nodefs
import (
"log"
"github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/raw"
)
type connectorDir struct {
......
......@@ -100,7 +100,7 @@ func (f *devNullFile) Truncate(size uint64) (code fuse.Status) {
func NewLoopbackFile(f *os.File) File {
return &loopbackFile{File: f}
}
type loopbackFile struct {
File *os.File
......@@ -112,7 +112,6 @@ type loopbackFile struct {
lock sync.Mutex
}
var _ = (File)((*loopbackFile)(nil))
func (f *loopbackFile) InnerFile() File {
......
package nodefs
import (
"time"
"syscall"
"time"
"github.com/hanwen/go-fuse/fuse"
)
......@@ -27,15 +27,15 @@ func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
} else {
n := a.UnixNano()
tv[0] = syscall.NsecToTimeval(n)
}
}
if m == nil {
tv[1].Usec = _UTIME_OMIT
} else {
n := a.UnixNano()
tv[1] = syscall.NsecToTimeval(n)
}
}
err := syscall.Futimes(int(f.File.Fd()), tv)
return fuse.ToStatus(err)
return fuse.ToStatus(err)
}
......@@ -12,8 +12,8 @@ import (
"time"
"unsafe"
"github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/raw"
)
// Tests should set to true.
......
......@@ -10,8 +10,8 @@ import (
"strings"
"time"
"github.com/hanwen/go-fuse/raw"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/raw"
)
var _ = log.Println
......@@ -38,7 +38,7 @@ func (c *rawBridge) FsyncDir(context *fuse.Context, input *raw.FsyncIn) fuse.Sta
func (c *rawBridge) fsConn() *FileSystemConnector {
return (*FileSystemConnector)(c)
}
func (c *rawBridge) String() string {
if c.rootNode == nil || c.rootNode.mount == nil {
return "go-fuse:unmounted"
......@@ -153,7 +153,7 @@ func (c *rawBridge) OpenDir(out *raw.OpenOut, context *fuse.Context, input *raw.
}
stream = append(stream, node.getMountDirEntries()...)
de := &connectorDir{
node: node.Node(),
node: node.Node(),
stream: append(stream,
fuse.DirEntry{fuse.S_IFDIR, "."},
fuse.DirEntry{fuse.S_IFDIR, ".."}),
......
......@@ -3,13 +3,12 @@ package nodefs
import (
"github.com/hanwen/go-fuse/fuse"
)
func MountFileSystem(mountpoint string, nodeFs FileSystem, opts *Options) (*fuse.MountState, *FileSystemConnector, error) {
func MountFileSystem(mountpoint string, nodeFs FileSystem, opts *Options) (*fuse.Server, *FileSystemConnector, error) {
conn := NewFileSystemConnector(nodeFs, opts)
mountState := fuse.NewMountState(conn.RawFS())
err := mountState.Mount(mountpoint, nil)
s, err := fuse.NewServer(conn.RawFS(), mountpoint, nil)
if err != nil {
return nil, nil, err
}
return mountState, conn, nil
return s, conn, nil
}
......@@ -7,7 +7,6 @@ import (
"github.com/hanwen/go-fuse/fuse"
)
// The inode reflects the kernel's idea of the inode. Inodes may be
// created automatically when the kernel does lookups inode, or by
// explicitly by calling Inode.New().
......
......@@ -49,8 +49,8 @@ func (fs *memNodeFs) newNode() *memNode {
fs.mutex.Lock()
n := &memNode{
Node: NewDefaultNode(),
fs: fs,
id: fs.nextFree,
fs: fs,
id: fs.nextFree,
}
now := time.Now()
n.info.SetTimes(&now, &now, &now)
......@@ -174,7 +174,7 @@ func (n *memNodeFile) Flush() fuse.Status {
func (n *memNode) newFile(f *os.File) File {
return &memNodeFile{
File: NewLoopbackFile(f),
node: n,
node: n,
}
}
......
......@@ -32,14 +32,16 @@ func setupMemNodeTest(t *testing.T) (wd string, fs FileSystem, clean func()) {
NegativeTimeout: 0.0,
})
connector.SetDebug(fuse.VerboseTest())
state := fuse.NewMountState(connector.RawFS())
state.Mount(mnt, nil)
state, err := fuse.NewServer(connector.RawFS(), mnt, nil)
if err != nil {
t.Fatal("NewServer", err)
}
//me.state.SetDebug(false)
state.SetDebug(fuse.VerboseTest())
// Unthreaded, but in background.
go state.Loop()
go state.Serve()
return mnt, fs, func() {
state.Unmount()
os.RemoveAll(tmp)
......
......@@ -7,4 +7,3 @@ func splitDuration(dt time.Duration, secs *uint64, nsecs *uint32) {
*nsecs = uint32(ns % 1e9)
*secs = uint64(ns / 1e9)
}
......@@ -10,4 +10,3 @@ func (me *WithFlags) String() string {
me.File, me.Description, raw.FlagString(raw.OpenFlagNames, int64(me.OpenFlags), "O_RDONLY"),
raw.FlagString(raw.FuseOpenFlagNames, int64(me.FuseFlags), ""))
}
......@@ -67,7 +67,7 @@ const (
////////////////////////////////////////////////////////////////
func doInit(state *MountState, req *request) {
func doInit(state *Server, req *request) {
input := (*raw.InitIn)(req.inData)
if input.Major != _FUSE_KERNEL_VERSION {
log.Printf("Major versions does not match. Given %d, want %d\n", input.Major, _FUSE_KERNEL_VERSION)
......@@ -105,7 +105,7 @@ func doInit(state *MountState, req *request) {
req.status = OK
}
func doOpen(state *MountState, req *request) {
func doOpen(state *Server, req *request) {
out := (*raw.OpenOut)(req.outData)
status := state.fileSystem.Open(out, &req.context, (*raw.OpenIn)(req.inData))
req.status = status
......@@ -114,13 +114,13 @@ func doOpen(state *MountState, req *request) {
}
}
func doCreate(state *MountState, req *request) {
func doCreate(state *Server, req *request) {
out := (*raw.CreateOut)(req.outData)
status := state.fileSystem.Create(out, &req.context, (*raw.CreateIn)(req.inData), req.filenames[0])
req.status = status
}
func doReadDir(state *MountState, req *request) {
func doReadDir(state *Server, req *request) {
in := (*raw.ReadIn)(req.inData)
buf := state.allocOut(req, in.Size)
entries := NewDirEntryList(buf, uint64(in.Offset))
......@@ -130,18 +130,18 @@ func doReadDir(state *MountState, req *request) {
req.status = code
}
func doOpenDir(state *MountState, req *request) {
func doOpenDir(state *Server, req *request) {
out := (*raw.OpenOut)(req.outData)
status := state.fileSystem.OpenDir(out, &req.context, (*raw.OpenIn)(req.inData))
req.status = status
}
func doSetattr(state *MountState, req *request) {
func doSetattr(state *Server, req *request) {
out := (*raw.AttrOut)(req.outData)
req.status = state.fileSystem.SetAttr(out, &req.context, (*raw.SetAttrIn)(req.inData))
}
func doWrite(state *MountState, req *request) {
func doWrite(state *Server, req *request) {
n, status := state.fileSystem.Write(&req.context, (*raw.WriteIn)(req.inData), req.arg)
o := (*raw.WriteOut)(req.outData)
o.Size = n
......@@ -152,7 +152,7 @@ const _SECURITY_CAPABILITY = "security.capability"
const _SECURITY_ACL = "system.posix_acl_access"
const _SECURITY_ACL_DEFAULT = "system.posix_acl_default"
func doGetXAttr(state *MountState, req *request) {
func doGetXAttr(state *Server, req *request) {
if state.opts.IgnoreSecurityLabels && req.inHeader.Opcode == _OP_GETXATTR {
fn := req.filenames[0]
if fn == _SECURITY_CAPABILITY || fn == _SECURITY_ACL_DEFAULT ||
......@@ -207,19 +207,19 @@ func doGetXAttr(state *MountState, req *request) {
req.flatData = data
}
func doGetAttr(state *MountState, req *request) {
func doGetAttr(state *Server, req *request) {
attrOut := (*raw.AttrOut)(req.outData)
s := state.fileSystem.GetAttr(attrOut, &req.context, (*raw.GetAttrIn)(req.inData))
req.status = s
}
func doForget(state *MountState, req *request) {
func doForget(state *Server, req *request) {
if !state.opts.RememberInodes {
state.fileSystem.Forget(req.inHeader.NodeId, (*raw.ForgetIn)(req.inData).Nlookup)
}
}
func doBatchForget(state *MountState, req *request) {
func doBatchForget(state *Server, req *request) {
in := (*raw.BatchForgetIn)(req.inData)
wantBytes := uintptr(in.Count) * unsafe.Sizeof(raw.BatchForgetIn{})
if uintptr(len(req.arg)) < wantBytes {
......@@ -236,42 +236,42 @@ func doBatchForget(state *MountState, req *request) {
}
}
func doReadlink(state *MountState, req *request) {
func doReadlink(state *Server, req *request) {
req.flatData, req.status = state.fileSystem.Readlink(&req.context)
}
func doLookup(state *MountState, req *request) {
func doLookup(state *Server, req *request) {
lookupOut := (*raw.EntryOut)(req.outData)
s := state.fileSystem.Lookup(lookupOut, &req.context, req.filenames[0])
req.status = s
req.outData = unsafe.Pointer(lookupOut)
}
func doMknod(state *MountState, req *request) {
func doMknod(state *Server, req *request) {
out := (*raw.EntryOut)(req.outData)
req.status = state.fileSystem.Mknod(out, &req.context, (*raw.MknodIn)(req.inData), req.filenames[0])
}
func doMkdir(state *MountState, req *request) {
func doMkdir(state *Server, req *request) {
out := (*raw.EntryOut)(req.outData)
req.status = state.fileSystem.Mkdir(out, &req.context, (*raw.MkdirIn)(req.inData), req.filenames[0])
}
func doUnlink(state *MountState, req *request) {
func doUnlink(state *Server, req *request) {
req.status = state.fileSystem.Unlink(&req.context, req.filenames[0])
}
func doRmdir(state *MountState, req *request) {
func doRmdir(state *Server, req *request) {
req.status = state.fileSystem.Rmdir(&req.context, req.filenames[0])
}
func doLink(state *MountState, req *request) {
func doLink(state *Server, req *request) {
out := (*raw.EntryOut)(req.outData)
req.status = state.fileSystem.Link(out, &req.context, (*raw.LinkIn)(req.inData), req.filenames[0])
}
func doRead(state *MountState, req *request) {
func doRead(state *Server, req *request) {
in := (*raw.ReadIn)(req.inData)
buf := state.allocOut(req, in.Size)
......@@ -284,68 +284,68 @@ func doRead(state *MountState, req *request) {
}
}
func doFlush(state *MountState, req *request) {
func doFlush(state *Server, req *request) {
req.status = state.fileSystem.Flush(&req.context, (*raw.FlushIn)(req.inData))
}
func doRelease(state *MountState, req *request) {
func doRelease(state *Server, req *request) {
state.fileSystem.Release(&req.context, (*raw.ReleaseIn)(req.inData))
}
func doFsync(state *MountState, req *request) {
func doFsync(state *Server, req *request) {
req.status = state.fileSystem.Fsync(&req.context, (*raw.FsyncIn)(req.inData))
}
func doReleaseDir(state *MountState, req *request) {
func doReleaseDir(state *Server, req *request) {
state.fileSystem.ReleaseDir(&req.context, (*raw.ReleaseIn)(req.inData))
}
func doFsyncDir(state *MountState, req *request) {
func doFsyncDir(state *Server, req *request) {
req.status = state.fileSystem.FsyncDir(&req.context, (*raw.FsyncIn)(req.inData))
}
func doSetXAttr(state *MountState, req *request) {
func doSetXAttr(state *Server, req *request) {
splits := bytes.SplitN(req.arg, []byte{0}, 2)
req.status = state.fileSystem.SetXAttr(&req.context, (*raw.SetXAttrIn)(req.inData), string(splits[0]), splits[1])
}
func doRemoveXAttr(state *MountState, req *request) {
func doRemoveXAttr(state *Server, req *request) {
req.status = state.fileSystem.RemoveXAttr(&req.context, req.filenames[0])
}
func doAccess(state *MountState, req *request) {
func doAccess(state *Server, req *request) {
req.status = state.fileSystem.Access(&req.context, (*raw.AccessIn)(req.inData))
}
func doSymlink(state *MountState, req *request) {
func doSymlink(state *Server, req *request) {
out := (*raw.EntryOut)(req.outData)
req.status = state.fileSystem.Symlink(out, &req.context, req.filenames[1], req.filenames[0])
}
func doRename(state *MountState, req *request) {
func doRename(state *Server, req *request) {
req.status = state.fileSystem.Rename(&req.context, (*raw.RenameIn)(req.inData), req.filenames[0], req.filenames[1])
}
func doStatFs(state *MountState, req *request) {
func doStatFs(state *Server, req *request) {
stat := (*raw.StatfsOut)(req.outData)
req.status = state.fileSystem.StatFs(stat, &req.context)
}
func doIoctl(state *MountState, req *request) {
func doIoctl(state *Server, req *request) {
req.status = ENOSYS
}
func doDestroy(state *MountState, req *request) {
func doDestroy(state *Server, req *request) {
req.status = OK
}
func doFallocate(state *MountState, req *request) {
func doFallocate(state *Server, req *request) {
req.status = state.fileSystem.Fallocate(&req.context, (*raw.FallocateIn)(req.inData))
}
////////////////////////////////////////////////////////////////
type operationFunc func(*MountState, *request)
type operationFunc func(*Server, *request)
type castPointerFunc func(unsafe.Pointer) interface{}
type operationHandler struct {
......
......@@ -39,7 +39,7 @@ func setupOwnerTest(t *testing.T, opts *nodefs.Options) (workdir string, cleanup
if err != nil {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
go state.Loop()
go state.Serve()
return wd, func() {
state.Unmount()
os.RemoveAll(wd)
......
......@@ -121,7 +121,7 @@ func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func())
}
state.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
return mountPoint, func() {
state.Unmount()
os.RemoveAll(mountPoint)
......
......@@ -19,9 +19,9 @@ const (
MAX_KERNEL_WRITE = 128 * 1024
)
// MountState contains the logic for reading from the FUSE device and
// Server contains the logic for reading from the FUSE device and
// translating it to RawFileSystem interface calls.
type MountState struct {
type Server struct {
// Empty if unmounted.
mountPoint string
fileSystem RawFileSystem
......@@ -54,7 +54,7 @@ type MountState struct {
// filesystem internally, so thread-sanitizer does not get confused.
//
// fs := SomeFSObj{ReadCalled: false}
// ms := NewMountState(fs)
// ms := NewServer(fs)
// ms.Mount("/mnt", nil)
// ..
// ioutil.ReadFile("/mnt/file")
......@@ -62,16 +62,16 @@ type MountState struct {
// mountstate.ThreadSanitizerSync()
// if fs.ReadCalled { ... // no race condition here.
//
func (ms *MountState) ThreadSanitizerSync() {
func (ms *Server) ThreadSanitizerSync() {
ms.reqMu.Lock()
ms.reqMu.Unlock()
}
func (ms *MountState) SetDebug(dbg bool) {
func (ms *Server) SetDebug(dbg bool) {
ms.debug = dbg
}
func (ms *MountState) KernelSettings() raw.InitIn {
func (ms *Server) KernelSettings() raw.InitIn {
ms.reqMu.Lock()
s := ms.kernelSettings
ms.reqMu.Unlock()
......@@ -79,14 +79,50 @@ func (ms *MountState) KernelSettings() raw.InitIn {
return s
}
func (ms *MountState) MountPoint() string {
func (ms *Server) MountPoint() string {
return ms.mountPoint
}
const _MAX_NAME_LEN = 20
// Mount filesystem on mountPoint.
func (ms *MountState) Mount(mountPoint string, opts *MountOptions) error {
// This type may be provided for recording latencies of each FUSE
// operation.
type LatencyMap interface {
Add(name string, dt time.Duration)
}
func (ms *Server) RecordLatencies(l LatencyMap) {
ms.latencies = l
}
func (ms *Server) Unmount() (err error) {
if ms.mountPoint == "" {
return nil
}
delay := time.Duration(0)
for try := 0; try < 5; try++ {
err = unmount(ms.mountPoint)
if err == nil {
break
}
// Sleep for a bit. This is not pretty, but there is
// no way we can be certain that the kernel thinks all
// open files have already been closed.
delay = 2*delay + 5*time.Millisecond
time.Sleep(delay)
}
if err != nil {
return
}
// Wait for event loops to exit.
ms.loops.Wait()
ms.mountPoint = ""
return err
}
// NewServer creates a server and attaches it to the given directory.
func NewServer(fs RawFileSystem, mountPoint string, opts *MountOptions) (*Server, error) {
if opts == nil {
opts = &MountOptions{
MaxBackground: _DEFAULT_BACKGROUND_TASKS,
......@@ -106,8 +142,12 @@ func (ms *MountState) Mount(mountPoint string, opts *MountOptions) error {
o.MaxWrite = MAX_KERNEL_WRITE
}
opts = &o
ms.opts = &o
ms := &Server{
fileSystem: fs,
started: make(chan struct{}),
opts: &o,
}
optStrs := opts.Options
if opts.AllowOther {
optStrs = append(optStrs, "allow_other")
......@@ -128,13 +168,13 @@ func (ms *MountState) Mount(mountPoint string, opts *MountOptions) error {
if !filepath.IsAbs(mountPoint) {
cwd, err := os.Getwd()
if err != nil {
return err
return nil, err
}
mountPoint = filepath.Clean(filepath.Join(cwd, mountPoint))
}
fd, err := mount(mountPoint, strings.Join(optStrs, ","))
if err != nil {
return err
return nil, err
}
initParams := RawFsInit{
InodeNotify: func(n *raw.NotifyInvalInodeOut) Status {
......@@ -150,54 +190,10 @@ func (ms *MountState) Mount(mountPoint string, opts *MountOptions) error {
ms.fileSystem.Init(&initParams)
ms.mountPoint = mountPoint
ms.mountFd = fd
return nil
}
// This type may be provided for recording latencies of each FUSE
// operation.
type LatencyMap interface {
Add(name string, dt time.Duration)
}
func (ms *MountState) RecordLatencies(l LatencyMap) {
ms.latencies = l
}
func (ms *MountState) Unmount() (err error) {
if ms.mountPoint == "" {
return nil
}
delay := time.Duration(0)
for try := 0; try < 5; try++ {
err = unmount(ms.mountPoint)
if err == nil {
break
}
// Sleep for a bit. This is not pretty, but there is
// no way we can be certain that the kernel thinks all
// open files have already been closed.
delay = 2*delay + 5*time.Millisecond
time.Sleep(delay)
}
if err != nil {
return
}
// Wait for event loops to exit.
ms.loops.Wait()
ms.mountPoint = ""
return err
}
func NewMountState(fs RawFileSystem) *MountState {
ms := new(MountState)
ms.mountPoint = ""
ms.fileSystem = fs
ms.started = make(chan struct{})
return ms
return ms, nil
}
func (ms *MountState) BufferPoolStats() string {
func (ms *Server) BufferPoolStats() string {
s := ms.opts.Buffers.String()
var r int
......@@ -215,7 +211,7 @@ const _MAX_READERS = 2
// Returns a new request, or error. In case exitIdle is given, returns
// nil, OK if we have too many readers already.
func (ms *MountState) readRequest(exitIdle bool) (req *request, code Status) {
func (ms *Server) readRequest(exitIdle bool) (req *request, code Status) {
var dest []byte
ms.reqMu.Lock()
......@@ -272,7 +268,7 @@ func (ms *MountState) readRequest(exitIdle bool) (req *request, code Status) {
return req, OK
}
func (ms *MountState) returnRequest(req *request) {
func (ms *Server) returnRequest(req *request) {
ms.recordStats(req)
if req.bufferPoolOutputBuf != nil {
......@@ -291,7 +287,7 @@ func (ms *MountState) returnRequest(req *request) {
ms.reqMu.Unlock()
}
func (ms *MountState) recordStats(req *request) {
func (ms *Server) recordStats(req *request) {
if ms.latencies != nil {
dt := time.Now().Sub(req.startTime)
opname := operationName(req.inHeader.Opcode)
......@@ -304,7 +300,7 @@ func (ms *MountState) recordStats(req *request) {
// goroutine.
//
// Each filesystem operation executes in a separate goroutine.
func (ms *MountState) Loop() {
func (ms *Server) Serve() {
ms.loops.Add(1)
ms.loop(false)
ms.loops.Wait()
......@@ -314,7 +310,7 @@ func (ms *MountState) Loop() {
ms.reqMu.Unlock()
}
func (ms *MountState) loop(exitIdle bool) {
func (ms *Server) loop(exitIdle bool) {
defer ms.loops.Done()
exit:
for {
......@@ -338,7 +334,7 @@ exit:
}
}
func (ms *MountState) handleRequest(req *request) {
func (ms *Server) handleRequest(req *request) {
req.parse()
if req.handler == nil {
req.status = ENOSYS
......@@ -365,7 +361,7 @@ func (ms *MountState) handleRequest(req *request) {
ms.returnRequest(req)
}
func (ms *MountState) allocOut(req *request, size uint32) []byte {
func (ms *Server) allocOut(req *request, size uint32) []byte {
if cap(req.bufferPoolOutputBuf) >= int(size) {
req.bufferPoolOutputBuf = req.bufferPoolOutputBuf[:size]
return req.bufferPoolOutputBuf
......@@ -377,7 +373,7 @@ func (ms *MountState) allocOut(req *request, size uint32) []byte {
return req.bufferPoolOutputBuf
}
func (ms *MountState) write(req *request) Status {
func (ms *Server) write(req *request) Status {
// Forget does not wait for reply.
if req.inHeader.Opcode == _OP_FORGET || req.inHeader.Opcode == _OP_BATCH_FORGET {
return OK
......@@ -399,7 +395,7 @@ func (ms *MountState) write(req *request) Status {
return s
}
func (ms *MountState) writeInodeNotify(entry *raw.NotifyInvalInodeOut) Status {
func (ms *Server) writeInodeNotify(entry *raw.NotifyInvalInodeOut) Status {
req := request{
inHeader: &raw.InHeader{
Opcode: _OP_NOTIFY_INODE,
......@@ -420,7 +416,7 @@ func (ms *MountState) writeInodeNotify(entry *raw.NotifyInvalInodeOut) Status {
return result
}
func (ms *MountState) writeDeleteNotify(parent uint64, child uint64, name string) Status {
func (ms *Server) writeDeleteNotify(parent uint64, child uint64, name string) Status {
if ms.kernelSettings.Minor < 18 {
return ms.writeEntryNotify(parent, name)
}
......@@ -457,7 +453,7 @@ func (ms *MountState) writeDeleteNotify(parent uint64, child uint64, name string
return result
}
func (ms *MountState) writeEntryNotify(parent uint64, name string) Status {
func (ms *Server) writeEntryNotify(parent uint64, name string) Status {
req := request{
inHeader: &raw.InHeader{
Opcode: _OP_NOTIFY_ENTRY,
......@@ -498,6 +494,6 @@ func init() {
// Wait for the first request to be served. Use this to avoid racing
// between accessing the (empty) mountpoint, and the OS trying to
// setup the user-space mount.
func (ms *MountState) WaitMount() {
func (ms *Server) WaitMount() {
<-ms.started
}
......@@ -4,7 +4,7 @@ import (
"syscall"
)
func (ms *MountState) systemWrite(req *request, header []byte) Status {
func (ms *Server) systemWrite(req *request, header []byte) Status {
if req.flatDataSize() == 0 {
_, err := syscall.Write(ms.mountFd, Write(header))
return ToStatus(err)
......
......@@ -5,7 +5,7 @@ import (
"syscall"
)
func (ms *MountState) systemWrite(req *request, header []byte) Status {
func (ms *Server) systemWrite(req *request, header []byte) Status {
if req.flatDataSize() == 0 {
_, err := syscall.Write(ms.mountFd, header)
return ToStatus(err)
......
......@@ -4,10 +4,10 @@ import (
"fmt"
)
func (s *MountState) setSplice() {
func (s *Server) setSplice() {
panic("darwin has no splice.")
}
func (ms *MountState) trySplice(header []byte, req *request, fdData *ReadResultFd) error {
func (ms *Server) trySplice(header []byte, req *request, fdData *ReadResultFd) error {
return fmt.Errorf("unimplemented")
}
......@@ -7,11 +7,11 @@ import (
"github.com/hanwen/go-fuse/splice"
)
func (s *MountState) setSplice() {
func (s *Server) setSplice() {
s.canSplice = splice.Resizable()
}
func (ms *MountState) trySplice(header []byte, req *request, fdData *ReadResultFd) error {
func (ms *Server) trySplice(header []byte, req *request, fdData *ReadResultFd) error {
pair, err := splice.Get()
if err != nil {
return err
......
......@@ -51,7 +51,7 @@ func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) {
state.SetDebug(fuse.VerboseTest())
conn.SetDebug(fuse.VerboseTest())
pfs.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
return dir, pfs, func() {
err := state.Unmount()
......@@ -151,7 +151,7 @@ func TestNonseekable(t *testing.T) {
state.SetDebug(fuse.VerboseTest())
defer state.Unmount()
go state.Loop()
go state.Serve()
f, err := os.Open(dir + "/file")
if err != nil {
......@@ -185,7 +185,7 @@ func TestGetAttrRace(t *testing.T) {
state.SetDebug(fuse.VerboseTest())
conn.SetDebug(fuse.VerboseTest())
pfs.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
defer state.Unmount()
......
......@@ -46,7 +46,7 @@ func defaultReadTest(t *testing.T) (root string, cleanup func()) {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
state.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
return dir, func() {
state.Unmount()
......
......@@ -37,18 +37,18 @@ func TestDeleteNotify(t *testing.T) {
fs := nodefs.NewMemNodeFs(dir + "/backing")
conn := nodefs.NewFileSystemConnector(fs,
&nodefs.Options{PortableInodes: true})
state := fuse.NewMountState(conn.RawFS())
mnt := dir + "/mnt"
err = os.Mkdir(mnt, 0755)
if err != nil {
t.Fatal(err)
}
err = state.Mount(mnt, nil)
state, err := fuse.NewServer(conn.RawFS(), mnt, nil)
if err != nil {
t.Fatal(err)
}
state.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
defer state.Unmount()
_, code := fs.Root().Mkdir("testdir", 0755, nil)
......
......@@ -145,7 +145,7 @@ func setupFAttrTest(t *testing.T, fs pathfs.FileSystem) (dir string, clean func(
}
state.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
// Trigger INIT.
os.Lstat(dir)
......
......@@ -38,7 +38,7 @@ type testCase struct {
origFile string
origSubdir string
tester *testing.T
state *fuse.MountState
state *fuse.Server
pathFs *pathfs.PathNodeFs
connector *nodefs.FileSystemConnector
}
......@@ -88,13 +88,15 @@ func NewTestCase(t *testing.T) *testCase {
rfs = fuse.NewLockingRawFileSystem(me.connector.RawFS())
me.connector.SetDebug(fuse.VerboseTest())
me.state = fuse.NewMountState(rfs)
me.state.Mount(me.mnt, nil)
me.state, err = fuse.NewServer(rfs, me.mnt, nil)
if err != nil {
t.Fatal("NewServer:", err)
}
me.state.SetDebug(fuse.VerboseTest())
// Unthreaded, but in background.
go me.state.Loop()
go me.state.Serve()
me.state.WaitMount()
return me
......@@ -937,7 +939,7 @@ func TestOriginalIsSymlink(t *testing.T) {
}
defer state.Unmount()
go state.Loop()
go state.Serve()
_, err = os.Lstat(mnt)
if err != nil {
......
......@@ -42,7 +42,7 @@ type NotifyTest struct {
pathfs *pathfs.PathNodeFs
connector *nodefs.FileSystemConnector
dir string
state *fuse.MountState
state *fuse.Server
}
func NewNotifyTest(t *testing.T) *NotifyTest {
......@@ -66,7 +66,7 @@ func NewNotifyTest(t *testing.T) *NotifyTest {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
me.state.SetDebug(fuse.VerboseTest())
go me.state.Loop()
go me.state.Serve()
return me
}
......
......@@ -50,4 +50,3 @@ type Context struct {
NodeId uint64
*raw.Context
}
......@@ -38,13 +38,13 @@ type autoUnionFs struct {
nodeFs *pathfs.PathNodeFs
options *AutoUnionFsOptions
mountState *fuse.MountState
mountState *fuse.Server
connector *nodefs.FileSystemConnector
}
type AutoUnionFsOptions struct {
UnionFsOptions
nodefs.Options
pathfs.PathNodeFsOptions
......@@ -69,7 +69,7 @@ const (
// A pathfs.FileSystem that we can hookup with MountState and
// FileSystemConnector
type RootFileSystem interface {
SetMountState(state *fuse.MountState)
SetMountState(state *fuse.Server)
SetFileSystemConnector(conn *nodefs.FileSystemConnector)
pathfs.FileSystem
}
......@@ -393,7 +393,7 @@ func (fs *autoUnionFs) StatusDir() (stream []fuse.DirEntry, status fuse.Status)
// SetMountState stores the MountState, which is necessary for
// retrieving debug data.
func (fs *autoUnionFs) SetMountState(state *fuse.MountState) {
func (fs *autoUnionFs) SetMountState(state *fuse.Server) {
fs.mountState = state
}
......
......@@ -63,7 +63,7 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
}
state.SetDebug(fuse.VerboseTest())
conn.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
return wd, func() {
state.Unmount()
......
......@@ -100,7 +100,7 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
}
conn.SetDebug(fuse.VerboseTest())
state.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
return wd, func() {
err := state.Unmount()
......@@ -1120,7 +1120,7 @@ func TestUnionFsDisappearing(t *testing.T) {
}
defer state.Unmount()
state.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
log.Println("TestUnionFsDisappearing2")
......
......@@ -29,7 +29,7 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) {
t.Fatalf("MountNodeFileSystem failed: %v", err)
}
state.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
return mountPoint, func() {
state.Unmount()
......
......@@ -30,7 +30,7 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) {
state, _, err := nodefs.MountFileSystem(mountPoint, zfs, nil)
state.SetDebug(fuse.VerboseTest())
go state.Loop()
go state.Serve()
return mountPoint, func() {
state.Unmount()
......
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