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 \
defaultraw.go \
direntry.go\
files.go \
fsinode.go \
fuse.go \
handle.go \
latencymap.go \
......
......@@ -3,9 +3,11 @@ package fuse
import (
"bytes"
"io/ioutil"
"log"
"os"
"testing"
)
var _ = log.Println
type cacheFs struct {
*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() {
_OP_READ: 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_FORGET: func(ptr unsafe.Pointer) interface{} { return (*ForgetIn)(ptr) },
} {
operationHandlers[op].DecodeIn = f
}
......
This diff is collapsed.
......@@ -25,14 +25,40 @@ func NewFileSystemConnector(fs FileSystem, opts *FileSystemOptions) (me *FileSys
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 {
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
}
......@@ -44,9 +70,6 @@ func (me *fileSystemMount) setOwner(attr *Attr) {
func (me *FileSystemConnector) Lookup(header *InHeader, name string) (out *EntryOut, status Status) {
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)
}
......@@ -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) {
fullPath, mount, isMountPoint := me.lookupMount(parent, name, lookupCount)
mount := me.lookupMount(parent, name, lookupCount)
isMountPoint := (mount != nil)
fullPath := ""
if isMountPoint {
node = mount.mountInode
} else {
fullPath, mount = parent.GetPath()
fullPath, mount = parent.fsInode.GetPath()
fullPath = filepath.Join(fullPath, name)
}
if mount == nil {
fmt.Println(me.rootNode)
fmt.Println(me.rootNode.mountPoint)
timeout := me.rootNode.mountPoint.options.NegativeTimeout
if timeout > 0 {
return NegativeEntry(timeout), OK, nil
......@@ -166,7 +189,7 @@ func (me *FileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (flags u
}
de := &connectorDir{
extra: node.GetMountDirEntries(),
extra: node.getMountDirEntries(),
stream: stream,
}
de.extra = append(de.extra, DirEntry{S_IFDIR, "."}, DirEntry{S_IFDIR, ".."})
......@@ -363,7 +386,7 @@ func (me *FileSystemConnector) Rename(header *InHeader, input *RenameIn, oldName
if mount == nil || oldMount == nil {
return ENOENT
}
_, _, isMountPoint := me.lookupMount(oldParent, oldName, 0)
isMountPoint := me.lookupMount(oldParent, oldName, 0) != nil
if isMountPoint {
return EBUSY
}
......@@ -443,7 +466,7 @@ func (me *FileSystemConnector) Flush(input *FlushIn) Status {
// open could have changed things.
var path string
var mount *fileSystemMount
path, mount = opened.inode.GetPath()
path, mount = opened.inode.fsInode.GetPath()
if mount != nil {
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