summaryrefslogtreecommitdiff
path: root/storage/innobase/os
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2020-10-27 20:54:03 +0100
committerVladislav Vaintroub <wlad@mariadb.com>2020-10-28 08:30:31 +0100
commit9478368d8193a7ccc14a1b336ef767aed500909c (patch)
treee15abbd66712a75ce93b5cade26da3f6e79df6fe /storage/innobase/os
parentdb56f9b8521077c119d700927510c7a0e54bd820 (diff)
downloadmariadb-git-9478368d8193a7ccc14a1b336ef767aed500909c.tar.gz
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
Diffstat (limited to 'storage/innobase/os')
-rw-r--r--storage/innobase/os/os0file.cc59
1 files changed, 38 insertions, 21 deletions
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 3afb68d26a1..24134479d8e 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -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.