Commit 8342bc7b authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Implement node generations.

* Use timestamp as base generation number

* increment for each newly used inode.

This prevents clashes when exporting Go-FUSE filesystems to NFS.
parent cfd3e6e6
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"log" "log"
"path/filepath" "path/filepath"
"strings" "strings"
"sync/atomic"
"time" "time"
"unsafe" "unsafe"
...@@ -42,6 +43,9 @@ type FileSystemConnector struct { ...@@ -42,6 +43,9 @@ type FileSystemConnector struct {
// The root of the FUSE file system. // The root of the FUSE file system.
rootNode *Inode rootNode *Inode
// Used as the generation inodes.
generation uint64
} }
func NewFileSystemOptions() *FileSystemOptions { func NewFileSystemOptions() *FileSystemOptions {
...@@ -61,15 +65,23 @@ func NewFileSystemConnector(nodeFs NodeFileSystem, opts *FileSystemOptions) (c * ...@@ -61,15 +65,23 @@ func NewFileSystemConnector(nodeFs NodeFileSystem, opts *FileSystemOptions) (c *
c.inodeMap = NewHandleMap(opts.PortableInodes) c.inodeMap = NewHandleMap(opts.PortableInodes)
c.rootNode = newInode(true, nodeFs.Root()) c.rootNode = newInode(true, nodeFs.Root())
// Make sure we don't reuse generation numbers.
c.generation = uint64(time.Now().UnixNano())
c.verify() c.verify()
c.MountRoot(nodeFs, opts) c.MountRoot(nodeFs, opts)
// FUSE does not issue a LOOKUP for 1 (obviously), but it does // FUSE does not issue a LOOKUP for 1 (obviously), but it does
// issue a forget. This lookupUpdate is to make the counts match. // issue a forget. This lookupUpdate is to make the counts match.
c.lookupUpdate(c.rootNode) c.lookupUpdate(c.rootNode)
return c return c
} }
func (c *FileSystemConnector) nextGeneration() uint64 {
return atomic.AddUint64(&c.generation, 1)
}
func (c *FileSystemConnector) verify() { func (c *FileSystemConnector) verify() {
if !paranoia { if !paranoia {
return return
......
...@@ -75,7 +75,7 @@ func (c *FileSystemConnector) Lookup(out *raw.EntryOut, header *raw.InHeader, na ...@@ -75,7 +75,7 @@ func (c *FileSystemConnector) Lookup(out *raw.EntryOut, header *raw.InHeader, na
child.mount.fillEntry(out) child.mount.fillEntry(out)
out.NodeId = c.lookupUpdate(child) out.NodeId = c.lookupUpdate(child)
out.Generation = 1 out.Generation = child.generation
out.Ino = out.NodeId out.Ino = out.NodeId
return OK return OK
......
...@@ -13,6 +13,10 @@ var _ = log.Println ...@@ -13,6 +13,10 @@ var _ = log.Println
type Inode struct { type Inode struct {
handled Handled handled Handled
// Generation number of the inode. Each (re)use of an inode
// should have a unique generation number.
generation uint64
// Number of open files and its protection. // Number of open files and its protection.
openFilesMutex sync.Mutex openFilesMutex sync.Mutex
openFiles []*openedFile openFiles []*openedFile
...@@ -136,6 +140,7 @@ func (n *Inode) New(isDir bool, fsi FsNode) *Inode { ...@@ -136,6 +140,7 @@ func (n *Inode) New(isDir bool, fsi FsNode) *Inode {
ch := newInode(isDir, fsi) ch := newInode(isDir, fsi)
ch.mount = n.mount ch.mount = n.mount
ch.treeLock = n.treeLock ch.treeLock = n.treeLock
n.generation = ch.mount.connector.nextGeneration()
return ch return ch
} }
......
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