mirror of
https://github.com/rclone/rclone.git
synced 2025-12-11 22:14:05 +01:00
vfs: move writeback of dirty data out of close() method into its own method (FlushWrites) and remove close() call from Flush()
If a file handle is duplicated with dup() and the duplicate handle is flushed, rclone will go ahead and close the file, making the original file handle stale. This change removes the close() call from Flush() and replaces it with FlushWrites() so that the file only gets closed when Release() is called. The new FlushWrites method takes care of actually writing the file back to the underlying storage. Fixes #3381
This commit is contained in:
committed by
Nick Craig-Wood
parent
0cac9d9bd0
commit
7d0d7e66ca
@@ -230,28 +230,14 @@ func (fh *RWFileHandle) modified() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// close the file handle returning EBADF if it has been
|
||||
// closed already.
|
||||
// flushWrites flushes any pending writes to cloud storage
|
||||
//
|
||||
// Must be called with fh.mu held
|
||||
//
|
||||
// Note that we leave the file around in the cache on error conditions
|
||||
// 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.muRW.Lock()
|
||||
defer fh.file.muRW.Unlock()
|
||||
|
||||
if fh.closed {
|
||||
return ECLOSED
|
||||
// Must be called with fh.muRW held
|
||||
func (fh *RWFileHandle) flushWrites(closeFile bool) error {
|
||||
if fh.closed && !closeFile {
|
||||
return nil
|
||||
}
|
||||
fh.closed = true
|
||||
defer func() {
|
||||
if fh.opened {
|
||||
fh.file.delRWOpen()
|
||||
}
|
||||
fh.d.vfs.cache.close(fh.remote)
|
||||
}()
|
||||
|
||||
rdwrMode := fh.flags & accessModeMask
|
||||
writer := rdwrMode != os.O_RDONLY
|
||||
|
||||
@@ -284,8 +270,8 @@ func (fh *RWFileHandle) close() (err error) {
|
||||
}
|
||||
|
||||
// Close the underlying file
|
||||
if fh.opened {
|
||||
err = fh.File.Close()
|
||||
if fh.opened && closeFile {
|
||||
err := fh.File.Close()
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "failed to close cache file")
|
||||
return err
|
||||
@@ -314,6 +300,32 @@ func (fh *RWFileHandle) close() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// close the file handle returning EBADF if it has been
|
||||
// closed already.
|
||||
//
|
||||
// Must be called with fh.mu held
|
||||
//
|
||||
// Note that we leave the file around in the cache on error conditions
|
||||
// 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.muRW.Lock()
|
||||
defer fh.file.muRW.Unlock()
|
||||
|
||||
if fh.closed {
|
||||
return ECLOSED
|
||||
}
|
||||
fh.closed = true
|
||||
defer func() {
|
||||
if fh.opened {
|
||||
fh.file.delRWOpen()
|
||||
}
|
||||
fh.d.vfs.cache.close(fh.remote)
|
||||
}()
|
||||
|
||||
return fh.flushWrites(true)
|
||||
}
|
||||
|
||||
// Close closes the file
|
||||
func (fh *RWFileHandle) Close() error {
|
||||
fh.mu.Lock()
|
||||
@@ -346,7 +358,11 @@ func (fh *RWFileHandle) Flush() error {
|
||||
fs.Debugf(fh.logPrefix(), "RWFileHandle.Flush ignoring flush on unwritten handle")
|
||||
return nil
|
||||
}
|
||||
err := fh.close()
|
||||
|
||||
fh.file.muRW.Lock()
|
||||
defer fh.file.muRW.Unlock()
|
||||
err := fh.flushWrites(false)
|
||||
|
||||
if err != nil {
|
||||
fs.Errorf(fh.logPrefix(), "RWFileHandle.Flush error: %v", err)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user