Commit 840bab85 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-28289 fts_optimize_sync_table() is acquiring dict_sys.latch while holding it

dict_acquire_mdl_shared(): Invoke the correct variant
dict_table_t::parse_name<true>() also when trylock=true,
that is, we are being called from fts_optimize_sync_table().

Ever since commit 82b7c561 (MDEV-24258)
this code was prone to a hang. If another thread requested an
exclusive dict_sys.latch between the time
dict_acquire_mdl_shared<trylock=true>() acquired a shared dict_sys.latch
and dict_table_t::parse_name<false>() was trying to acquire another
shared dict_sys.latch, InnoDB would get into an infinite livelock
of threads, because the futex-based srw-lock implementation prioritizes
exclusive latch requests.

dict_table_t::parse_name(): Rename the template parameter dict_locked
into dict_frozen.
parent 7bccf3dd
...@@ -602,13 +602,13 @@ dict_index_get_nth_field_pos( ...@@ -602,13 +602,13 @@ dict_index_get_nth_field_pos(
} }
/** Parse the table file name into table name and database name. /** Parse the table file name into table name and database name.
@tparam dict_locked whether dict_sys.lock() was called @tparam dict_frozen whether the caller holds dict_sys.latch
@param[in,out] db_name database name buffer @param[in,out] db_name database name buffer
@param[in,out] tbl_name table name buffer @param[in,out] tbl_name table name buffer
@param[out] db_name_len database name length @param[out] db_name_len database name length
@param[out] tbl_name_len table name length @param[out] tbl_name_len table name length
@return whether the table name is visible to SQL */ @return whether the table name is visible to SQL */
template<bool dict_locked> template<bool dict_frozen>
bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1],
char (&tbl_name)[NAME_LEN + 1], char (&tbl_name)[NAME_LEN + 1],
size_t *db_name_len, size_t *tbl_name_len) const size_t *db_name_len, size_t *tbl_name_len) const
...@@ -616,7 +616,7 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], ...@@ -616,7 +616,7 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1],
char db_buf[MAX_DATABASE_NAME_LEN + 1]; char db_buf[MAX_DATABASE_NAME_LEN + 1];
char tbl_buf[MAX_TABLE_NAME_LEN + 1]; char tbl_buf[MAX_TABLE_NAME_LEN + 1];
if (!dict_locked) if (!dict_frozen)
dict_sys.freeze(SRW_LOCK_CALL); /* protect against renaming */ dict_sys.freeze(SRW_LOCK_CALL); /* protect against renaming */
ut_ad(dict_sys.frozen()); ut_ad(dict_sys.frozen());
const size_t db_len= name.dblen(); const size_t db_len= name.dblen();
...@@ -636,7 +636,7 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], ...@@ -636,7 +636,7 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1],
memcpy(tbl_buf, mdl_name.m_name + db_len + 1, tbl_len); memcpy(tbl_buf, mdl_name.m_name + db_len + 1, tbl_len);
tbl_buf[tbl_len]= 0; tbl_buf[tbl_len]= 0;
if (!dict_locked) if (!dict_frozen)
dict_sys.unfreeze(); dict_sys.unfreeze();
*db_name_len= filename_to_tablename(db_buf, db_name, *db_name_len= filename_to_tablename(db_buf, db_name,
...@@ -782,7 +782,7 @@ dict_acquire_mdl_shared(dict_table_t *table, ...@@ -782,7 +782,7 @@ dict_acquire_mdl_shared(dict_table_t *table,
size_t db1_len, tbl1_len; size_t db1_len, tbl1_len;
if (!table->parse_name<!trylock>(db_buf1, tbl_buf1, &db1_len, &tbl1_len)) if (!table->parse_name<true>(db_buf1, tbl_buf1, &db1_len, &tbl1_len))
{ {
/* The table was renamed to #sql prefix. /* The table was renamed to #sql prefix.
Release MDL (if any) for the old name and return. */ Release MDL (if any) for the old name and return. */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2021, MariaDB Corporation. Copyright (c) 2013, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2021, MariaDB Corporation. Copyright (c) 2013, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
...@@ -1935,13 +1935,13 @@ struct dict_table_t { ...@@ -1935,13 +1935,13 @@ struct dict_table_t {
inline size_t get_overflow_field_local_len() const; inline size_t get_overflow_field_local_len() const;
/** Parse the table file name into table name and database name. /** Parse the table file name into table name and database name.
@tparam dict_locked whether dict_sys.lock() was called @tparam dict_frozen whether the caller holds dict_sys.latch
@param[in,out] db_name database name buffer @param[in,out] db_name database name buffer
@param[in,out] tbl_name table name buffer @param[in,out] tbl_name table name buffer
@param[out] db_name_len database name length @param[out] db_name_len database name length
@param[out] tbl_name_len table name length @param[out] tbl_name_len table name length
@return whether the table name is visible to SQL */ @return whether the table name is visible to SQL */
template<bool dict_locked= false> template<bool dict_frozen= false>
bool parse_name(char (&db_name)[NAME_LEN + 1], bool parse_name(char (&db_name)[NAME_LEN + 1],
char (&tbl_name)[NAME_LEN + 1], char (&tbl_name)[NAME_LEN + 1],
size_t *db_name_len, size_t *tbl_name_len) const; size_t *db_name_len, size_t *tbl_name_len) const;
......
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