Commit c612a1e7 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

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.
parent 1dd3c8f8
......@@ -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
......
......@@ -4109,6 +4109,32 @@ os_file_readdir_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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment