summaryrefslogtreecommitdiff
path: root/internal/fusefrontend/write_lock.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-11-17 22:29:45 +0100
committerJakob Unterwurzacher2016-11-17 22:29:45 +0100
commit0489d08ae21107990d0efd0685443293aa26b35f (patch)
tree1e4824a32f2a53d5ae323db9ee65c8eaba8a1ed7 /internal/fusefrontend/write_lock.go
parente04dc050126edcf7440ea5412bc74c6ad8b42e95 (diff)
fusefrontend: get the file ID from the open files table
This fixes the problem that a truncate can reset the file ID without the other open FDs noticing it.
Diffstat (limited to 'internal/fusefrontend/write_lock.go')
-rw-r--r--internal/fusefrontend/write_lock.go64
1 files changed, 31 insertions, 33 deletions
diff --git a/internal/fusefrontend/write_lock.go b/internal/fusefrontend/write_lock.go
index 71e911e..bbab81c 100644
--- a/internal/fusefrontend/write_lock.go
+++ b/internal/fusefrontend/write_lock.go
@@ -22,7 +22,7 @@ func DevInoFromStat(st *syscall.Stat_t) DevInoStruct {
}
func init() {
- wlock.inodeLocks = make(map[DevInoStruct]*refCntMutex)
+ openFileMap.entries = make(map[DevInoStruct]*openFileEntryT)
}
// wlock - serializes write accesses to each file (identified by inode number)
@@ -30,14 +30,14 @@ func init() {
// really don't want concurrent writes there.
// Concurrent full-block writes could actually be allowed, but are not to
// keep the locking simple.
-var wlock wlockMap
+var openFileMap openFileMapT
// wlockMap - usage:
// 1) register
// 2) lock ... unlock ...
// 3) unregister
-type wlockMap struct {
- // opCount counts lock() calls. As every operation that modifies a file should
+type openFileMapT struct {
+ // opCount counts writeLock.Lock() calls. As every operation that modifies a file should
// call it, this effectively serves as a write-operation counter.
// The variable is accessed without holding any locks so atomic operations
// must be used. It must be the first element of the struct to guarantee
@@ -45,58 +45,56 @@ type wlockMap struct {
opCount uint64
// Protects map access
sync.Mutex
- inodeLocks map[DevInoStruct]*refCntMutex
+ entries map[DevInoStruct]*openFileEntryT
}
-// refCntMutex - mutex with reference count
-type refCntMutex struct {
- // Write lock for this inode
+type opCountMutex struct {
sync.Mutex
+ // Points to the opCount variable of the parent openFileMapT
+ opCount *uint64
+}
+
+func (o *opCountMutex) Lock() {
+ o.Mutex.Lock()
+ atomic.AddUint64(o.opCount, 1)
+}
+
+// refCntMutex - mutex with reference count
+type openFileEntryT struct {
// Reference count
refCnt int
+ // Write lock for this inode
+ writeLock *opCountMutex
+ // ID is the file ID in the file header.
+ ID []byte
+ IDLock sync.RWMutex
}
// register creates an entry for "ino", or incrementes the reference count
// if the entry already exists.
-func (w *wlockMap) register(di DevInoStruct) {
+func (w *openFileMapT) register(di DevInoStruct) *openFileEntryT {
w.Lock()
defer w.Unlock()
- r := w.inodeLocks[di]
+ r := w.entries[di]
if r == nil {
- r = &refCntMutex{}
- w.inodeLocks[di] = r
+ o := opCountMutex{opCount: &w.opCount}
+ r = &openFileEntryT{writeLock: &o}
+ w.entries[di] = r
}
r.refCnt++
+ return r
}
// unregister decrements the reference count for "di" and deletes the entry if
// the reference count has reached 0.
-func (w *wlockMap) unregister(di DevInoStruct) {
+func (w *openFileMapT) unregister(di DevInoStruct) {
w.Lock()
defer w.Unlock()
- r := w.inodeLocks[di]
+ r := w.entries[di]
r.refCnt--
if r.refCnt == 0 {
- delete(w.inodeLocks, di)
+ delete(w.entries, di)
}
}
-
-// lock retrieves the entry for "di" and locks it.
-func (w *wlockMap) lock(di DevInoStruct) {
- atomic.AddUint64(&w.opCount, 1)
- w.Lock()
- r := w.inodeLocks[di]
- w.Unlock()
- // this can take a long time - execute outside the wlockMap lock
- r.Lock()
-}
-
-// unlock retrieves the entry for "di" and unlocks it.
-func (w *wlockMap) unlock(di DevInoStruct) {
- w.Lock()
- r := w.inodeLocks[di]
- w.Unlock()
- r.Unlock()
-}