mirror of https://github.com/rclone/rclone.git
vfs: fix directory cache serving stale data
The VFS directory cache layer didn't update directory entry properties if they are reused after cache invalidation. Update them unconditionally as newDir sets them to the same value and setting a pointer is cheaper in both LoC as well as CPU cycles than a branch. Also add a test exercising this behavior. Fixes #6335
This commit is contained in:
parent
6560ea9bdc
commit
ceef78ce44
|
@ -760,6 +760,7 @@ func (d *Dir) _readDirFromEntries(entries fs.DirEntries, dirTree dirtree.DirTree
|
||||||
dir := node.(*Dir)
|
dir := node.(*Dir)
|
||||||
dir.mu.Lock()
|
dir.mu.Lock()
|
||||||
dir.modTime = item.ModTime(context.TODO())
|
dir.modTime = item.ModTime(context.TODO())
|
||||||
|
dir.entry = item
|
||||||
if dirTree != nil {
|
if dirTree != nil {
|
||||||
err = dir._readDirFromDirTree(dirTree, when)
|
err = dir._readDirFromDirTree(dirTree, when)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -655,3 +656,34 @@ func TestDirFileOpen(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(12), fi.Size())
|
assert.Equal(t, int64(12), fi.Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDirEntryModTimeInvalidation(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
t.Skip("dirent modtime is unreliable on Windows filesystems")
|
||||||
|
}
|
||||||
|
r, vfs := newTestVFS(t)
|
||||||
|
|
||||||
|
// Needs to be less than 2x the wait time below, othewrwise the entry
|
||||||
|
// gets cleared out before it had a chance to be updated.
|
||||||
|
vfs.Opt.DirCacheTime = fs.Duration(50 * time.Millisecond)
|
||||||
|
|
||||||
|
r.WriteObject(context.Background(), "dir/file1", "file1 contents", t1)
|
||||||
|
|
||||||
|
node, err := vfs.Stat("dir")
|
||||||
|
require.NoError(t, err)
|
||||||
|
modTime1 := node.(*Dir).DirEntry().ModTime(context.Background())
|
||||||
|
|
||||||
|
// Wait some time, then write another file which must update ModTime of
|
||||||
|
// the directory.
|
||||||
|
time.Sleep(75 * time.Millisecond)
|
||||||
|
r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
|
||||||
|
|
||||||
|
node2, err := vfs.Stat("dir")
|
||||||
|
require.NoError(t, err)
|
||||||
|
modTime2 := node2.(*Dir).DirEntry().ModTime(context.Background())
|
||||||
|
|
||||||
|
// ModTime of directory must be different after second file was written.
|
||||||
|
if modTime1.Equal(modTime2) {
|
||||||
|
t.Error("ModTime not invalidated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue