Skip to content

Commit

Permalink
handleMap: track per-handle generation number
Browse files Browse the repository at this point in the history
We used to hand out a new generation number even
for already-known handles. This does not seem to
cause problems on Linux, but osxfuse throws errors
to userspace with

	osxfuse: vnode changed generation

showing up in the kernel log.

Introduce a per-handle generation number that stays
constant until the handle is forgotten.

Tested on Linux and MacOS via gocryptfs.

Fixes hanwen#204
See also hanwen#205
  • Loading branch information
rfjakob committed Mar 16, 2018
1 parent 73e231d commit 3bcf9f9
Showing 1 changed file with 23 additions and 18 deletions.
41 changes: 23 additions & 18 deletions fuse/nodefs/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ type handleMap interface {
}

type handled struct {
handle uint64
count int
handle uint64
generation uint64
count int
}

func (h *handled) verify() {
Expand Down Expand Up @@ -75,25 +76,29 @@ func newPortableHandleMap() *portableHandleMap {

func (m *portableHandleMap) Register(obj *handled) (handle, generation uint64) {
m.Lock()
if obj.count == 0 {
if len(m.freeIds) == 0 {
handle = uint64(len(m.handles))
m.handles = append(m.handles, obj)
} else {
handle = m.freeIds[len(m.freeIds)-1]
m.freeIds = m.freeIds[:len(m.freeIds)-1]
m.generation++
m.handles[handle] = obj
}
m.used++
obj.handle = handle
defer m.Unlock()
// Reuse existing handle
if obj.count != 0 {
obj.count++
return obj.handle, obj.generation
}
// Create a new handle number or recycle one on from the free list
if len(m.freeIds) == 0 {
obj.handle = uint64(len(m.handles))
m.handles = append(m.handles, obj)
} else {
handle = obj.handle
obj.handle = m.freeIds[len(m.freeIds)-1]
m.freeIds = m.freeIds[:len(m.freeIds)-1]
m.handles[obj.handle] = obj
}
// Increment generation number to guarantee the (handle, generation) tuple
// is unique
m.generation++
m.used++
obj.generation = m.generation
obj.count++
generation = m.generation
m.Unlock()
return

return obj.handle, obj.generation
}

func (m *portableHandleMap) Handle(obj *handled) (h uint64) {
Expand Down

0 comments on commit 3bcf9f9

Please sign in to comment.