summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-01-23 12:05:24 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-01-23 12:18:00 +0200
commit31d592ba7d3a2d2d227e5d4bf36f0866c9932c57 (patch)
tree3a388a682245a4a1f11de786f1c3b8689027f984
parent6786fb004c5f88f2d4da6534c49456e90676274d (diff)
downloadmariadb-git-31d592ba7d3a2d2d227e5d4bf36f0866c9932c57.tar.gz
MDEV-18349 InnoDB file size changes are not safe when file system crashes
When InnoDB is invoking posix_fallocate() to extend data files, it was missing a call to fsync() to update the file system metadata. If file system recovery is needed, the file size could be incorrect. When the setting innodb_flush_method=O_DIRECT_NO_FSYNC that was introduced in MariaDB 10.0.11 (and MySQL 5.6) is enabled, InnoDB would wrongly skip fsync() after extending files. Furthermore, the merge commit d8b45b0c004edc0b91029b232d7cc9aad02cc822 inadvertently removed XtraDB error checking for posix_fallocate() which this fix is restoring. fil_flush(): Add the parameter bool metadata=false to request that fil_buffering_disabled() be ignored. fil_extend_space_to_desired_size(): Invoke fil_flush() with the extra parameter. After successful posix_fallocate(), invoke os_file_flush(). Note: The bookkeeping for fil_flush() would not be updated the posix_fallocate() code path, so the "redundant" fil_flush() should be a no-op.
-rw-r--r--storage/innobase/fil/fil0fil.cc27
-rw-r--r--storage/innobase/include/fil0fil.h16
-rw-r--r--storage/xtradb/fil/fil0fil.cc36
-rw-r--r--storage/xtradb/include/fil0fil.h16
4 files changed, 47 insertions, 48 deletions
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index f852a64e2e9..e05d9565507 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2014, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -4914,6 +4914,8 @@ retry:
" failed with error %d",
node->name, start_offset, len + start_offset,
err);
+ } else {
+ os_file_flush(node->handle);
}
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
@@ -5025,7 +5027,7 @@ file_extended:
size_after_extend, *actual_size); */
mutex_exit(&fil_system->mutex);
- fil_flush(space_id);
+ fil_flush(space_id, true);
return(success);
}
@@ -5641,21 +5643,16 @@ fil_aio_wait(
}
#endif /* UNIV_HOTBACKUP */
-/**********************************************************************//**
-Flushes to disk possible writes cached by the OS. If the space does not exist
-or is being dropped, does not do anything. */
-UNIV_INTERN
-void
-fil_flush(
-/*======*/
- ulint space_id) /*!< in: file space id (this can be a group of
- log files or a tablespace of the database) */
+/** Make persistent possible writes cached by the OS.
+If the space does not exist or is being dropped, do nothing.
+@param[in] space_id tablespace identifier
+@param[in] metadata whether to update file system metadata */
+UNIV_INTERN void fil_flush(ulint space_id, bool metadata)
{
fil_space_t* space;
fil_node_t* node;
pfs_os_file_t file;
-
mutex_enter(&fil_system->mutex);
space = fil_space_get_by_id(space_id);
@@ -5684,8 +5681,10 @@ fil_flush(
}
#endif /* UNIV_DEBUG */
- mutex_exit(&fil_system->mutex);
- return;
+ if (!metadata) {
+ mutex_exit(&fil_system->mutex);
+ return;
+ }
}
space->n_pending_flushes++; /*!< prevent dropping of the space while
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 7c0f623d890..ad279487a3d 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -972,15 +972,11 @@ fil_aio_wait(
/*=========*/
ulint segment); /*!< in: the number of the segment in the aio
array to wait for */
-/**********************************************************************//**
-Flushes to disk possible writes cached by the OS. If the space does not exist
-or is being dropped, does not do anything. */
-UNIV_INTERN
-void
-fil_flush(
-/*======*/
- ulint space_id); /*!< in: file space id (this can be a group of
- log files or a tablespace of the database) */
+/** Make persistent possible writes cached by the OS.
+If the space does not exist or is being dropped, do nothing.
+@param[in] space_id tablespace identifier
+@param[in] metadata whether to update file system metadata */
+UNIV_INTERN void fil_flush(ulint space_id, bool metadata = false);
/**********************************************************************//**
Flushes to disk writes in file spaces of the given type possibly cached by
the OS. */
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 49c5f4b090b..755672d9962 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2014, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -4947,6 +4947,17 @@ retry:
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
+ success = !err;
+ if (!success) {
+ ib_logf(IB_LOG_LEVEL_ERROR, "extending file %s"
+ " from " INT64PF " to " INT64PF " bytes"
+ " failed with error %d",
+ node->name, start_offset, len + start_offset,
+ err);
+ } else {
+ os_file_flush(node->handle);
+ }
+
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
success = FALSE; os_has_said_disk_full = TRUE;);
@@ -5056,7 +5067,7 @@ file_extended:
size_after_extend, *actual_size); */
mutex_exit(&fil_system->mutex);
- fil_flush(space_id);
+ fil_flush(space_id, true);
return(success);
}
@@ -5705,21 +5716,16 @@ fil_aio_wait(
}
#endif /* UNIV_HOTBACKUP */
-/**********************************************************************//**
-Flushes to disk possible writes cached by the OS. If the space does not exist
-or is being dropped, does not do anything. */
-UNIV_INTERN
-void
-fil_flush(
-/*======*/
- ulint space_id) /*!< in: file space id (this can be a group of
- log files or a tablespace of the database) */
+/** Make persistent possible writes cached by the OS.
+If the space does not exist or is being dropped, do nothing.
+@param[in] space_id tablespace identifier
+@param[in] metadata whether to update file system metadata */
+UNIV_INTERN void fil_flush(ulint space_id, bool metadata)
{
fil_space_t* space;
fil_node_t* node;
pfs_os_file_t file;
-
mutex_enter(&fil_system->mutex);
space = fil_space_get_by_id(space_id);
@@ -5748,8 +5754,10 @@ fil_flush(
}
#endif /* UNIV_DEBUG */
- mutex_exit(&fil_system->mutex);
- return;
+ if (!metadata) {
+ mutex_exit(&fil_system->mutex);
+ return;
+ }
}
space->n_pending_flushes++; /*!< prevent dropping of the space while
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 1f3574d4f71..8e737f8fb0e 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -976,15 +976,11 @@ fil_aio_wait(
/*=========*/
ulint segment); /*!< in: the number of the segment in the aio
array to wait for */
-/**********************************************************************//**
-Flushes to disk possible writes cached by the OS. If the space does not exist
-or is being dropped, does not do anything. */
-UNIV_INTERN
-void
-fil_flush(
-/*======*/
- ulint space_id); /*!< in: file space id (this can be a group of
- log files or a tablespace of the database) */
+/** Make persistent possible writes cached by the OS.
+If the space does not exist or is being dropped, do nothing.
+@param[in] space_id tablespace identifier
+@param[in] metadata whether to update file system metadata */
+UNIV_INTERN void fil_flush(ulint space_id, bool metadata = false);
/**********************************************************************//**
Flushes to disk writes in file spaces of the given type possibly cached by
the OS. */