MDEV-24863 AHI entries mismatch with the index while reloading the evicted tables.

- This is caused by commit ad6171b9
(MDEV-22456). InnoDB reloads the evicted table again from dictionary.
In that case, AHI entries and current index object mismatches
happens. When index object mismatches then InnoDB should drop
the page hash AHI entries for the block. In
btr_search_drop_page_hash_index(), InnoDB should take exclusive
lock on the AHI latch if index is already freed to avoid the
freed memory access during buf_pool_resize()
parent 374f4c3f
......@@ -2,7 +2,7 @@
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2017, 2020, MariaDB Corporation.
Copyright (c) 2017, 2021, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -624,6 +624,12 @@ btr_search_update_hash_ref(
return;
}
if (cursor->index != index) {
ut_ad(cursor->index->id == index->id);
btr_search_drop_page_hash_index(block);
return;
}
ut_ad(block->page.id.space() == index->space);
ut_a(index == cursor->index);
ut_ad(!dict_index_is_ibuf(index));
......@@ -1139,18 +1145,28 @@ btr_search_drop_page_hash_index(buf_block_t* block)
% btr_ahi_parts;
latch = btr_search_latches[ahi_slot];
dict_index_t* index = block->index;
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
rw_lock_s_lock(latch);
bool is_freed = index && index->freed();
if (is_freed) {
rw_lock_x_lock(latch);
} else {
rw_lock_s_lock(latch);
}
assert_block_ahi_valid(block);
if (!block->index || !btr_search_enabled) {
rw_lock_s_unlock(latch);
if (!index || !btr_search_enabled) {
if (is_freed) {
rw_lock_x_unlock(latch);
} else {
rw_lock_s_unlock(latch);
}
return;
}
dict_index_t* index = block->index;
#ifdef MYSQL_INDEX_DISABLE_AHI
ut_ad(!index->disable_ahi);
#endif
......@@ -1167,7 +1183,9 @@ btr_search_drop_page_hash_index(buf_block_t* block)
/* NOTE: The AHI fields of block must not be accessed after
releasing search latch, as the index page might only be s-latched! */
rw_lock_s_unlock(latch);
if (!is_freed) {
rw_lock_s_unlock(latch);
}
ut_a(n_fields > 0 || n_bytes > 0);
......@@ -1215,16 +1233,18 @@ btr_search_drop_page_hash_index(buf_block_t* block)
mem_heap_free(heap);
}
rw_lock_x_lock(latch);
if (!is_freed) {
rw_lock_x_lock(latch);
if (UNIV_UNLIKELY(!block->index)) {
/* Someone else has meanwhile dropped the hash index */
if (UNIV_UNLIKELY(!block->index)) {
/* Someone else has meanwhile dropped the
hash index */
goto cleanup;
}
goto cleanup;
ut_a(block->index == index);
}
ut_a(block->index == index);
if (block->curr_n_fields != n_fields
|| block->curr_n_bytes != n_bytes) {
......@@ -1544,19 +1564,25 @@ btr_search_move_or_delete_hash_entries(
rw_lock_s_lock(latch);
ut_a(!new_block->index || new_block->index == index);
ut_a(!block->index || block->index == index);
ut_a(!block->index || block->index->id == index->id);
ut_ad(!(new_block->index || block->index)
|| !dict_index_is_ibuf(index));
assert_block_ahi_valid(block);
assert_block_ahi_valid(new_block);
if (new_block->index) {
drop_exit:
rw_lock_s_unlock(latch);
btr_search_drop_page_hash_index(block);
return;
}
if (block->index) {
if (block->index != index) {
goto drop_exit;
}
ulint n_fields = block->curr_n_fields;
ulint n_bytes = block->curr_n_bytes;
ibool left_side = block->curr_left_side;
......@@ -1576,7 +1602,6 @@ btr_search_move_or_delete_hash_entries(
ut_ad(left_side == block->curr_left_side);
return;
}
rw_lock_s_unlock(latch);
}
......@@ -1616,6 +1641,12 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor)
return;
}
if (index != cursor->index) {
ut_ad(index->id == cursor->index->id);
btr_search_drop_page_hash_index(block);
return;
}
ut_ad(block->page.id.space() == index->space);
ut_a(index == cursor->index);
ut_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0);
......@@ -1688,6 +1719,12 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor)
return;
}
if (cursor->index != index) {
ut_ad(cursor->index->id == index->id);
btr_search_drop_page_hash_index(block);
return;
}
ut_a(cursor->index == index);
ut_ad(!dict_index_is_ibuf(index));
......@@ -1774,6 +1811,12 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
#ifdef MYSQL_INDEX_DISABLE_AHI
ut_a(!index->disable_ahi);
#endif
if (index != cursor->index) {
ut_ad(index->id == cursor->index->id);
btr_search_drop_page_hash_index(block);
return;
}
ut_a(index == cursor->index);
ut_ad(!dict_index_is_ibuf(index));
......
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