Commit 94f9b193 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Implement entry notify.

parent 25145ebb
......@@ -187,4 +187,5 @@ type DefaultRawFileSystem struct{}
// kernel error.
type RawFsInit struct {
InodeNotify func(*NotifyInvalInodeOut) Status
EntryNotify func(parent uint64, name string) Status
}
......@@ -68,6 +68,9 @@ func (me *MountState) Mount(mountPoint string, opts *MountOptions) os.Error {
InodeNotify: func(n *NotifyInvalInodeOut) Status {
return me.writeInodeNotify(n)
},
EntryNotify: func(parent uint64, n string) Status {
return me.writeEntryNotify(parent, n)
},
}
me.fileSystem.Init(&initParams)
me.mountPoint = mp
......@@ -275,3 +278,33 @@ func (me *MountState) writeInodeNotify(entry *NotifyInvalInodeOut) Status {
}
return result
}
func (me *MountState) writeEntryNotify(parent uint64, name string) Status {
req := request{
inHeader: &InHeader{
opcode: _OP_NOTIFY_ENTRY,
},
handler: operationHandlers[_OP_NOTIFY_ENTRY],
status: NOTIFY_INVAL_ENTRY,
}
entry := &NotifyInvalEntryOut{
Parent: parent,
NameLen: uint32(len(name)),
}
// Many versions of FUSE generate stacktraces if the
// terminating null byte is missing.
nameBytes := []byte(name + "\000")
req.outData = unsafe.Pointer(entry)
req.flatData = nameBytes
req.serialize()
log.Println([][]byte{req.outHeaderBytes, req.flatData})
result := me.write(&req)
if me.Debug {
log.Printf("ENTRY_NOTIFY: %v", result)
}
return result
}
......@@ -15,6 +15,9 @@ type NotifyFs struct {
}
func (me *NotifyFs) GetAttr(name string) (*os.FileInfo, Status) {
if name == "" {
return &os.FileInfo{Mode: S_IFDIR | 0755}, OK
}
if name == "file" || (name == "dir/file" && me.exist) {
return &os.FileInfo{Mode: S_IFREG | 0644, Size: me.size}, OK
}
......@@ -119,3 +122,33 @@ func TestInodeNotifyRemoval(t *testing.T) {
t.Error("should have been removed", fi)
}
}
func TestEntryNotify(t *testing.T) {
test := NewNotifyTest()
defer test.Clean()
dir := test.dir
test.fs.size = 42
test.fs.exist = false
fn := dir + "/dir/file"
fi, _ := os.Lstat(fn)
if fi != nil {
t.Errorf("File should not exist, %#v", fi)
}
test.fs.exist = true
fi, _ = os.Lstat(fn)
if fi != nil {
t.Errorf("negative entry should have been cached: %#v", fi)
}
code := test.connector.EntryNotify("dir", "file")
if !code.Ok() {
t.Errorf("EntryNotify returns error: %v", code)
}
fi, err := os.Lstat(fn)
CheckSuccess(err)
}
......@@ -460,6 +460,10 @@ func (me *FileSystemConnector) unlinkUpdate(parent *inode, name string) {
// Walk the file system starting from the root. Will return nil if
// node not found.
func (me *FileSystemConnector) findInode(fullPath string) *inode {
if fullPath == "" {
return me.rootNode
}
fullPath = strings.TrimLeft(filepath.Clean(fullPath), "/")
comps := strings.Split(fullPath, "/")
......@@ -667,3 +671,13 @@ func (me *FileSystemConnector) FileNotify(path string, off int64, length int64)
}
return me.fsInit.InodeNotify(&out)
}
func (me *FileSystemConnector) EntryNotify(dir string, name string) Status {
node := me.findInode(dir)
if node == nil {
log.Printf("dir not found, %q",dir)
return ENOENT
}
return me.fsInit.EntryNotify(node.NodeId, name)
}
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