Commit ee80c196 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-26551 InnoDB crash on multiple concurrent SHOW TABLE STATUS

dict_get_and_save_data_dir_path(): Protect the operation with
dict_table_t::lock_mutex and avoid unnecessary memory allocation.
parent 31ad9277
...@@ -2078,72 +2078,24 @@ const char *dict_load_table_low(const span<const char> &name, ...@@ -2078,72 +2078,24 @@ const char *dict_load_table_low(const span<const char> &name,
return(NULL); return(NULL);
} }
/********************************************************************//**
Using the table->heap, copy the null-terminated filepath into
table->data_dir_path and replace the 'databasename/tablename.ibd'
portion with 'tablename'.
This allows SHOW CREATE TABLE to return the correct DATA DIRECTORY path.
Make this data directory path only if it has not yet been saved. */
static
void
dict_save_data_dir_path(
/*====================*/
dict_table_t* table, /*!< in/out: table */
const char* filepath) /*!< in: filepath of tablespace */
{
ut_ad(dict_sys.frozen());
ut_a(DICT_TF_HAS_DATA_DIR(table->flags));
ut_a(!table->data_dir_path);
ut_a(filepath);
/* Be sure this filepath is not the default filepath. */
if (char* default_filepath = fil_make_filepath(nullptr, table->name,
IBD, false)) {
if (0 != strcmp(filepath, default_filepath)) {
ulint pathlen = strlen(filepath);
ut_a(pathlen < OS_FILE_MAX_PATH);
ut_a(0 == strcmp(filepath + pathlen - 4, DOT_IBD));
table->data_dir_path = mem_heap_strdup(
table->heap, filepath);
os_file_make_data_dir_path(table->data_dir_path);
}
ut_free(default_filepath);
}
}
/** Make sure the data_file_name is saved in dict_table_t if needed. /** Make sure the data_file_name is saved in dict_table_t if needed.
@param[in,out] table Table object @param[in,out] table Table object */
@param[in] dict_locked dict_sys.frozen() */ void dict_get_and_save_data_dir_path(dict_table_t *table)
void dict_get_and_save_data_dir_path(dict_table_t* table, bool dict_locked)
{ {
ut_ad(!table->is_temporary()); ut_ad(!table->is_temporary());
ut_ad(!table->space || table->space->id == table->space_id); ut_ad(!table->space || table->space->id == table->space_id);
if (!table->data_dir_path && table->space_id && table->space) { if (!table->data_dir_path && table->space_id && table->space)
if (!dict_locked) { {
dict_sys.freeze(SRW_LOCK_CALL); const char *filepath= table->space->chain.start->name;
} if (strncmp(fil_path_to_mysql_datadir, filepath,
strlen(fil_path_to_mysql_datadir)))
table->flags |= 1 << DICT_TF_POS_DATA_DIR {
& ((1U << DICT_TF_BITS) - 1); table->lock_mutex_lock();
dict_save_data_dir_path(table, table->flags|= 1 << DICT_TF_POS_DATA_DIR & ((1U << DICT_TF_BITS) - 1);
table->space->chain.start->name); table->data_dir_path= mem_heap_strdup(table->heap, filepath);
os_file_make_data_dir_path(table->data_dir_path);
if (table->data_dir_path == NULL) { table->lock_mutex_unlock();
/* Since we did not set the table data_dir_path,
unset the flag. This does not change
SYS_TABLES or FSP_SPACE_FLAGS on the header page
of the tablespace, but it makes dict_table_t
consistent. */
table->flags &= ~DICT_TF_MASK_DATA_DIR
& ((1U << DICT_TF_BITS) - 1);
}
if (!dict_locked) {
dict_sys.unfreeze();
} }
} }
} }
...@@ -2199,7 +2151,7 @@ dict_load_tablespace( ...@@ -2199,7 +2151,7 @@ dict_load_tablespace(
char* filepath = NULL; char* filepath = NULL;
if (DICT_TF_HAS_DATA_DIR(table->flags)) { if (DICT_TF_HAS_DATA_DIR(table->flags)) {
/* This will set table->data_dir_path from fil_system */ /* This will set table->data_dir_path from fil_system */
dict_get_and_save_data_dir_path(table, true); dict_get_and_save_data_dir_path(table);
if (table->data_dir_path) { if (table->data_dir_path) {
filepath = fil_make_filepath( filepath = fil_make_filepath(
......
...@@ -11427,7 +11427,7 @@ ha_innobase::update_create_info( ...@@ -11427,7 +11427,7 @@ ha_innobase::update_create_info(
return; return;
} }
dict_get_and_save_data_dir_path(m_prebuilt->table, false); dict_get_and_save_data_dir_path(m_prebuilt->table);
if (m_prebuilt->table->data_dir_path) { if (m_prebuilt->table->data_dir_path) {
create_info->data_file_name = m_prebuilt->table->data_dir_path; create_info->data_file_name = m_prebuilt->table->data_dir_path;
...@@ -13842,7 +13842,7 @@ int ha_innobase::truncate() ...@@ -13842,7 +13842,7 @@ int ha_innobase::truncate()
mem_heap_t* heap = mem_heap_create(1000); mem_heap_t* heap = mem_heap_create(1000);
dict_get_and_save_data_dir_path(ib_table, false); dict_get_and_save_data_dir_path(ib_table);
info.data_file_name = ib_table->data_dir_path; info.data_file_name = ib_table->data_dir_path;
const char* temp_name = dict_mem_create_temporary_tablename( const char* temp_name = dict_mem_create_temporary_tablename(
heap, ib_table->name.m_name, ib_table->id); heap, ib_table->name.m_name, ib_table->id);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2021, MariaDB Corporation. Copyright (c) 2017, 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
...@@ -53,9 +53,8 @@ We also scan the biggest space id, and store it to fil_system. */ ...@@ -53,9 +53,8 @@ We also scan the biggest space id, and store it to fil_system. */
void dict_check_tablespaces_and_store_max_id(); void dict_check_tablespaces_and_store_max_id();
/** Make sure the data_file_name is saved in dict_table_t if needed. /** Make sure the data_file_name is saved in dict_table_t if needed.
@param[in,out] table Table object @param[in,out] table Table object */
@param[in] dict_locked dict_sys.frozen() */ void dict_get_and_save_data_dir_path(dict_table_t* table);
void dict_get_and_save_data_dir_path(dict_table_t* table, bool dict_locked);
/***********************************************************************//** /***********************************************************************//**
Loads a table object based on the table id. Loads a table object based on the table id.
......
...@@ -3128,7 +3128,7 @@ and apply it to dict_table_t ...@@ -3128,7 +3128,7 @@ and apply it to dict_table_t
static dberr_t handle_instant_metadata(dict_table_t *table, static dberr_t handle_instant_metadata(dict_table_t *table,
const row_import &cfg) const row_import &cfg)
{ {
dict_get_and_save_data_dir_path(table, false); dict_get_and_save_data_dir_path(table);
char *filepath; char *filepath;
if (DICT_TF_HAS_DATA_DIR(table->flags)) if (DICT_TF_HAS_DATA_DIR(table->flags))
...@@ -4167,7 +4167,7 @@ fil_tablespace_iterate( ...@@ -4167,7 +4167,7 @@ fil_tablespace_iterate(
return(DB_CORRUPTION);); return(DB_CORRUPTION););
/* Make sure the data_dir_path is set. */ /* Make sure the data_dir_path is set. */
dict_get_and_save_data_dir_path(table, false); dict_get_and_save_data_dir_path(table);
ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path); ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path);
...@@ -4488,7 +4488,7 @@ row_import_for_mysql( ...@@ -4488,7 +4488,7 @@ row_import_for_mysql(
/* If the table is stored in a remote tablespace, we need to /* If the table is stored in a remote tablespace, we need to
determine that filepath from the link file and system tables. determine that filepath from the link file and system tables.
Find the space ID in SYS_TABLES since this is an ALTER TABLE. */ Find the space ID in SYS_TABLES since this is an ALTER TABLE. */
dict_get_and_save_data_dir_path(table, true); dict_get_and_save_data_dir_path(table);
ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path); ut_ad(!DICT_TF_HAS_DATA_DIR(table->flags) || table->data_dir_path);
const char *data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags) const char *data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags)
......
...@@ -2072,7 +2072,7 @@ srv_get_meta_data_filename( ...@@ -2072,7 +2072,7 @@ srv_get_meta_data_filename(
char* path; char* path;
/* Make sure the data_dir_path is set. */ /* Make sure the data_dir_path is set. */
dict_get_and_save_data_dir_path(table, false); dict_get_and_save_data_dir_path(table);
const char* data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags) const char* data_dir_path = DICT_TF_HAS_DATA_DIR(table->flags)
? table->data_dir_path : nullptr; ? table->data_dir_path : nullptr;
......
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