From 8d33fb8d6b165d458656f66ccd05a29fa9757e30 Mon Sep 17 00:00:00 2001 From: Jackson Owens Date: Thu, 27 Oct 2022 10:57:29 -0400 Subject: [PATCH] vfs: default to Unix semantics in MemFS Default to Unix semantics in MemFS. The Windows semantics are left as configurable for unit tests that seek to ensure we don't remove open files, when possible. There are existing cases where we cannot satisfy Windows semantics, and Go does not support opening files with the appropriate `FILE_SHARE_DELETE` permission bit (see golang/go#34681, golang/go#32088). The MemFS's implementation of Windows semantics is useful for ensuring we don't regress in the cases where we can satisfy Windows semantics. Close #2064. Informs #1236. --- ingest_test.go | 1 + vfs/mem_fs.go | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/ingest_test.go b/ingest_test.go index 5930869dbc..78f1d475b6 100644 --- a/ingest_test.go +++ b/ingest_test.go @@ -1432,6 +1432,7 @@ func TestIngestCleanup(t *testing.T) { for _, tc := range testCases { t.Run("", func(t *testing.T) { mem := vfs.NewMem() + mem.UseWindowsSemantics(true) // Create the files in the VFS. metaMap := make(map[base.FileNum]vfs.File) diff --git a/vfs/mem_fs.go b/vfs/mem_fs.go index d573c5d92f..e343b3eec2 100644 --- a/vfs/mem_fs.go +++ b/vfs/mem_fs.go @@ -78,10 +78,23 @@ type MemFS struct { strict bool ignoreSyncs bool + // Windows has peculiar semantics with respect to hard links and deleting + // open files. In tests meant to exercise this behavior, this flag can be + // set to error if removing an open file. + windowsSemantics bool } var _ FS = &MemFS{} +// UseWindowsSemantics configures whether the MemFS implements Windows-style +// semantics, in particular with respect to whether any of an open file's links +// may be removed. Windows semantics default to off. +func (y *MemFS) UseWindowsSemantics(windowsSemantics bool) { + y.mu.Lock() + defer y.mu.Unlock() + y.windowsSemantics = windowsSemantics +} + // String dumps the contents of the MemFS. func (y *MemFS) String() string { y.mu.Lock() @@ -303,11 +316,14 @@ func (y *MemFS) Remove(fullname string) error { if !ok { return oserror.ErrNotExist } - // Disallow removal of open files/directories which implements Windows - // semantics. This ensures that we don't regress in the ordering of - // operations and try to remove a file while it is still open. - if n := atomic.LoadInt32(&child.refs); n > 0 { - return oserror.ErrInvalid + if y.windowsSemantics { + // Disallow removal of open files/directories which implements + // Windows semantics. This ensures that we don't regress in the + // ordering of operations and try to remove a file while it is + // still open. + if n := atomic.LoadInt32(&child.refs); n > 0 { + return oserror.ErrInvalid + } } if len(child.children) > 0 { return errNotEmpty