From b7a75fbb8a93cf732b1b562647486246ea7f70dc Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 7 Jun 2024 13:11:17 +0530 Subject: [PATCH 01/11] MDEV-34169 Don't allow innodb_open_files to be lesser than number of non-user tablespace. - InnoDB only closes the user tablespace when the number of open files exceeds innodb_open_files limit. In that case, InnoDB should make sure that innodb_open_files value should be greater than number of undo tablespace, system and temporary tablespace files. --- mysql-test/suite/innodb/r/open_files_limit.result | 4 ++++ mysql-test/suite/innodb/t/open_files_limit.opt | 3 +++ mysql-test/suite/innodb/t/open_files_limit.test | 9 +++++++++ storage/innobase/handler/ha_innodb.cc | 15 +++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 mysql-test/suite/innodb/r/open_files_limit.result create mode 100644 mysql-test/suite/innodb/t/open_files_limit.opt create mode 100644 mysql-test/suite/innodb/t/open_files_limit.test diff --git a/mysql-test/suite/innodb/r/open_files_limit.result b/mysql-test/suite/innodb/r/open_files_limit.result new file mode 100644 index 00000000000..f2f63376495 --- /dev/null +++ b/mysql-test/suite/innodb/r/open_files_limit.result @@ -0,0 +1,4 @@ +call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*"); +FOUND 1 /\[Warning\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*/ in mysqld.1.err +CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/open_files_limit.opt b/mysql-test/suite/innodb/t/open_files_limit.opt new file mode 100644 index 00000000000..cd71a062da8 --- /dev/null +++ b/mysql-test/suite/innodb/t/open_files_limit.opt @@ -0,0 +1,3 @@ +--innodb_undo_tablespaces=8 +--innodb_open_files=10 +--innodb_temp_data_file_path=ibtmp1:32M;ibtmp2:32M:autoextend diff --git a/mysql-test/suite/innodb/t/open_files_limit.test b/mysql-test/suite/innodb/t/open_files_limit.test new file mode 100644 index 00000000000..ea7383150a8 --- /dev/null +++ b/mysql-test/suite/innodb/t/open_files_limit.test @@ -0,0 +1,9 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*"); +let SEARCH_PATTERN= \[Warning\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +--source include/search_pattern_in_file.inc + +CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7bed0ed73eb..ae79e7f39a0 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3860,6 +3860,21 @@ static int innodb_init_params() } } + ulint min_open_files_limit = srv_undo_tablespaces + + srv_sys_space.m_files.size() + + srv_tmp_space.m_files.size() + 1; + if (min_open_files_limit > innobase_open_files) { + sql_print_warning( + "InnoDB: innodb_open_files=%lu is not greater " + "than the number of system tablespace files, " + "temporary tablespace files, " + "innodb_undo_tablespaces=%lu; adjusting " + "to innodb_open_files=%zu", + innobase_open_files, srv_undo_tablespaces, + min_open_files_limit); + innobase_open_files = (ulong) min_open_files_limit; + } + srv_max_n_open_files = innobase_open_files; srv_innodb_status = (ibool) innobase_create_status_file; From d9d0e8fd604bacf21e62a78d81c9763b90a79843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 7 Jun 2024 13:51:46 +0300 Subject: [PATCH 02/11] MDEV-34321: call to crc32c_3way through pointer to incorrect function type In commit 9ec7819c585d139c8fe64d0f7f0f0f51dcafa01f the CRC-32 function signatures had been unified somewhat, but not enough. clang -fsanitize=undefined would flag a function pointer signature mismatch between const char* and const void*, but not between uint32_t and unsigned. We try to fix both inconsistencies anyway. Reviewed by: Vladislav Vaintroub --- mysys/crc32/crc32c.cc | 2 +- mysys/crc32/crc32c_amd64.cc | 4 ++-- mysys/crc32/crc32c_x86.cc | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysys/crc32/crc32c.cc b/mysys/crc32/crc32c.cc index 32a45478e94..6de7af70db7 100644 --- a/mysys/crc32/crc32c.cc +++ b/mysys/crc32/crc32c.cc @@ -526,7 +526,7 @@ extern "C" const char *my_crc32c_implementation() } // namespace crc32c } // namespace mysys_namespace -extern "C" unsigned my_crc32c(unsigned int crc, const char *buf, size_t size) +extern "C" uint32 my_crc32c(uint32 crc, const void *buf, size_t size) { return mysys_namespace::crc32c::ChosenExtend(crc,buf, size); } diff --git a/mysys/crc32/crc32c_amd64.cc b/mysys/crc32/crc32c_amd64.cc index 147c0ccaba6..6706ed0fadc 100644 --- a/mysys/crc32/crc32c_amd64.cc +++ b/mysys/crc32/crc32c_amd64.cc @@ -184,9 +184,9 @@ static inline uint64_t CombineCRC( // Compute CRC-32C using the Intel hardware instruction. extern "C" USE_PCLMUL -uint32_t crc32c_3way(uint32_t crc, const char *buf, size_t len) +uint32_t crc32c_3way(uint32_t crc, const void *buf, size_t len) { - const unsigned char* next = (const unsigned char*)buf; + const unsigned char* next = static_cast(buf); uint64_t count; uint64_t crc0, crc1, crc2; crc0 = crc ^ 0xffffffffu; diff --git a/mysys/crc32/crc32c_x86.cc b/mysys/crc32/crc32c_x86.cc index 1ea0689a14b..6d9169f9384 100644 --- a/mysys/crc32/crc32c_x86.cc +++ b/mysys/crc32/crc32c_x86.cc @@ -54,9 +54,9 @@ static uint32_t cpuid_ecx() #endif } -typedef unsigned (*my_crc32_t)(unsigned, const void *, size_t); -extern "C" unsigned int crc32_pclmul(unsigned int, const void *, size_t); -extern "C" unsigned int crc32c_3way(unsigned int, const void *, size_t); +typedef uint32_t (*my_crc32_t)(uint32_t, const void *, size_t); +extern "C" uint32_t crc32_pclmul(uint32_t, const void *, size_t); +extern "C" uint32_t crc32c_3way(uint32_t, const void *, size_t); #ifdef USE_VPCLMULQDQ # include From 77c4c0f256f3c268d3f72625b04240d24a70513c Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 7 Jun 2024 12:13:21 +0200 Subject: [PATCH 03/11] MDEV-34203 Sandbox mode \- is not compatible with --binary-mode "Process" sandbox short command put by masqldump to avoid an error. --- client/mysql.cc | 30 +++++++++++++++++++++++++----- mysql-test/main/mysql.result | 11 +++++++++++ mysql-test/main/mysql.test | 16 ++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 5c79dd7890b..1e235c8a34d 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1117,6 +1117,8 @@ inline int get_command_index(char cmd_char) static int delimiter_index= -1; static int charset_index= -1; +static int sandbox_index= -1; + static bool real_binary_mode= FALSE; @@ -1127,7 +1129,8 @@ int main(int argc,char *argv[]) MY_INIT(argv[0]); DBUG_ENTER("main"); DBUG_PROCESS(argv[0]); - + + sandbox_index= get_command_index('-'); charset_index= get_command_index('C'); delimiter_index= get_command_index('d'); delimiter_str= delimiter; @@ -2234,8 +2237,9 @@ static int read_and_execute(bool interactive) /** It checks if the input is a short form command. It returns the command's - pointer if a command is found, else return NULL. Note that if binary-mode - is set, then only \C is searched for. + pointer if a command is found, else return NULL. + + Note that if binary-mode is set, then only \C and \- are searched for. @param cmd_char A character of one byte. @@ -2250,13 +2254,23 @@ static COMMANDS *find_command(char cmd_char) int index= -1; /* - In binary-mode, we disallow all mysql commands except '\C' - and DELIMITER. + In binary-mode, we disallow all client commands except '\C', + DELIMITER (see long comand finding find_command(char *)) + and '\-' (sandbox, see following comment). */ if (real_binary_mode) { if (cmd_char == 'C') index= charset_index; + /* + binary-mode enforces stricter controls compared to sandbox mode. + Whether sandbox mode is enabled or not is irrelevant when + binary-mode is active. + The only purpose of processing sandbox mode here is to avoid error + messages on files made by mysqldump. + */ + else if (cmd_char == '-') + index= sandbox_index; } else index= get_command_index(cmd_char); @@ -2312,6 +2326,12 @@ static COMMANDS *find_command(char *name) len= (uint) strlen(name); int index= -1; + /* + In binary-mode, we disallow all client commands except DELIMITER + and short commands '\C' and '\-' (see short command finding + find_command(char)). + */ + if (real_binary_mode) { if (is_delimiter_command(name, len)) diff --git a/mysql-test/main/mysql.result b/mysql-test/main/mysql.result index c6834d0fc20..445aa602241 100644 --- a/mysql-test/main/mysql.result +++ b/mysql-test/main/mysql.result @@ -658,4 +658,15 @@ tee source ^^^ 3 +# +# MDEV-34203: Sandbox mode \- is not compatible with --binary-mode +# +create table t1 (a int); +drop table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t1; # End of 10.5 tests diff --git a/mysql-test/main/mysql.test b/mysql-test/main/mysql.test index 2f189e70b18..fe79b2c87cb 100644 --- a/mysql-test/main/mysql.test +++ b/mysql-test/main/mysql.test @@ -757,4 +757,20 @@ source $MYSQL_TMP_DIR/mysql_in;" $MYSQL_TMP_DIR/mysql_in2; --remove_file $MYSQL_TMP_DIR/mysql_in --remove_file $MYSQL_TMP_DIR/mysql_in2 +--echo # +--echo # MDEV-34203: Sandbox mode \- is not compatible with --binary-mode +--echo # + +create table t1 (a int); + +--exec $MYSQL_DUMP test t1 > $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql + +drop table t1; + +--exec $MYSQL --binary-mode test 2>&1 < $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql + +show create table t1; +drop table t1; +--remove_file $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql + --echo # End of 10.5 tests From 4b4dbb23eac79040b39173693a53124183108317 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 7 Jun 2024 20:24:39 +0530 Subject: [PATCH 04/11] MDEV-34169 Don't allow innodb_open_files to be lesser than number of non-user tablespace. fil_space_t::try_to_close(): Don't try to close the tablespace which is acquired by the caller of the function Added the suppression message in open_files_limit test case --- mysql-test/suite/innodb/r/open_files_limit.result | 1 + mysql-test/suite/innodb/t/open_files_limit.test | 1 + storage/innobase/fil/fil0fil.cc | 12 +++++++----- storage/innobase/include/fil0fil.h | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/innodb/r/open_files_limit.result b/mysql-test/suite/innodb/r/open_files_limit.result index f2f63376495..1c66bab7533 100644 --- a/mysql-test/suite/innodb/r/open_files_limit.result +++ b/mysql-test/suite/innodb/r/open_files_limit.result @@ -1,4 +1,5 @@ call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*"); +call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is exceeded \\(.* files stay open\\)"); FOUND 1 /\[Warning\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*/ in mysqld.1.err CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/open_files_limit.test b/mysql-test/suite/innodb/t/open_files_limit.test index ea7383150a8..c10f62f3333 100644 --- a/mysql-test/suite/innodb/t/open_files_limit.test +++ b/mysql-test/suite/innodb/t/open_files_limit.test @@ -1,6 +1,7 @@ --source include/have_innodb.inc --source include/not_embedded.inc call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*"); +call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is exceeded \\(.* files stay open\\)"); let SEARCH_PATTERN= \[Warning\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; --source include/search_pattern_in_file.inc diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 88c1115969a..ba4fbc49204 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -66,9 +66,10 @@ inline bool fil_is_user_tablespace_id(ulint space_id) } /** Try to close a file to adhere to the innodb_open_files limit. +@param ignore_space Ignore the tablespace which is acquired by caller @param print_info whether to diagnose why a file cannot be closed @return whether a file was closed */ -bool fil_space_t::try_to_close(bool print_info) +bool fil_space_t::try_to_close(fil_space_t *ignore_space, bool print_info) { ut_ad(mutex_own(&fil_system.mutex)); for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); space; @@ -80,7 +81,8 @@ bool fil_space_t::try_to_close(bool print_info) case FIL_TYPE_IMPORT: break; case FIL_TYPE_TABLESPACE: - if (!fil_is_user_tablespace_id(space->id)) + if (space == ignore_space + || !fil_is_user_tablespace_id(space->id)) continue; } @@ -354,7 +356,7 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, n_pending.fetch_and(~CLOSING, std::memory_order_relaxed); if (++fil_system.n_open >= srv_max_n_open_files) { reacquire(); - try_to_close(true); + try_to_close(this, true); release(); } } @@ -405,7 +407,7 @@ static bool fil_node_open_file_low(fil_node_t *node) /* The following call prints an error message */ if (os_file_get_last_error(true) == EMFILE + 100 && - fil_space_t::try_to_close(true)) + fil_space_t::try_to_close(nullptr, true)) continue; ib::warn() << "Cannot open '" << node->name << "'."; @@ -449,7 +451,7 @@ static bool fil_node_open_file(fil_node_t *node) for (ulint count= 0; fil_system.n_open >= srv_max_n_open_files; count++) { - if (fil_space_t::try_to_close(count > 1)) + if (fil_space_t::try_to_close(nullptr, count > 1)) count= 0; else if (count >= 2) { diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 1f5589a4a20..059a3456c50 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -590,9 +590,10 @@ private: public: /** Try to close a file to adhere to the innodb_open_files limit. + @param ignore_space Ignore the tablespace which is acquired by caller @param print_info whether to diagnose why a file cannot be closed @return whether a file was closed */ - static bool try_to_close(bool print_info); + static bool try_to_close(fil_space_t *ignore_space, bool print_info); /** Close all tablespace files at shutdown */ static void close_all(); From e255837eaf90e72eaf122d88b30011db17f7ecf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 30 May 2024 09:16:42 +0300 Subject: [PATCH 05/11] MDEV-34266 safe_strcpy() includes an unnecessary conditional branch The strncpy() wrapper that was introduced in commit 567b68129943a1cceab1d7b4c68e2a4ba011cdc0 is checking whether the output was truncated even in cases where the caller does not care about it. Let us introduce a separate function safe_strcpy_truncated() that indidates whether the output was truncated. --- client/mysql_plugin.c | 8 +++--- client/mysqltest.cc | 5 ++-- include/m_string.h | 63 ++++++++++++++++++++++--------------------- 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c index 73fa43752a9..679fbf3204c 100644 --- a/client/mysql_plugin.c +++ b/client/mysql_plugin.c @@ -686,7 +686,7 @@ static int load_plugin_data(char *plugin_name, char *config_file) if (i == -1) /* if first pass, read this line as so_name */ { /* Add proper file extension for soname */ - if (safe_strcpy(line + line_len - 1, sizeof(line), FN_SOEXT)) + if (safe_strcpy_truncated(line + line_len - 1, sizeof line, FN_SOEXT)) { reason= "Plugin name too long."; fclose(file_ptr); @@ -749,7 +749,7 @@ static int check_options(int argc, char **argv, char *operation) const char *plugin_dir_prefix = "--plugin_dir="; size_t plugin_dir_len= strlen(plugin_dir_prefix); - strcpy(plugin_name, ""); + *plugin_name= '\0'; for (i = 0; i < argc && num_found < 5; i++) { @@ -787,8 +787,8 @@ static int check_options(int argc, char **argv, char *operation) /* read the plugin config file and check for match against argument */ else { - if (safe_strcpy(plugin_name, sizeof(plugin_name), argv[i]) || - safe_strcpy(config_file, sizeof(config_file), argv[i]) || + if (safe_strcpy_truncated(plugin_name, sizeof plugin_name, argv[i]) || + safe_strcpy_truncated(config_file, sizeof config_file, argv[i]) || safe_strcat(config_file, sizeof(config_file), ".ini")) { fprintf(stderr, "ERROR: argument is too long.\n"); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index fdee3e09851..fa542fe7787 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6265,7 +6265,7 @@ int do_done(struct st_command *command) if (*cur_block->delim) { /* Restore "old" delimiter after false if block */ - if (safe_strcpy(delimiter, sizeof(delimiter), cur_block->delim)) + if (safe_strcpy_truncated(delimiter, sizeof delimiter, cur_block->delim)) die("Delimiter too long, truncated"); delimiter_length= strlen(delimiter); @@ -6526,7 +6526,8 @@ void do_block(enum block_cmd cmd, struct st_command* command) else { /* Remember "old" delimiter if entering a false if block */ - if (safe_strcpy(cur_block->delim, sizeof(cur_block->delim), delimiter)) + if (safe_strcpy_truncated(cur_block->delim, sizeof cur_block->delim, + delimiter)) die("Delimiter too long, truncated"); } diff --git a/include/m_string.h b/include/m_string.h index c45e62770ef..3da252b0912 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -239,15 +239,14 @@ static inline void lex_string_set3(LEX_CSTRING *lex_str, const char *c_str, lex_str->length= len; } -/* - Copies src into dst and ensures dst is a NULL terminated C string. +/** + Copies a string. - Returns 1 if the src string was truncated due to too small size of dst. - Returns 0 if src completely fit within dst. Pads the remaining dst with '\0' - - Note: dst_size must be > 0 + @param dst destination buffer, will be NUL padded. + @param dst_size size of dst buffer, must be > 0 + @param src NUL terminated source string */ -static inline int safe_strcpy(char *dst, size_t dst_size, const char *src) +static inline void safe_strcpy(char *dst, size_t dst_size, const char *src) { DBUG_ASSERT(dst_size > 0); @@ -256,45 +255,49 @@ static inline int safe_strcpy(char *dst, size_t dst_size, const char *src) * * 2) IF there is no 0 byte in the first dst_size bytes of src, strncpy will * copy dst_size bytes, and the final byte won't be 0. - * - * In GCC 8+, the `-Wstringop-truncation` warning will object to strncpy() - * being used in this way, so we need to disable this warning for this - * single statement. */ -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-truncation" -#endif strncpy(dst, src, dst_size); -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic pop -#endif + dst[dst_size - 1]= 0; +} - if (dst[dst_size-1]) +/** + Copies a string, checking for truncation. + + @param dst destination buffer, will be NUL padded. + @param dst_size size of dst buffer, must be > 0 + @param src NUL terminated source string + + @retval 1 if the src string was truncated due to too small size of dst. + @retval 0 if src completely fit within dst, +*/ +static inline int safe_strcpy_truncated(char *dst, size_t dst_size, + const char *src) +{ + DBUG_ASSERT(dst_size > 0); + + strncpy(dst, src, dst_size); + if (dst[dst_size - 1]) { - /* Only possible in case (2), meaning src was truncated. */ - dst[dst_size-1]= 0; + dst[dst_size - 1]= 0; return 1; } return 0; } -/* - Appends src to dst and ensures dst is a NULL terminated C string. +/** + Appends src to dst and ensures dst is a NUL terminated C string. - Returns 1 if the src string was truncated due to too small size of dst. - Returns 0 if src completely fit within the remaining dst space. Pads the - remaining dst with '\0'. - - Note: dst_size must be > 0 + @retval 1 if the src string was truncated due to too small size of dst. + @retval 0 if src completely fit within the remaining dst space, + including NUL termination. */ static inline int safe_strcat(char *dst, size_t dst_size, const char *src) { size_t init_len= strlen(dst); - if (unlikely(init_len >= dst_size - 1)) + if (unlikely(init_len > dst_size)) return 1; - return safe_strcpy(dst + init_len, dst_size - init_len, src); + return safe_strcpy_truncated(dst + init_len, dst_size - init_len, src); } #ifdef __cplusplus From 0172887980cd6297cbda1dda79ecbde0568c4664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 6 Jun 2024 10:35:56 +0300 Subject: [PATCH 06/11] MDEV-34269 : 10.11.8 cluster becomes inconsistent when using composite primary key and partitioning This is regression from commit 3228c08fa8. Problem is that when table storage engine is determined there should be check is table partitioned and if it is then determine partition implementing storage engine. Reported bug is reproducible only with --log-bin so make sure tests changed by 3228c08fa8 and new test are run with --log-bin and binlog disabled. Signed-off-by: Julius Goryavsky --- mysql-test/include/log_bin.combinations | 4 ++ mysql-test/include/log_bin.inc | 3 + .../galera/r/galera_partition_key.result | 46 ++++++++++++++++ .../galera/t/galera_myisam_autocommit.test | 1 + .../suite/galera/t/galera_partition.test | 1 + .../suite/galera/t/galera_partition_key.test | 55 +++++++++++++++++++ mysql-test/suite/galera/t/mdev-22063.test | 2 +- sql/sql_parse.cc | 4 +- 8 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 mysql-test/include/log_bin.combinations create mode 100644 mysql-test/include/log_bin.inc create mode 100644 mysql-test/suite/galera/r/galera_partition_key.result create mode 100644 mysql-test/suite/galera/t/galera_partition_key.test diff --git a/mysql-test/include/log_bin.combinations b/mysql-test/include/log_bin.combinations new file mode 100644 index 00000000000..1eeb8fb4614 --- /dev/null +++ b/mysql-test/include/log_bin.combinations @@ -0,0 +1,4 @@ +[binlogoff] + +[binlogon] +log-bin diff --git a/mysql-test/include/log_bin.inc b/mysql-test/include/log_bin.inc new file mode 100644 index 00000000000..d318c7967e1 --- /dev/null +++ b/mysql-test/include/log_bin.inc @@ -0,0 +1,3 @@ +# include file for test files that can be run with and without log-bin +# (see include/log_bin.combinations) + diff --git a/mysql-test/suite/galera/r/galera_partition_key.result b/mysql-test/suite/galera/r/galera_partition_key.result new file mode 100644 index 00000000000..b4965482779 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_partition_key.result @@ -0,0 +1,46 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE `t1` ( +`id` int(10) unsigned NOT NULL, +`other_id` int(10) unsigned NOT NULL, +PRIMARY KEY (`id`,`other_id`) +) ENGINE=InnoDB +PARTITION BY LIST (`id` MOD 2) +(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB, +PARTITION `p1` VALUES IN (1) ENGINE = InnoDB); +INSERT INTO t1 VALUES (1, 0); +CREATE TABLE t2 LIKE t1; +START TRANSACTION; +INSERT INTO t2(SELECT * FROM t1 WHERE id = 1); +DELETE FROM t1 WHERE id = 1; +COMMIT; +connection node_2; +SELECT * from t1; +id other_id +SELECT * from t2; +id other_id +1 0 +DROP TABLE t1, t2; +connection node_1; +CREATE TABLE `t1` ( +`id` int(10) unsigned NOT NULL, +`other_id` int(10) unsigned NOT NULL, +PRIMARY KEY (`id`) +) ENGINE=InnoDB +PARTITION BY LIST (`id` MOD 2) +(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB, +PARTITION `p1` VALUES IN (1) ENGINE = InnoDB); +INSERT INTO t1 VALUES (1, 0); +CREATE TABLE t2 LIKE t1; +START TRANSACTION; +INSERT INTO t2(SELECT * FROM t1 WHERE id = 1); +DELETE FROM t1 WHERE id = 1; +COMMIT; +connection node_2; +SELECT * from t1; +id other_id +SELECT * from t2; +id other_id +1 0 +DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/t/galera_myisam_autocommit.test b/mysql-test/suite/galera/t/galera_myisam_autocommit.test index 65f957e8422..00799cf2479 100644 --- a/mysql-test/suite/galera/t/galera_myisam_autocommit.test +++ b/mysql-test/suite/galera/t/galera_myisam_autocommit.test @@ -1,5 +1,6 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +--source include/log_bin.inc # # This tests simple autocommit replication of MyISAM tables. diff --git a/mysql-test/suite/galera/t/galera_partition.test b/mysql-test/suite/galera/t/galera_partition.test index 269291311f1..d69f87b6472 100644 --- a/mysql-test/suite/galera/t/galera_partition.test +++ b/mysql-test/suite/galera/t/galera_partition.test @@ -2,6 +2,7 @@ --source include/have_partition.inc --source include/big_test.inc --source include/force_restart.inc +--source include/log_bin.inc --connection node_1 diff --git a/mysql-test/suite/galera/t/galera_partition_key.test b/mysql-test/suite/galera/t/galera_partition_key.test new file mode 100644 index 00000000000..ac1fcf72f06 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_partition_key.test @@ -0,0 +1,55 @@ +--source include/galera_cluster.inc +--source include/have_partition.inc +--source include/log_bin.inc + +--connection node_1 +CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL, + `other_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`,`other_id`) +) ENGINE=InnoDB + PARTITION BY LIST (`id` MOD 2) +(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB, + PARTITION `p1` VALUES IN (1) ENGINE = InnoDB); + +INSERT INTO t1 VALUES (1, 0); + +CREATE TABLE t2 LIKE t1; + +START TRANSACTION; + +INSERT INTO t2(SELECT * FROM t1 WHERE id = 1); +DELETE FROM t1 WHERE id = 1; + +COMMIT; + +--connection node_2 +SELECT * from t1; +SELECT * from t2; +DROP TABLE t1, t2; + +--connection node_1 +CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL, + `other_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB + PARTITION BY LIST (`id` MOD 2) +(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB, + PARTITION `p1` VALUES IN (1) ENGINE = InnoDB); + +INSERT INTO t1 VALUES (1, 0); + +CREATE TABLE t2 LIKE t1; + +START TRANSACTION; + +INSERT INTO t2(SELECT * FROM t1 WHERE id = 1); +DELETE FROM t1 WHERE id = 1; + +COMMIT; + +--connection node_2 +SELECT * from t1; +SELECT * from t2; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/t/mdev-22063.test b/mysql-test/suite/galera/t/mdev-22063.test index a8e7b87ad38..ef16c0c8716 100644 --- a/mysql-test/suite/galera/t/mdev-22063.test +++ b/mysql-test/suite/galera/t/mdev-22063.test @@ -1,6 +1,6 @@ --source include/galera_cluster.inc --source include/have_innodb.inc ---source include/have_log_bin.inc +--source include/log_bin.inc --source include/have_sequence.inc --source include/have_aria.inc diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b071c74b245..ca991b34e9f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4747,7 +4747,9 @@ mysql_execute_command(THD *thd) #ifdef WITH_WSREP if (wsrep && !first_table->view) { - bool is_innodb= (first_table->table->file->ht->db_type == DB_TYPE_INNODB); + const handlerton *hton = first_table->table->file->partition_ht() ? + first_table->table->file->partition_ht() : first_table->table->file->ht; + bool is_innodb= (hton->db_type == DB_TYPE_INNODB); // For consistency check inserted table needs to be InnoDB if (!is_innodb && thd->wsrep_consistency_check != NO_CONSISTENCY_CHECK) From 0d85c905c44f9d88e4a17f56594cc389d777abaf Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Fri, 7 Jun 2024 14:53:11 +0200 Subject: [PATCH 07/11] MDEV-34269: post-fix code simplification The code is slightly simplified taking into account the fact that partition_ht() always returns a normal hton when there is no partitioning. --- sql/sql_load.cc | 4 +--- sql/sql_parse.cc | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 0eced4e74b4..7329a7d2db5 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -117,10 +117,8 @@ public: */ if (WSREP(thd) && wsrep_load_data_splitting) { - handlerton *ht= table->s->db_type(); // For partitioned tables find underlying hton - if (table->file->partition_ht()) - ht= table->file->partition_ht(); + handlerton *ht= table->file->partition_ht(); if (ht->db_type != DB_TYPE_INNODB) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ca991b34e9f..69164a95be6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4747,9 +4747,7 @@ mysql_execute_command(THD *thd) #ifdef WITH_WSREP if (wsrep && !first_table->view) { - const handlerton *hton = first_table->table->file->partition_ht() ? - first_table->table->file->partition_ht() : first_table->table->file->ht; - bool is_innodb= (hton->db_type == DB_TYPE_INNODB); + bool is_innodb= first_table->table->file->partition_ht()->db_type == DB_TYPE_INNODB; // For consistency check inserted table needs to be InnoDB if (!is_innodb && thd->wsrep_consistency_check != NO_CONSISTENCY_CHECK) From bf0aa99aeb7dd2bb7497f5ae9a82d1e72e7ee1d5 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Thu, 6 Jun 2024 11:46:27 -0600 Subject: [PATCH 08/11] MDEV-34237: On Startup: UBSAN: runtime error: call to function MDL_lock::lf_hash_initializer lf_hash_insert through pointer to incorrect function type 'void (*)(st_lf_hash *, void *, const void *)' A few different incorrect function type UBSAN issues have been grouped into this patch. The only real potentially undefined behavior is an error about show_func_mutex_instances_lost, which when invoked in sql_show.cc::show_status_array(), puts 5 arguments onto the stack; however, the implementing function only actually has 3 parameters (so only 3 would be popped). This was fixed by adding in the remaining parameters to satisfy the type mysql_show_var_func. The rest of the findings are pointer type mismatches that wouldn't lead to actual undefined behavior. The lf_hash_initializer function type definition is typedef void (*lf_hash_initializer)(LF_HASH *hash, void *dst, const void *src); but the MDL_lock and table cache's implementations of this function do not have that signature. The MDL_lock has specific MDL object parameters: static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)), MDL_lock *lock, MDL_key *key_arg) and the table cache has specific TDC parameters: static void tdc_hash_initializer(LF_HASH *, TDC_element *element, LEX_STRING *key) leading to UBSAN runtime errors when invoking these functions. This patch fixes these type mis-matches by changing the implementing functions to use void * and const void * for their respective parameters, and later casting them to their expected type in the function body. Note too the functions tdc_hash_key and tc_purge_callback had a similar problem to tdc_hash_initializer and was fixed similarly. Reviewed By: ============ Sergei Golubchik --- sql/mdl.cc | 4 +++- sql/sql_show.cc | 2 +- sql/table_cache.cc | 13 +++++++++---- storage/perfschema/ha_perfschema.cc | 4 +++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/sql/mdl.cc b/sql/mdl.cc index 6b8d3599c00..fb106a1af47 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -673,8 +673,10 @@ public: { ((MDL_lock*)(arg + LF_HASH_OVERHEAD))->~MDL_lock(); } static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)), - MDL_lock *lock, MDL_key *key_arg) + void *_lock, const void *_key_arg) { + MDL_lock *lock= static_cast(_lock); + const MDL_key *key_arg= static_cast(_key_arg); DBUG_ASSERT(key_arg->mdl_namespace() != MDL_key::BACKUP); new (&lock->key) MDL_key(key_arg); if (key_arg->mdl_namespace() == MDL_key::SCHEMA) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index eb84ef56419..ca291bd9e5d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3789,7 +3789,7 @@ static bool show_status_array(THD *thd, const char *wild, */ for (var=variables; var->type == SHOW_FUNC || var->type == SHOW_SIMPLE_FUNC; var= &tmp) - ((mysql_show_var_func)(var->value))(thd, &tmp, buff, + ((mysql_show_var_func)(var->value))(thd, &tmp, (void *) buff, status_var, scope); SHOW_TYPE show_type=var->type; diff --git a/sql/table_cache.cc b/sql/table_cache.cc index 499e82fafea..b76ba4fd239 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -293,9 +293,11 @@ static void tc_remove_all_unused_tables(TDC_element *element, periodicly flush all not used tables. */ -static my_bool tc_purge_callback(TDC_element *element, - Share_free_tables::List *purge_tables) +static my_bool tc_purge_callback(void *_element, void *_purge_tables) { + TDC_element *element= static_cast(_element); + Share_free_tables::List *purge_tables= + static_cast(_purge_tables); mysql_mutex_lock(&element->LOCK_table_share); tc_remove_all_unused_tables(element, purge_tables); mysql_mutex_unlock(&element->LOCK_table_share); @@ -566,17 +568,20 @@ static void lf_alloc_destructor(uchar *arg) static void tdc_hash_initializer(LF_HASH *, - TDC_element *element, LEX_STRING *key) + void *_element, const void *_key) { + TDC_element *element= static_cast(_element); + const LEX_STRING *key= static_cast(_key); memcpy(element->m_key, key->str, key->length); element->m_key_length= (uint)key->length; tdc_assert_clean_share(element); } -static uchar *tdc_hash_key(const TDC_element *element, size_t *length, +static uchar *tdc_hash_key(const unsigned char *_element, size_t *length, my_bool) { + const TDC_element *element= (const TDC_element *) _element; *length= element->m_key_length; return (uchar*) element->m_key; } diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index c6d2f23d653..8b7825f3816 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -133,7 +133,9 @@ static int pfs_done_func(void *p) DBUG_RETURN(0); } -static int show_func_mutex_instances_lost(THD *thd, SHOW_VAR *var, char *buff) +static int show_func_mutex_instances_lost(THD *thd, SHOW_VAR *var, void *buff, + struct system_status_var *status_var, + enum enum_var_type) { var->type= SHOW_LONG; var->value= buff; From 21f56583bf209e00907203ca1e313f8d0a7d8d7f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 10 Jun 2024 09:31:14 +0400 Subject: [PATCH 09/11] MDEV-32376 SHOW CREATE DATABASE statement crashes the server when db name contains some unicode characters, ASAN stack-buffer-overflow Adding the test for the length of lex->name into show_create_db(). Without this test writes beyond the end of db_name_buff were possible upon a too long database name. --- mysql-test/main/create.result | 7 +++++++ mysql-test/main/create.test | 9 +++++++++ sql/sql_parse.cc | 17 +++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result index fc508108a97..95812106c7f 100644 --- a/mysql-test/main/create.result +++ b/mysql-test/main/create.result @@ -2061,4 +2061,11 @@ DROP TABLE t1; # CREATE TABLE t1 (id1 INT, id2 INT, primary key (id1), unique index (id2) visible); drop table t1; +# +# MDEV-32376 SHOW CREATE DATABASE statement crashes the server when db name contains some unicode characters, ASAN stack-buffer-overflow +# +SET NAMES utf8mb3; +SHOW CREATE DATABASE `#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■`; +ERROR 42000: Incorrect database name '#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■...' +SET NAMES DEFAULT; # End of 10.5 Test diff --git a/mysql-test/main/create.test b/mysql-test/main/create.test index e9470edefab..14541d84dc9 100644 --- a/mysql-test/main/create.test +++ b/mysql-test/main/create.test @@ -1935,4 +1935,13 @@ DROP TABLE t1; CREATE TABLE t1 (id1 INT, id2 INT, primary key (id1), unique index (id2) visible); drop table t1; +--echo # +--echo # MDEV-32376 SHOW CREATE DATABASE statement crashes the server when db name contains some unicode characters, ASAN stack-buffer-overflow +--echo # + +SET NAMES utf8mb3; +--error ER_WRONG_DB_NAME +SHOW CREATE DATABASE `#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■`; +SET NAMES DEFAULT; + --echo # End of 10.5 Test diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 69164a95be6..559af2fc813 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6637,6 +6637,23 @@ show_create_db(THD *thd, LEX *lex) DBUG_EXECUTE_IF("4x_server_emul", my_error(ER_UNKNOWN_ERROR, MYF(0)); return 1;); +#if MYSQL_VERSION_ID<=110301 + /* + This piece of the code was added in 10.5 to fix MDEV-32376. + It should not get to 11.3 or higer, as MDEV-32376 was fixed + in a different way in 11.3.1 (see MDEV-31948). + */ + if (lex->name.length > sizeof(db_name_buff) - 1) + { + my_error(ER_WRONG_DB_NAME, MYF(0), + ErrConvString(lex->name.str, lex->name.length, + system_charset_info).ptr()); + return 1; + } +#else +#error Remove this preprocessor-conditional code in 11.3.1+ +#endif + db_name.str= db_name_buff; db_name.length= lex->name.length; strmov(db_name_buff, lex->name.str); From 246c0b3a353d0831fb00ac4cd46599a33a808d0c Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 10 Jun 2024 12:17:01 +0400 Subject: [PATCH 10/11] MDEV-34227 On startup: UBSAN: runtime error: applying non-zero offset in JOIN::make_aggr_tables_info in sql/sql_select.cc Avoid undefined behaviour (applying offset to nullptr). The reported scenario is covered in mysql-test/connect-no-db.test No new tests needed. --- sql/sql_select.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 215a7113b71..b99ea744ae8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3325,7 +3325,8 @@ bool JOIN::make_aggr_tables_info() { List *curr_all_fields= &all_fields; List *curr_fields_list= &fields_list; - JOIN_TAB *curr_tab= join_tab + const_tables; + // Avoid UB (applying .. offset to nullptr) when join_tab is nullptr + JOIN_TAB *curr_tab= join_tab ? join_tab + const_tables : nullptr; TABLE *exec_tmp_table= NULL; bool distinct= false; bool keep_row_order= false; @@ -3883,9 +3884,9 @@ bool JOIN::make_aggr_tables_info() - duplicate value removal Both of these operations are done after window function computation step. */ - curr_tab= join_tab + total_join_tab_cnt(); if (select_lex->window_funcs.elements) { + curr_tab= join_tab + total_join_tab_cnt(); if (!(curr_tab->window_funcs_step= new Window_funcs_computation)) DBUG_RETURN(true); if (curr_tab->window_funcs_step->setup(thd, &select_lex->window_funcs, From a2bd936c528adb17415b35f38ba4fef5792adb55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 10 Jun 2024 12:35:33 +0300 Subject: [PATCH 11/11] MDEV-33161 Function pointer signature mismatch in LF_HASH In cmake -DWITH_UBSAN=ON builds with clang but not with GCC, -fsanitize=undefined will flag several runtime errors on function pointer mismatch related to the lock-free hash table LF_HASH. Let us use matching function signatures and remove function pointer casts in order to avoid potential bugs due to undefined behaviour. These errors could be caught at compilation time by -Wcast-function-type-strict, which is available starting with clang-16, but not available in any version of GCC as of now. The old GCC flag -Wcast-function-type is enabled as part of -Wextra, but it specifically does not catch these errors. Reviewed by: Vladislav Vaintroub --- mysys/lf_alloc-pin.c | 29 ++++++++------- mysys/thr_mutex.c | 58 ++++++++++++++---------------- mysys/waiting_threads.c | 4 ++- sql/mdl.cc | 11 +++--- sql/sql_base.cc | 16 ++++----- sql/sql_servers.cc | 9 +++-- sql/sql_test.cc | 2 +- sql/table_cache.cc | 11 +++--- sql/xa.cc | 42 +++++++++++----------- storage/innobase/include/trx0sys.h | 55 ++++++++++++++-------------- storage/innobase/lock/lock0lock.cc | 22 +++++++----- storage/innobase/trx/trx0trx.cc | 9 ++--- 12 files changed, 137 insertions(+), 131 deletions(-) diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 4dc41645530..8726349daa4 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -242,8 +242,10 @@ void lf_pinbox_put_pins(LF_PINS *pins) return; } -static int ptr_cmp(void **a, void **b) +static int ptr_cmp(const void *pa, const void *pb) { + const void *const*a= pa; + const void *const*b= pb; return *a < *b ? -1 : *a == *b ? 0 : 1; } @@ -283,8 +285,10 @@ struct st_harvester { callback forlf_dynarray_iterate: scan all pins of all threads and accumulate all pins */ -static int harvest_pins(LF_PINS *el, struct st_harvester *hv) +static int harvest_pins(void *e, void *h) { + LF_PINS *el= e; + struct st_harvester *hv= h; int i; LF_PINS *el_end= el+MY_MIN(hv->npins, LF_DYNARRAY_LEVEL_LENGTH); for (; el < el_end; el++) @@ -310,8 +314,9 @@ static int harvest_pins(LF_PINS *el, struct st_harvester *hv) callback forlf_dynarray_iterate: scan all pins of all threads and see if addr is present there */ -static int match_pins(LF_PINS *el, void *addr) +static int match_pins(void *e, void *addr) { + LF_PINS *el= e; int i; LF_PINS *el_end= el+LF_DYNARRAY_LEVEL_LENGTH; for (; el < el_end; el++) @@ -352,13 +357,12 @@ static void lf_pinbox_real_free(LF_PINS *pins) hv.granary= addr; hv.npins= npins; /* scan the dynarray and accumulate all pinned addresses */ - lf_dynarray_iterate(&pinbox->pinarray, - (lf_dynarray_func)harvest_pins, &hv); + lf_dynarray_iterate(&pinbox->pinarray, harvest_pins, &hv); npins= (int)(hv.granary-addr); /* and sort them */ if (npins) - qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); + qsort(addr, npins, sizeof(void *), ptr_cmp); } } #endif @@ -387,8 +391,7 @@ static void lf_pinbox_real_free(LF_PINS *pins) } else /* no alloca - no cookie. linear search here */ { - if (lf_dynarray_iterate(&pinbox->pinarray, - (lf_dynarray_func)match_pins, cur)) + if (lf_dynarray_iterate(&pinbox->pinarray, match_pins, cur)) goto found; } } @@ -416,10 +419,11 @@ found: 'first' and 'last' are the ends of the linked list of nodes: first->el->el->....->el->last. Use first==last to free only one element. */ -static void alloc_free(uchar *first, - uchar volatile *last, - LF_ALLOCATOR *allocator) +static void alloc_free(void *f, void *l, void *alloc) { + uchar *first= f; + uchar volatile *last= l; + LF_ALLOCATOR *allocator= alloc; /* we need a union here to access type-punned pointer reliably. otherwise gcc -fstrict-aliasing will not see 'tmp' changed in the loop @@ -448,8 +452,7 @@ static void alloc_free(uchar *first, */ void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset) { - lf_pinbox_init(&allocator->pinbox, free_ptr_offset, - (lf_pinbox_free_func *)alloc_free, allocator); + lf_pinbox_init(&allocator->pinbox, free_ptr_offset, alloc_free, allocator); allocator->top= 0; allocator->mallocs= 0; allocator->element_size= size; diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 2a8e54621c0..5b5f4360b73 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -62,14 +62,10 @@ my_bool safe_mutex_deadlock_detector= 1; /* On by default */ static struct st_safe_mutex_create_info_t *safe_mutex_create_root= NULL; #endif -static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, - safe_mutex_deadlock_t *locked_mutex); -static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, - safe_mutex_t *current_mutex); -static my_bool remove_from_locked_mutex(safe_mutex_t *mp, - safe_mutex_t *delete_mutex); -static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex, - safe_mutex_t *mutex); +static my_bool add_used_to_locked_mutex(void *used, void *locked); +static my_bool add_to_locked_mutex(void *locked, void *current); +static my_bool remove_from_locked_mutex(void *m, void* remove); +static my_bool remove_from_used_mutex(void *locked, void *m); static void print_deadlock_warning(safe_mutex_t *new_mutex, safe_mutex_t *conflicting_mutex); #endif @@ -373,8 +369,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, are now locking (C) in B->C, then we would add C into B->locked_mutex and A->locked_mutex */ - my_hash_iterate(mutex_root->used_mutex, - (my_hash_walk_action) add_used_to_locked_mutex, + my_hash_iterate(mutex_root->used_mutex, add_used_to_locked_mutex, deadlock); /* @@ -654,12 +649,8 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp) if (!(mp->create_flags & MYF_NO_DEADLOCK_DETECTION) && mp->used_mutex != NULL) { pthread_mutex_lock(&THR_LOCK_mutex); - my_hash_iterate(mp->used_mutex, - (my_hash_walk_action) remove_from_locked_mutex, - mp); - my_hash_iterate(mp->locked_mutex, - (my_hash_walk_action) remove_from_used_mutex, - mp); + my_hash_iterate(mp->used_mutex, remove_from_locked_mutex, mp); + my_hash_iterate(mp->locked_mutex, remove_from_used_mutex, mp); pthread_mutex_unlock(&THR_LOCK_mutex); my_hash_free(mp->used_mutex); @@ -709,15 +700,15 @@ void safe_mutex_end(FILE *file __attribute__((unused))) #endif /* SAFE_MUTEX_DETECT_DESTROY */ } -static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, - safe_mutex_deadlock_t *locked_mutex) +static my_bool add_used_to_locked_mutex(void *used, void *locked) { + safe_mutex_t *used_mutex= used; + safe_mutex_deadlock_t *locked_mutex= locked; /* Add mutex to all parent of the current mutex */ if (!locked_mutex->warning_only) { (void) my_hash_iterate(locked_mutex->mutex->locked_mutex, - (my_hash_walk_action) add_to_locked_mutex, - used_mutex); + add_to_locked_mutex, used_mutex); /* mark that locked_mutex is locked after used_mutex */ (void) add_to_locked_mutex(locked_mutex, used_mutex); } @@ -729,12 +720,13 @@ static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, register that locked_mutex was locked after current_mutex */ -static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, - safe_mutex_t *current_mutex) +static my_bool add_to_locked_mutex(void *locked, void *current) { + safe_mutex_deadlock_t *locked_mutex= locked; + safe_mutex_t *current_mutex= current; DBUG_ENTER("add_to_locked_mutex"); - DBUG_PRINT("info", ("inserting 0x%lx into 0x%lx (id: %lu -> %lu)", - (ulong) locked_mutex, (long) current_mutex, + DBUG_PRINT("info", ("inserting %p into %p (id: %lu -> %lu)", + locked_mutex, current_mutex, locked_mutex->id, current_mutex->id)); if (my_hash_insert(current_mutex->locked_mutex, (uchar*) locked_mutex)) { @@ -762,13 +754,14 @@ static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, When counter goes to 0, we delete the safe_mutex_deadlock_t entry. */ -static my_bool remove_from_locked_mutex(safe_mutex_t *mp, - safe_mutex_t *delete_mutex) +static my_bool remove_from_locked_mutex(void *m, void *remove) { + safe_mutex_t *mp= m; + safe_mutex_t *delete_mutex= remove; safe_mutex_deadlock_t *found; DBUG_ENTER("remove_from_locked_mutex"); - DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)", - (ulong) delete_mutex, (ulong) mp, + DBUG_PRINT("enter", ("delete_mutex: %p mutex: %p (id: %lu <- %lu)", + delete_mutex, mp, delete_mutex->id, mp->id)); found= (safe_mutex_deadlock_t *) my_hash_search(mp->locked_mutex, @@ -786,12 +779,13 @@ static my_bool remove_from_locked_mutex(safe_mutex_t *mp, DBUG_RETURN(0); } -static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex, - safe_mutex_t *mutex) +static my_bool remove_from_used_mutex(void *locked, void *m) { + safe_mutex_deadlock_t *locked_mutex= locked; + safe_mutex_t *mutex= m; DBUG_ENTER("remove_from_used_mutex"); - DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)", - (ulong) mutex, (ulong) locked_mutex, + DBUG_PRINT("enter", ("delete_mutex: %p mutex: %p (id: %lu <- %lu)", + mutex, locked_mutex, mutex->id, locked_mutex->id)); if (my_hash_delete(locked_mutex->mutex->used_mutex, (uchar*) mutex)) { diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c index dd60088d534..445e9f4781a 100644 --- a/mysys/waiting_threads.c +++ b/mysys/waiting_threads.c @@ -424,8 +424,10 @@ static void wt_resource_destroy(uchar *arg) It's called from lf_hash when an element is inserted. */ static void wt_resource_init(LF_HASH *hash __attribute__((unused)), - WT_RESOURCE *rc, WT_RESOURCE_ID *id) + void *resource, const void *ident) { + WT_RESOURCE *rc= resource; + const WT_RESOURCE_ID *id= ident; DBUG_ENTER("wt_resource_init"); rc->id= *id; rc->waiter_count= 0; diff --git a/sql/mdl.cc b/sql/mdl.cc index fb106a1af47..669f2c142db 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -762,8 +762,10 @@ struct mdl_iterate_arg }; -static my_bool mdl_iterate_lock(MDL_lock *lock, mdl_iterate_arg *arg) +static my_bool mdl_iterate_lock(void *lk, void *a) { + MDL_lock *lock= static_cast(lk); + mdl_iterate_arg *arg= static_cast(a); /* We can skip check for m_strategy here, becase m_granted must be empty for such locks anyway. @@ -786,14 +788,13 @@ int mdl_iterate(mdl_iterator_callback callback, void *arg) { DBUG_ENTER("mdl_iterate"); mdl_iterate_arg argument= { callback, arg }; - LF_PINS *pins= mdl_locks.get_pins(); int res= 1; - if (pins) + if (LF_PINS *pins= mdl_locks.get_pins()) { res= mdl_iterate_lock(mdl_locks.m_backup_lock, &argument) || - lf_hash_iterate(&mdl_locks.m_locks, pins, - (my_hash_walk_action) mdl_iterate_lock, &argument); + lf_hash_iterate(&mdl_locks.m_locks, pins, mdl_iterate_lock, + &argument); lf_hash_put_pins(pins); } DBUG_RETURN(res); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index eb66d33b5b0..bac6026cb1e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -252,9 +252,10 @@ public: }; -static my_bool list_open_tables_callback(TDC_element *element, - list_open_tables_arg *arg) +static my_bool list_open_tables_callback(void *el, void *a) { + TDC_element *element= static_cast(el); + list_open_tables_arg *arg= static_cast(a); const Lex_ident_db db= Lex_ident_db(Lex_cstring_strlen((const char*) element->m_key)); const char *table_name= db.str + db.length + 1; @@ -302,8 +303,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, DBUG_ENTER("list_open_tables"); list_open_tables_arg argument(thd, db, wild); - if (tdc_iterate(thd, (my_hash_walk_action) list_open_tables_callback, - &argument, true)) + if (tdc_iterate(thd, list_open_tables_callback, &argument, true)) DBUG_RETURN(0); DBUG_RETURN(argument.open_list); @@ -462,9 +462,10 @@ struct tc_collect_arg flush_tables_type flush_type; }; -static my_bool tc_collect_used_shares(TDC_element *element, - tc_collect_arg *arg) +static my_bool tc_collect_used_shares(void *el, void *a) { + TDC_element *element= static_cast(el); + tc_collect_arg *arg= static_cast(a); my_bool result= FALSE; DYNAMIC_ARRAY *shares= &arg->shares; @@ -573,8 +574,7 @@ bool flush_tables(THD *thd, flush_tables_type flag) my_init_dynamic_array(PSI_INSTRUMENT_ME, &collect_arg.shares, sizeof(TABLE_SHARE*), 100, 100, MYF(0)); collect_arg.flush_type= flag; - if (tdc_iterate(thd, (my_hash_walk_action) tc_collect_used_shares, - &collect_arg, true)) + if (tdc_iterate(thd, tc_collect_used_shares, &collect_arg, true)) { /* Release already collected shares */ for (uint i= 0 ; i < collect_arg.shares.elements ; i++) diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index d52d6071e89..d63b0d66a5e 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -133,9 +133,10 @@ struct close_cached_connection_tables_arg }; -static my_bool close_cached_connection_tables_callback( - TDC_element *element, close_cached_connection_tables_arg *arg) +static my_bool close_cached_connection_tables_callback(void *el, void *a) { + TDC_element *element= static_cast(el); + auto arg= static_cast(a); TABLE_LIST *tmp; mysql_mutex_lock(&element->LOCK_table_share); @@ -188,9 +189,7 @@ static bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection) close_cached_connection_tables_arg argument= { thd, connection, 0 }; DBUG_ENTER("close_cached_connections"); - if (tdc_iterate(thd, - (my_hash_walk_action) close_cached_connection_tables_callback, - &argument)) + if (tdc_iterate(thd, close_cached_connection_tables_callback, &argument)) DBUG_RETURN(true); DBUG_RETURN(argument.tables ? diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 47acdaf8d7c..b625341fe5e 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -116,7 +116,7 @@ static void print_cached_tables(void) /* purecov: begin tested */ puts("DB Table Version Thread Open Lock"); - tdc_iterate(0, (my_hash_walk_action) print_cached_tables_callback, NULL, true); + tdc_iterate(0, print_cached_tables_callback, NULL, true); fflush(stdout); /* purecov: end */ diff --git a/sql/table_cache.cc b/sql/table_cache.cc index b76ba4fd239..f073dd1ec87 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -309,7 +309,7 @@ void tc_purge() { Share_free_tables::List purge_tables; - tdc_iterate(0, (my_hash_walk_action) tc_purge_callback, &purge_tables); + tdc_iterate(0, tc_purge_callback, &purge_tables); while (auto table= purge_tables.pop_front()) intern_close_table(table); } @@ -1126,7 +1126,7 @@ struct eliminate_duplicates_arg static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length, - my_bool not_used __attribute__((unused))) + my_bool) { LEX_STRING *key= (LEX_STRING *) element; *length= key->length; @@ -1134,9 +1134,10 @@ static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length, } -static my_bool eliminate_duplicates(TDC_element *element, - eliminate_duplicates_arg *arg) +static my_bool eliminate_duplicates(void *el, void *a) { + TDC_element *element= static_cast(el); + eliminate_duplicates_arg *arg= static_cast(a); LEX_STRING *key= (LEX_STRING *) alloc_root(&arg->root, sizeof(LEX_STRING)); if (!key || !(key->str= (char*) memdup_root(&arg->root, element->m_key, @@ -1182,7 +1183,7 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, hash_flags); no_dups_argument.action= action; no_dups_argument.argument= argument; - action= (my_hash_walk_action) eliminate_duplicates; + action= eliminate_duplicates; argument= &no_dups_argument; } diff --git a/sql/xa.cc b/sql/xa.cc index 7935c06c2ad..c4cd548b132 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -126,10 +126,11 @@ public: } return true; } - static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)), - XID_cache_element *element, - XID_cache_insert_element *new_element) + static void lf_hash_initializer(LF_HASH *, void *el, const void *ie) { + XID_cache_element *element= static_cast(el); + XID_cache_insert_element *new_element= + static_cast(const_cast(ie)); DBUG_ASSERT(!element->is_set(ACQUIRED | RECOVERED)); element->rm_error= 0; element->xa_state= new_element->xa_state; @@ -146,11 +147,11 @@ public: DBUG_ASSERT(!reinterpret_cast(ptr + LF_HASH_OVERHEAD) ->is_set(ACQUIRED)); } - static uchar *key(const XID_cache_element *element, size_t *length, - my_bool not_used __attribute__((unused))) + static uchar *key(const unsigned char *el, size_t *length, my_bool) { - *length= element->xid.key_length(); - return element->xid.key(); + const XID &xid= reinterpret_cast(el)->xid; + *length= xid.key_length(); + return xid.key(); } }; @@ -221,11 +222,10 @@ void xid_cache_init() { xid_cache_inited= true; lf_hash_init(&xid_cache, sizeof(XID_cache_element), LF_HASH_UNIQUE, 0, 0, - (my_hash_get_key) XID_cache_element::key, &my_charset_bin); + XID_cache_element::key, &my_charset_bin); xid_cache.alloc.constructor= XID_cache_element::lf_alloc_constructor; xid_cache.alloc.destructor= XID_cache_element::lf_alloc_destructor; - xid_cache.initializer= - (lf_hash_initializer) XID_cache_element::lf_hash_initializer; + xid_cache.initializer= XID_cache_element::lf_hash_initializer; } @@ -331,9 +331,10 @@ struct xid_cache_iterate_arg void *argument; }; -static my_bool xid_cache_iterate_callback(XID_cache_element *element, - xid_cache_iterate_arg *arg) +static my_bool xid_cache_iterate_callback(void *el, void *a) { + XID_cache_element *element= static_cast(el); + xid_cache_iterate_arg *arg= static_cast(a); my_bool res= FALSE; if (element->lock()) { @@ -348,8 +349,7 @@ static int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg) xid_cache_iterate_arg argument= { action, arg }; return thd->fix_xid_hash_pins() ? -1 : lf_hash_iterate(&xid_cache, thd->xid_hash_pins, - (my_hash_walk_action) xid_cache_iterate_callback, - &argument); + xid_cache_iterate_callback, &argument); } @@ -1039,17 +1039,19 @@ static my_bool xa_recover_callback(XID_cache_element *xs, Protocol *protocol, } -static my_bool xa_recover_callback_short(XID_cache_element *xs, - Protocol *protocol) +static my_bool xa_recover_callback_short(void *x, void *p) { + XID_cache_element *xs= static_cast(x); + Protocol *protocol= static_cast(p); return xa_recover_callback(xs, protocol, xs->xid.data, xs->xid.gtrid_length + xs->xid.bqual_length, &my_charset_bin); } -static my_bool xa_recover_callback_verbose(XID_cache_element *xs, - Protocol *protocol) +static my_bool xa_recover_callback_verbose(void *x, void *p) { + XID_cache_element *xs= static_cast(x); + Protocol *protocol= static_cast(p); char buf[SQL_XIDSIZE]; uint len= get_sql_xid(&xs->xid, buf); return xa_recover_callback(xs, protocol, buf, len, @@ -1082,13 +1084,13 @@ bool mysql_xa_recover(THD *thd) { len= SQL_XIDSIZE; cs= &my_charset_utf8mb3_general_ci; - action= (my_hash_walk_action) xa_recover_callback_verbose; + action= xa_recover_callback_verbose; } else { len= XIDDATASIZE; cs= &my_charset_bin; - action= (my_hash_walk_action) xa_recover_callback_short; + action= xa_recover_callback_short; } field_list.push_back(new (mem_root) diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index caac9af29ed..acd18935914 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -453,10 +453,10 @@ class rw_trx_hash_t not accessible by concurrent threads. */ - static void rw_trx_hash_initializer(LF_HASH *, - rw_trx_hash_element_t *element, - trx_t *trx) + static void rw_trx_hash_initializer(LF_HASH *, void *el, const void *t) { + rw_trx_hash_element_t *element= static_cast(el); + trx_t *trx= static_cast(const_cast(t)); ut_ad(element->trx == 0); element->trx= trx; element->id= trx->id; @@ -470,7 +470,7 @@ class rw_trx_hash_t Pins are used to protect object from being destroyed or reused. They are normally stored in trx object for quick access. If caller doesn't have trx - available, we try to get it using currnet_trx(). If caller doesn't have trx + available, we try to get it using current_trx(). If caller doesn't have trx at all, temporary pins are allocated. */ @@ -496,9 +496,10 @@ class rw_trx_hash_t template - static my_bool eliminate_duplicates(rw_trx_hash_element_t *element, - eliminate_duplicates_arg *arg) + static my_bool eliminate_duplicates(void *el, void *a) { + rw_trx_hash_element_t *element= static_cast(el); + auto arg= static_cast*>(a); for (trx_ids_t::iterator it= arg->ids.begin(); it != arg->ids.end(); it++) { if (*it == element->id) @@ -524,17 +525,17 @@ class rw_trx_hash_t } - template struct debug_iterator_arg + struct debug_iterator_arg { - walk_action *action; - T *argument; + my_hash_walk_action action; + void *argument; }; - template - static my_bool debug_iterator(rw_trx_hash_element_t *element, - debug_iterator_arg *arg) + static my_bool debug_iterator(void *el, void *a) { + rw_trx_hash_element_t *element= static_cast(el); + debug_iterator_arg *arg= static_cast(a); mutex_enter(&element->mutex); if (element->trx) validate_element(element->trx); @@ -744,7 +745,7 @@ public: @param caller_trx used to get/set pins @param action called for every element in hash - @param argument opque argument passed to action + @param argument opaque argument passed to action May return the same element multiple times if hash is under contention. If caller doesn't like to see the same transaction multiple times, it has @@ -767,28 +768,24 @@ public: @retval 1 iteration was interrupted (action returned 1) */ - template - int iterate(trx_t *caller_trx, walk_action *action, T *argument= nullptr) + int iterate(trx_t *caller_trx, my_hash_walk_action action, + void *argument= nullptr) { LF_PINS *pins= caller_trx ? get_pins(caller_trx) : lf_hash_get_pins(&hash); ut_a(pins); #ifdef UNIV_DEBUG - debug_iterator_arg debug_arg= { action, argument }; - action= reinterpret_cast(debug_iterator); - argument= reinterpret_cast(&debug_arg); + debug_iterator_arg debug_arg= { action, argument }; + action= debug_iterator; + argument= reinterpret_cast(&debug_arg); #endif - int res= lf_hash_iterate(&hash, pins, - reinterpret_cast(action), - const_cast(static_cast - (argument))); + int res= lf_hash_iterate(&hash, pins, action, argument); if (!caller_trx) lf_hash_put_pins(pins); return res; } - template - int iterate(walk_action *action, T *argument= nullptr) + int iterate(my_hash_walk_action action, void *argument= nullptr) { return iterate(current_trx(), action, argument); } @@ -1176,9 +1173,10 @@ public: } private: - static my_bool get_min_trx_id_callback(rw_trx_hash_element_t *element, - trx_id_t *id) + static my_bool get_min_trx_id_callback(void *el, void *i) { + auto element= static_cast(el); + auto id= static_cast(i); if (element->id < *id) { mutex_enter(&element->mutex); @@ -1200,9 +1198,10 @@ private: }; - static my_bool copy_one_id(rw_trx_hash_element_t *element, - snapshot_ids_arg *arg) + static my_bool copy_one_id(void* el, void *a) { + auto element= static_cast(el); + auto arg= static_cast(a); if (element->id < arg->m_id) { trx_id_t no= element->no; diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index d9a3c96aab0..05a3260f705 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5234,8 +5234,9 @@ static void lock_rec_block_validate(const page_id_t page_id) } -static my_bool lock_validate_table_locks(rw_trx_hash_element_t *element, void*) +static my_bool lock_validate_table_locks(void *el, void*) { + rw_trx_hash_element_t *element= static_cast(el); ut_ad(lock_mutex_own()); mutex_enter(&element->mutex); if (element->trx) @@ -5499,10 +5500,10 @@ struct lock_rec_other_trx_holds_expl_arg }; -static my_bool lock_rec_other_trx_holds_expl_callback( - rw_trx_hash_element_t *element, - lock_rec_other_trx_holds_expl_arg *arg) +static my_bool lock_rec_other_trx_holds_expl_callback(void *el, void *a) { + auto element= static_cast(el); + auto arg= static_cast(a); mutex_enter(&element->mutex); if (element->trx) { @@ -6325,13 +6326,14 @@ lock_table_get_n_locks( /** Do an exhaustive check for any locks (table or rec) against the table. - @param[in] table check if there are any locks held on records in this table - or on the table itself + @param t check if there are any locks held on records in this table + or on the table itself */ -static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element, - const dict_table_t *table) +static my_bool lock_table_locks_lookup(void *el, void *t) { + auto element= static_cast(el); + const dict_table_t *table= static_cast(t); ut_ad(lock_mutex_own()); mutex_enter(&element->mutex); if (element->trx) @@ -6381,7 +6383,9 @@ lock_table_has_locks( #ifdef UNIV_DEBUG if (!has_locks) { - trx_sys.rw_trx_hash.iterate(lock_table_locks_lookup, table); + trx_sys.rw_trx_hash.iterate(lock_table_locks_lookup, + const_cast + (static_cast(table))); } #endif /* UNIV_DEBUG */ diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 7f1f26547dc..284437497b5 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -2053,9 +2053,9 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element, } -static my_bool trx_recover_reset_callback(rw_trx_hash_element_t *element, - void*) +static my_bool trx_recover_reset_callback(void *el, void*) { + rw_trx_hash_element_t *element= static_cast(el); mutex_enter(&element->mutex); if (trx_t *trx= element->trx) { @@ -2107,9 +2107,10 @@ struct trx_get_trx_by_xid_callback_arg }; -static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, - trx_get_trx_by_xid_callback_arg *arg) +static my_bool trx_get_trx_by_xid_callback(void *el, void *a) { + auto element= static_cast(el); + auto arg= static_cast(a); my_bool found= 0; mutex_enter(&element->mutex); if (trx_t *trx= element->trx)