Commit 1668465f authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-23998 Race between buf_page_optimistic_get() and buf_page_t::init()

MDEV-22871 tried to optimize the buf_page_t initialization in
buf_page_init_for_read() by initializing everything while the block
is in freed state, and only afterwards attaching the block to
buf_pool.page_hash.

In an rr replay trace, we have multiple threads executing in
buf_page_optimistic_get() on the same buf_block_t while the block is
being freed and reallocated several times in buf_page_init_for_read().
Because also the buf_page_t::id() is changing, the buf_pool.page_hash
is being protected by a different rw-lock than the one that
buf_page_optimistic_get() are successfully read-locking.

buf_page_optimistic_get(): Validate also buf_page_t::id() after
acquiring the buf_pool.page_hash latch.

Reviewed by: Thirunarayanan Balathandayuthapani
parent 05cd5acb
...@@ -3630,10 +3630,13 @@ buf_page_optimistic_get( ...@@ -3630,10 +3630,13 @@ buf_page_optimistic_get(
return FALSE; return FALSE;
} }
page_hash_latch *hash_lock = buf_pool.hash_lock_get(block->page.id()); const page_id_t id(block->page.id());
page_hash_latch *hash_lock = buf_pool.hash_lock_get(id);
hash_lock->read_lock(); hash_lock->read_lock();
if (UNIV_UNLIKELY(block->page.state() != BUF_BLOCK_FILE_PAGE if (UNIV_UNLIKELY(id != block->page.id()
|| block->page.state() != BUF_BLOCK_FILE_PAGE
|| block->page.io_fix() != BUF_IO_NONE)) { || block->page.io_fix() != BUF_IO_NONE)) {
hash_lock->read_unlock(); hash_lock->read_unlock();
return(FALSE); return(FALSE);
...@@ -3646,8 +3649,7 @@ buf_page_optimistic_get( ...@@ -3646,8 +3649,7 @@ buf_page_optimistic_get(
buf_page_make_young_if_needed(&block->page); buf_page_make_young_if_needed(&block->page);
ut_ad(!ibuf_inside(mtr) ut_ad(!ibuf_inside(mtr) || ibuf_page(id, block->zip_size(), NULL));
|| ibuf_page(block->page.id(), block->zip_size(), NULL));
mtr_memo_type_t fix_type; mtr_memo_type_t fix_type;
...@@ -3660,6 +3662,8 @@ buf_page_optimistic_get( ...@@ -3660,6 +3662,8 @@ buf_page_optimistic_get(
&block->lock, file, line); &block->lock, file, line);
} }
ut_ad(id == block->page.id());
if (!success) { if (!success) {
buf_block_buf_fix_dec(block); buf_block_buf_fix_dec(block);
return(FALSE); return(FALSE);
......
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