Skip to content

Commit

Permalink
vfs: default to Unix semantics in MemFS
Browse files Browse the repository at this point in the history
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 cockroachdb#2064.
Informs cockroachdb#1236.
  • Loading branch information
jbowens committed Oct 17, 2023
1 parent 7d3c5ff commit db91e5c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
1 change: 1 addition & 0 deletions ingest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1630,6 +1630,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)
Expand Down
26 changes: 21 additions & 5 deletions vfs/mem_fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,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()
Expand Down Expand Up @@ -305,11 +318,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
Expand Down

0 comments on commit db91e5c

Please sign in to comment.