Skip to content

Commit

Permalink
MDEV-16596 : Windows - redo log does not work on native 4K sector disks.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vaintroub committed Jul 2, 2018
1 parent 3d4beee commit 0897a25
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
2 changes: 1 addition & 1 deletion cmake/os/Windows.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ IF(CMAKE_C_COMPILER MATCHES "icl")
ENDIF()

ADD_DEFINITIONS(-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE)
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501)
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
Expand Down
37 changes: 37 additions & 0 deletions storage/xtradb/os/os0file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1691,6 +1691,31 @@ os_file_set_atomic_writes(
#endif
}

/** 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!
Expand Down Expand Up @@ -1851,6 +1876,18 @@ os_file_create_func(
(LPCTSTR) name, access, share_mode, NULL,
create_flag, attributes, NULL);

/* 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.m_file != INVALID_HANDLE_VALUE)
&& (attributes & FILE_FLAG_NO_BUFFERING)
&& (type == OS_LOG_FILE)
&& !unbuffered_io_possible(file.m_file, OS_FILE_LOG_BLOCK_SIZE)) {
ut_a(CloseHandle(file.m_file));
attributes &= ~FILE_FLAG_NO_BUFFERING;
create_flag = OPEN_ALWAYS;
continue;
}

if (file.m_file == INVALID_HANDLE_VALUE) {
const char* operation;

Expand Down

0 comments on commit 0897a25

Please sign in to comment.