[PATCH v2 0/1] MR9809: server: Support creating files with direct and synchronous I/O
This allows various disk benchmarking software like CrystalDiskMark and ATTO disk benchmark to actually benchmark the disk rather than the file cache Implementation based on public Microsoft NtCreateFile() documentation: https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntc... According to the documentation, Windows forbids FILE_APPEND_DATA and FILE_NO_INTERMEDIATE_BUFFERING being set together, but Linux has no such limitation with the equivalent O_APPEND and O_DIRECT... -- v2: server: Support creating files with direct and synchronous I/O https://gitlab.winehq.org/wine/wine/-/merge_requests/9809
From: 小太 <nospam@kota.moe> This allows various disk benchmarking software like CrystalDiskMark and ATTO disk benchmark to actually benchmark the disk rather than the file cache Implementation based on public Microsoft NtCreateFile() documentation: https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntc... --- server/fd.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/fd.c b/server/fd.c index f70bec354a3..bd7475bfd26 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1974,6 +1974,17 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam } else rw_mode = O_RDONLY; + if (options & FILE_NO_INTERMEDIATE_BUFFERING) + { +#if defined(O_DIRECT) /* O_DIRECT is not available on OSX */ + flags |= O_DIRECT; +#endif + /* FILE_NO_INTERMEDIATE_BUFFERING implies FILE_WRITE_THROUGH according + to documentation */ + options |= FILE_WRITE_THROUGH; + } + if (options & FILE_WRITE_THROUGH) flags |= O_SYNC; + if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1) { /* if we tried to open a directory for write access, retry read-only */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9809
I am afraid that making no buffering flag really work may do more harm than good by affecting apps IO performance if they use it.
Surely correctness is more important here? If an app explicitly requests no buffering, it must already understand that this can significantly impact performance if I/O is done incorrectly And aside from benchmarking software, I believe it's also commonly used by database software. Though probably a much rarer use case to be running databases under wine... (excepting sqlite?)
Also, O_DIRECT implies limitations (e.g. extra alignment for data), not sure this can work as is.
Direct I/O on Windows broadly has the same limitations as O_DIRECT according to the documentation (access must be aligned and an integer multiple of block size): https://learn.microsoft.com/en-us/windows/win32/fileio/file-buffering#alignm... -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9809#note_126000
On Mon Dec 22 16:15:18 2025 +0000, Jinoh Kang wrote:
Many poorly-written Windows apps & games "use the API incorrectly." We support them, so our tests *intentionally* mirror the incorrect API usage as well. I've removed the validation in light of this
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9809#note_126001
On Mon Dec 22 16:15:56 2025 +0000, Elizabeth Figura wrote:
Looks like the parameter validation I added (based on the documentation) breaks a bunch of tests in obscure places - presumably because they were using the API incorrectly.
Do you think it's worth going through and fixing all usages, or should I just remove the validation? If the tests are breaking, and they currently pass on Windows, presumably the validation is wrong. Microsoft's documentation is not always truthful. Any validation like this that's user-visible should have tests anyway.
+ if (options & FILE_SYNCHRONOUS_IO_NONALERT) flags |= O_SYNC; + if (options & FILE_SYNCHRONOUS_IO_ALERT) flags |= O_SYNC;That's not the same semantics. FILE_SYNCHRONOUS_IO_* is about whether the I/O operation will return STATUS_SUCCESS or STATUS_PENDING (and we already implement it). It doesn't guarantee that the data will be written to disk. I think the corresponding flag there is actually FILE_WRITE_THROUGH. Thanks for catching this. I've changed it to check for FILE_WRITE_THROUGH instead
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9809#note_126002
participants (2)
-
小太 -
小太 (@kotarou3)