Skip to content
Permalink
Browse files
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
  • Loading branch information
vaintroub committed Oct 28, 2020
1 parent db56f9b commit 9478368
Showing 1 changed file with 38 additions and 21 deletions.
@@ -1891,39 +1891,56 @@ os_file_status_win32(
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
function!
Flushes the write buffers of a given file to the disk.
@param[in] file handle to a file
@return true if success */
bool
os_file_flush_func(
os_file_t file)
bool os_file_flush_func(os_file_t file)
{
++os_n_fsyncs;

BOOL ret = FlushFileBuffers(file);
++os_n_fsyncs;
static bool disable_datasync;

if (ret) {
return(true);
}
if (my_NtFlushBuffersFileEx && !disable_datasync)
{
IO_STATUS_BLOCK iosb{};
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;
}

/* Since Windows returns ERROR_INVALID_FUNCTION if the 'file' is
actually a raw device, we choose to ignore that error if we are using
raw disks */
if (FlushFileBuffers(file))
return true;

if (srv_start_raw_disk_in_use && GetLastError()
== ERROR_INVALID_FUNCTION) {
return(true);
}
/* Since Windows returns ERROR_INVALID_FUNCTION if the 'file' is
actually a raw device, we choose to ignore that error if we are using
raw disks */
if (srv_start_raw_disk_in_use && GetLastError() == ERROR_INVALID_FUNCTION)
return true;

os_file_handle_error(NULL, "flush");
os_file_handle_error(nullptr, "flush");

/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
ut_error;
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
ut_error;

return(false);
return false;
}

/** Retrieves the last error number if an error occurs in a file io function.

0 comments on commit 9478368

Please sign in to comment.