diff options
author | Jakob Unterwurzacher | 2018-07-22 22:29:22 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2018-07-22 22:29:22 +0200 |
commit | f316f1b2df47dca651174e574ab072f6b46c0b01 (patch) | |
tree | 16176cb053718ba6b2815d08df44040f75d3fdae /internal/openfiletable | |
parent | c70df522d2a78f3152fa61511bed9fafa7c495a3 (diff) |
fusefronted: disallow writes running concurrently with reads
As uncovered by xfstests generic/465, concurrent reads and writes
could lead to this,
doRead 3015532: corrupt block #1039: stupidgcm: message authentication failed,
as the read could pick up a block that has not yet been completely written -
write() is not atomic!
Now writes take ContentLock exclusively, while reads take it shared,
meaning that multiple reads can run in parallel with each other, but
not with a write.
This also simplifies the file header locking.
Diffstat (limited to 'internal/openfiletable')
-rw-r--r-- | internal/openfiletable/open_file_table.go | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/internal/openfiletable/open_file_table.go b/internal/openfiletable/open_file_table.go index d70bcfa..e21c96d 100644 --- a/internal/openfiletable/open_file_table.go +++ b/internal/openfiletable/open_file_table.go @@ -57,18 +57,16 @@ type table struct { // Entry is an entry in the open file table type Entry struct { - // Reference count + // Reference count. Protected by the table lock. refCount int - // ContentLock guards the file content from concurrent writes. Every writer + // ContentLock protects on-disk content from concurrent writes. Every writer // must take this lock before modifying the file content. ContentLock countingMutex - // HeaderLock guards the file ID (in this struct) and the file header (on - // disk). Take HeaderLock.RLock() to make sure the file ID does not change - // behind your back. If you modify the file ID, you must take - // HeaderLock.Lock(). - HeaderLock sync.RWMutex // ID is the file ID in the file header. ID []byte + // IDLock must be taken before reading or writing the ID field in this struct, + // unless you have an exclusive lock on ContentLock. + IDLock sync.Mutex } // Register creates an open file table entry for "qi" (or incrementes the @@ -101,15 +99,15 @@ func Unregister(qi QIno) { // countingMutex incrementes t.writeLockCount on each Lock() call. type countingMutex struct { - sync.Mutex + sync.RWMutex } func (c *countingMutex) Lock() { - c.Mutex.Lock() + c.RWMutex.Lock() atomic.AddUint64(&t.writeOpCount, 1) } -// WriteOpCount returns the write lock counter value. This value is encremented +// WriteOpCount returns the write lock counter value. This value is incremented // each time writeLock.Lock() on a file table entry is called. func WriteOpCount() uint64 { return atomic.LoadUint64(&t.writeOpCount) |