Commit 04b2200a authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Make FileSystemConnector issue an fs.Flush() on flush.

Drop fs.Release() as FileSystem API method.

This should fix GetAttr racing with Release in UnionFs, where the
GetAttr may pickup the size from before the write.
parent 320886f5
...@@ -51,9 +51,8 @@ type FileSystem interface { ...@@ -51,9 +51,8 @@ type FileSystem interface {
Open(name string, flags uint32) (file File, code Status) Open(name string, flags uint32) (file File, code Status)
Create(name string, flags uint32, mode uint32) (file File, code Status) Create(name string, flags uint32, mode uint32) (file File, code Status)
// Release() gets called after File.Release() on a file opened // Flush() gets called as a file opened for read/write.
// as writable. Flush(name string) Status
Release(name string)
// Directory handling // Directory handling
OpenDir(name string) (stream chan DirEntry, code Status) OpenDir(name string) (stream chan DirEntry, code Status)
......
...@@ -146,7 +146,7 @@ func (me *DefaultFile) Write(*WriteIn, []byte) (uint32, Status) { ...@@ -146,7 +146,7 @@ func (me *DefaultFile) Write(*WriteIn, []byte) (uint32, Status) {
} }
func (me *DefaultFile) Flush() Status { func (me *DefaultFile) Flush() Status {
return ENOSYS return OK
} }
func (me *DefaultFile) Release() { func (me *DefaultFile) Release() {
...@@ -252,7 +252,8 @@ func (me *DefaultFileSystem) Open(name string, flags uint32) (file File, code St ...@@ -252,7 +252,8 @@ func (me *DefaultFileSystem) Open(name string, flags uint32) (file File, code St
return nil, ENOSYS return nil, ENOSYS
} }
func (me *DefaultFileSystem) Release(name string) { func (me *DefaultFileSystem) Flush(name string) Status {
return OK
} }
func (me *DefaultFileSystem) OpenDir(name string) (stream chan DirEntry, status Status) { func (me *DefaultFileSystem) OpenDir(name string) (stream chan DirEntry, status Status) {
......
...@@ -198,6 +198,7 @@ type FileSystemConnector struct { ...@@ -198,6 +198,7 @@ type FileSystemConnector struct {
type fileBridge struct { type fileBridge struct {
*mountData *mountData
*inode *inode
Flags uint32
Iface interface{} Iface interface{}
} }
...@@ -226,7 +227,7 @@ func (me *FileSystemConnector) unregisterFile(node *inode, handle uint64) (inter ...@@ -226,7 +227,7 @@ func (me *FileSystemConnector) unregisterFile(node *inode, handle uint64) (inter
return b.Iface return b.Iface
} }
func (me *FileSystemConnector) registerFile(node *inode, mount *mountData, f interface{}) uint64 { func (me *FileSystemConnector) registerFile(node *inode, mount *mountData, f interface{}, flags uint32) uint64 {
me.fileLock.Lock() me.fileLock.Lock()
defer me.fileLock.Unlock() defer me.fileLock.Unlock()
...@@ -234,6 +235,7 @@ func (me *FileSystemConnector) registerFile(node *inode, mount *mountData, f int ...@@ -234,6 +235,7 @@ func (me *FileSystemConnector) registerFile(node *inode, mount *mountData, f int
Iface: f, Iface: f,
inode: node, inode: node,
mountData: mount, mountData: mount,
Flags: flags,
} }
h := uint64(uintptr(unsafe.Pointer(b))) h := uint64(uintptr(unsafe.Pointer(b)))
_, ok := me.openFiles[h] _, ok := me.openFiles[h]
...@@ -246,9 +248,9 @@ func (me *FileSystemConnector) registerFile(node *inode, mount *mountData, f int ...@@ -246,9 +248,9 @@ func (me *FileSystemConnector) registerFile(node *inode, mount *mountData, f int
return h return h
} }
func (me *FileSystemConnector) decodeFileHandle(h uint64) (interface{}, *mountData, *inode) { func (me *FileSystemConnector) decodeFileHandle(h uint64) (*fileBridge) {
b := (*fileBridge)(unsafe.Pointer(uintptr(h))) b := (*fileBridge)(unsafe.Pointer(uintptr(h)))
return b.Iface, b.mountData, b.inode return b
} }
type rawDir interface { type rawDir interface {
...@@ -256,14 +258,14 @@ type rawDir interface { ...@@ -256,14 +258,14 @@ type rawDir interface {
Release() Release()
} }
func (me *FileSystemConnector) getDir(h uint64) (rawDir, *mountData, *inode) { func (me *FileSystemConnector) getDir(h uint64) (dir rawDir, bridge *fileBridge) {
f, m, n := me.decodeFileHandle(h) b := me.decodeFileHandle(h)
return f.(rawDir), m, n return b.Iface.(rawDir), b
} }
func (me *FileSystemConnector) getFile(h uint64) (File, *mountData, *inode) { func (me *FileSystemConnector) getFile(h uint64) (file File, bridge *fileBridge) {
f, m, n := me.decodeFileHandle(h) b := me.decodeFileHandle(h)
return f.(File), m, n return b.Iface.(File), b
} }
func (me *FileSystemConnector) verify() { func (me *FileSystemConnector) verify() {
...@@ -524,9 +526,11 @@ func (me *FileSystemConnector) GetPath(nodeid uint64) (path string, mount *mount ...@@ -524,9 +526,11 @@ func (me *FileSystemConnector) GetPath(nodeid uint64) (path string, mount *mount
return p, m, n return p, m, n
} }
func (me *FileSystemConnector) getOpenFileData(nodeid uint64, fh uint64) (f File, m *mountData, p string) { func (me *FileSystemConnector) getOpenFileData(nodeid uint64, fh uint64) (f File, m *mountData, p string) {
if fh != 0 { if fh != 0 {
f, m, _ = me.getFile(fh) var bridge *fileBridge
f, bridge = me.getFile(fh)
m = bridge.mountData
} }
me.treeLock.RLock() me.treeLock.RLock()
defer me.treeLock.RUnlock() defer me.treeLock.RUnlock()
......
...@@ -76,7 +76,7 @@ func (me *FileSystemConnector) Forget(h *InHeader, input *ForgetIn) { ...@@ -76,7 +76,7 @@ func (me *FileSystemConnector) Forget(h *InHeader, input *ForgetIn) {
func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out *AttrOut, code Status) { func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out *AttrOut, code Status) {
if input.Flags&FUSE_GETATTR_FH != 0 { if input.Flags&FUSE_GETATTR_FH != 0 {
f, mount, _ := me.getFile(input.Fh) f, bridge := me.getFile(input.Fh)
fi, err := f.GetAttr() fi, err := f.GetAttr()
if err != OK && err != ENOSYS { if err != OK && err != ENOSYS {
return nil, err return nil, err
...@@ -86,7 +86,7 @@ func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out ...@@ -86,7 +86,7 @@ func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out
out = &AttrOut{} out = &AttrOut{}
CopyFileInfo(fi, &out.Attr) CopyFileInfo(fi, &out.Attr)
out.Attr.Ino = header.NodeId out.Attr.Ino = header.NodeId
SplitNs(mount.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec) SplitNs(bridge.mountData.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
return out, OK return out, OK
} }
...@@ -124,13 +124,13 @@ func (me *FileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (flags u ...@@ -124,13 +124,13 @@ func (me *FileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (flags u
de := &Dir{ de := &Dir{
stream: stream, stream: stream,
} }
h := me.registerFile(node, mount, de) h := me.registerFile(node, mount, de, input.Flags)
return 0, h, OK return 0, h, OK
} }
func (me *FileSystemConnector) ReadDir(header *InHeader, input *ReadIn) (*DirEntryList, Status) { func (me *FileSystemConnector) ReadDir(header *InHeader, input *ReadIn) (*DirEntryList, Status) {
d, _, _ := me.getDir(input.Fh) d, _ := me.getDir(input.Fh)
de, code := d.ReadDir(input) de, code := d.ReadDir(input)
if code != OK { if code != OK {
return nil, code return nil, code
...@@ -149,7 +149,7 @@ func (me *FileSystemConnector) Open(header *InHeader, input *OpenIn) (flags uint ...@@ -149,7 +149,7 @@ func (me *FileSystemConnector) Open(header *InHeader, input *OpenIn) (flags uint
if err != OK { if err != OK {
return 0, 0, err return 0, 0, err
} }
h := me.registerFile(node, mount, f) h := me.registerFile(node, mount, f, input.Flags)
return 0, h, OK return 0, h, OK
} }
...@@ -367,30 +367,35 @@ func (me *FileSystemConnector) Create(header *InHeader, input *CreateIn, name st ...@@ -367,30 +367,35 @@ func (me *FileSystemConnector) Create(header *InHeader, input *CreateIn, name st
} }
out, code, inode := me.internalLookupWithNode(parent, name, 1) out, code, inode := me.internalLookupWithNode(parent, name, 1)
return 0, me.registerFile(inode, mount, f), out, code return 0, me.registerFile(inode, mount, f, input.Flags), out, code
} }
func (me *FileSystemConnector) Release(header *InHeader, input *ReleaseIn) { func (me *FileSystemConnector) Release(header *InHeader, input *ReleaseIn) {
node := me.getInodeData(header.NodeId) node := me.getInodeData(header.NodeId)
f := me.unregisterFile(node, input.Fh).(File) f := me.unregisterFile(node, input.Fh).(File)
f.Release() f.Release()
}
if input.Flags & O_ANYWRITE != 0 { func (me *FileSystemConnector) Flush(input *FlushIn) Status {
f, b := me.getFile(input.Fh)
code := f.Flush()
if code.Ok() && b.Flags & O_ANYWRITE != 0 {
// We only signal releases to the FS if the // We only signal releases to the FS if the
// open could have changed things. // open could have changed things.
var path string var path string
var mount *mountData var mount *mountData
me.treeLock.RLock() me.treeLock.RLock()
if node.Parent != nil { if b.inode.Parent != nil {
path, mount = node.GetPath() path, mount = b.inode.GetPath()
} }
me.treeLock.RUnlock() me.treeLock.RUnlock()
if mount != nil { if mount != nil {
mount.fs.Release(path) code = mount.fs.Flush(path)
} }
} }
me.considerDropInode(node) return code
} }
func (me *FileSystemConnector) ReleaseDir(header *InHeader, input *ReleaseIn) { func (me *FileSystemConnector) ReleaseDir(header *InHeader, input *ReleaseIn) {
...@@ -459,25 +464,25 @@ func (me *FileSystemConnector) fileDebug(fh uint64, n *inode) { ...@@ -459,25 +464,25 @@ func (me *FileSystemConnector) fileDebug(fh uint64, n *inode) {
} }
func (me *FileSystemConnector) Write(input *WriteIn, data []byte) (written uint32, code Status) { func (me *FileSystemConnector) Write(input *WriteIn, data []byte) (written uint32, code Status) {
f, _, n := me.getFile(input.Fh) f, b := me.getFile(input.Fh)
if me.Debug { if me.Debug {
me.fileDebug(input.Fh, n) me.fileDebug(input.Fh, b.inode)
} }
return f.Write(input, data) return f.Write(input, data)
} }
func (me *FileSystemConnector) Read(input *ReadIn, bp BufferPool) ([]byte, Status) { func (me *FileSystemConnector) Read(input *ReadIn, bp BufferPool) ([]byte, Status) {
f, _, n := me.getFile(input.Fh) f, b := me.getFile(input.Fh)
if me.Debug { if me.Debug {
me.fileDebug(input.Fh, n) me.fileDebug(input.Fh, b.inode)
} }
return f.Read(input, bp) return f.Read(input, bp)
} }
func (me *FileSystemConnector) Ioctl(header *InHeader, input *IoctlIn) (out *IoctlOut, data []byte, code Status) { func (me *FileSystemConnector) Ioctl(header *InHeader, input *IoctlIn) (out *IoctlOut, data []byte, code Status) {
f, _, n := me.getFile(input.Fh) f, b := me.getFile(input.Fh)
if me.Debug { if me.Debug {
me.fileDebug(input.Fh, n) me.fileDebug(input.Fh, b.inode)
} }
return f.Ioctl(input) return f.Ioctl(input)
} }
......
...@@ -717,10 +717,11 @@ func (me *UnionFs) Open(name string, flags uint32) (fuseFile fuse.File, status f ...@@ -717,10 +717,11 @@ func (me *UnionFs) Open(name string, flags uint32) (fuseFile fuse.File, status f
return me.fileSystems[r.branch].Open(name, uint32(flags)) return me.fileSystems[r.branch].Open(name, uint32(flags))
} }
func (me *UnionFs) Release(name string) { func (me *UnionFs) Flush(name string) fuse.Status {
// Refresh timestamps and size field. // Refresh timestamps and size field.
me.branchCache.DropEntry(name) me.branchCache.DropEntry(name)
me.getBranch(name) me.getBranch(name)
return fuse.OK
} }
func (me *UnionFs) Roots() (result []string) { func (me *UnionFs) Roots() (result []string) {
......
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