summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2018-06-29 22:18:47 +0100
committerVladislav Vaintroub <wlad@mariadb.com>2018-06-29 22:18:47 +0100
commit84d7df16c020eebb972280c5f406575f837ec75c (patch)
treeb497955f000c61998ad946259dca7c8cb89e4c6a
parent47510ebbdcdf9841f3b76c1b433fc0e962a098dc (diff)
downloadmariadb-git-bb-10.3-findgssapi.tar.gz
MDEV-16596 : Windows - redo log does not work on native 4K sector disks.bb-10.3-findgssapi
Disks with native 4K sectors need 4K alignment and size for unbuffered IO (i.e files opened with FILE_FLAG_NO_BUFFERING) Innodb opens redo log with FILE_FLAG_NO_BUFFERING, but it does 512byte IOs Thus, the IO fails, and Innodb is non-functional. The fix is to check whether OS_FILE_LOG_BLOCK_SIZE is multiple of logical sector size, and if it is not, reopen the redo log without FILE_FLAG_NO_BUFFERING flag.
-rw-r--r--storage/innobase/os/os0file.cc103
1 files changed, 73 insertions, 30 deletions
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index da3b2822fa0..304b1aaa3e6 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -33,6 +33,12 @@ The interface to the operating system file i/o primitives
Created 10/21/1995 Heikki Tuuri
*******************************************************/
+/* Need some Windows 8 constants and structs.*/
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0602
+#endif
+
#ifndef UNIV_INNOCHECKSUM
#include "ha_prototypes.h"
@@ -4062,6 +4068,32 @@ next_file:
return(status);
}
+/** Check that IO of specific size is possible for the file
+opened with FILE_FLAG_NO_BUFFERING.
+
+The requirement is that IO is multiple of the disk sector size.
+
+@param[in] file file handle
+@param[in] io_size expected io size
+@return true - unbuffered io of requested size is possible, false otherwise.
+
+@note: this function only works correctly with Windows 8 or later,
+(GetFileInformationByHandleEx with FileStorageInfo is only supported there).
+It will return true on earlier Windows version.
+ */
+static bool unbuffered_io_possible(HANDLE file, size_t io_size)
+{
+ FILE_STORAGE_INFO info;
+ if (GetFileInformationByHandleEx(
+ file, FileStorageInfo, &info, sizeof(info))) {
+ ULONG sector_size = info.LogicalBytesPerSector;
+ if (sector_size)
+ return io_size % sector_size == 0;
+ }
+ return true;
+}
+
+
/** NOTE! Use the corresponding macro os_file_create(), not directly
this function!
Opens an existing file or creates a new.
@@ -4237,46 +4269,57 @@ os_file_create_func(
access |= GENERIC_WRITE;
}
- do {
+ for (;;) {
+ const char *operation;
+
/* Use default security attributes and no template file. */
file = CreateFile(
- (LPCTSTR) name, access, share_mode, NULL,
+ name, access, share_mode, NULL,
create_flag, attributes, NULL);
- if (file == INVALID_HANDLE_VALUE) {
- const char* operation;
-
- operation = (create_mode == OS_FILE_CREATE
- && !read_only)
- ? "create" : "open";
+ /* If FILE_FLAG_NO_BUFFERING was set, check if this can work at all,
+ for expected IO sizes. Reopen without the unbuffered flag, if it is won't work*/
+ if ((file != INVALID_HANDLE_VALUE)
+ && (attributes & FILE_FLAG_NO_BUFFERING)
+ && (type == OS_LOG_FILE)
+ && !unbuffered_io_possible(file, OS_FILE_LOG_BLOCK_SIZE)) {
+ ut_a(CloseHandle(file));
+ attributes &= ~FILE_FLAG_NO_BUFFERING;
+ continue;
+ }
- *success = false;
+ *success = (file != INVALID_HANDLE_VALUE);
+ if (*success) {
+ break;
+ }
- if (on_error_no_exit) {
- retry = os_file_handle_error_no_exit(
- name, operation, on_error_silent);
- } else {
- retry = os_file_handle_error(name, operation);
- }
- } else {
+ operation = (create_mode == OS_FILE_CREATE && !read_only) ?
+ "create" : "open";
- retry = false;
+ if (on_error_no_exit) {
+ retry = os_file_handle_error_no_exit(
+ name, operation, on_error_silent);
+ }
+ else {
+ retry = os_file_handle_error(name, operation);
+ }
- *success = true;
+ if (!retry) {
+ break;
+ }
+ }
- if (srv_use_native_aio && ((attributes & FILE_FLAG_OVERLAPPED) != 0)) {
- /* Bind the file handle to completion port. Completion port
- might not be created yet, in some stages of backup, but
- must always be there for the server.*/
- HANDLE port =(type == OS_LOG_FILE)?
- log_completion_port : data_completion_port;
- ut_a(port || srv_operation != SRV_OPERATION_NORMAL);
- if (port) {
- ut_a(CreateIoCompletionPort(file, port, 0, 0));
- }
- }
+ if (*success && srv_use_native_aio && (attributes & FILE_FLAG_OVERLAPPED)) {
+ /* Bind the file handle to completion port. Completion port
+ might not be created yet, in some stages of backup, but
+ must always be there for the server.*/
+ HANDLE port = (type == OS_LOG_FILE) ?
+ log_completion_port : data_completion_port;
+ ut_a(port || srv_operation != SRV_OPERATION_NORMAL);
+ if (port) {
+ ut_a(CreateIoCompletionPort(file, port, 0, 0));
}
- } while (retry);
+ }
return(file);
}