diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2018-06-30 11:02:49 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2018-06-30 11:04:51 +0100 |
commit | c612a1e77c36abe08576d67de30b7e45365cad30 (patch) | |
tree | 2ac1bf33a72a6ee5e0aff2fb93c995da8cb8d7fa | |
parent | 1dd3c8f8ba49ec06e550d7376d27ff05ce024bec (diff) | |
download | mariadb-git-c612a1e77c36abe08576d67de30b7e45365cad30.tar.gz |
MDEV-16596 : Windows - redo log does not work on native 4K sector disks.
Disks with native 4K sectors need 4K alignment and size for unbuffered IO
(i.e for files opened with FILE_FLAG_NO_BUFFERING)
Innodb opens redo log with FILE_FLAG_NO_BUFFERING, however it always does
512byte IOs. Thus, the IO on 4K native sectors will fail, rendering
Innodb 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-- | cmake/os/Windows.cmake | 2 | ||||
-rw-r--r-- | storage/innobase/os/os0file.cc | 97 |
2 files changed, 68 insertions, 31 deletions
diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake index c6cbfca2346..e94099670f9 100644 --- a/cmake/os/Windows.cmake +++ b/cmake/os/Windows.cmake @@ -47,7 +47,7 @@ IF(CMAKE_C_COMPILER MATCHES "icl") ENDIF() ADD_DEFINITIONS(-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE) -ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600) +ADD_DEFINITIONS(-D_WIN32_WINNT=0x0A00) # We do not want the windows.h macros min/max ADD_DEFINITIONS(-DNOMINMAX) # Speed up build process excluding unused header files diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 01b801461d6..45fb04600f3 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4109,6 +4109,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. @@ -4284,46 +4310,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; + /* 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; + } - operation = (create_mode == OS_FILE_CREATE - && !read_only) - ? "create" : "open"; + *success = (file != INVALID_HANDLE_VALUE); + if (*success) { + break; + } - *success = false; + operation = (create_mode == OS_FILE_CREATE && !read_only) ? + "create" : "open"; - 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 { - - 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); } |