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:
Lorenz Brun 2022-09-20 00:31:56 +02:00 committed by Nick Craig-Wood
parent 6560ea9bdc
commit ceef78ce44
2 changed files with 33 additions and 0 deletions

View File

@ -760,6 +760,7 @@ func (d *Dir) _readDirFromEntries(entries fs.DirEntries, dirTree dirtree.DirTree
dir := node.(*Dir)
dir.mu.Lock()
dir.modTime = item.ModTime(context.TODO())
dir.entry = item
if dirTree != nil {
err = dir._readDirFromDirTree(dirTree, when)
if err != nil {

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"os"
"runtime"
"sort"
"testing"
"time"
@ -655,3 +656,34 @@ func TestDirFileOpen(t *testing.T) {
require.NoError(t, err)
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")
}
}