From 63128834dae262f4413130458f552737a867fac1 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 13 Jan 2020 17:37:54 +0000 Subject: [PATCH] vfs: fix open file renaming on drive when using --vfs-cache-mode writes Before this change, when uploading files from the VFS cache which were pending a rename, rclone would use the new path of the object when specifiying the destination remote. This didn't cause a problem with most backends as the subsequent rename did nothing, however with the drive backend, since it updates objects, the incorrect Remote was embedded in the object. This caused the rename to apparently succeed but the object be at the wrong location. The fix for this was to make sure we upload to the path stored in the object if available. This problem was spotted by the new rename tests for the VFS layer. --- vfs/file.go | 17 ++++++++++------- vfs/read_write.go | 7 ++++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/vfs/file.go b/vfs/file.go index bc213d537..c3a227b74 100644 --- a/vfs/file.go +++ b/vfs/file.go @@ -150,13 +150,6 @@ func (f *File) rename(ctx context.Context, destDir *Dir, newName string) error { newPath := path.Join(destDir.path, newName) renameCall := func(ctx context.Context) error { - f.mu.RLock() - o := f.o - f.mu.RUnlock() - if o == nil { - return errors.New("Cannot rename: file object is not available") - } - // chain rename calls if any if oldPendingRenameFun != nil { err := oldPendingRenameFun(ctx) @@ -165,6 +158,16 @@ func (f *File) rename(ctx context.Context, destDir *Dir, newName string) error { } } + f.mu.RLock() + o := f.o + f.mu.RUnlock() + if o == nil { + return errors.New("Cannot rename: file object is not available") + } + if o.Remote() == newPath { + return nil // no need to rename + } + // do the move of the remote object dstOverwritten, _ := d.f.NewObject(ctx, newPath) newObject, err := operations.Move(ctx, d.f, dstOverwritten, newPath, o) diff --git a/vfs/read_write.go b/vfs/read_write.go index 05fcf8a88..2344f1223 100644 --- a/vfs/read_write.go +++ b/vfs/read_write.go @@ -284,7 +284,12 @@ func (fh *RWFileHandle) flushWrites(closeFile bool) error { return err } - o, err := copyObj(fh.d.vfs.f, fh.file.getObject(), fh.file.Path(), cacheObj) + objPath := fh.file.Path() + objOld := fh.file.getObject() + if objOld != nil { + objPath = objOld.Remote() // use the path of the actual object if available + } + o, err := copyObj(fh.d.vfs.f, objOld, objPath, cacheObj) if err != nil { err = errors.Wrap(err, "failed to transfer file from cache to remote") fs.Errorf(fh.logPrefix(), "%v", err)