Commit 38ca9be4 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-13684 InnoDB race condition between fil_crypt_thread and btr_scrub_init

There is a race condition in InnoDB startup. A number of
fil_crypt_thread are created by fil_crypt_threads_init(). These threads
may call btr_scrub_complete_space() before btr_scrub_init() was called.
Those too early calls would be accessing an uninitialized scrub_stat_mutex.

innobase_start_or_create_for_mysql(): Invoke btr_scrub_init() before
fil_crypt_threads_init().

fil_crypt_complete_rotate_space(): Only invoke btr_scrub_complete_space()
if scrubbing is enabled. There is no need to update the statistics if
it is not enabled.
parent 28b2896a
...@@ -886,17 +886,15 @@ btr_scrub_update_total_stat(btr_scrub_t *scrub_data) ...@@ -886,17 +886,15 @@ btr_scrub_update_total_stat(btr_scrub_t *scrub_data)
memset(&scrub_data->scrub_stat, 0, sizeof(scrub_data->scrub_stat)); memset(&scrub_data->scrub_stat, 0, sizeof(scrub_data->scrub_stat));
} }
/**************************************************************//** /** Complete iterating a space.
Complete iterating a space */ @param[in,out] scrub_data scrub data */
UNIV_INTERN UNIV_INTERN
bool void
btr_scrub_complete_space( btr_scrub_complete_space(btr_scrub_t* scrub_data)
/*=====================*/
btr_scrub_t* scrub_data) /*!< in/out: scrub data */
{ {
ut_ad(scrub_data->scrubbing);
btr_scrub_table_close_for_thread(scrub_data); btr_scrub_table_close_for_thread(scrub_data);
btr_scrub_update_total_stat(scrub_data); btr_scrub_update_total_stat(scrub_data);
return scrub_data->scrubbing;
} }
/********************************************************************* /*********************************************************************
......
...@@ -2127,7 +2127,8 @@ fil_crypt_complete_rotate_space( ...@@ -2127,7 +2127,8 @@ fil_crypt_complete_rotate_space(
mutex_exit(&crypt_data->mutex); mutex_exit(&crypt_data->mutex);
/* all threads must call btr_scrub_complete_space wo/ mutex held */ /* all threads must call btr_scrub_complete_space wo/ mutex held */
if (btr_scrub_complete_space(&state->scrub_data) == true) { if (state->scrub_data.scrubbing) {
btr_scrub_complete_space(&state->scrub_data);
if (should_flush) { if (should_flush) {
/* only last thread updates last_scrub_completed */ /* only last thread updates last_scrub_completed */
ut_ad(crypt_data); ut_ad(crypt_data);
......
...@@ -154,13 +154,10 @@ btr_scrub_start_space( ...@@ -154,13 +154,10 @@ btr_scrub_start_space(
ulint space, /*!< in: space */ ulint space, /*!< in: space */
btr_scrub_t* scrub_data); /*!< in/out: scrub data */ btr_scrub_t* scrub_data); /*!< in/out: scrub data */
/**************************************************************** /** Complete iterating a space.
Complete iterating a space @param[in,out] scrub_data scrub data */
* @return true if space was scrubbed */
UNIV_INTERN UNIV_INTERN
bool void
btr_scrub_complete_space( btr_scrub_complete_space(btr_scrub_t* scrub_data);
/*=====================*/
btr_scrub_t* scrub_data); /*!< in/out: scrub data */
#endif #endif
...@@ -3030,12 +3030,10 @@ innobase_start_or_create_for_mysql() ...@@ -3030,12 +3030,10 @@ innobase_start_or_create_for_mysql()
/* Create thread(s) that handles key rotation */ /* Create thread(s) that handles key rotation */
fil_system_enter(); fil_system_enter();
btr_scrub_init();
fil_crypt_threads_init(); fil_crypt_threads_init();
fil_system_exit(); fil_system_exit();
/* Init data for datafile scrub threads */
btr_scrub_init();
/* Initialize online defragmentation. */ /* Initialize online defragmentation. */
btr_defragment_init(); btr_defragment_init();
btr_defragment_thread_active = true; btr_defragment_thread_active = true;
......
...@@ -886,17 +886,15 @@ btr_scrub_update_total_stat(btr_scrub_t *scrub_data) ...@@ -886,17 +886,15 @@ btr_scrub_update_total_stat(btr_scrub_t *scrub_data)
memset(&scrub_data->scrub_stat, 0, sizeof(scrub_data->scrub_stat)); memset(&scrub_data->scrub_stat, 0, sizeof(scrub_data->scrub_stat));
} }
/**************************************************************//** /** Complete iterating a space.
Complete iterating a space */ @param[in,out] scrub_data scrub data */
UNIV_INTERN UNIV_INTERN
bool void
btr_scrub_complete_space( btr_scrub_complete_space(btr_scrub_t* scrub_data)
/*=====================*/
btr_scrub_t* scrub_data) /*!< in/out: scrub data */
{ {
ut_ad(scrub_data->scrubbing);
btr_scrub_table_close_for_thread(scrub_data); btr_scrub_table_close_for_thread(scrub_data);
btr_scrub_update_total_stat(scrub_data); btr_scrub_update_total_stat(scrub_data);
return scrub_data->scrubbing;
} }
/********************************************************************* /*********************************************************************
......
...@@ -2127,7 +2127,8 @@ fil_crypt_complete_rotate_space( ...@@ -2127,7 +2127,8 @@ fil_crypt_complete_rotate_space(
mutex_exit(&crypt_data->mutex); mutex_exit(&crypt_data->mutex);
/* all threads must call btr_scrub_complete_space wo/ mutex held */ /* all threads must call btr_scrub_complete_space wo/ mutex held */
if (btr_scrub_complete_space(&state->scrub_data) == true) { if (state->scrub_data.scrubbing) {
btr_scrub_complete_space(&state->scrub_data);
if (should_flush) { if (should_flush) {
/* only last thread updates last_scrub_completed */ /* only last thread updates last_scrub_completed */
ut_ad(crypt_data); ut_ad(crypt_data);
......
...@@ -154,13 +154,10 @@ btr_scrub_start_space( ...@@ -154,13 +154,10 @@ btr_scrub_start_space(
ulint space, /*!< in: space */ ulint space, /*!< in: space */
btr_scrub_t* scrub_data); /*!< in/out: scrub data */ btr_scrub_t* scrub_data); /*!< in/out: scrub data */
/**************************************************************** /** Complete iterating a space.
Complete iterating a space @param[in,out] scrub_data scrub data */
* @return true if space was scrubbed */
UNIV_INTERN UNIV_INTERN
bool void
btr_scrub_complete_space( btr_scrub_complete_space(btr_scrub_t* scrub_data);
/*=====================*/
btr_scrub_t* scrub_data); /*!< in/out: scrub data */
#endif #endif
...@@ -3146,12 +3146,10 @@ innobase_start_or_create_for_mysql() ...@@ -3146,12 +3146,10 @@ innobase_start_or_create_for_mysql()
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/* Create thread(s) that handles key rotation */ /* Create thread(s) that handles key rotation */
fil_system_enter(); fil_system_enter();
btr_scrub_init();
fil_crypt_threads_init(); fil_crypt_threads_init();
fil_system_exit(); fil_system_exit();
/* Init data for datafile scrub threads */
btr_scrub_init();
/* Initialize online defragmentation. */ /* Initialize online defragmentation. */
btr_defragment_init(); btr_defragment_init();
btr_defragment_thread_active = true; btr_defragment_thread_active = true;
......
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