Skip to content

Commit

Permalink
Merge 10.3 into 10.4
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-m committed Aug 25, 2022
2 parents e404315 + d1a80c4 commit 851058a
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 61 deletions.
2 changes: 1 addition & 1 deletion mysql-test/include/mtr_warnings.sql
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ INSERT INTO global_suppressions VALUES

/* Added 2009-08-XX after fixing Bug #42408 */

("Although a path was specified for the .* option, log tables are used"),
("Although a .* file was specified, log tables are used. To enable logging to files "),
("Backup: Operation aborted"),
("Restore: Operation aborted"),
("Restore: The grant .* was skipped because the user does not exist"),
Expand Down
55 changes: 55 additions & 0 deletions mysql-test/suite/rpl/r/rpl_filter_set_var_missing_data.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
include/master-slave.inc
[connection master]
#
# Set replica to ignore system mysql tables
connection slave;
include/stop_slave.inc
SET @@GLOBAL.replicate_wild_ignore_table="mysql.%";
include/start_slave.inc
#
# Execute grant-based commands on primary which modify mysql system
# tables
connection master;
CREATE ROLE journalist;
CREATE USER testuser@localhost IDENTIFIED by '';
GRANT journalist to testuser@localhost;
#
# Execute SET commands which use the previous user/role data
SET DEFAULT ROLE journalist for testuser@localhost;
SET PASSWORD for testuser@localhost= PASSWORD('123');
include/save_master_gtid.inc
#
# Verify primary's grant tables have the correct user/role data
select count(*)=1 from mysql.user where User='testuser';
count(*)=1
1
select count(*)=1 from mysql.roles_mapping where User='testuser';
count(*)=1
1
#
# Ensure that the replica receives all of the primary's events without
# error
connection slave;
include/sync_with_master_gtid.inc
Last_SQL_Error =
Last_SQL_Errno = 0
#
# Verify that the replica did not execute the master's commands
select count(*)=0 from mysql.user where User='testuser';
count(*)=0
1
select count(*)=0 from mysql.roles_mapping where User='testuser';
count(*)=0
1
#
# Clean up
connection master;
DROP ROLE journalist;
DROP USER testuser@localhost;
include/save_master_gtid.inc
connection slave;
include/sync_with_master_gtid.inc
include/stop_slave.inc
SET @@GLOBAL.replicate_wild_ignore_table="";
include/start_slave.inc
include/rpl_end.inc
83 changes: 83 additions & 0 deletions mysql-test/suite/rpl/t/rpl_filter_set_var_missing_data.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#
# Purpose:
# This test ensures that the SET DEFAULT ROLE and SET PASSWORD commands can
# be ignored by replica filter rules. MDEV-28294 exposed a bug in which
# SET DEFAULT ROLE would check for the existence of the given roles/user even
# when the targeted tables are ignored, resulting in errors if the targeted
# data does not exist. More specifically, when previously issued
# CREATE USER/ROLE commands are ignored by the replica because of the
# replication filtering rules, SET DEFAULT ROLE would result in an error
# because the targeted data does not exist.
#
# Methodology:
# Using a replica configured with replicate_wild_ignore_table="mysql.%",
# execute SET DEFAULT ROLE and SET PASSWORD on the primary and ensure that the
# replica neither errors nor executes the commands which the primary sends.
#
# References:
# MDEV-28294: set default role bypasses Replicate_Wild_Ignore_Table: mysql.%
#

source include/master-slave.inc;
source include/have_binlog_format_mixed.inc;

--echo #
--echo # Set replica to ignore system mysql tables
connection slave;
let $old_filter= query_get_value(SHOW SLAVE STATUS, Replicate_Wild_Ignore_Table, 1);
source include/stop_slave.inc;
SET @@GLOBAL.replicate_wild_ignore_table="mysql.%";
source include/start_slave.inc;

--echo #
--echo # Execute grant-based commands on primary which modify mysql system
--echo # tables
connection master;
CREATE ROLE journalist;
CREATE USER testuser@localhost IDENTIFIED by '';
GRANT journalist to testuser@localhost;

--echo #
--echo # Execute SET commands which use the previous user/role data
SET DEFAULT ROLE journalist for testuser@localhost;
SET PASSWORD for testuser@localhost= PASSWORD('123');
--source include/save_master_gtid.inc

--echo #
--echo # Verify primary's grant tables have the correct user/role data
select count(*)=1 from mysql.user where User='testuser';
select count(*)=1 from mysql.roles_mapping where User='testuser';

--echo #
--echo # Ensure that the replica receives all of the primary's events without
--echo # error
connection slave;
--source include/sync_with_master_gtid.inc
let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
--echo Last_SQL_Error = $error
let $errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
--echo Last_SQL_Errno = $errno

--echo #
--echo # Verify that the replica did not execute the master's commands
select count(*)=0 from mysql.user where User='testuser';
select count(*)=0 from mysql.roles_mapping where User='testuser';

--echo #
--echo # Clean up

# The master has to drop the role/user combination while the slave still has
# its filters active; otherwise, the slave would try to drop users/roles that
# were never replicated.
--connection master
DROP ROLE journalist;
DROP USER testuser@localhost;
--source include/save_master_gtid.inc

--connection slave
--source include/sync_with_master_gtid.inc
source include/stop_slave.inc;
--eval SET @@GLOBAL.replicate_wild_ignore_table="$old_filter"
source include/start_slave.inc;

--source include/rpl_end.inc
94 changes: 79 additions & 15 deletions sql/sql_acl.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
Copyright (c) 2009, 2020, MariaDB
Copyright (c) 2009, 2022, MariaDB

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
Expand Down Expand Up @@ -1814,10 +1814,17 @@ class Grant_tables
public:
Grant_tables() : p_user_table(&m_user_table_json) { }

int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type)
/**
An auxiliary to build a list of involved tables.

@retval 0 Success
@retval -1 A my_error reported error
*/
int build_table_list(THD *thd, TABLE_LIST** ptr_first,
int which_tables, enum thr_lock_type lock_type,
TABLE_LIST *tables)
{
DBUG_ENTER("Grant_tables::open_and_lock");
TABLE_LIST tables[USER_TABLE+1], *first= NULL;
DBUG_ENTER("Grant_tables::build_table_list");

DBUG_ASSERT(which_tables); /* At least one table must be opened. */
/*
Expand All @@ -1842,12 +1849,23 @@ class Grant_tables
tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE;
if (i >= FIRST_OPTIONAL_TABLE)
tl->open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
tl->next_global= tl->next_local= first;
first= tl;
tl->next_global= tl->next_local= *ptr_first;
*ptr_first= tl;
}
else
tl->table= NULL;
}
DBUG_RETURN(0);
}

int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type)
{
DBUG_ENTER("Grant_tables::open_and_lock");

TABLE_LIST tables[USER_TABLE+1], *first= NULL;

if (build_table_list(thd, &first, which_tables, lock_type, tables))
DBUG_RETURN(-1);

uint counter;
int res= really_open(thd, first, &counter);
Expand Down Expand Up @@ -1916,6 +1934,48 @@ class Grant_tables
inline const Roles_mapping_table& roles_mapping_table() const
{ return m_roles_mapping_table; }

#ifdef HAVE_REPLICATION
/**
Checks if the tables targeted by a grant command should be ignored because
of the configured replication filters

@retval 1 Tables are excluded for replication
@retval 0 tables are included for replication
*/
int rpl_ignore_tables(THD *thd, TABLE_LIST* tables, int which_tables= 0,
enum thr_lock_type lock_type= TL_IGNORE)
{
DBUG_ENTER("Grant_tables::rpl_ignore_tables");

if (!(thd->slave_thread && !thd->spcont))
DBUG_RETURN(0);

TABLE_LIST all_tables[USER_TABLE+1];

if (!tables)
{
int rc __attribute__((unused))=
build_table_list(thd, &tables, which_tables, lock_type, all_tables);

DBUG_ASSERT(!rc); // Grant_tables must be already initialized
DBUG_ASSERT(tables);
}

if (tables->lock_type >= TL_WRITE_ALLOW_WRITE)
{
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
some kind of updates to the mysql.% tables.
*/
Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;

if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, tables))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
#endif

private:

/* Before any operation is possible on grant tables, they must be opened.
Expand All @@ -1929,16 +1989,9 @@ class Grant_tables
{
DBUG_ENTER("Grant_tables::really_open:");
#ifdef HAVE_REPLICATION
if (tables->lock_type >= TL_WRITE_ALLOW_WRITE &&
thd->slave_thread && !thd->spcont)
if (rpl_ignore_tables(thd, tables))
{
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
some kind of updates to the mysql.% tables.
*/
Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, tables))
DBUG_RETURN(1);
DBUG_RETURN(1);
}
#endif
if (open_tables(thd, &tables, counter, MYSQL_LOCK_IGNORE_TIMEOUT))
Expand Down Expand Up @@ -3940,6 +3993,17 @@ int acl_check_set_default_role(THD *thd, const char *host, const char *user,
const char *role)
{
DBUG_ENTER("acl_check_set_default_role");
#ifdef HAVE_REPLICATION
/*
If the roles_mapping table is excluded by the replication filter, we return
successful without validating the user/role data because the command will
be ignored in a later call to `acl_set_default_role()` for a graceful exit.
*/
Grant_tables tables;
TABLE_LIST* first= NULL;
if (tables.rpl_ignore_tables(thd, first, Table_roles_mapping, TL_WRITE))
DBUG_RETURN(0);
#endif
DBUG_RETURN(check_alter_user(thd, host, user) ||
check_user_can_set_role(thd, user, host, NULL, role, NULL));
}
Expand Down
5 changes: 1 addition & 4 deletions storage/innobase/btr/btr0sea.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) 2008, Google Inc.
Copyright (c) 2017, 2021, MariaDB Corporation.
Copyright (c) 2017, 2022, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
Expand Down Expand Up @@ -1116,9 +1116,6 @@ void btr_search_drop_page_hash_index(buf_block_t* block,
rw_lock_t* latch;

retry:
/* This debug check uses a dirty read that could theoretically cause
false positives while buf_pool_clear_hash_index() is executing. */
assert_block_ahi_valid(block);
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));

Expand Down
41 changes: 1 addition & 40 deletions storage/innobase/buf/buf0buf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3897,42 +3897,6 @@ buf_wait_for_read(
}
}

#ifdef BTR_CUR_HASH_ADAPT
/** If a stale adaptive hash index exists on the block, drop it.
Multiple executions of btr_search_drop_page_hash_index() on the
same block must be prevented by exclusive page latch. */
ATTRIBUTE_COLD
static void buf_defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type)
{
switch (fix_type) {
case MTR_MEMO_BUF_FIX:
/* We do not drop the adaptive hash index, because safely doing
so would require acquiring block->lock, and that is not safe
to acquire in some RW_NO_LATCH access paths. Those code paths
should have no business accessing the adaptive hash index anyway. */
break;
case MTR_MEMO_PAGE_S_FIX:
/* Temporarily release our S-latch. */
rw_lock_s_unlock(&block->lock);
rw_lock_x_lock(&block->lock);
btr_search_drop_page_hash_index(block, true);
rw_lock_x_unlock(&block->lock);
rw_lock_s_lock(&block->lock);
break;
case MTR_MEMO_PAGE_SX_FIX:
rw_lock_sx_unlock(&block->lock);
rw_lock_x_lock(&block->lock);
btr_search_drop_page_hash_index(block, true);
rw_lock_x_unlock(&block->lock);
rw_lock_sx_lock(&block->lock);
break;
default:
ut_ad(fix_type == MTR_MEMO_PAGE_X_FIX);
btr_search_drop_page_hash_index(block);
}
}
#endif /* BTR_CUR_HASH_ADAPT */

/** Lock the page with the given latch type.
@param[in,out] block block to be locked
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
Expand Down Expand Up @@ -3968,10 +3932,7 @@ static buf_block_t* buf_page_mtr_lock(buf_block_t *block,
}

#ifdef BTR_CUR_HASH_ADAPT
{
if (block->index)
buf_defer_drop_ahi(block, fix_type);
}
btr_search_drop_page_hash_index(block, true);
#endif /* BTR_CUR_HASH_ADAPT */

done:
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/dict/dict0crea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,7 @@ dict_create_table_step(
if (node->state == TABLE_ADD_TO_CACHE) {
DBUG_EXECUTE_IF("ib_ddl_crash_during_create", DBUG_SUICIDE(););

node->table->can_be_evicted = true;
node->table->can_be_evicted = !node->table->fts;
node->table->add_to_cache();

err = DB_SUCCESS;
Expand Down
2 changes: 2 additions & 0 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14397,9 +14397,11 @@ ha_innobase::info_low(
stats.index_file_length
= ulonglong(stat_sum_of_other_index_sizes)
* size;
rw_lock_s_lock(&space->latch);
stats.delete_length = 1024
* fsp_get_available_space_in_free_extents(
*space);
rw_lock_s_unlock(&space->latch);
}
stats.check_time = 0;
stats.mrr_length_per_rec= (uint)ref_length + 8; // 8 = max(sizeof(void *));
Expand Down

0 comments on commit 851058a

Please sign in to comment.