diff options
author | Jakob Unterwurzacher | 2016-11-17 22:29:45 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2016-11-17 22:29:45 +0100 |
commit | 0489d08ae21107990d0efd0685443293aa26b35f (patch) | |
tree | 1e4824a32f2a53d5ae323db9ee65c8eaba8a1ed7 /internal/fusefrontend/write_lock.go | |
parent | e04dc050126edcf7440ea5412bc74c6ad8b42e95 (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.go | 64 |
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() -} |