Commit 7f67ef14 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-16115 Hang after reducing innodb_encryption_threads

The test encryption.create_or_replace would occasionally fail,
because some fil_space_t::n_pending_ops would never be decremented.

fil_crypt_find_space_to_rotate(): If rotate_thread_t::should_shutdown()
holds due to innodb_encryption_threads having been reduced, do
release the reference.

fil_space_remove_from_keyrotation(), fil_space_next(): Declare the
functions static, simplify a little, and define in the same compilation
unit with the only caller, fil_crypt_find_space_to_rotate().

fil_crypt_key_mutex: Remove (unused).
parent 3e3da164
...@@ -44,15 +44,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com ...@@ -44,15 +44,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
#include "ha_prototypes.h" // IB_LOG_ #include "ha_prototypes.h" // IB_LOG_
#include <my_crypt.h> #include <my_crypt.h>
/** Mutex for keys */
static ib_mutex_t fil_crypt_key_mutex;
static bool fil_crypt_threads_inited = false; static bool fil_crypt_threads_inited = false;
#ifdef UNIV_PFS_MUTEX
static mysql_pfs_key_t fil_crypt_key_mutex_key;
#endif
/** Is encryption enabled/disabled */ /** Is encryption enabled/disabled */
UNIV_INTERN ulong srv_encrypt_tables = 0; UNIV_INTERN ulong srv_encrypt_tables = 0;
...@@ -133,9 +126,6 @@ UNIV_INTERN ...@@ -133,9 +126,6 @@ UNIV_INTERN
void void
fil_space_crypt_init() fil_space_crypt_init()
{ {
mutex_create(fil_crypt_key_mutex_key,
&fil_crypt_key_mutex, SYNC_NO_ORDER_CHECK);
fil_crypt_throttle_sleep_event = os_event_create(); fil_crypt_throttle_sleep_event = os_event_create();
mutex_create(fil_crypt_stat_mutex_key, mutex_create(fil_crypt_stat_mutex_key,
...@@ -152,7 +142,6 @@ fil_space_crypt_cleanup() ...@@ -152,7 +142,6 @@ fil_space_crypt_cleanup()
{ {
os_event_free(fil_crypt_throttle_sleep_event); os_event_free(fil_crypt_throttle_sleep_event);
fil_crypt_throttle_sleep_event = NULL; fil_crypt_throttle_sleep_event = NULL;
mutex_free(&fil_crypt_key_mutex);
mutex_free(&crypt_stat_mutex); mutex_free(&crypt_stat_mutex);
} }
...@@ -1451,6 +1440,109 @@ fil_crypt_return_iops( ...@@ -1451,6 +1440,109 @@ fil_crypt_return_iops(
fil_crypt_update_total_stat(state); fil_crypt_update_total_stat(state);
} }
/** Remove space from key rotation list if there are no pending operations. */
static void fil_space_remove_from_keyrotation(fil_space_t *space)
{
ut_ad(mutex_own(&fil_system->mutex));
if (space->n_pending_ops == 0 && space->is_in_rotation_list)
{
space->is_in_rotation_list= false;
ut_a(UT_LIST_GET_LEN(fil_system->rotation_list) > 0);
UT_LIST_REMOVE(rotation_list, fil_system->rotation_list, space);
}
}
/** Return the next tablespace from key rotation list.
@param space previous tablespace (NULL to start from the beginning)
@return pointer to the next tablespace (with n_pending_ops incremented)
@retval NULL if this was the last */
static fil_space_t *fil_space_keyrotate_next(fil_space_t *space)
{
ut_ad(mutex_own(&fil_system->mutex));
if (UT_LIST_GET_LEN(fil_system->rotation_list) == 0)
{
if (space)
{
space->n_pending_ops--;
fil_space_remove_from_keyrotation(space);
}
return NULL;
}
if (!space)
{
space= UT_LIST_GET_FIRST(fil_system->rotation_list);
/* We can trust that space is not NULL because we
checked list length above */
}
else
{
space->n_pending_ops--;
fil_space_t *old = space;
space= UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
/* Skip spaces that are being created by fil_ibd_create(),
or dropped. Note that rotation_list contains only
space->purpose == FIL_TABLESPACE. */
while (space && (!UT_LIST_GET_LEN(space->chain) || space->is_stopping()))
{
fil_space_t *old = space;
space= UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
if (space)
space->n_pending_ops++;
return space;
}
/** Return the next tablespace.
@param space previous tablespace (NULL to start from the beginning)
@return pointer to the next tablespace (with n_pending_ops incremented)
@retval NULL if this was the last */
static fil_space_t *fil_space_next(fil_space_t *space)
{
mutex_enter(&fil_system->mutex);
ut_ad(!space || space->n_pending_ops);
if (!srv_fil_crypt_rotate_key_age)
space= fil_space_keyrotate_next(space);
else if (!space)
{
space= UT_LIST_GET_FIRST(fil_system->space_list);
/* We can trust that space is not NULL because at least the
system tablespace is always present and loaded first. */
space->n_pending_ops++;
}
else
{
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
space= UT_LIST_GET_NEXT(space_list, space);
/* Skip abnormal tablespaces or those that are being created by
fil_ibd_create(), or being dropped. */
while (space &&
(UT_LIST_GET_LEN(space->chain) == 0 ||
space->is_stopping() || space->purpose != FIL_TABLESPACE))
space= UT_LIST_GET_NEXT(space_list, space);
if (space)
space->n_pending_ops++;
}
mutex_exit(&fil_system->mutex);
return space;
}
/*********************************************************************** /***********************************************************************
Search for a space needing rotation Search for a space needing rotation
@param[in,out] key_state Key state @param[in,out] key_state Key state
...@@ -1485,14 +1577,7 @@ fil_crypt_find_space_to_rotate( ...@@ -1485,14 +1577,7 @@ fil_crypt_find_space_to_rotate(
state->space = NULL; state->space = NULL;
} }
/* If key rotation is enabled (default) we iterate all tablespaces. state->space = fil_space_next(state->space);
If key rotation is not enabled we iterate only the tablespaces
added to keyrotation list. */
if (srv_fil_crypt_rotate_key_age) {
state->space = fil_space_next(state->space);
} else {
state->space = fil_space_keyrotate_next(state->space);
}
while (!state->should_shutdown() && state->space) { while (!state->should_shutdown() && state->space) {
fil_crypt_read_crypt_data(state->space); fil_crypt_read_crypt_data(state->space);
...@@ -1505,14 +1590,15 @@ fil_crypt_find_space_to_rotate( ...@@ -1505,14 +1590,15 @@ fil_crypt_find_space_to_rotate(
return true; return true;
} }
if (srv_fil_crypt_rotate_key_age) { state->space = fil_space_next(state->space);
state->space = fil_space_next(state->space); }
} else {
state->space = fil_space_keyrotate_next(state->space); if (state->space) {
} fil_space_release(state->space);
state->space = NULL;
} }
/* if we didn't find any space return iops */ /* no work to do; release our allocation of I/O capacity */
fil_crypt_return_iops(state); fil_crypt_return_iops(state);
return false; return false;
......
...@@ -6476,137 +6476,3 @@ fil_space_release_for_io(fil_space_t* space) ...@@ -6476,137 +6476,3 @@ fil_space_release_for_io(fil_space_t* space)
space->n_pending_ios--; space->n_pending_ios--;
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
} }
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_next(fil_space_t* prev_space)
{
fil_space_t* space=prev_space;
mutex_enter(&fil_system->mutex);
if (prev_space == NULL) {
space = UT_LIST_GET_FIRST(fil_system->space_list);
/* We can trust that space is not NULL because at least the
system tablespace is always present and loaded first. */
space->n_pending_ops++;
} else {
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
space = UT_LIST_GET_NEXT(space_list, space);
/* Skip spaces that are being created by
fil_ibd_create(), or dropped, or !tablespace. */
while (space != NULL
&& (UT_LIST_GET_LEN(space->chain) == 0
|| space->is_stopping()
|| space->purpose != FIL_TABLESPACE)) {
space = UT_LIST_GET_NEXT(space_list, space);
}
if (space != NULL) {
space->n_pending_ops++;
}
}
mutex_exit(&fil_system->mutex);
return(space);
}
/**
Remove space from key rotation list if there are no more
pending operations.
@param[in] space Tablespace */
static
void
fil_space_remove_from_keyrotation(
fil_space_t* space)
{
ut_ad(mutex_own(&fil_system->mutex));
ut_ad(space);
if (space->n_pending_ops == 0 && space->is_in_rotation_list) {
space->is_in_rotation_list = false;
ut_a(UT_LIST_GET_LEN(fil_system->rotation_list) > 0);
UT_LIST_REMOVE(rotation_list, fil_system->rotation_list, space);
}
}
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_keyrotate_next(
fil_space_t* prev_space)
{
fil_space_t* space = prev_space;
fil_space_t* old = NULL;
mutex_enter(&fil_system->mutex);
if (UT_LIST_GET_LEN(fil_system->rotation_list) == 0) {
if (space) {
ut_ad(space->n_pending_ops > 0);
space->n_pending_ops--;
fil_space_remove_from_keyrotation(space);
}
mutex_exit(&fil_system->mutex);
return(NULL);
}
if (prev_space == NULL) {
space = UT_LIST_GET_FIRST(fil_system->rotation_list);
/* We can trust that space is not NULL because we
checked list length above */
} else {
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
old = space;
space = UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
/* Skip spaces that are being created by fil_ibd_create(),
or dropped. Note that rotation_list contains only
space->purpose == FIL_TABLESPACE. */
while (space != NULL
&& (UT_LIST_GET_LEN(space->chain) == 0
|| space->is_stopping())) {
old = space;
space = UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
if (space != NULL) {
space->n_pending_ops++;
}
mutex_exit(&fil_system->mutex);
return(space);
}
...@@ -699,34 +699,6 @@ UNIV_INTERN ...@@ -699,34 +699,6 @@ UNIV_INTERN
void void
fil_space_release_for_io(fil_space_t* space); fil_space_release_for_io(fil_space_t* space);
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in,out] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last */
UNIV_INTERN
fil_space_t*
fil_space_next(
fil_space_t* prev_space)
MY_ATTRIBUTE((warn_unused_result));
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in,out] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_keyrotate_next(
fil_space_t* prev_space)
MY_ATTRIBUTE((warn_unused_result));
/** Wrapper with reference-counting for a fil_space_t. */ /** Wrapper with reference-counting for a fil_space_t. */
class FilSpace class FilSpace
{ {
......
...@@ -44,15 +44,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com ...@@ -44,15 +44,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
#include "ha_prototypes.h" // IB_LOG_ #include "ha_prototypes.h" // IB_LOG_
#include <my_crypt.h> #include <my_crypt.h>
/** Mutex for keys */
static ib_mutex_t fil_crypt_key_mutex;
static bool fil_crypt_threads_inited = false; static bool fil_crypt_threads_inited = false;
#ifdef UNIV_PFS_MUTEX
static mysql_pfs_key_t fil_crypt_key_mutex_key;
#endif
/** Is encryption enabled/disabled */ /** Is encryption enabled/disabled */
UNIV_INTERN ulong srv_encrypt_tables = 0; UNIV_INTERN ulong srv_encrypt_tables = 0;
...@@ -133,9 +126,6 @@ UNIV_INTERN ...@@ -133,9 +126,6 @@ UNIV_INTERN
void void
fil_space_crypt_init() fil_space_crypt_init()
{ {
mutex_create(fil_crypt_key_mutex_key,
&fil_crypt_key_mutex, SYNC_NO_ORDER_CHECK);
fil_crypt_throttle_sleep_event = os_event_create(); fil_crypt_throttle_sleep_event = os_event_create();
mutex_create(fil_crypt_stat_mutex_key, mutex_create(fil_crypt_stat_mutex_key,
...@@ -152,7 +142,6 @@ fil_space_crypt_cleanup() ...@@ -152,7 +142,6 @@ fil_space_crypt_cleanup()
{ {
os_event_free(fil_crypt_throttle_sleep_event); os_event_free(fil_crypt_throttle_sleep_event);
fil_crypt_throttle_sleep_event = NULL; fil_crypt_throttle_sleep_event = NULL;
mutex_free(&fil_crypt_key_mutex);
mutex_free(&crypt_stat_mutex); mutex_free(&crypt_stat_mutex);
} }
...@@ -1451,6 +1440,109 @@ fil_crypt_return_iops( ...@@ -1451,6 +1440,109 @@ fil_crypt_return_iops(
fil_crypt_update_total_stat(state); fil_crypt_update_total_stat(state);
} }
/** Remove space from key rotation list if there are no pending operations. */
static void fil_space_remove_from_keyrotation(fil_space_t *space)
{
ut_ad(mutex_own(&fil_system->mutex));
if (space->n_pending_ops == 0 && space->is_in_rotation_list)
{
space->is_in_rotation_list= false;
ut_a(UT_LIST_GET_LEN(fil_system->rotation_list) > 0);
UT_LIST_REMOVE(rotation_list, fil_system->rotation_list, space);
}
}
/** Return the next tablespace from key rotation list.
@param space previous tablespace (NULL to start from the beginning)
@return pointer to the next tablespace (with n_pending_ops incremented)
@retval NULL if this was the last */
static fil_space_t *fil_space_keyrotate_next(fil_space_t *space)
{
ut_ad(mutex_own(&fil_system->mutex));
if (UT_LIST_GET_LEN(fil_system->rotation_list) == 0)
{
if (space)
{
space->n_pending_ops--;
fil_space_remove_from_keyrotation(space);
}
return NULL;
}
if (!space)
{
space= UT_LIST_GET_FIRST(fil_system->rotation_list);
/* We can trust that space is not NULL because we
checked list length above */
}
else
{
space->n_pending_ops--;
fil_space_t *old = space;
space= UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
/* Skip spaces that are being created by fil_ibd_create(),
or dropped. Note that rotation_list contains only
space->purpose == FIL_TABLESPACE. */
while (space && (!UT_LIST_GET_LEN(space->chain) || space->is_stopping()))
{
fil_space_t *old = space;
space= UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
if (space)
space->n_pending_ops++;
return space;
}
/** Return the next tablespace.
@param space previous tablespace (NULL to start from the beginning)
@return pointer to the next tablespace (with n_pending_ops incremented)
@retval NULL if this was the last */
static fil_space_t *fil_space_next(fil_space_t *space)
{
mutex_enter(&fil_system->mutex);
ut_ad(!space || space->n_pending_ops);
if (!srv_fil_crypt_rotate_key_age)
space= fil_space_keyrotate_next(space);
else if (!space)
{
space= UT_LIST_GET_FIRST(fil_system->space_list);
/* We can trust that space is not NULL because at least the
system tablespace is always present and loaded first. */
space->n_pending_ops++;
}
else
{
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
space= UT_LIST_GET_NEXT(space_list, space);
/* Skip abnormal tablespaces or those that are being created by
fil_ibd_create(), or being dropped. */
while (space &&
(UT_LIST_GET_LEN(space->chain) == 0 ||
space->is_stopping() || space->purpose != FIL_TABLESPACE))
space= UT_LIST_GET_NEXT(space_list, space);
if (space)
space->n_pending_ops++;
}
mutex_exit(&fil_system->mutex);
return space;
}
/*********************************************************************** /***********************************************************************
Search for a space needing rotation Search for a space needing rotation
@param[in,out] key_state Key state @param[in,out] key_state Key state
...@@ -1485,14 +1577,7 @@ fil_crypt_find_space_to_rotate( ...@@ -1485,14 +1577,7 @@ fil_crypt_find_space_to_rotate(
state->space = NULL; state->space = NULL;
} }
/* If key rotation is enabled (default) we iterate all tablespaces. state->space = fil_space_next(state->space);
If key rotation is not enabled we iterate only the tablespaces
added to keyrotation list. */
if (srv_fil_crypt_rotate_key_age) {
state->space = fil_space_next(state->space);
} else {
state->space = fil_space_keyrotate_next(state->space);
}
while (!state->should_shutdown() && state->space) { while (!state->should_shutdown() && state->space) {
fil_crypt_read_crypt_data(state->space); fil_crypt_read_crypt_data(state->space);
...@@ -1505,14 +1590,15 @@ fil_crypt_find_space_to_rotate( ...@@ -1505,14 +1590,15 @@ fil_crypt_find_space_to_rotate(
return true; return true;
} }
if (srv_fil_crypt_rotate_key_age) { state->space = fil_space_next(state->space);
state->space = fil_space_next(state->space); }
} else {
state->space = fil_space_keyrotate_next(state->space); if (state->space) {
} fil_space_release(state->space);
state->space = NULL;
} }
/* if we didn't find any space return iops */ /* no work to do; release our allocation of I/O capacity */
fil_crypt_return_iops(state); fil_crypt_return_iops(state);
return false; return false;
......
...@@ -6863,137 +6863,3 @@ fil_space_release(fil_space_t* space) ...@@ -6863,137 +6863,3 @@ fil_space_release(fil_space_t* space)
space->n_pending_ops--; space->n_pending_ops--;
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
} }
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_next(fil_space_t* prev_space)
{
fil_space_t* space=prev_space;
mutex_enter(&fil_system->mutex);
if (prev_space == NULL) {
space = UT_LIST_GET_FIRST(fil_system->space_list);
/* We can trust that space is not NULL because at least the
system tablespace is always present and loaded first. */
space->n_pending_ops++;
} else {
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
space = UT_LIST_GET_NEXT(space_list, space);
/* Skip spaces that are being created by
fil_ibd_create(), or dropped, or !tablespace. */
while (space != NULL
&& (UT_LIST_GET_LEN(space->chain) == 0
|| space->is_stopping()
|| space->purpose != FIL_TABLESPACE)) {
space = UT_LIST_GET_NEXT(space_list, space);
}
if (space != NULL) {
space->n_pending_ops++;
}
}
mutex_exit(&fil_system->mutex);
return(space);
}
/**
Remove space from key rotation list if there are no more
pending operations.
@param[in] space Tablespace */
static
void
fil_space_remove_from_keyrotation(
fil_space_t* space)
{
ut_ad(mutex_own(&fil_system->mutex));
ut_ad(space);
if (space->n_pending_ops == 0 && space->is_in_rotation_list) {
space->is_in_rotation_list = false;
ut_a(UT_LIST_GET_LEN(fil_system->rotation_list) > 0);
UT_LIST_REMOVE(rotation_list, fil_system->rotation_list, space);
}
}
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_keyrotate_next(
fil_space_t* prev_space)
{
fil_space_t* space = prev_space;
fil_space_t* old = NULL;
mutex_enter(&fil_system->mutex);
if (UT_LIST_GET_LEN(fil_system->rotation_list) == 0) {
if (space) {
ut_ad(space->n_pending_ops > 0);
space->n_pending_ops--;
fil_space_remove_from_keyrotation(space);
}
mutex_exit(&fil_system->mutex);
return(NULL);
}
if (prev_space == NULL) {
space = UT_LIST_GET_FIRST(fil_system->rotation_list);
/* We can trust that space is not NULL because we
checked list length above */
} else {
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
old = space;
space = UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
/* Skip spaces that are being created by fil_ibd_create(),
or dropped. Note that rotation_list contains only
space->purpose == FIL_TABLESPACE. */
while (space != NULL
&& (UT_LIST_GET_LEN(space->chain) == 0
|| space->is_stopping())) {
old = space;
space = UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
if (space != NULL) {
space->n_pending_ops++;
}
mutex_exit(&fil_system->mutex);
return(space);
}
...@@ -705,34 +705,6 @@ UNIV_INTERN ...@@ -705,34 +705,6 @@ UNIV_INTERN
void void
fil_space_release_for_io(fil_space_t* space); fil_space_release_for_io(fil_space_t* space);
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in,out] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last */
UNIV_INTERN
fil_space_t*
fil_space_next(
fil_space_t* prev_space)
MY_ATTRIBUTE((warn_unused_result));
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in,out] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_keyrotate_next(
fil_space_t* prev_space)
MY_ATTRIBUTE((warn_unused_result));
/** Wrapper with reference-counting for a fil_space_t. */ /** Wrapper with reference-counting for a fil_space_t. */
class FilSpace class FilSpace
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment