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/fusefrontend/file_allocate_truncate.go | |
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/fusefrontend/file_allocate_truncate.go')
-rw-r--r-- | internal/fusefrontend/file_allocate_truncate.go | 6 |
1 files changed, 1 insertions, 5 deletions
diff --git a/internal/fusefrontend/file_allocate_truncate.go b/internal/fusefrontend/file_allocate_truncate.go index 81ac8d3..34fe2c0 100644 --- a/internal/fusefrontend/file_allocate_truncate.go +++ b/internal/fusefrontend/file_allocate_truncate.go @@ -111,9 +111,7 @@ func (f *File) Truncate(newSize uint64) fuse.Status { return fuse.ToStatus(err) } // Truncate to zero kills the file header - f.fileTableEntry.HeaderLock.Lock() f.fileTableEntry.ID = nil - f.fileTableEntry.HeaderLock.Unlock() return fuse.OK } // We need the old file size to determine if we are growing or shrinking @@ -144,7 +142,7 @@ func (f *File) Truncate(newSize uint64) fuse.Status { var data []byte if lastBlockLen > 0 { var status fuse.Status - data, status = f.doRead(nil, plainOff, lastBlockLen, false) + data, status = f.doRead(nil, plainOff, lastBlockLen) if status != fuse.OK { tlog.Warn.Printf("Truncate: shrink doRead returned error: %v", err) return status @@ -206,8 +204,6 @@ func (f *File) truncateGrowFile(oldPlainSz uint64, newPlainSz uint64) fuse.Statu if newPlainSz%f.contentEnc.PlainBS() == 0 { // The file was empty, so it did not have a header. Create one. if oldPlainSz == 0 { - f.fileTableEntry.HeaderLock.Lock() - defer f.fileTableEntry.HeaderLock.Unlock() id, err := f.createHeader() if err != nil { return fuse.ToStatus(err) |