From 6ca7198f57ae1f9ee24c65f96f39dfda31b482a9 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 1 May 2020 18:31:19 +0100 Subject: [PATCH] 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. --- cmd/mount/dir.go | 24 +++++++++++++++++++----- cmd/mount2/node.go | 20 +++++++++++++------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/cmd/mount/dir.go b/cmd/mount/dir.go index 0841cd937..013bee7c6 100644 --- a/cmd/mount/dir.go +++ b/cmd/mount/dir.go @@ -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) diff --git a/cmd/mount2/node.go b/cmd/mount2/node.go index dcf204c1a..e1c52ce7b 100644 --- a/cmd/mount2/node.go +++ b/cmd/mount2/node.go @@ -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)