Skip to content

Commit

Permalink
MDEV-26383 fixup: Consistently protect freed_indexes with autoinc_mutex
Browse files Browse the repository at this point in the history
To avoid potential race conditions between concurrent access to
dict_table_t::freed_indexes, let us consistently use
dict_table_t::autoinc_mutex.

dict_table_remove_from_cache_low(): To avoid extensive hold time
of table->autoinc_mutex, unconditionally free the FTS data structures.
  • Loading branch information
dr-m committed Aug 23, 2021
1 parent 08e5a3d commit ca89489
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 23 deletions.
15 changes: 3 additions & 12 deletions storage/innobase/btr/btr0sea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -253,15 +253,7 @@ ATTRIBUTE_COLD static void btr_search_lazy_free(dict_index_t *index)
{
ut_ad(index->freed());
dict_table_t *table= index->table;
bool non_exist_table= (table->id == 0);

if (non_exist_table)
{
/* autoinc_mutex should be acquired to avoid the race condition
in case of multiple threads accessing the evicted table
or dropped table. */
mysql_mutex_lock(&table->autoinc_mutex);
}
mysql_mutex_lock(&table->autoinc_mutex);

/* Perform the skipped steps of dict_index_remove_from_cache_low(). */
UT_LIST_REMOVE(table->freed_indexes, index);
Expand All @@ -271,15 +263,14 @@ ATTRIBUTE_COLD static void btr_search_lazy_free(dict_index_t *index)
if (!UT_LIST_GET_LEN(table->freed_indexes) &&
!UT_LIST_GET_LEN(table->indexes))
{
ut_ad(non_exist_table);
ut_ad(!table->id);
mysql_mutex_unlock(&table->autoinc_mutex);
mysql_mutex_destroy(&table->autoinc_mutex);
dict_mem_table_free(table);
return;
}

if (non_exist_table)
mysql_mutex_unlock(&table->autoinc_mutex);
mysql_mutex_unlock(&table->autoinc_mutex);
}

/** Clear the adaptive hash index on all pages in the buffer pool. */
Expand Down
28 changes: 19 additions & 9 deletions storage/innobase/dict/dict0dict.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2020, MariaDB Corporation.
Copyright (c) 2013, 2021, 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
Expand Down Expand Up @@ -1258,6 +1258,7 @@ dict_index_t *dict_index_t::clone_if_needed()
return this;
dict_index_t *prev= UT_LIST_GET_PREV(indexes, this);

mysql_mutex_lock(&table->autoinc_mutex);
UT_LIST_REMOVE(table->indexes, this);
UT_LIST_ADD_LAST(table->freed_indexes, this);
dict_index_t *index= clone();
Expand All @@ -1266,6 +1267,7 @@ dict_index_t *dict_index_t::clone_if_needed()
UT_LIST_INSERT_AFTER(table->indexes, prev, index);
else
UT_LIST_ADD_FIRST(table->indexes, index);
mysql_mutex_unlock(&table->autoinc_mutex);
return index;
}
#endif /* BTR_CUR_HASH_ADAPT */
Expand Down Expand Up @@ -1961,15 +1963,21 @@ dict_table_remove_from_cache_low(
}

#ifdef BTR_CUR_HASH_ADAPT
if (UNIV_UNLIKELY(UT_LIST_GET_LEN(table->freed_indexes) != 0)) {
if (table->fts) {
fts_optimize_remove_table(table);
fts_free(table);
table->fts = NULL;
}
if (table->fts) {
fts_optimize_remove_table(table);
fts_free(table);
table->fts = NULL;
}

mysql_mutex_lock(&table->autoinc_mutex);

ulint freed = UT_LIST_GET_LEN(table->freed_indexes);

table->vc_templ = NULL;
table->id = 0;
mysql_mutex_unlock(&table->autoinc_mutex);

table->vc_templ = NULL;
table->id = 0;
if (UNIV_UNLIKELY(freed != 0)) {
return;
}
#endif /* BTR_CUR_HASH_ADAPT */
Expand Down Expand Up @@ -2244,8 +2252,10 @@ dict_index_remove_from_cache_low(
zero. See also: dict_table_can_be_evicted() */

if (index->n_ahi_pages()) {
mysql_mutex_lock(&table->autoinc_mutex);
index->set_freed();
UT_LIST_ADD_LAST(table->freed_indexes, index);
mysql_mutex_unlock(&table->autoinc_mutex);
return;
}
#endif /* BTR_CUR_HASH_ADAPT */
Expand Down
5 changes: 3 additions & 2 deletions storage/innobase/include/dict0mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -1713,7 +1713,8 @@ struct dict_table_t {
UT_LIST_BASE_NODE_T(dict_index_t) indexes;
#ifdef BTR_CUR_HASH_ADAPT
/** List of detached indexes that are waiting to be freed along with
the last adaptive hash index entry */
the last adaptive hash index entry.
Protected by autoinc_mutex (sic!) */
UT_LIST_BASE_NODE_T(dict_index_t) freed_indexes;
#endif /* BTR_CUR_HASH_ADAPT */

Expand Down Expand Up @@ -1880,7 +1881,7 @@ struct dict_table_t {
from a select. */
lock_t* autoinc_lock;

/** Mutex protecting the autoincrement counter. */
/** Mutex protecting the autoinc counter and freed_indexes. */
mysql_mutex_t autoinc_mutex;

/** Autoinc counter value to give to the next inserted row. */
Expand Down

0 comments on commit ca89489

Please sign in to comment.