diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-02-21 16:52:41 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-02-22 12:21:44 +0200 |
commit | 81695ab8b53013c302b50e015836d38146436cba (patch) | |
tree | b84d73ed2125a46660a090217794d12d0c573efe /storage/xtradb/os | |
parent | 6dc00f97b7db13975a26fd92ffd08aaa60339b87 (diff) | |
download | mariadb-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.cc | 79 |
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)); } /***********************************************************************//** |