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:
parent
34c45a7c04
commit
c19e675ca6
2 changed files with 7 additions and 6 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue