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) | 
