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