Skip to content

Commit 83a5567

Browse files
committed
MDEV-24188 fixup: Simplify the wait loop
Starting with commit 7cffb5f (MDEV-23399) the function buf_flush_page() will first acquire block->lock and only after that invoke set_io_fix(). Before that, it was possible to reach a livelock between buf_page_create() and buf_flush_page(). buf_page_create(): Directly try acquiring the exclusive page latch without checking whether the page is io-fixed or buffer-fixed. (As a matter of fact, the have_x_latch() check is not strictly necessary, because we still support recursive X-latches.) In case of a latch conflict, wait while allowing buf_page_write_complete() to acquire buf_pool.mutex and release the block->lock. An attempt to wait for exclusive block->lock while holding buf_pool.mutex would lead to a hang in the tests parts.part_supported_sql_func_innodb and stress.ddl_innodb, due to a deadlock between buf_page_write_complete() and buf_page_create(). Similarly, in case of an I/O fixed compressed-only ROW_FORMAT=COMPRESSED page, we will sleep before retrying. In both cases, we will sleep for 1ms or until a flush batch is completed.
1 parent 694926a commit 83a5567

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

storage/innobase/buf/buf0buf.cc

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3755,9 +3755,9 @@ buf_page_create(fil_space_t *space, uint32_t offset,
37553755
free_block->initialise(page_id, zip_size, 1);
37563756

37573757
const ulint fold= page_id.fold();
3758-
loop:
37593758
mysql_mutex_lock(&buf_pool.mutex);
37603759

3760+
loop:
37613761
buf_block_t *block= reinterpret_cast<buf_block_t*>
37623762
(buf_pool.page_hash_get_low(page_id, fold));
37633763

@@ -3775,17 +3775,15 @@ buf_page_create(fil_space_t *space, uint32_t offset,
37753775
if (!mtr->have_x_latch(*block))
37763776
{
37773777
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
3778+
while (!rw_lock_x_lock_nowait(&block->lock))
37783779
{
3779-
while (block->page.io_fix() != BUF_IO_NONE ||
3780-
block->page.buf_fix_count() != 1)
3781-
{
3782-
timespec abstime;
3783-
set_timespec_nsec(abstime, 1000000);
3784-
mysql_cond_timedwait(&buf_pool.done_flush_list, &buf_pool.mutex,
3785-
&abstime);
3786-
}
3780+
/* Wait for buf_page_write_complete() to release block->lock.
3781+
We must not hold buf_pool.mutex while waiting. */
3782+
timespec abstime;
3783+
set_timespec_nsec(abstime, 1000000);
3784+
mysql_cond_timedwait(&buf_pool.done_flush_list, &buf_pool.mutex,
3785+
&abstime);
37873786
}
3788-
rw_lock_x_lock(&block->lock);
37893787
mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
37903788
}
37913789
else
@@ -3805,7 +3803,11 @@ buf_page_create(fil_space_t *space, uint32_t offset,
38053803
if (block->page.io_fix() != BUF_IO_NONE)
38063804
{
38073805
hash_lock->write_unlock();
3808-
mysql_mutex_unlock(&buf_pool.mutex);
3806+
/* Wait for buf_page_write_complete() to release the I/O fix. */
3807+
timespec abstime;
3808+
set_timespec_nsec(abstime, 1000000);
3809+
mysql_cond_timedwait(&buf_pool.done_flush_list, &buf_pool.mutex,
3810+
&abstime);
38093811
goto loop;
38103812
}
38113813

0 commit comments

Comments
 (0)