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 {
Open(name string, flags 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
// as writable.
Release(name string)
// Flush() gets called as a file opened for read/write.
Flush(name string) Status
// Directory handling
OpenDir(name string) (stream chan DirEntry, code Status)
......
......@@ -146,7 +146,7 @@ func (me *DefaultFile) Write(*WriteIn, []byte) (uint32, Status) {
}
func (me *DefaultFile) Flush() Status {
return ENOSYS
return OK
}
func (me *DefaultFile) Release() {
......@@ -252,7 +252,8 @@ func (me *DefaultFileSystem) Open(name string, flags uint32) (file File, code St
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) {
......
......@@ -198,6 +198,7 @@ type FileSystemConnector struct {
type fileBridge struct {
*mountData
*inode
Flags uint32
Iface interface{}
}
......@@ -226,7 +227,7 @@ func (me *FileSystemConnector) unregisterFile(node *inode, handle uint64) (inter
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()
defer me.fileLock.Unlock()
......@@ -234,6 +235,7 @@ func (me *FileSystemConnector) registerFile(node *inode, mount *mountData, f int
Iface: f,
inode: node,
mountData: mount,
Flags: flags,
}
h := uint64(uintptr(unsafe.Pointer(b)))
_, ok := me.openFiles[h]
......@@ -246,9 +248,9 @@ func (me *FileSystemConnector) registerFile(node *inode, mount *mountData, f int
return h
}
func (me *FileSystemConnector) decodeFileHandle(h uint64) (interface{}, *mountData, *inode) {
func (me *FileSystemConnector) decodeFileHandle(h uint64) (*fileBridge) {
b := (*fileBridge)(unsafe.Pointer(uintptr(h)))
return b.Iface, b.mountData, b.inode
return b
}
type rawDir interface {
......@@ -256,14 +258,14 @@ type rawDir interface {
Release()
}
func (me *FileSystemConnector) getDir(h uint64) (rawDir, *mountData, *inode) {
f, m, n := me.decodeFileHandle(h)
return f.(rawDir), m, n
func (me *FileSystemConnector) getDir(h uint64) (dir rawDir, bridge *fileBridge) {
b := me.decodeFileHandle(h)
return b.Iface.(rawDir), b
}
func (me *FileSystemConnector) getFile(h uint64) (File, *mountData, *inode) {
f, m, n := me.decodeFileHandle(h)
return f.(File), m, n
func (me *FileSystemConnector) getFile(h uint64) (file File, bridge *fileBridge) {
b := me.decodeFileHandle(h)
return b.Iface.(File), b
}
func (me *FileSystemConnector) verify() {
......@@ -524,9 +526,11 @@ func (me *FileSystemConnector) GetPath(nodeid uint64) (path string, mount *mount
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 {
f, m, _ = me.getFile(fh)
var bridge *fileBridge
f, bridge = me.getFile(fh)
m = bridge.mountData
}
me.treeLock.RLock()
defer me.treeLock.RUnlock()
......
......@@ -76,7 +76,7 @@ func (me *FileSystemConnector) Forget(h *InHeader, input *ForgetIn) {
func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out *AttrOut, code Status) {
if input.Flags&FUSE_GETATTR_FH != 0 {
f, mount, _ := me.getFile(input.Fh)
f, bridge := me.getFile(input.Fh)
fi, err := f.GetAttr()
if err != OK && err != ENOSYS {
return nil, err
......@@ -86,7 +86,7 @@ func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out
out = &AttrOut{}
CopyFileInfo(fi, &out.Attr)
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
}
......@@ -124,13 +124,13 @@ func (me *FileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (flags u
de := &Dir{
stream: stream,
}
h := me.registerFile(node, mount, de)
h := me.registerFile(node, mount, de, input.Flags)
return 0, h, OK
}
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)
if code != OK {
return nil, code
......@@ -149,7 +149,7 @@ func (me *FileSystemConnector) Open(header *InHeader, input *OpenIn) (flags uint
if err != OK {
return 0, 0, err
}
h := me.registerFile(node, mount, f)
h := me.registerFile(node, mount, f, input.Flags)
return 0, h, OK
}
......@@ -367,30 +367,35 @@ func (me *FileSystemConnector) Create(header *InHeader, input *CreateIn, name st
}
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) {
node := me.getInodeData(header.NodeId)
f := me.unregisterFile(node, input.Fh).(File)
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
// open could have changed things.
var path string
var mount *mountData
me.treeLock.RLock()
if node.Parent != nil {
path, mount = node.GetPath()
if b.inode.Parent != nil {
path, mount = b.inode.GetPath()
}
me.treeLock.RUnlock()
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) {
......@@ -459,25 +464,25 @@ func (me *FileSystemConnector) fileDebug(fh uint64, n *inode) {
}
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 {
me.fileDebug(input.Fh, n)
me.fileDebug(input.Fh, b.inode)
}
return f.Write(input, data)
}
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 {
me.fileDebug(input.Fh, n)
me.fileDebug(input.Fh, b.inode)
}
return f.Read(input, bp)
}
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 {
me.fileDebug(input.Fh, n)
me.fileDebug(input.Fh, b.inode)
}
return f.Ioctl(input)
}
......
......@@ -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))
}
func (me *UnionFs) Release(name string) {
func (me *UnionFs) Flush(name string) fuse.Status {
// Refresh timestamps and size field.
me.branchCache.DropEntry(name)
me.getBranch(name)
return fuse.OK
}
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