diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2018-06-29 22:18:47 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2018-06-29 22:18:47 +0100 |
commit | 84d7df16c020eebb972280c5f406575f837ec75c (patch) | |
tree | b497955f000c61998ad946259dca7c8cb89e4c6a | |
parent | 47510ebbdcdf9841f3b76c1b433fc0e962a098dc (diff) | |
download | mariadb-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.cc | 103 |
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); } |