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
} }
......
...@@ -114,9 +114,7 @@ func (me *fileSystemMount) registerFileHandle(node *inode, dir rawDir, f File, f ...@@ -114,9 +114,7 @@ func (me *fileSystemMount) registerFileHandle(node *inode, dir rawDir, f File, f
// Tests should set to true. // Tests should set to true.
var paranoia = false var paranoia = false
// The inode is a combination of dentry (entry in the file/directory // The inode reflects the kernel's idea of the inode.
// tree) and inode. We do this, since in the high-level API, each
// files and inodes correspond one-to-one.
type inode struct { type inode struct {
Handled Handled
...@@ -136,9 +134,12 @@ type inode struct { ...@@ -136,9 +134,12 @@ type inode struct {
treeLock *sync.RWMutex treeLock *sync.RWMutex
// All data below is protected by treeLock. // All data below is protected by treeLock.
Name string fsInode *fsInode
Parent *inode
Children map[string]*inode Children map[string]*inode
// Contains directories that function as mounts. The entries
// are duplicated in Children.
Mounts map[string]*fileSystemMount Mounts map[string]*fileSystemMount
LookupCount int LookupCount int
...@@ -151,6 +152,29 @@ type inode struct { ...@@ -151,6 +152,29 @@ type inode struct {
mount *fileSystemMount mount *fileSystemMount
} }
// Must be called with treeLock for the mount held.
func (me *inode) addChild(name string, child *inode) {
if paranoia {
ch := me.Children[name]
if ch != nil {
panic(fmt.Sprintf("Already have an inode with same name: %v: %v", name, ch))
}
}
me.Children[name] = child
me.fsInode.addChild(name, child.fsInode)
}
// Must be called with treeLock for the mount held.
func (me *inode) rmChild(name string) (ch *inode) {
ch = me.Children[name]
if ch != nil {
me.Children[name] = nil, false
me.fsInode.rmChild(name, ch.fsInode)
}
return ch
}
// Can only be called on untouched inodes. // Can only be called on untouched inodes.
func (me *inode) mountFs(fs FileSystem, opts *FileSystemOptions) { func (me *inode) mountFs(fs FileSystem, opts *FileSystemOptions) {
me.mountPoint = &fileSystemMount{ me.mountPoint = &fileSystemMount{
...@@ -193,7 +217,7 @@ func (me *inode) IsDir() bool { ...@@ -193,7 +217,7 @@ func (me *inode) IsDir() bool {
return me.Children != nil return me.Children != nil
} }
func (me *inode) GetMountDirEntries() (out []DirEntry) { func (me *inode) getMountDirEntries() (out []DirEntry) {
me.treeLock.RLock() me.treeLock.RLock()
defer me.treeLock.RUnlock() defer me.treeLock.RUnlock()
...@@ -209,10 +233,6 @@ func (me *inode) GetMountDirEntries() (out []DirEntry) { ...@@ -209,10 +233,6 @@ func (me *inode) GetMountDirEntries() (out []DirEntry) {
const initDirSize = 20 const initDirSize = 20
func (me *inode) verify(cur *fileSystemMount) { func (me *inode) verify(cur *fileSystemMount) {
if !(me.NodeId == FUSE_ROOT_ID || me.LookupCount > 0 || len(me.Children) > 0 || me.mountPoint != nil) {
p, _ := me.GetPath()
panic(fmt.Sprintf("node %v %d should be dead: %v %v", p, me.NodeId, len(me.Children), me.LookupCount))
}
if me.mountPoint != nil { if me.mountPoint != nil {
if me != me.mountPoint.mountInode { if me != me.mountPoint.mountInode {
panic("mountpoint mismatch") panic("mountpoint mismatch")
...@@ -229,91 +249,15 @@ func (me *inode) verify(cur *fileSystemMount) { ...@@ -229,91 +249,15 @@ func (me *inode) verify(cur *fileSystemMount) {
me.mountPoint, name, me.Children)) me.mountPoint, name, me.Children))
} }
} }
for n, ch := range me.Children {
for _, ch := range me.Children {
if ch == nil { if ch == nil {
panic("Found nil child.") panic("Found nil child.")
} }
if ch.Name != n {
panic(fmt.Sprintf("parent/child name corrupted %v %v",
ch.Name, n))
}
if ch.Parent != me {
panic(fmt.Sprintf("parent/child relation corrupted %v %v %v",
ch.Parent, me, ch))
}
ch.verify(cur) ch.verify(cur)
} }
} }
func (me *inode) GetFullPath() (path string) {
rev_components := make([]string, 0, 10)
inode := me
for ; inode != nil; inode = inode.Parent {
rev_components = append(rev_components, inode.Name)
}
return ReverseJoin(rev_components, "/")
}
// 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 *inode) GetPath() (path string, mount *fileSystemMount) {
me.treeLock.RLock()
defer me.treeLock.RUnlock()
if me.mount == nil {
// Node from unmounted file system.
return ".deleted", nil
}
if me.NodeId != FUSE_ROOT_ID && me.Parent == nil {
// Deleted node. Treat as if the filesystem was unmounted.
return ".deleted", nil
}
rev_components := make([]string, 0, 10)
inode := me
for ; inode != nil && inode.mountPoint == nil; inode = inode.Parent {
rev_components = append(rev_components, inode.Name)
}
if inode == nil {
panic(fmt.Sprintf("did not find parent with mount: %v", rev_components))
}
mount = inode.mountPoint
return ReverseJoin(rev_components, "/"), mount
}
// Must be called with treeLock for the mount held.
func (me *inode) setParent(newParent *inode) {
oldParent := me.Parent
if oldParent == newParent {
return
}
if oldParent != nil {
if paranoia {
ch := oldParent.Children[me.Name]
if ch == nil {
panic(fmt.Sprintf("parent has no child named %v", me.Name))
}
}
oldParent.Children[me.Name] = nil, false
me.Parent = nil
}
if newParent != nil {
me.Parent = newParent
if paranoia {
ch := me.Parent.Children[me.Name]
if ch != nil {
panic(fmt.Sprintf("Already have an inode with same name: %v: %v", me.Name, ch))
}
}
me.Parent.Children[me.Name] = me
}
}
func NewFileSystemOptions() *FileSystemOptions { func NewFileSystemOptions() *FileSystemOptions {
return &FileSystemOptions{ return &FileSystemOptions{
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
...@@ -352,6 +296,8 @@ func (me *FileSystemConnector) verify() { ...@@ -352,6 +296,8 @@ func (me *FileSystemConnector) verify() {
func (me *FileSystemConnector) newInode(isDir bool) *inode { func (me *FileSystemConnector) newInode(isDir bool) *inode {
data := new(inode) data := new(inode)
data.NodeId = me.inodeMap.Register(&data.Handled) data.NodeId = me.inodeMap.Register(&data.Handled)
data.fsInode = new(fsInode)
data.fsInode.inode = data
if isDir { if isDir {
data.Children = make(map[string]*inode, initDirSize) data.Children = make(map[string]*inode, initDirSize)
} }
...@@ -368,8 +314,7 @@ func (me *FileSystemConnector) lookupUpdate(parent *inode, name string, isDir bo ...@@ -368,8 +314,7 @@ func (me *FileSystemConnector) lookupUpdate(parent *inode, name string, isDir bo
data, ok := parent.Children[name] data, ok := parent.Children[name]
if !ok { if !ok {
data = me.newInode(isDir) data = me.newInode(isDir)
data.Name = name parent.addChild(name, data)
data.setParent(parent)
data.mount = parent.mount data.mount = parent.mount
data.treeLock = &data.mount.treeLock data.treeLock = &data.mount.treeLock
} }
...@@ -377,11 +322,11 @@ func (me *FileSystemConnector) lookupUpdate(parent *inode, name string, isDir bo ...@@ -377,11 +322,11 @@ func (me *FileSystemConnector) lookupUpdate(parent *inode, name string, isDir bo
return data return data
} }
func (me *FileSystemConnector) lookupMount(parent *inode, name string, lookupCount int) (path string, mount *fileSystemMount, isMount bool) { func (me *FileSystemConnector) lookupMount(parent *inode, name string, lookupCount int) (mount *fileSystemMount) {
parent.treeLock.RLock() parent.treeLock.RLock()
defer parent.treeLock.RUnlock() defer parent.treeLock.RUnlock()
if parent.Mounts == nil { if parent.Mounts == nil {
return "", nil, false return nil
} }
mount, ok := parent.Mounts[name] mount, ok := parent.Mounts[name]
...@@ -389,9 +334,9 @@ func (me *FileSystemConnector) lookupMount(parent *inode, name string, lookupCou ...@@ -389,9 +334,9 @@ func (me *FileSystemConnector) lookupMount(parent *inode, name string, lookupCou
mount.treeLock.Lock() mount.treeLock.Lock()
defer mount.treeLock.Unlock() defer mount.treeLock.Unlock()
mount.mountInode.LookupCount += lookupCount mount.mountInode.LookupCount += lookupCount
return "", mount, true return mount
} }
return "", nil, false return nil
} }
func (me *FileSystemConnector) getInodeData(nodeid uint64) *inode { func (me *FileSystemConnector) getInodeData(nodeid uint64) *inode {
...@@ -406,30 +351,38 @@ func (me *FileSystemConnector) forgetUpdate(nodeId uint64, forgetCount int) { ...@@ -406,30 +351,38 @@ func (me *FileSystemConnector) forgetUpdate(nodeId uint64, forgetCount int) {
node := me.getInodeData(nodeId) node := me.getInodeData(nodeId)
node.treeLock.Lock()
defer node.treeLock.Unlock()
node.LookupCount -= forgetCount node.LookupCount -= forgetCount
me.considerDropInode(node) me.considerDropInode(node)
} }
func (me *FileSystemConnector) considerDropInode(n *inode) { func (me *FileSystemConnector) considerDropInode(n *inode) (drop bool) {
if n.Parent != nil { delChildren := []string{}
n.Parent.treeLock.Lock() for k, v := range n.Children {
defer n.Parent.treeLock.Unlock() if v.mountPoint == nil && me.considerDropInode(v) {
delChildren = append(delChildren, k)
}
} }
if n.Parent == nil || n.Parent.treeLock != n.treeLock { for _, k := range delChildren {
n.treeLock.Lock() ch := n.rmChild(k)
defer n.treeLock.Unlock() if ch == nil {
panic(fmt.Sprintf("trying to del child %q, but not present", k))
}
me.inodeMap.Forget(ch.NodeId)
} }
if len(n.Children) > 0 || n.LookupCount > 0 {
return false
}
if n == me.rootNode || n.mountPoint != nil {
return false
}
n.OpenFilesMutex.Lock() n.OpenFilesMutex.Lock()
defer n.OpenFilesMutex.Unlock() defer n.OpenFilesMutex.Unlock()
dropInode := n.LookupCount <= 0 && len(n.Children) == 0 && return len(n.OpenFiles) == 0
len(n.OpenFiles) <= 0 && n != me.rootNode && n.mountPoint == nil
if dropInode {
n.setParent(nil)
if n != me.rootNode {
me.inodeMap.Forget(n.NodeId)
}
}
} }
func (me *FileSystemConnector) renameUpdate(oldParent *inode, oldName string, newParent *inode, newName string) { func (me *FileSystemConnector) renameUpdate(oldParent *inode, oldName string, newParent *inode, newName string) {
...@@ -440,30 +393,22 @@ func (me *FileSystemConnector) renameUpdate(oldParent *inode, oldName string, ne ...@@ -440,30 +393,22 @@ func (me *FileSystemConnector) renameUpdate(oldParent *inode, oldName string, ne
if oldParent.mount != newParent.mount { if oldParent.mount != newParent.mount {
panic("Cross mount rename") panic("Cross mount rename")
} }
node := oldParent.Children[oldName] node := oldParent.rmChild(oldName)
if node == nil { if node == nil {
panic("Source of rename does not exist") panic("Source of rename does not exist")
} }
newParent.rmChild(newName)
dest := newParent.Children[newName] newParent.addChild(newName, node)
if dest != nil {
dest.setParent(nil)
}
node.setParent(nil)
node.Name = newName
node.setParent(newParent)
} }
func (me *FileSystemConnector) unlinkUpdate(parent *inode, name string) { func (me *FileSystemConnector) unlinkUpdate(parent *inode, name string) {
defer me.verify() defer me.verify()
parent.treeLock.Lock() parent.treeLock.Lock()
defer parent.treeLock.Unlock() defer parent.treeLock.Unlock()
node := parent.Children[name] parent.rmChild(name)
node.setParent(nil)
node.Name = ".deleted"
} }
// Walk the file system starting from the root. Will return nil if // Walk the file system starting from the root. Will return nil if
...@@ -547,17 +492,17 @@ func (me *FileSystemConnector) Mount(mountPoint string, fs FileSystem, opts *Fil ...@@ -547,17 +492,17 @@ func (me *FileSystemConnector) Mount(mountPoint string, fs FileSystem, opts *Fil
} }
node = me.newInode(true) node = me.newInode(true)
node.Name = base
node.setParent(parent)
if opts == nil { if opts == nil {
opts = me.rootNode.mountPoint.options opts = me.rootNode.mountPoint.options
} }
node.mountFs(fs, opts) node.mountFs(fs, opts)
parent.addChild(base, node)
if parent.Mounts == nil { if parent.Mounts == nil {
parent.Mounts = make(map[string]*fileSystemMount) parent.Mounts = make(map[string]*fileSystemMount)
} }
parent.Mounts[node.Name] = node.mountPoint parent.Mounts[base] = node.mountPoint
if me.Debug { if me.Debug {
log.Println("Mount: ", fs, "on dir", mountPoint, log.Println("Mount: ", fs, "on dir", mountPoint,
"parent", parent) "parent", parent)
...@@ -583,15 +528,10 @@ func (me *FileSystemConnector) mountRoot(fs FileSystem, opts *FileSystemOptions) ...@@ -583,15 +528,10 @@ func (me *FileSystemConnector) mountRoot(fs FileSystem, opts *FileSystemOptions)
// //
// EBUSY: there are open files, or submounts below this node. // EBUSY: there are open files, or submounts below this node.
func (me *FileSystemConnector) Unmount(path string) Status { func (me *FileSystemConnector) Unmount(path string) Status {
node := me.findInode(path) dir, name := filepath.Split(path)
if node == nil { parentNode := me.findInode(dir)
log.Println("Could not find mountpoint:", path)
return EINVAL
}
parentNode := node.Parent
if parentNode == nil { if parentNode == nil {
// attempt to unmount root? log.Println("Could not find parent of mountpoint:", path)
return EINVAL return EINVAL
} }
...@@ -599,78 +539,31 @@ func (me *FileSystemConnector) Unmount(path string) Status { ...@@ -599,78 +539,31 @@ func (me *FileSystemConnector) Unmount(path string) Status {
parentNode.treeLock.Lock() parentNode.treeLock.Lock()
defer parentNode.treeLock.Unlock() defer parentNode.treeLock.Unlock()
if node.treeLock != parentNode.treeLock { mount := parentNode.Mounts[name]
node.treeLock.Lock() if mount == nil {
defer node.treeLock.Unlock()
}
if node.mountPoint == nil {
return EINVAL return EINVAL
} }
if node.mountPoint.openFiles.Count() > 0 { if mount.openFiles.Count() > 0 {
return EBUSY return EBUSY
} }
if !node.canUnmount() { mountInode := mount.mountInode
if !mountInode.canUnmount() {
return EBUSY return EBUSY
} }
me.unsafeUnmountNode(node) mountInode.recursiveUnmount()
notifyMessage := NotifyInvalInodeOut{ mount.mountInode = nil
Ino: node.NodeId, mountInode.mountPoint = nil
}
me.fsInit.InodeNotify(&notifyMessage)
return OK
}
// Assumes node.treeLock and node.Parent.treeLock have been taken. parentNode.Mounts[name] = nil, false
func (me *FileSystemConnector) unsafeUnmountNode(node *inode) { parentNode.Children[name] = nil, false
if node == me.rootNode { mount.fs.Unmount()
return
}
node.recursiveUnmount()
unmounted := node.mountPoint
unmounted.mountInode = nil
node.mountPoint = nil
parentNode := node.Parent me.fsInit.EntryNotify(parentNode.NodeId, name)
node.Parent = nil
if parentNode != nil {
parentNode.Mounts[node.Name] = nil, false
parentNode.Children[node.Name] = nil, false
}
unmounted.fs.Unmount()
}
// Returns an openedFile for the gived inode. return OK
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.GetPath()
if me.Debug {
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) FileNotify(path string, off int64, length int64) Status { func (me *FileSystemConnector) FileNotify(path string, off int64, length int64) Status {
......
...@@ -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