diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-02-20 17:58:42 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-02-21 16:45:03 +0200 |
commit | 978179a9d4933d3d8d2ac99028798e8a07095dd4 (patch) | |
tree | a4f21dbbd812e8c347413f7ead578b1677d08691 /storage/xtradb/os | |
parent | 2bfe83adec576a27aed2d87ff65cebddc3430d2e (diff) | |
download | mariadb-git-978179a9d4933d3d8d2ac99028798e8a07095dd4.tar.gz |
MDEV-11520 Extending an InnoDB data file unnecessarily allocates
a large memory buffer on Windows
fil_extend_space_to_desired_size(), os_file_set_size(): Use calloc()
for memory allocation, and handle failures. Properly check the return
status of posix_fallocate().
On Windows, instead of extending the file by at most 1 megabyte at a time,
write a zero-filled page at the end of the file.
According to the Microsoft blog post
https://blogs.msdn.microsoft.com/oldnewthing/20110922-00/?p=9573
this will physically extend the file by writing zero bytes.
(InnoDB never uses DeviceIoControl() to set the file sparse.)
For innodb_plugin, port the XtraDB fix for MySQL Bug#56433
(introducing fil_system->file_extend_mutex). The bug was
fixed differently in MySQL 5.6 (and MariaDB Server 10.0).
Diffstat (limited to 'storage/xtradb/os')
-rw-r--r-- | storage/xtradb/os/os0file.c | 76 |
1 files changed, 28 insertions, 48 deletions
diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c index cca5ffa4772..201e4487ada 100644 --- a/storage/xtradb/os/os0file.c +++ b/storage/xtradb/os/os0file.c @@ -2,6 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. +Copyright (c) 2011, 2017, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -2184,42 +2185,44 @@ os_file_set_size( ut_a(size == (size & 0xFFFFFFFF)); - current_size = 0; desired_size = (ib_int64_t)size + (((ib_int64_t)size_high) << 32); #ifdef HAVE_POSIX_FALLOCATE if (srv_use_posix_fallocate) { - - if (posix_fallocate(file, current_size, desired_size) == -1) { - - fprintf(stderr, "InnoDB: Error: preallocating file " - "space for file \'%s\' failed. Current size " - "%lld, desired size %lld\n", - name, current_size, desired_size); - os_file_handle_error_no_exit(name, "posix_fallocate"); - return(FALSE); + int err = posix_fallocate(file, 0, desired_size); + if (err) { + fprintf(stderr, + "InnoDB: Error: preallocating %lld bytes for" + " file %s failed with error %d.\n", + desired_size, name, err); } - return(TRUE); + return(!err); } #endif +#ifdef _WIN32 + /* Write 1 page of zeroes at the desired end. */ + buf_size = UNIV_PAGE_SIZE; + current_size = desired_size - buf_size; +#else /* Write up to 1 megabyte at a time. */ buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE)) * UNIV_PAGE_SIZE; - buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE); + current_size = 0; +#endif + buf2 = calloc(1, buf_size + UNIV_PAGE_SIZE); + + if (!buf2) { + fprintf(stderr, "InnoDB: Cannot allocate " ULINTPF + " bytes to extend file\n", + buf_size + UNIV_PAGE_SIZE); + return(FALSE); + } /* Align the buffer for possible raw i/o */ buf = ut_align(buf2, UNIV_PAGE_SIZE); - /* Write buffer full of zeros */ - memset(buf, 0, buf_size); - - if (desired_size >= (ib_int64_t)(100 * 1024 * 1024)) { - - fprintf(stderr, "InnoDB: Progress in MB:"); - } - - while (current_size < desired_size) { + do { ulint n_bytes; if (desired_size - current_size < (ib_int64_t) buf_size) { @@ -2233,37 +2236,14 @@ os_file_set_size( (ulint)(current_size >> 32), n_bytes); if (!ret) { - ut_free(buf2); - goto error_handling; - } - - /* Print about progress for each 100 MB written */ - if ((ib_int64_t) (current_size + n_bytes) / (ib_int64_t)(100 * 1024 * 1024) - != current_size / (ib_int64_t)(100 * 1024 * 1024)) { - - fprintf(stderr, " %lu00", - (ulong) ((current_size + n_bytes) - / (ib_int64_t)(100 * 1024 * 1024))); + break; } current_size += n_bytes; - } - - if (desired_size >= (ib_int64_t)(100 * 1024 * 1024)) { - - fprintf(stderr, "\n"); - } - - ut_free(buf2); - - ret = os_file_flush(file, TRUE); - - if (ret) { - return(TRUE); - } + } while (current_size < desired_size); -error_handling: - return(FALSE); + free(buf2); + return(ret && os_file_flush(file, TRUE)); } /***********************************************************************//** |