summaryrefslogtreecommitdiff
path: root/storage/xtradb/os
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-02-21 16:52:41 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2017-02-22 12:21:44 +0200
commit81695ab8b53013c302b50e015836d38146436cba (patch)
treeb84d73ed2125a46660a090217794d12d0c573efe /storage/xtradb/os
parent6dc00f97b7db13975a26fd92ffd08aaa60339b87 (diff)
downloadmariadb-git-81695ab8b53013c302b50e015836d38146436cba.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(), and pass the correct arguments to 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.) I tested that the file extension works properly with a multi-file system tablespace, both with --innodb-use-fallocate and --skip-innodb-use-fallocate (the default): ./mtr \ --mysqld=--innodb-use-fallocate \ --mysqld=--innodb-autoextend-increment=1 \ --mysqld=--innodb-data-file-path='ibdata1:5M;ibdata2:5M:autoextend' \ --parallel=auto --force --retry=0 --suite=innodb & ls -lsh mysql-test/var/*/mysqld.1/data/ibdata2 (several samples while running the test)
Diffstat (limited to 'storage/xtradb/os')
-rw-r--r--storage/xtradb/os/os0file.cc79
1 files changed, 28 insertions, 51 deletions
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index bf957d24ea7..5e7a0251a00 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted
by Percona Inc.. Those modifications are
@@ -2341,48 +2341,47 @@ os_file_set_size(
os_file_t file, /*!< in: handle to a file */
os_offset_t size) /*!< in: file size */
{
- os_offset_t current_size;
ibool ret;
byte* buf;
byte* buf2;
ulint buf_size;
- current_size = 0;
-
#ifdef HAVE_POSIX_FALLOCATE
if (srv_use_posix_fallocate) {
-
- if (posix_fallocate(file, current_size, size) == -1) {
-
- ib_logf(IB_LOG_LEVEL_ERROR, "preallocating file "
- "space for file \'%s\' failed. Current size "
- INT64PF ", desired size " INT64PF,
- name, current_size, size);
- os_file_handle_error_no_exit (name, "posix_fallocate",
- FALSE);
- return(FALSE);
+ int err = posix_fallocate(file, 0, size);
+ if (err) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "preallocating " INT64PF " bytes for"
+ "file %s failed with error %d",
+ size, name, err);
}
- return(TRUE);
+ return(!err);
}
#endif
+#ifdef _WIN32
+ /* Write 1 page of zeroes at the desired end. */
+ buf_size = UNIV_PAGE_SIZE;
+ os_offset_t current_size = size - buf_size;
+#else
/* Write up to 1 megabyte at a time. */
buf_size = ut_min(64, (ulint) (size / UNIV_PAGE_SIZE))
* UNIV_PAGE_SIZE;
- buf2 = static_cast<byte*>(ut_malloc(buf_size + UNIV_PAGE_SIZE));
+ os_offset_t current_size = 0;
+#endif
+ buf2 = static_cast<byte*>(calloc(1, buf_size + UNIV_PAGE_SIZE));
+
+ if (!buf2) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Cannot allocate " ULINTPF " bytes to extend file\n",
+ buf_size + UNIV_PAGE_SIZE);
+ return(FALSE);
+ }
/* Align the buffer for possible raw i/o */
buf = static_cast<byte*>(ut_align(buf2, UNIV_PAGE_SIZE));
- /* Write buffer full of zeros */
- memset(buf, 0, buf_size);
-
- if (size >= (os_offset_t) 100 << 20) {
-
- fprintf(stderr, "InnoDB: Progress in MB:");
- }
-
- while (current_size < size) {
+ do {
ulint n_bytes;
if (size - current_size < (os_offset_t) buf_size) {
@@ -2393,37 +2392,15 @@ os_file_set_size(
ret = os_file_write(name, file, buf, current_size, n_bytes);
if (!ret) {
- ut_free(buf2);
- goto error_handling;
- }
-
- /* Print about progress for each 100 MB written */
- if ((current_size + n_bytes) / (100 << 20)
- != current_size / (100 << 20)) {
-
- fprintf(stderr, " %lu00",
- (ulong) ((current_size + n_bytes)
- / (100 << 20)));
+ break;
}
current_size += n_bytes;
- }
-
- if (size >= (os_offset_t) 100 << 20) {
+ } while (current_size < size);
- fprintf(stderr, "\n");
- }
-
- ut_free(buf2);
-
- ret = os_file_flush(file);
-
- if (ret) {
- return(TRUE);
- }
+ free(buf2);
-error_handling:
- return(FALSE);
+ return(ret && os_file_flush(file));
}
/***********************************************************************//**