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.
This commit is contained in:
Nick Craig-Wood 2018-03-15 20:36:48 +00:00
parent 34c45a7c04
commit c19e675ca6
2 changed files with 7 additions and 6 deletions

View file

@ -29,8 +29,7 @@ type File struct {
modified bool // has the cache file be modified by a RWFileHandle? 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 pendingModTime time.Time // will be applied once o becomes available, i.e. after file was written
muClose sync.Mutex // synchonize RWFileHandle.close() muRW sync.Mutex // synchonize RWFileHandle.openPending(), RWFileHandle.close() and File.Remove
muOpen sync.Mutex // synchonize RWFileHandle.openPending()
} }
// newFile creates a new File // newFile creates a new File
@ -385,6 +384,8 @@ func (f *File) Sync() error {
// Remove the file // Remove the file
func (f *File) Remove() error { func (f *File) Remove() error {
f.muRW.Lock()
defer f.muRW.Unlock()
if f.d.vfs.Opt.ReadOnly { if f.d.vfs.Opt.ReadOnly {
return EROFS return EROFS
} }

View file

@ -102,8 +102,8 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
return nil return nil
} }
fh.file.muOpen.Lock() fh.file.muRW.Lock()
defer fh.file.muOpen.Unlock() defer fh.file.muRW.Unlock()
o := fh.file.getObject() o := fh.file.getObject()
@ -240,8 +240,8 @@ func (fh *RWFileHandle) modified() bool {
// to give the user a chance to recover it. // to give the user a chance to recover it.
func (fh *RWFileHandle) close() (err error) { func (fh *RWFileHandle) close() (err error) {
defer log.Trace(fh.logPrefix(), "")("err=%v", &err) defer log.Trace(fh.logPrefix(), "")("err=%v", &err)
fh.file.muClose.Lock() fh.file.muRW.Lock()
defer fh.file.muClose.Unlock() defer fh.file.muRW.Unlock()
if fh.closed { if fh.closed {
return ECLOSED return ECLOSED