summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-06-29 14:28:23 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-06-29 14:28:23 +0300
commit58252fff15acfe7c7b0452a87e202e3f8e454e19 (patch)
tree51e7246953d305d65198541730616fe4b1a0aeac
parent8147d2e6183a1a4a4f3db2884966f5da2d17678c (diff)
downloadmariadb-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.cc38
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;