mount: fix disappearing cwd problem - fixes #4104

Before this change, the current working directory could disappear
according to the Linux kernel.

This was caused by mount returning different nodes with the same
information in.

This change uses vfs.Node.SetSys to cache the information so we always
return the same node.
This commit is contained in:
Nick Craig-Wood 2020-05-01 18:31:19 +01:00
parent cfcdc85b26
commit 6ca7198f57
2 changed files with 32 additions and 12 deletions

View file

@ -76,13 +76,23 @@ func (d *Dir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.Lo
return nil, translateError(err)
}
resp.EntryValid = mountlib.AttrTimeout
// Check the mnode to see if it has a fuse Node cached
// We must return the same fuse nodes for vfs Nodes
node, ok := mnode.Sys().(fusefs.Node)
if ok {
return node, nil
}
switch x := mnode.(type) {
case *vfs.File:
return &File{x}, nil
node = &File{x}
case *vfs.Dir:
return &Dir{x}, nil
node = &Dir{x}
default:
panic("bad type")
}
panic("bad type")
// Cache the node for later
mnode.SetSys(node)
return node, nil
}
// Check interface satisfied
@ -129,7 +139,9 @@ func (d *Dir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.Cr
if err != nil {
return nil, nil, translateError(err)
}
return &File{file}, &FileHandle{fh}, err
node = &File{file}
file.SetSys(node) // cache the FUSE node for later
return node, &FileHandle{fh}, err
}
var _ fusefs.NodeMkdirer = (*Dir)(nil)
@ -141,7 +153,9 @@ func (d *Dir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (node fusefs.No
if err != nil {
return nil, translateError(err)
}
return &Dir{dir}, nil
node = &Dir{dir}
dir.SetSys(node) // cache the FUSE node for later
return node, nil
}
var _ fusefs.NodeRemover = (*Dir)(nil)

View file

@ -27,11 +27,20 @@ type Node struct {
var _ fusefs.InodeEmbedder = (*Node)(nil)
// newNode creates a new fusefs.Node from a vfs Node
func newNode(fsys *FS, node vfs.Node) *Node {
return &Node{
node: node,
func newNode(fsys *FS, vfsNode vfs.Node) (node *Node) {
// Check the vfsNode to see if it has a fuse Node cached
// We must return the same fuse nodes for vfs Nodes
node, ok := vfsNode.Sys().(*Node)
if ok {
return node
}
node = &Node{
node: vfsNode,
fsys: fsys,
}
// Cache the node for later
vfsNode.SetSys(node)
return node
}
// String used for pretty printing.
@ -183,10 +192,7 @@ func (n *Node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (ino
if errno != 0 {
return nil, errno
}
newNode := &Node{
node: vfsNode,
fsys: n.fsys,
}
newNode := newNode(n.fsys, vfsNode)
// FIXME
// out.SetEntryTimeout(dt time.Duration)