Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement O_DIRECT (NO_BUFFERING) support for Unix #55463

Closed
wants to merge 1 commit into from

Conversation

adamsitnik
Copy link
Member

With the introduction of the new NativeMemory API it's much easier to perform direct file IO with .NET.

Since we already support it on Windows by simply allowing the users to pass magic (FileOptions)0x20000000 as FileOptions:

if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0)

We could do it on Unix as well.

@ghost
Copy link

ghost commented Jul 10, 2021

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

Issue Details

With the introduction of the new NativeMemory API it's much easier to perform direct file IO with .NET.

Since we already support it on Windows by simply allowing the users to pass magic (FileOptions)0x20000000 as FileOptions:

if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0)

We could do it on Unix as well.

Author: adamsitnik
Assignees: -
Labels:

area-System.IO

Milestone: -

@jkotas
Copy link
Member

jkotas commented Jul 10, 2021

(FileOptions)0x20000000

Should we add this value to the public API surface?

@@ -263,6 +263,8 @@ static int32_t ConvertOpenFlags(int32_t flags)
ret |= O_TRUNC;
if (flags & PAL_O_SYNC)
ret |= O_SYNC;
if (flags & PAL_O_DIRECT)
ret |= O_DIRECT;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this exist on macOS?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The man page states:

O_DIRECT I/Os should never be run concurrently with the fork(2)
       system call, if the memory buffer is a private mapping (i.e., any
       mapping created with the mmap(2) MAP_PRIVATE flag; this includes
       memory allocated on the heap and statically allocated buffers).
       Any such I/Os, whether submitted via an asynchronous I/O
       interface or from another thread in the process, should be
       completed before fork(2) is called.  Failure to do so can result
       in data corruption and undefined behavior in parent and child
       processes.

How are you guaranteeing this, in our tests but also for use in the wild? fork is used by Process.Start.

public unsafe void NoBufferingOptions(FileOptions option)
{
void* pWrite = NativeMemory.AlignedAlloc(c_DefaultBufferSize, c_DefaultBufferSize);
void* pRead = NativeMemory.AlignedAlloc(c_DefaultBufferSize, c_DefaultBufferSize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why two buffers rather than one?

Copy link
Member

@stephentoub stephentoub Jul 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the man page:

       the alignment of the user
       buffer, and the file offset must all be multiples of the logical
       block size of the filesystem

How are you guaranteeing that this 4096 alignment is valid everywhere this test runs?

I'm also not clear how this works with the loop that is here. Is the implementation guaranteed to successfully read/write in multiples of the alignment such that the loop will use a correctly aligned offset at every iteration?

@adamsitnik
Copy link
Member Author

I am going to close the PR right now and re-start the discussion when I am back from vacations.

@adamsitnik adamsitnik closed this Jul 11, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Aug 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants