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

Handle setattr and getattr on open files too.

parent f7de38df
......@@ -3,7 +3,6 @@ package fuse
import (
"fmt"
"log"
"json"
"os"
"syscall"
"testing"
......@@ -152,28 +151,25 @@ func TestFSetAttr(t *testing.T) {
if state.KernelSettings().Flags&CAP_FILE_OPS == 0 {
log.Println("Mount does not support file operations")
m, _ := json.Marshal(state.KernelSettings())
log.Println("Kernel settings: ", string(m))
return
}
_, err = os.Lstat(fn)
_, err = f.Stat()
CheckSuccess(err)
if !fs.file.GetAttrCalled {
t.Error("Should have called File.GetAttr")
}
err = os.Chmod(fn, 024)
err = f.Chmod(024)
CheckSuccess(err)
if fs.file.FileInfo.Mode&07777 != 024 {
t.Error("chmod")
}
err = os.Chtimes(fn, 100, 101)
err = os.Chtimes(fn, 100e3, 101e3)
CheckSuccess(err)
if fs.file.FileInfo.Atime_ns != 100 || fs.file.FileInfo.Atime_ns != 101 {
t.Error("Utimens")
if fs.file.FileInfo.Atime_ns != 100e3 || fs.file.FileInfo.Mtime_ns != 101e3 {
t.Error("Utimens", fs.file.FileInfo)
}
// TODO - test chown if run as root.
......
......@@ -648,8 +648,8 @@ func (me *FileSystemConnector) unsafeUnmountNode(node *inode) {
unmounted.fs.Unmount()
}
func (me *FileSystemConnector) getOpenFileData(nodeid uint64, fh uint64) (f File, m *fileSystemMount, p string) {
node := me.getInodeData(nodeid)
func (me *FileSystemConnector) getOpenFileData(nodeid uint64, fh uint64) (f File, m *fileSystemMount, p string, node *inode) {
node = me.getInodeData(nodeid)
node.treeLock.RLock()
defer node.treeLock.RUnlock()
......@@ -666,6 +666,14 @@ func (me *FileSystemConnector) getOpenFileData(nodeid uint64, fh uint64) (f File
m = mount
p = path
}
if f == nil {
node.OpenFilesMutex.Lock()
defer node.OpenFilesMutex.Unlock()
if len(node.OpenFiles) > 0 {
f = node.OpenFiles[0].file
}
}
return
}
......
......@@ -98,9 +98,18 @@ func (me *FileSystemConnector) Forget(h *InHeader, input *ForgetIn) {
}
func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out *AttrOut, code Status) {
fh := uint64(0)
if input.Flags&FUSE_GETATTR_FH != 0 {
opened := me.getOpenedFile(input.Fh)
fi, err := opened.file.GetAttr()
fh = input.Fh
}
f, mount, fullPath, node := me.getOpenFileData(header.NodeId, fh)
if mount == nil && f == nil {
return nil, ENOENT
}
if f != nil {
fi, err := f.GetAttr()
if err != OK && err != ENOSYS {
return nil, err
}
......@@ -109,13 +118,12 @@ func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out
out = &AttrOut{}
CopyFileInfo(fi, &out.Attr)
out.Attr.Ino = header.NodeId
SplitNs(opened.fileSystemMount.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
SplitNs(node.mount.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
return out, OK
}
}
fullPath, mount, _ := me.GetPath(header.NodeId)
if mount == nil {
return nil, ENOENT
}
......@@ -192,7 +200,7 @@ func (me *FileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn) (out
getAttrIn.Flags |= FUSE_GETATTR_FH
}
f, mount, fullPath := me.getOpenFileData(header.NodeId, fh)
f, mount, fullPath, _ := me.getOpenFileData(header.NodeId, fh)
if mount == nil {
return nil, ENOENT
}
......
......@@ -807,3 +807,23 @@ func TestDisappearing(t *testing.T) {
t.Fatal("write should succeed", err)
}
}
func TestDeletedGetAttr(t *testing.T) {
t.Log("TestDeletedGetAttr")
wd, clean := setupUfs(t)
defer clean()
err := ioutil.WriteFile(wd+"/ro/file", []byte("blabla"), 0644)
CheckSuccess(err)
f, err := os.Open(wd + "/mount/file")
CheckSuccess(err)
defer f.Close()
err = os.Remove(wd+"/mount/file")
CheckSuccess(err)
if fi, err := f.Stat(); err != nil || !fi.IsRegular() {
t.Fatalf("stat returned error or non-file: %v %v", err, fi)
}
}
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