Commit 9478368d authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-24037 Use NtFlushBuffersFileEx(FLUSH_FLAGS_FILE_DATA_SYNC_ONLY) on Windows

This avoids flushing file metadata on NTFS , and writing to <drive>:\$Log
file. With heavy write workload this can consume up to 1/3 of the
server's IO bandwidth.

Reviewed by : Marko
parent db56f9b8
...@@ -1891,39 +1891,56 @@ os_file_status_win32( ...@@ -1891,39 +1891,56 @@ os_file_status_win32(
return(true); return(true);
} }
/* Dynamically load NtFlushBuffersFileEx, used in os_file_flush_func */
#include <winternl.h>
typedef NTSTATUS(WINAPI* pNtFlushBuffersFileEx)(
HANDLE FileHandle, ULONG Flags, PVOID Parameters, ULONG ParametersSize,
PIO_STATUS_BLOCK IoStatusBlock);
static pNtFlushBuffersFileEx my_NtFlushBuffersFileEx
= (pNtFlushBuffersFileEx)GetProcAddress(GetModuleHandle("ntdll"),
"NtFlushBuffersFileEx");
/** NOTE! Use the corresponding macro os_file_flush(), not directly this /** NOTE! Use the corresponding macro os_file_flush(), not directly this
function! function!
Flushes the write buffers of a given file to the disk. Flushes the write buffers of a given file to the disk.
@param[in] file handle to a file @param[in] file handle to a file
@return true if success */ @return true if success */
bool bool os_file_flush_func(os_file_t file)
os_file_flush_func(
os_file_t file)
{ {
++os_n_fsyncs; ++os_n_fsyncs;
static bool disable_datasync;
BOOL ret = FlushFileBuffers(file); if (my_NtFlushBuffersFileEx && !disable_datasync)
{
if (ret) { IO_STATUS_BLOCK iosb{};
return(true); NTSTATUS status= my_NtFlushBuffersFileEx(
file, FLUSH_FLAGS_FILE_DATA_SYNC_ONLY, nullptr, 0, &iosb);
if (!status)
return true;
/*
NtFlushBuffersFileEx(FLUSH_FLAGS_FILE_DATA_SYNC_ONLY) might fail
unless on Win10+, and maybe non-NTFS. Switch to using FlushFileBuffers().
*/
disable_datasync= true;
} }
if (FlushFileBuffers(file))
return true;
/* Since Windows returns ERROR_INVALID_FUNCTION if the 'file' is /* Since Windows returns ERROR_INVALID_FUNCTION if the 'file' is
actually a raw device, we choose to ignore that error if we are using actually a raw device, we choose to ignore that error if we are using
raw disks */ raw disks */
if (srv_start_raw_disk_in_use && GetLastError() == ERROR_INVALID_FUNCTION)
return true;
if (srv_start_raw_disk_in_use && GetLastError() os_file_handle_error(nullptr, "flush");
== ERROR_INVALID_FUNCTION) {
return(true);
}
os_file_handle_error(NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then /* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */ the database can get corrupt on disk */
ut_error; ut_error;
return(false); return false;
} }
/** Retrieves the last error number if an error occurs in a file io function. /** Retrieves the last error number if an error occurs in a file io function.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment