diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-06-29 14:28:23 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-06-29 14:28:23 +0300 |
commit | 58252fff15acfe7c7b0452a87e202e3f8e454e19 (patch) | |
tree | 51e7246953d305d65198541730616fe4b1a0aeac | |
parent | 8147d2e6183a1a4a4f3db2884966f5da2d17678c (diff) | |
download | mariadb-git-58252fff15acfe7c7b0452a87e202e3f8e454e19.tar.gz |
MDEV-26040 os_file_set_size() may not work on O_DIRECT files
os_file_set_size(): Trim the current size down to the file system
block size, to obey the constraints for unbuffered I/O.
-rw-r--r-- | storage/innobase/os/os0file.cc | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index d2d5769d85e..884cadaf9f6 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -5420,6 +5420,8 @@ os_file_set_size( fallback: #else + struct stat statbuf; + if (is_sparse) { bool success = !ftruncate(file, size); if (!success) { @@ -5433,10 +5435,17 @@ fallback: # ifdef HAVE_POSIX_FALLOCATE int err; do { - os_offset_t current_size = os_file_get_size(file); - err = current_size >= size - ? 0 : posix_fallocate(file, current_size, + if (fstat(file, &statbuf)) { + err = errno; + } else { + os_offset_t current_size = statbuf.st_size; + if (current_size >= size) { + return true; + } + current_size &= ~os_offset_t(statbuf.st_blksize - 1); + err = posix_fallocate(file, current_size, size - current_size); + } } while (err == EINTR && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED); @@ -5459,6 +5468,27 @@ fallback: # endif /* HAVE_POSIX_ALLOCATE */ #endif /* _WIN32*/ +#ifdef _WIN32 + os_offset_t current_size = os_file_get_size(file); + FILE_STORAGE_INFO info; + if (GetFileInformationByHandleEx(file, FileStorageInfo, &info, + sizeof info)) { + if (info.LogicalBytesPerSector) { + current_size &= ~os_offset_t(info.LogicalBytesPerSector + - 1); + } + } +#else + if (fstat(file, &statbuf)) { + return false; + } + os_offset_t current_size = statbuf.st_size + & ~os_offset_t(statbuf.st_blksize - 1); +#endif + if (current_size >= size) { + return true; + } + /* Write up to 1 megabyte at a time. */ ulint buf_size = ut_min( static_cast<ulint>(64), @@ -5476,8 +5506,6 @@ fallback: /* Write buffer full of zeros */ memset(buf, 0, buf_size); - os_offset_t current_size = os_file_get_size(file); - while (current_size < size && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { ulint n_bytes; |