summaryrefslogtreecommitdiff
path: root/storage/innobase/fsp/fsp0fsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/fsp/fsp0fsp.c')
-rw-r--r--storage/innobase/fsp/fsp0fsp.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
index 1ec1c262a52..1f033c4b140 100644
--- a/storage/innobase/fsp/fsp0fsp.c
+++ b/storage/innobase/fsp/fsp0fsp.c
@@ -2842,12 +2842,61 @@ fsp_get_available_space_in_free_extents(
ut_ad(!mutex_own(&kernel_mutex));
+ /* The convoluted mutex acquire is to overcome latching order
+ issues: The problem is that the fil_mutex is at a lower level
+ than the tablespace latch and the buffer pool mutex. We have to
+ first prevent any operations on the file system by acquiring the
+ dictionary mutex. Then acquire the tablespace latch to obey the
+ latching order and then release the dictionary mutex. That way we
+ ensure that the tablespace instance can't be freed while we are
+ examining its contents (see fil_space_free()).
+
+ However, there is one further complication, we release the fil_mutex
+ when we need to invalidate the the pages in the buffer pool and we
+ reacquire the fil_mutex when deleting and freeing the tablespace
+ instance in fil0fil.c. Here we need to account for that situation
+ too. */
+
+ dict_mutex_enter_for_mysql();
+
+ /* At this stage there is no guarantee that the tablespace even
+ exists in the cache. */
+
+ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) {
+
+ dict_mutex_exit_for_mysql();
+
+ return(ULLINT_UNDEFINED);
+ }
+
mtr_start(&mtr);
latch = fil_space_get_latch(space);
+ /* This should ensure that the tablespace instance can't be freed
+ by another thread. However, the tablespace pages can still be freed
+ from the buffer pool. We need to check for that again. */
+
mtr_x_lock(latch, &mtr);
+ dict_mutex_exit_for_mysql();
+
+ /* At this point it is possible for the tablespace to be deleted and
+ its pages removed from the buffer pool. We need to check for that
+ situation. However, the tablespace instance can't be deleted because
+ our latching above should ensure that. */
+
+ if (fil_tablespace_is_being_deleted(space)) {
+
+ mtr_commit(&mtr);
+
+ return(ULLINT_UNDEFINED);
+ }
+
+ /* From here on even if the user has dropped the tablespace, the
+ pages _must_ still exist in the buffer pool and the tablespace
+ instance _must be in the file system hash table. */
+
space_header = fsp_get_space_header(space, &mtr);
size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, &mtr);