Commit a236359c authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Split out the path behavior into fsInode.

Only fsInode maintains Parent links. This prepares for inserting
a layer between RawFileSystem and FileSystem, which can define
filesystems in terms of inodes.
parent cd97de67
...@@ -11,6 +11,7 @@ MANUAL_GOFILES=api.go \ ...@@ -11,6 +11,7 @@ MANUAL_GOFILES=api.go \
defaultraw.go \ defaultraw.go \
direntry.go\ direntry.go\
files.go \ files.go \
fsinode.go \
fuse.go \ fuse.go \
handle.go \ handle.go \
latencymap.go \ latencymap.go \
......
...@@ -3,9 +3,11 @@ package fuse ...@@ -3,9 +3,11 @@ package fuse
import ( import (
"bytes" "bytes"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"testing" "testing"
) )
var _ = log.Println
type cacheFs struct { type cacheFs struct {
*LoopbackFileSystem *LoopbackFileSystem
......
package fuse
import (
"log"
)
var _ = log.Println
// This is a combination of dentry (entry in the file/directory and
// the inode). This structure is used to implement glue for FSes where
// there is a one-to-one mapping of paths and inodes, ie. FSes that
// disallow hardlinks.
type fsInode struct {
*inode
Name string
// This is nil at the root of the mount.
Parent *fsInode
}
// GetPath returns the path relative to the mount governing this
// inode. It returns nil for mount if the file was deleted or the
// filesystem unmounted. This will take the treeLock for the mount,
// so it can not be used in internal methods.
func (me *fsInode) GetPath() (path string, mount *fileSystemMount) {
me.inode.treeLock.RLock()
defer me.inode.treeLock.RUnlock()
if me.inode.mount == nil {
// Node from unmounted file system.
return ".deleted", nil
}
rev_components := make([]string, 0, 10)
n := me
for ; n.Parent != nil; n = n.Parent {
rev_components = append(rev_components, n.Name)
}
if n.mountPoint == nil {
return ".deleted", nil
}
return ReverseJoin(rev_components, "/"), n.mountPoint
}
func (me *fsInode) addChild(name string, ch *fsInode) {
if ch.inode.mountPoint == nil {
ch.Parent = me
}
ch.Name = name
}
func (me *fsInode) rmChild(name string, ch *fsInode) {
ch.Name = ".deleted"
ch.Parent = nil
}
...@@ -503,6 +503,7 @@ func init() { ...@@ -503,6 +503,7 @@ func init() {
_OP_READ: func(ptr unsafe.Pointer) interface{} { return (*ReadIn)(ptr) }, _OP_READ: func(ptr unsafe.Pointer) interface{} { return (*ReadIn)(ptr) },
_OP_READDIR: func(ptr unsafe.Pointer) interface{} { return (*ReadIn)(ptr) }, _OP_READDIR: func(ptr unsafe.Pointer) interface{} { return (*ReadIn)(ptr) },
_OP_ACCESS: func(ptr unsafe.Pointer) interface{} { return (*AccessIn)(ptr) }, _OP_ACCESS: func(ptr unsafe.Pointer) interface{} { return (*AccessIn)(ptr) },
_OP_FORGET: func(ptr unsafe.Pointer) interface{} { return (*ForgetIn)(ptr) },
} { } {
operationHandlers[op].DecodeIn = f operationHandlers[op].DecodeIn = f
} }
......
This diff is collapsed.
...@@ -25,14 +25,40 @@ func NewFileSystemConnector(fs FileSystem, opts *FileSystemOptions) (me *FileSys ...@@ -25,14 +25,40 @@ func NewFileSystemConnector(fs FileSystem, opts *FileSystemOptions) (me *FileSys
return me return me
} }
func (me *FileSystemConnector) GetPath(nodeid uint64) (path string, mount *fileSystemMount, node *inode) {
n := me.getInodeData(nodeid)
p, m := n.GetPath() // Returns an openedFile for the given inode.
func (me *FileSystemConnector) getOpenFileData(nodeid uint64, fh uint64) (opened *openedFile, m *fileSystemMount, p string, node *inode) {
node = me.getInodeData(nodeid)
if fh != 0 {
opened = me.getOpenedFile(fh)
}
path, mount := node.fsInode.GetPath()
if me.Debug { if me.Debug {
log.Printf("Node %v = '%s'", nodeid, n.GetFullPath()) log.Printf("Node %v = '%s'", nodeid, path)
}
// If the file was deleted, GetPath() will return nil.
if mount != nil {
m = mount
p = path
}
if opened == nil {
node.OpenFilesMutex.Lock()
defer node.OpenFilesMutex.Unlock()
for _, f := range node.OpenFiles {
if f.OpenFlags & O_ANYWRITE != 0 || opened == nil {
opened = f
}
} }
}
return
}
func (me *FileSystemConnector) GetPath(nodeid uint64) (path string, mount *fileSystemMount, node *inode) {
n := me.getInodeData(nodeid)
p, m := n.fsInode.GetPath()
return p, m, n return p, m, n
} }
...@@ -44,9 +70,6 @@ func (me *fileSystemMount) setOwner(attr *Attr) { ...@@ -44,9 +70,6 @@ func (me *fileSystemMount) setOwner(attr *Attr) {
func (me *FileSystemConnector) Lookup(header *InHeader, name string) (out *EntryOut, status Status) { func (me *FileSystemConnector) Lookup(header *InHeader, name string) (out *EntryOut, status Status) {
parent := me.getInodeData(header.NodeId) parent := me.getInodeData(header.NodeId)
if me.Debug {
log.Printf("Node %v = '%s'", parent.NodeId, parent.GetFullPath())
}
return me.internalLookup(parent, name, 1, &header.Context) return me.internalLookup(parent, name, 1, &header.Context)
} }
...@@ -56,17 +79,17 @@ func (me *FileSystemConnector) internalLookup(parent *inode, name string, lookup ...@@ -56,17 +79,17 @@ func (me *FileSystemConnector) internalLookup(parent *inode, name string, lookup
} }
func (me *FileSystemConnector) internalLookupWithNode(parent *inode, name string, lookupCount int, context *Context) (out *EntryOut, status Status, node *inode) { func (me *FileSystemConnector) internalLookupWithNode(parent *inode, name string, lookupCount int, context *Context) (out *EntryOut, status Status, node *inode) {
fullPath, mount, isMountPoint := me.lookupMount(parent, name, lookupCount) mount := me.lookupMount(parent, name, lookupCount)
isMountPoint := (mount != nil)
fullPath := ""
if isMountPoint { if isMountPoint {
node = mount.mountInode node = mount.mountInode
} else { } else {
fullPath, mount = parent.GetPath() fullPath, mount = parent.fsInode.GetPath()
fullPath = filepath.Join(fullPath, name) fullPath = filepath.Join(fullPath, name)
} }
if mount == nil { if mount == nil {
fmt.Println(me.rootNode)
fmt.Println(me.rootNode.mountPoint)
timeout := me.rootNode.mountPoint.options.NegativeTimeout timeout := me.rootNode.mountPoint.options.NegativeTimeout
if timeout > 0 { if timeout > 0 {
return NegativeEntry(timeout), OK, nil return NegativeEntry(timeout), OK, nil
...@@ -166,7 +189,7 @@ func (me *FileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (flags u ...@@ -166,7 +189,7 @@ func (me *FileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (flags u
} }
de := &connectorDir{ de := &connectorDir{
extra: node.GetMountDirEntries(), extra: node.getMountDirEntries(),
stream: stream, stream: stream,
} }
de.extra = append(de.extra, DirEntry{S_IFDIR, "."}, DirEntry{S_IFDIR, ".."}) de.extra = append(de.extra, DirEntry{S_IFDIR, "."}, DirEntry{S_IFDIR, ".."})
...@@ -363,7 +386,7 @@ func (me *FileSystemConnector) Rename(header *InHeader, input *RenameIn, oldName ...@@ -363,7 +386,7 @@ func (me *FileSystemConnector) Rename(header *InHeader, input *RenameIn, oldName
if mount == nil || oldMount == nil { if mount == nil || oldMount == nil {
return ENOENT return ENOENT
} }
_, _, isMountPoint := me.lookupMount(oldParent, oldName, 0) isMountPoint := me.lookupMount(oldParent, oldName, 0) != nil
if isMountPoint { if isMountPoint {
return EBUSY return EBUSY
} }
...@@ -443,7 +466,7 @@ func (me *FileSystemConnector) Flush(input *FlushIn) Status { ...@@ -443,7 +466,7 @@ func (me *FileSystemConnector) Flush(input *FlushIn) Status {
// open could have changed things. // open could have changed things.
var path string var path string
var mount *fileSystemMount var mount *fileSystemMount
path, mount = opened.inode.GetPath() path, mount = opened.inode.fsInode.GetPath()
if mount != nil { if mount != nil {
code = mount.fs.Flush(path) code = mount.fs.Flush(path)
......
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