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

Move directory handling to PathFileSystemConnector too.

parent 19073846
......@@ -101,11 +101,8 @@ func (me *DefaultRawFuseFileSystem) Poll(header *InHeader, input *PollIn) (out *
return nil, ENOSYS
}
func (me *DefaultRawFuseFileSystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, fuseFile RawFuseDir, status Status) {
return 0, nil, ENOSYS
}
func (me *DefaultRawFuseFileSystem) ReleaseDir(header *InHeader, f RawFuseDir) {
func (me *DefaultRawFuseFileSystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status) {
return 0, 0, ENOSYS
}
func (me *DefaultRawFuseFileSystem) Read(*ReadIn, *BufferPool) ([]byte, Status) {
......@@ -127,6 +124,18 @@ func (me *DefaultRawFuseFileSystem) Fsync(input *FsyncIn) (code Status) {
return ENOSYS
}
func (me *DefaultRawFuseFileSystem) ReadDir(header *InHeader, input *ReadIn) (*DirEntryList, Status) {
return nil, ENOSYS
}
func (me *DefaultRawFuseFileSystem) ReleaseDir(header *InHeader, input *ReleaseIn) {
}
func (me *DefaultRawFuseFileSystem) FsyncDir(header *InHeader, input *FsyncIn) (code Status) {
return ENOSYS
}
////////////////////////////////////////////////////////////////
// DefaultRawFuseFile
......@@ -150,7 +159,6 @@ func (me *DefaultRawFuseFile) Fsync(*FsyncIn) (code Status) {
return ENOSYS
}
////////////////////////////////////////////////////////////////
//
......
......@@ -29,9 +29,5 @@ func TestPathFs(t *testing.T) {
func TestDummyFile(t *testing.T) {
d := new(DefaultRawFuseFile)
var filePtr RawFuseFile = d
d2 := new(DefaultRawFuseDir)
var fileDir RawFuseDir = d2
_ = fileDir
_ = filePtr
}
......@@ -68,8 +68,6 @@ func (me *DirEntryList) Bytes() []byte {
type FuseDir struct {
stream chan DirEntry
leftOver DirEntry
connector *PathFileSystemConnector
parentIno uint64
DefaultRawFuseDir
}
......@@ -115,5 +113,12 @@ func (me *FuseDir) ReadDir(input *ReadIn) (*DirEntryList, Status) {
return list, OK
}
func (me *FuseDir) ReleaseDir() {
// Read everything so we make goroutines exit.
func (me *FuseDir) Release() {
for ok := true; ok && me.stream != nil; {
_, ok = <-me.stream
if !ok {
break
}
}
}
......@@ -84,49 +84,6 @@ type MountState struct {
operationLatencies map[string]int64
}
func (me *MountState) RegisterFile(file RawFuseFile) uint64 {
me.openedFilesMutex.Lock()
defer me.openedFilesMutex.Unlock()
// We will be screwed if nextFree ever wraps.
me.nextFreeFile++
index := me.nextFreeFile
me.openedFiles[index] = file
return index
}
func (me *MountState) FindFile(index uint64) RawFuseFile {
me.openedFilesMutex.RLock()
defer me.openedFilesMutex.RUnlock()
return me.openedFiles[index]
}
func (me *MountState) UnregisterFile(handle uint64) {
me.openedFilesMutex.Lock()
defer me.openedFilesMutex.Unlock()
me.openedFiles[handle] = nil, false
}
func (me *MountState) RegisterDir(dir RawFuseDir) uint64 {
me.openedDirsMutex.Lock()
defer me.openedDirsMutex.Unlock()
me.nextFreeDir++
index := me.nextFreeDir
me.openedDirs[index] = dir
return index
}
func (me *MountState) FindDir(index uint64) RawFuseDir {
me.openedDirsMutex.RLock()
defer me.openedDirsMutex.RUnlock()
return me.openedDirs[index]
}
func (me *MountState) UnregisterDir(handle uint64) {
me.openedDirsMutex.Lock()
defer me.openedDirsMutex.Unlock()
me.openedDirs[handle] = nil, false
}
// Mount filesystem on mountPoint.
//
// If threaded is set, each filesystem operation executes in a
......@@ -467,10 +424,9 @@ func (me *MountState) dispatch(req *fuseRequest) {
case FUSE_READDIR:
req.flatData, status = doReadDir(me, h, (*ReadIn)(inData))
case FUSE_RELEASEDIR:
status = doReleaseDir(me, h, (*ReleaseIn)(inData))
me.fileSystem.ReleaseDir(h, (*ReleaseIn)(inData))
case FUSE_FSYNCDIR:
// todo- check inData type.
status = doFsyncDir(me, h, (*FsyncIn)(inData))
status = me.fileSystem.FsyncDir(h, (*FsyncIn)(inData))
case FUSE_SETXATTR:
splits := bytes.Split(data, []byte{0}, 2)
status = fs.SetXAttr(h, (*SetXAttrIn)(inData), string(splits[0]), splits[1])
......@@ -648,35 +604,23 @@ func doGetXAttr(state *MountState, header *InHeader, input *GetXAttrIn, attr str
////////////////////////////////////////////////////////////////
// Handling directories
func doReleaseDir(state *MountState, header *InHeader, input *ReleaseIn) (code Status) {
d := state.FindDir(input.Fh)
state.fileSystem.ReleaseDir(header, d)
d.ReleaseDir()
state.UnregisterDir(input.Fh)
return OK
}
func doOpenDir(state *MountState, header *InHeader, input *OpenIn) (unsafe.Pointer, Status) {
flags, fuseDir, status := state.fileSystem.OpenDir(header, input)
flags, handle, status := state.fileSystem.OpenDir(header, input)
if status != OK {
return nil, status
}
out := new(OpenOut)
out.Fh = state.RegisterDir(fuseDir)
out.Fh = handle
out.OpenFlags = flags
return unsafe.Pointer(out), status
}
func doReadDir(state *MountState, header *InHeader, input *ReadIn) (out []byte, code Status) {
dir := state.FindDir(input.Fh)
entries, code := dir.ReadDir(input)
entries, code := state.fileSystem.ReadDir(header, input)
if entries == nil {
return nil, code
}
return entries.Bytes(), code
}
func doFsyncDir(state *MountState, header *InHeader, input *FsyncIn) (code Status) {
return state.FindDir(input.Fh).FsyncDir(input)
}
......@@ -314,7 +314,7 @@ func (me *LockingRawFilesystem) Poll(header *InHeader, input *PollIn) (out *Poll
return me.Original.Poll(header, input)
}
func (me *LockingRawFilesystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, fuseFile RawFuseDir, status Status) {
func (me *LockingRawFilesystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, h uint64, status Status) {
me.lock.Lock()
defer me.lock.Unlock()
return me.Original.OpenDir(header, input)
......@@ -326,24 +326,44 @@ func (me *LockingRawFilesystem) Release(header *InHeader, input *ReleaseIn) {
me.Original.Release(header, input)
}
func (me *LockingRawFilesystem) ReleaseDir(header *InHeader, f RawFuseDir) {
func (me *LockingRawFilesystem) ReleaseDir(header *InHeader, h *ReleaseIn) {
me.lock.Lock()
defer me.lock.Unlock()
me.Original.ReleaseDir(header, f)
me.Original.ReleaseDir(header, h)
}
func (me *LockingRawFilesystem) Read(input *ReadIn, bp *BufferPool) ([]byte, Status) {
me.lock.Lock()
defer me.lock.Unlock()
return me.Original.Read(input, bp)
}
func (me *LockingRawFilesystem) Write(input *WriteIn, data []byte) (written uint32, code Status) {
me.lock.Lock()
defer me.lock.Unlock()
return me.Original.Write(input, data)
}
func (me *LockingRawFilesystem) Flush(input *FlushIn) Status {
me.lock.Lock()
defer me.lock.Unlock()
return me.Original.Flush(input)
}
func (me *LockingRawFilesystem) Fsync(input *FsyncIn) (code Status) {
me.lock.Lock()
defer me.lock.Unlock()
return me.Original.Fsync(input)
}
func (me *LockingRawFilesystem) ReadDir(header *InHeader, input *ReadIn) (*DirEntryList, Status) {
me.lock.Lock()
defer me.lock.Unlock()
return me.Original.ReadDir(header, input)
}
func (me *LockingRawFilesystem) FsyncDir(header *InHeader, input *FsyncIn) (code Status) {
me.lock.Lock()
defer me.lock.Unlock()
return me.Original.FsyncDir(header, input)
}
......@@ -61,11 +61,12 @@ func (me *testCase) Setup(t *testing.T) {
var rfs RawFileSystem
me.connector = NewPathFileSystemConnector(pfs)
rfs = NewTimingRawFilesystem(me.connector)
rfs = me.connector
rfs = NewTimingRawFilesystem(rfs)
rfs = NewLockingRawFilesystem(rfs)
me.connector.Debug = true
me.state = NewMountState(me.connector)
me.state = NewMountState(rfs)
me.state.Mount(me.mountPoint)
//me.state.Debug = false
......
......@@ -44,8 +44,7 @@ type inode struct {
Name string
LookupCount int
OpenCount int
// ?
Type uint32
Type uint32 // dirent type, used to check if mounts are valid.
mount *mountData
}
......@@ -152,11 +151,11 @@ type PathFileSystemConnector struct {
// Open files/directories.
fileLock sync.RWMutex
openFiles map[uint64]RawFuseFile
openFiles map[uint64]interface{}
nextFreeHandle uint64
}
func (me *PathFileSystemConnector) unregisterFile(node *inode, handle uint64) RawFuseFile {
func (me *PathFileSystemConnector) unregisterFile(node *inode, handle uint64) interface{} {
me.fileLock.Lock()
defer me.fileLock.Unlock()
f, ok := me.openFiles[handle]
......@@ -168,13 +167,7 @@ func (me *PathFileSystemConnector) unregisterFile(node *inode, handle uint64) Ra
return f
}
func (me *PathFileSystemConnector) getFile(h uint64) RawFuseFile {
me.fileLock.RLock()
defer me.fileLock.RUnlock()
return me.openFiles[h]
}
func (me *PathFileSystemConnector) registerFile(node *inode, f RawFuseFile) uint64 {
func (me *PathFileSystemConnector) registerFile(node *inode, f interface{}) uint64 {
me.fileLock.Lock()
defer me.fileLock.Unlock()
......@@ -190,6 +183,18 @@ func (me *PathFileSystemConnector) registerFile(node *inode, f RawFuseFile) uint
return h
}
func (me *PathFileSystemConnector) getDir(h uint64) RawFuseDir {
me.fileLock.RLock()
defer me.fileLock.RUnlock()
return me.openFiles[h].(RawFuseDir)
}
func (me *PathFileSystemConnector) getFile(h uint64) RawFuseFile {
me.fileLock.RLock()
defer me.fileLock.RUnlock()
return me.openFiles[h].(RawFuseFile)
}
func (me *PathFileSystemConnector) verify() {
if !paranoia {
return
......@@ -317,7 +322,7 @@ func (me *PathFileSystemConnector) findInode(fullPath string) *inode {
func NewPathFileSystemConnector(fs PathFilesystem) (out *PathFileSystemConnector) {
out = new(PathFileSystemConnector)
out.inodeMap = make(map[uint64]*inode)
out.openFiles = make(map[uint64]RawFuseFile)
out.openFiles = make(map[uint64]interface{})
out.nextFreeInode = FUSE_ROOT_ID
rootData := out.newInode()
......@@ -503,24 +508,34 @@ func (me *PathFileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (
return out, OK
}
func (me *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (flags uint32, fuseFile RawFuseDir, status Status) {
fullPath, mount, _ := me.GetPath(header.NodeId)
func (me *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status) {
fullPath, mount, node := me.GetPath(header.NodeId)
if mount == nil {
return 0, nil, ENOENT
return 0, 0, ENOENT
}
// TODO - how to handle return flags, the FUSE open flags?
stream, err := mount.fs.OpenDir(fullPath)
if err != OK {
return 0, nil, err
return 0, 0, err
}
mount.incOpenCount(1)
de := new(FuseDir)
de.connector = me
de.parentIno = header.NodeId
de.stream = stream
return 0, de, OK
h := me.registerFile(node, de)
return 0, h, OK
}
func (me *PathFileSystemConnector) ReadDir(header *InHeader, input *ReadIn) (*DirEntryList, Status) {
d := me.getDir(input.Fh)
de, code := d.ReadDir(input)
if code != OK {
return nil, code
}
return de, OK
}
func (me *PathFileSystemConnector) Open(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status) {
......@@ -722,18 +737,25 @@ func (me *PathFileSystemConnector) Create(header *InHeader, input *CreateIn, nam
func (me *PathFileSystemConnector) Release(header *InHeader, input *ReleaseIn) {
_, mount, node := me.GetPath(header.NodeId)
f := me.unregisterFile(node, input.Fh)
f := me.unregisterFile(node, input.Fh).(RawFuseFile)
f.Release()
if mount != nil {
mount.incOpenCount(-1)
}
}
func (me *PathFileSystemConnector) ReleaseDir(header *InHeader, f RawFuseDir) {
_, mount, _ := me.GetPath(header.NodeId)
func (me *PathFileSystemConnector) ReleaseDir(header *InHeader, input *ReleaseIn) {
_, mount, node := me.GetPath(header.NodeId)
if mount != nil {
mount.incOpenCount(-1)
}
d := me.unregisterFile(node, input.Fh).(RawFuseDir)
d.Release()
}
func (me *PathFileSystemConnector) FsyncDir(header *InHeader, input *FsyncIn) (code Status) {
// What the heck is FsyncDir supposed to do?
return OK
}
func (me *PathFileSystemConnector) GetXAttr(header *InHeader, attribute string) (data []byte, code Status) {
......@@ -785,7 +807,7 @@ func (me *PathFileSystemConnector) ListXAttr(header *InHeader) (data []byte, cod
}
func (me *PathFileSystemConnector) Write(input *WriteIn, data []byte) (written uint32, code Status) {
f := me.getFile(input.Fh)
f := me.getFile(input.Fh).(RawFuseFile)
return f.Write(input, data)
}
......
......@@ -166,7 +166,7 @@ func (me *TimingRawFilesystem) Poll(header *InHeader, input *PollIn) (out *PollO
return me.Original.Poll(header, input)
}
func (me *TimingRawFilesystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, fuseFile RawFuseDir, status Status) {
func (me *TimingRawFilesystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status) {
defer me.startTimer("OpenDir")()
return me.Original.OpenDir(header, input)
}
......@@ -176,11 +176,6 @@ func (me *TimingRawFilesystem) Release(header *InHeader, input *ReleaseIn) {
me.Original.Release(header, input)
}
func (me *TimingRawFilesystem) ReleaseDir(header *InHeader, f RawFuseDir) {
defer me.startTimer("ReleaseDir")()
me.Original.ReleaseDir(header, f)
}
func (me *TimingRawFilesystem) Read(input *ReadIn, bp *BufferPool) ([]byte, Status) {
defer me.startTimer("Read")()
return me.Original.Read(input, bp)
......@@ -200,3 +195,18 @@ func (me *TimingRawFilesystem) Fsync(input *FsyncIn) (code Status) {
defer me.startTimer("Fsync")()
return me.Original.Fsync(input)
}
func (me *TimingRawFilesystem) ReadDir(header *InHeader, input *ReadIn) (*DirEntryList, Status) {
defer me.startTimer("ReadDir")()
return me.Original.ReadDir(header, input)
}
func (me *TimingRawFilesystem) ReleaseDir(header *InHeader, input *ReleaseIn) {
defer me.startTimer("ReleaseDir")()
me.Original.ReleaseDir(header, input)
}
func (me *TimingRawFilesystem) FsyncDir(header *InHeader, input *FsyncIn) (code Status) {
defer me.startTimer("FsyncDir")()
return me.Original.FsyncDir(header, input)
}
......@@ -529,18 +529,19 @@ type RawFileSystem interface {
Ioctl(header *InHeader, input *IoctlIn) (out *IoctlOut, code Status)
Poll(header *InHeader, input *PollIn) (out *PollOut, code Status)
// The return flags are FOPEN_xx.
Open(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status)
OpenDir(header *InHeader, input *OpenIn) (flags uint32, fuseFile RawFuseDir, status Status)
ReleaseDir(header *InHeader, f RawFuseDir)
// File handling.
Open(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status)
Read(*ReadIn, *BufferPool) ([]byte, Status)
Release(header *InHeader, input *ReleaseIn)
Write(*WriteIn, []byte) (written uint32, code Status)
Flush(*FlushIn) Status
Fsync(*FsyncIn) (code Status)
// Directory handling
OpenDir(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status)
ReadDir(header *InHeader, input *ReadIn) (*DirEntryList, Status)
ReleaseDir(header *InHeader, input *ReleaseIn)
FsyncDir(header *InHeader, input *FsyncIn) (code Status)
}
type RawFuseFile interface {
......@@ -554,8 +555,7 @@ type RawFuseFile interface {
type RawFuseDir interface {
ReadDir(input *ReadIn) (*DirEntryList, Status)
ReleaseDir()
FsyncDir(input *FsyncIn) (code Status)
Release()
}
type PathFilesystem interface {
......@@ -593,7 +593,7 @@ type PathFilesystem interface {
// unimplemented: poll, ioctl, bmap.
}
// Include this method in your implementation to inherit default nop
// Include this struct in your implementation to inherit default nop
// implementations.
type DefaultRawFuseDir struct{}
......
......@@ -201,7 +201,7 @@ func (me *WrappingRawFilesystem) Poll(header *InHeader, input *PollIn) (out *Pol
return me.Original.Poll(header, input)
}
func (me *WrappingRawFilesystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, fuseFile RawFuseDir, status Status) {
func (me *WrappingRawFilesystem) OpenDir(header *InHeader, input *OpenIn) (flags uint32, handle uint64, status Status) {
return me.Original.OpenDir(header, input)
}
......@@ -209,10 +209,6 @@ func (me *WrappingRawFilesystem) Release(header *InHeader, input *ReleaseIn) {
me.Original.Release(header, input)
}
func (me *WrappingRawFilesystem) ReleaseDir(header *InHeader, f RawFuseDir) {
me.Original.ReleaseDir(header, f)
}
func (me *WrappingRawFilesystem) Read(input *ReadIn, bp *BufferPool) ([]byte, Status) {
return me.Original.Read(input, bp)
}
......@@ -228,3 +224,15 @@ func (me *WrappingRawFilesystem) Flush(input *FlushIn) Status {
func (me *WrappingRawFilesystem) Fsync(input *FsyncIn) (code Status) {
return me.Original.Fsync(input)
}
func (me *WrappingRawFilesystem) ReadDir(header *InHeader, input *ReadIn) (*DirEntryList, Status) {
return me.Original.ReadDir(header, input)
}
func (me *WrappingRawFilesystem) ReleaseDir(header *InHeader, input *ReleaseIn) {
me.Original.ReleaseDir(header, input)
}
func (me *WrappingRawFilesystem) FsyncDir(header *InHeader, input *FsyncIn) (code Status) {
return me.Original.FsyncDir(header, input)
}
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