From c19e675ca6b8590e65b222f4b37bc41c47fc5f51 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 15 Mar 2018 20:36:48 +0000 Subject: [PATCH] vfs: unify locking for RWFileHandle.openPending,.close and File.Delete #2141 Without this fix the cached file can be removed as the file is being uploaded or downloaded. This can cause the directory listings to become inconsistent (this issue) or data loss (if a retry was needed in the Copy). Remove file needs to be excluded from running at the same time as both openPending and close so it makes sense to unify the locking between all 3. --- vfs/file.go | 5 +++-- vfs/read_write.go | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/vfs/file.go b/vfs/file.go index 967adae60..c556fb5d8 100644 --- a/vfs/file.go +++ b/vfs/file.go @@ -29,8 +29,7 @@ type File struct { modified bool // has the cache file be modified by a RWFileHandle? pendingModTime time.Time // will be applied once o becomes available, i.e. after file was written - muClose sync.Mutex // synchonize RWFileHandle.close() - muOpen sync.Mutex // synchonize RWFileHandle.openPending() + muRW sync.Mutex // synchonize RWFileHandle.openPending(), RWFileHandle.close() and File.Remove } // newFile creates a new File @@ -385,6 +384,8 @@ func (f *File) Sync() error { // Remove the file func (f *File) Remove() error { + f.muRW.Lock() + defer f.muRW.Unlock() if f.d.vfs.Opt.ReadOnly { return EROFS } diff --git a/vfs/read_write.go b/vfs/read_write.go index b612fdf1d..9817027f4 100644 --- a/vfs/read_write.go +++ b/vfs/read_write.go @@ -102,8 +102,8 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) { return nil } - fh.file.muOpen.Lock() - defer fh.file.muOpen.Unlock() + fh.file.muRW.Lock() + defer fh.file.muRW.Unlock() o := fh.file.getObject() @@ -240,8 +240,8 @@ func (fh *RWFileHandle) modified() bool { // to give the user a chance to recover it. func (fh *RWFileHandle) close() (err error) { defer log.Trace(fh.logPrefix(), "")("err=%v", &err) - fh.file.muClose.Lock() - defer fh.file.muClose.Unlock() + fh.file.muRW.Lock() + defer fh.file.muRW.Unlock() if fh.closed { return ECLOSED