MDEV-24188 Hang in buf_page_create() after reusing a previously freed page

The fix of MDEV-23456 (commit b1009ae5c1)
introduced a livelock between page flushing and a thread that is
executing buf_page_create().

buf_page_create(): If the current mini-transaction is holding
an exclusive latch on the page, do not attempt to acquire another
one, and do not care about any I/O fix.

mtr_t::have_x_latch(): Replaces mtr_t::get_fix_count().

dyn_buf_t::for_each_block(const Functor&) const: A new variant.

rw_lock_own(): Add a const qualifier.

Reviewed by: Thirunarayanan Balathandayuthapani
This commit is contained in:
Marko Mäkelä 2020-11-13 20:12:29 +02:00
commit bb328a2a27
6 changed files with 97 additions and 58 deletions

View file

@ -5511,6 +5511,7 @@ loop:
&& !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
ut_d(block->page.file_page_was_freed = FALSE);
buf_page_state page_state = buf_block_get_state(block);
bool have_x_latch = false;
#ifdef BTR_CUR_HASH_ADAPT
const dict_index_t *drop_hash_entry= NULL;
#endif
@ -5563,26 +5564,26 @@ loop:
free_block = NULL;
break;
case BUF_BLOCK_FILE_PAGE:
buf_block_fix(block);
const int32_t num_fix_count =
mtr->get_fix_count(block) + 1;
buf_page_mutex_enter(block);
while (buf_block_get_io_fix(block) != BUF_IO_NONE
|| (num_fix_count
!= block->page.buf_fix_count)) {
buf_page_mutex_exit(block);
buf_pool_mutex_exit(buf_pool);
rw_lock_x_unlock(hash_lock);
os_thread_yield();
buf_pool_mutex_enter(buf_pool);
rw_lock_x_lock(hash_lock);
have_x_latch = mtr->have_x_latch(*block);
if (!have_x_latch) {
buf_block_fix(block);
buf_page_mutex_enter(block);
}
while (buf_block_get_io_fix(block)
!= BUF_IO_NONE
|| block->page.buf_fix_count != 1) {
buf_page_mutex_exit(block);
buf_pool_mutex_exit(buf_pool);
rw_lock_x_unlock(hash_lock);
rw_lock_x_lock(&block->lock);
buf_page_mutex_exit(block);
os_thread_sleep(1000);
buf_pool_mutex_enter(buf_pool);
rw_lock_x_lock(hash_lock);
buf_page_mutex_enter(block);
}
rw_lock_x_lock(&block->lock);
buf_page_mutex_exit(block);
}
#ifdef BTR_CUR_HASH_ADAPT
drop_hash_entry = block->index;
#endif
@ -5601,16 +5602,17 @@ loop:
}
#endif /* BTR_CUR_HASH_ADAPT */
if (!have_x_latch) {
#ifdef UNIV_DEBUG
if (!fsp_is_system_temporary(page_id.space())) {
rw_lock_s_lock_nowait(
&block->debug_latch,
__FILE__, __LINE__);
}
if (!fsp_is_system_temporary(page_id.space())) {
rw_lock_s_lock_nowait(
&block->debug_latch,
__FILE__, __LINE__);
}
#endif /* UNIV_DEBUG */
mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
}
return block;
}