Commit ff2d9e12 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-13941 followup.

Try to fix fragmentation (unsparse files), for pre-existing
installations.

Unsparse the innodb file, when it needs to be extended, unless compression
is used. For Win7/2008R2 unsparse  does not work (as documented in MSDN),
therefore for sparse files in older Windows, file extension will be done
via writing zeroes at the end of file.
parent fe18e6b0
......@@ -1583,8 +1583,10 @@ os_file_set_umask(ulint umask);
Make file sparse, on Windows.
@param[in] file file handle
@param[in] is_sparse if true, make file sparse,
otherwise "unsparse" the file
@return true on success, false on error */
bool os_file_set_sparse_win32(os_file_t file);
bool os_file_set_sparse_win32(os_file_t file, bool is_sparse = true);
/**
Changes file size on Windows
......
......@@ -4743,11 +4743,20 @@ Sets a sparse flag on Windows file.
@param[in] file file handle
@return true on success, false on error
*/
bool os_file_set_sparse_win32(os_file_t file)
#include <versionhelpers.h>
bool os_file_set_sparse_win32(os_file_t file, bool is_sparse)
{
if (!is_sparse && !IsWindows8OrGreater()) {
/* Cannot unset sparse flag on older Windows.
Until Windows8 it is documented to produce unpredictable results,
if there are unallocated ranges in file.*/
return false;
}
DWORD temp;
return os_win32_device_io_control(file, FSCTL_SET_SPARSE, 0, 0, 0, 0,&temp);
FILE_SET_SPARSE_BUFFER sparse_buffer;
sparse_buffer.SetSparse = is_sparse;
return os_win32_device_io_control(file,
FSCTL_SET_SPARSE, &sparse_buffer, sizeof(sparse_buffer), 0, 0,&temp);
}
......@@ -5342,7 +5351,23 @@ os_file_set_size(
bool is_sparse)
{
#ifdef _WIN32
/* On Windows, changing file size works well and as expected for both
sparse and normal files.
However, 10.2 up until 10.2.9 made every file sparse in innodb,
causing NTFS fragmentation issues(MDEV-13941). We try to undo
the damage, and unsparse the file.*/
if (!is_sparse && os_is_sparse_file_supported(file)) {
if (!os_file_set_sparse_win32(file, false))
/* Unsparsing file failed. Fallback to writing binary
zeros, to avoid even higher fragmentation.*/
goto fallback;
}
return os_file_change_size_win32(name, file, size);
fallback:
#else
if (is_sparse) {
bool success = !ftruncate(file, size);
......@@ -5368,6 +5393,7 @@ os_file_set_size(
errno = err;
return(!err);
# endif /* HAVE_POSIX_ALLOCATE */
#endif /* _WIN32*/
/* Write up to 1 megabyte at a time. */
ulint buf_size = ut_min(
......@@ -5386,13 +5412,14 @@ os_file_set_size(
/* Write buffer full of zeros */
memset(buf, 0, buf_size);
if (size >= (os_offset_t) 100 << 20) {
os_offset_t current_size = os_file_get_size(file);
bool write_progress_info =
(size - current_size >= (os_offset_t) 100 << 20);
if (write_progress_info) {
ib::info() << "Progress in MB:";
}
os_offset_t current_size = os_file_get_size(file);
while (current_size < size) {
ulint n_bytes;
......@@ -5415,8 +5442,9 @@ os_file_set_size(
}
/* Print about progress for each 100 MB written */
if ((current_size + n_bytes) / (100 << 20)
!= current_size / (100 << 20)) {
if (write_progress_info &&
((current_size + n_bytes) / (100 << 20)
!= current_size / (100 << 20))) {
fprintf(stderr, " %lu00",
(ulong) ((current_size + n_bytes)
......@@ -5426,7 +5454,7 @@ os_file_set_size(
current_size += n_bytes;
}
if (size >= (os_offset_t) 100 << 20) {
if (write_progress_info) {
fprintf(stderr, "\n");
}
......@@ -5434,7 +5462,6 @@ os_file_set_size(
ut_free(buf2);
return(os_file_flush(file));
#endif /* !WIN32 */
}
/** Truncates a file to a specified size in bytes.
......
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