Skip to content

Commit c612a1e

Browse files
committed
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.
1 parent 1dd3c8f commit c612a1e

File tree

2 files changed

+68
-31
lines changed

2 files changed

+68
-31
lines changed

cmake/os/Windows.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ IF(CMAKE_C_COMPILER MATCHES "icl")
4747
ENDIF()
4848

4949
ADD_DEFINITIONS(-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE)
50-
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600)
50+
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0A00)
5151
# We do not want the windows.h macros min/max
5252
ADD_DEFINITIONS(-DNOMINMAX)
5353
# Speed up build process excluding unused header files

storage/innobase/os/os0file.cc

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4109,6 +4109,32 @@ os_file_readdir_next_file(
41094109
return(status);
41104110
}
41114111

4112+
/** Check that IO of specific size is possible for the file
4113+
opened with FILE_FLAG_NO_BUFFERING.
4114+
4115+
The requirement is that IO is multiple of the disk sector size.
4116+
4117+
@param[in] file file handle
4118+
@param[in] io_size expected io size
4119+
@return true - unbuffered io of requested size is possible, false otherwise.
4120+
4121+
@note: this function only works correctly with Windows 8 or later,
4122+
(GetFileInformationByHandleEx with FileStorageInfo is only supported there).
4123+
It will return true on earlier Windows version.
4124+
*/
4125+
static bool unbuffered_io_possible(HANDLE file, size_t io_size)
4126+
{
4127+
FILE_STORAGE_INFO info;
4128+
if (GetFileInformationByHandleEx(
4129+
file, FileStorageInfo, &info, sizeof(info))) {
4130+
ULONG sector_size = info.LogicalBytesPerSector;
4131+
if (sector_size)
4132+
return io_size % sector_size == 0;
4133+
}
4134+
return true;
4135+
}
4136+
4137+
41124138
/** NOTE! Use the corresponding macro os_file_create(), not directly
41134139
this function!
41144140
Opens an existing file or creates a new.
@@ -4284,46 +4310,57 @@ os_file_create_func(
42844310
access |= GENERIC_WRITE;
42854311
}
42864312

4287-
do {
4313+
for (;;) {
4314+
const char *operation;
4315+
42884316
/* Use default security attributes and no template file. */
42894317
file = CreateFile(
4290-
(LPCTSTR) name, access, share_mode, NULL,
4318+
name, access, share_mode, NULL,
42914319
create_flag, attributes, NULL);
42924320

4293-
if (file == INVALID_HANDLE_VALUE) {
4294-
const char* operation;
4321+
/* If FILE_FLAG_NO_BUFFERING was set, check if this can work at all,
4322+
for expected IO sizes. Reopen without the unbuffered flag, if it is won't work*/
4323+
if ((file != INVALID_HANDLE_VALUE)
4324+
&& (attributes & FILE_FLAG_NO_BUFFERING)
4325+
&& (type == OS_LOG_FILE)
4326+
&& !unbuffered_io_possible(file, OS_FILE_LOG_BLOCK_SIZE)) {
4327+
ut_a(CloseHandle(file));
4328+
attributes &= ~FILE_FLAG_NO_BUFFERING;
4329+
continue;
4330+
}
42954331

4296-
operation = (create_mode == OS_FILE_CREATE
4297-
&& !read_only)
4298-
? "create" : "open";
4332+
*success = (file != INVALID_HANDLE_VALUE);
4333+
if (*success) {
4334+
break;
4335+
}
42994336

4300-
*success = false;
4337+
operation = (create_mode == OS_FILE_CREATE && !read_only) ?
4338+
"create" : "open";
43014339

4302-
if (on_error_no_exit) {
4303-
retry = os_file_handle_error_no_exit(
4304-
name, operation, on_error_silent);
4305-
} else {
4306-
retry = os_file_handle_error(name, operation);
4307-
}
4308-
} else {
4309-
4310-
retry = false;
4340+
if (on_error_no_exit) {
4341+
retry = os_file_handle_error_no_exit(
4342+
name, operation, on_error_silent);
4343+
}
4344+
else {
4345+
retry = os_file_handle_error(name, operation);
4346+
}
43114347

4312-
*success = true;
4348+
if (!retry) {
4349+
break;
4350+
}
4351+
}
43134352

4314-
if (srv_use_native_aio && ((attributes & FILE_FLAG_OVERLAPPED) != 0)) {
4315-
/* Bind the file handle to completion port. Completion port
4316-
might not be created yet, in some stages of backup, but
4317-
must always be there for the server.*/
4318-
HANDLE port =(type == OS_LOG_FILE)?
4319-
log_completion_port : data_completion_port;
4320-
ut_a(port || srv_operation != SRV_OPERATION_NORMAL);
4321-
if (port) {
4322-
ut_a(CreateIoCompletionPort(file, port, 0, 0));
4323-
}
4324-
}
4353+
if (*success && srv_use_native_aio && (attributes & FILE_FLAG_OVERLAPPED)) {
4354+
/* Bind the file handle to completion port. Completion port
4355+
might not be created yet, in some stages of backup, but
4356+
must always be there for the server.*/
4357+
HANDLE port = (type == OS_LOG_FILE) ?
4358+
log_completion_port : data_completion_port;
4359+
ut_a(port || srv_operation != SRV_OPERATION_NORMAL);
4360+
if (port) {
4361+
ut_a(CreateIoCompletionPort(file, port, 0, 0));
43254362
}
4326-
} while (retry);
4363+
}
43274364

43284365
return(file);
43294366
}

0 commit comments

Comments
 (0)