vfs: make uploaded files retain modtime with non-modtime backends
Before this change if a file was uploaded to a backend which didn't support modtimes, the time of the file read after the upload had completed would change to the time the file was uploaded on the backend. When using `--vfs-cache-mode writes` or `full` this time would be different by the `--vfs-write-back` delay which would cause applications to think the file had been modified. This changes uses the last modification time read by the OS as a virtual modtime for backends which don't support setting modtimes. It does not change the modtime to that actually uploaded. This means that as long as the file remains in the directory cache it will have the expected modtime. See: https://forum.rclone.org/t/saving-files-causes-wrong-modified-time-to-be-set-for-a-few-seconds-on-webdav-mount-with-bitrix24/36451
This commit is contained in:
parent
580d72f0f6
commit
e405ca7733
1 changed files with 19 additions and 1 deletions
20
vfs/file.go
20
vfs/file.go
|
@ -47,6 +47,7 @@ type File struct {
|
|||
o fs.Object // NB o may be nil if file is being written
|
||||
leaf string // leaf name of the object
|
||||
writers []Handle // writers for this file
|
||||
virtualModTime *time.Time // modtime for backends with Precision == fs.ModTimeNotSupported
|
||||
pendingModTime time.Time // will be applied once o becomes available, i.e. after file was written
|
||||
pendingRenameFun func(ctx context.Context) error // will be run/renamed after all writers close
|
||||
sys atomic.Value // user defined info to be attached here
|
||||
|
@ -314,9 +315,20 @@ func (f *File) _roundModTime(modTime time.Time) time.Time {
|
|||
// if NoModTime is set then it returns the mod time of the directory
|
||||
func (f *File) ModTime() (modTime time.Time) {
|
||||
f.mu.RLock()
|
||||
d, o, pendingModTime := f.d, f.o, f.pendingModTime
|
||||
d, o, pendingModTime, virtualModTime := f.d, f.o, f.pendingModTime, f.virtualModTime
|
||||
f.mu.RUnlock()
|
||||
|
||||
// Set the virtual modtime up for backends which don't support setting modtime
|
||||
//
|
||||
// Note that we only cache modtime values that we have returned to the OS
|
||||
// if we haven't returned a value to the OS then we can change it
|
||||
defer func() {
|
||||
if f.d.f.Precision() == fs.ModTimeNotSupported && (virtualModTime == nil || !virtualModTime.Equal(modTime)) {
|
||||
f.virtualModTime = &modTime
|
||||
fs.Debugf(f._path(), "Set virtual modtime to %v", f.virtualModTime)
|
||||
}
|
||||
}()
|
||||
|
||||
if d.vfs.Opt.NoModTime {
|
||||
return d.ModTime()
|
||||
}
|
||||
|
@ -334,6 +346,10 @@ func (f *File) ModTime() (modTime time.Time) {
|
|||
if !pendingModTime.IsZero() {
|
||||
return f._roundModTime(pendingModTime)
|
||||
}
|
||||
if virtualModTime != nil && !virtualModTime.IsZero() {
|
||||
fs.Debugf(f._path(), "Returning virtual modtime %v", f.virtualModTime)
|
||||
return f._roundModTime(*virtualModTime)
|
||||
}
|
||||
if o == nil {
|
||||
return time.Now()
|
||||
}
|
||||
|
@ -477,6 +493,8 @@ func (f *File) setObject(o fs.Object) {
|
|||
func (f *File) setObjectNoUpdate(o fs.Object) {
|
||||
f.mu.Lock()
|
||||
f.o = o
|
||||
f.virtualModTime = nil
|
||||
fs.Debugf(f._path(), "Reset virtual modtime")
|
||||
f.mu.Unlock()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue