vfs/cache: Fix promoteToFast race with WriteCloser Close
promoteToFast read FileInfo.Size from Stat after the VFS lock was released, while WriteCloser.Close updated Size on the same live object. Concurrent Create/Open on overlapping keys tripped the race detector. Stat now returns a FileInfo snapshot, and promotion uses the ReadAll length for the fast-tier Create size. Promotion stays best-effort. #21
This commit is contained in:
@@ -346,6 +346,45 @@ func TestMemoryFS_ConcurrentCloseAndEvict_RaceFree(t *testing.T) {
|
||||
_ = m.LRU.Len()
|
||||
}
|
||||
|
||||
func TestMemoryFS_StatReturnsSnapshot(t *testing.T) {
|
||||
t.Parallel()
|
||||
m, err := New(1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w, err := m.Create("k", 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := w.Write([]byte("hello")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fi, err := m.Stat("k")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if fi.Size != 5 {
|
||||
t.Fatalf("size %d want 5", fi.Size)
|
||||
}
|
||||
fi.Size = 999
|
||||
fi.AccessCount = 0
|
||||
|
||||
fi2, err := m.Stat("k")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if fi2.Size != 5 {
|
||||
t.Errorf("Stat returned live FileInfo; store size became %d", fi2.Size)
|
||||
}
|
||||
if fi2.AccessCount == 0 {
|
||||
t.Error("Stat returned live FileInfo; AccessCount mutation leaked")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoryFS_EvictVariantsAndErrors(t *testing.T) {
|
||||
t.Parallel()
|
||||
m, err := New(800)
|
||||
|
||||
Reference in New Issue
Block a user