Commit af3eff8d authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#12584374 LOCK_VALIDATE TRIPS ASSERTION !BLOCK->PAGE.FILE_PAGE_WAS_FREE

Fix a deadlock in the initial patch. lock_validate() must not hold the
lock system mutex while s-latching a block, because some functions,
such as lock_rec_convert_impl_to_expl(), may be already holding an x-latch
on the block that lock_validate() is interested in while attempting to
acquire the lock system mutex.

This deadlock was not caught by UNIV_SYNC_DEBUG because of
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK).
parent 7a73cb12
...@@ -352,7 +352,6 @@ ibool ...@@ -352,7 +352,6 @@ ibool
lock_validate(void); lock_validate(void);
/*===============*/ /*===============*/
# ifdef UNIV_DEBUG_LOCK_VALIDATE
/*********************************************************************//** /*********************************************************************//**
Validates the record lock queues on a page. Validates the record lock queues on a page.
@return TRUE if ok */ @return TRUE if ok */
...@@ -362,7 +361,6 @@ lock_rec_validate_page( ...@@ -362,7 +361,6 @@ lock_rec_validate_page(
/*===================*/ /*===================*/
const buf_block_t* block) /*!< in: buffer block */ const buf_block_t* block) /*!< in: buffer block */
__attribute__((nonnull, warn_unused_result)); __attribute__((nonnull, warn_unused_result));
# endif /* UNIV_DEBUG_LOCK_VALIDATE */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/* The lock system */ /* The lock system */
...@@ -4865,10 +4863,10 @@ lock_rec_queue_validate( ...@@ -4865,10 +4863,10 @@ lock_rec_queue_validate(
/*********************************************************************//** /*********************************************************************//**
Validates the record lock queues on a page. Validates the record lock queues on a page.
@return TRUE if ok */ @return TRUE if ok */
static __attribute__((nonnull, warn_unused_result)) static
ibool ibool
lock_rec_validate_page_low( lock_rec_validate_page(
/*=======================*/ /*===================*/
const buf_block_t* block) /*!< in: buffer block */ const buf_block_t* block) /*!< in: buffer block */
{ {
const lock_t* lock; const lock_t* lock;
...@@ -4881,9 +4879,10 @@ lock_rec_validate_page_low( ...@@ -4881,9 +4879,10 @@ lock_rec_validate_page_low(
ulint* offsets = offsets_; ulint* offsets = offsets_;
rec_offs_init(offsets_); rec_offs_init(offsets_);
ut_ad(mutex_own(&kernel_mutex)); ut_ad(!mutex_own(&kernel_mutex));
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
lock_mutex_enter_kernel();
loop: loop:
lock = lock_rec_get_first_on_page_addr(buf_block_get_space(block), lock = lock_rec_get_first_on_page_addr(buf_block_get_space(block),
buf_block_get_page_no(block)); buf_block_get_page_no(block));
...@@ -4892,6 +4891,10 @@ loop: ...@@ -4892,6 +4891,10 @@ loop:
goto function_exit; goto function_exit;
} }
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(!block->page.file_page_was_freed);
#endif
for (i = 0; i < nth_lock; i++) { for (i = 0; i < nth_lock; i++) {
lock = lock_rec_get_next_on_page_const(lock); lock = lock_rec_get_next_on_page_const(lock);
...@@ -4950,32 +4953,14 @@ loop: ...@@ -4950,32 +4953,14 @@ loop:
goto loop; goto loop;
function_exit: function_exit:
lock_mutex_exit_kernel();
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
} }
return(TRUE); return(TRUE);
} }
#ifdef UNIV_DEBUG_LOCK_VALIDATE
/*********************************************************************//**
Validates the record lock queues on a page.
@return TRUE if ok */
static
ibool
lock_rec_validate_page(
/*===================*/
const buf_block_t* block) /*!< in: buffer block */
{
ibool valid;
lock_mutex_enter_kernel();
valid = lock_rec_validate_page_low(block);
lock_mutex_exit_kernel();
return(valid);
}
#endif /* UNIV_DEBUG_LOCK_VALIDATE */
/*********************************************************************//** /*********************************************************************//**
Validates the lock system. Validates the lock system.
@return TRUE if ok */ @return TRUE if ok */
...@@ -5041,16 +5026,28 @@ lock_validate(void) ...@@ -5041,16 +5026,28 @@ lock_validate(void)
break; break;
} }
lock_mutex_exit_kernel();
/* The lock and the block that it is referring
to may be freed at this point. We pass
BUF_GET_POSSIBLY_FREED to skip a debug check.
If the lock exists in lock_rec_validate_page()
we assert !block->page.file_page_was_freed. */
mtr_start(&mtr); mtr_start(&mtr);
block = buf_page_get( block = buf_page_get_gen(
space, fil_space_get_zip_size(space), space, fil_space_get_zip_size(space),
page_no, RW_X_LATCH, &mtr); page_no, RW_X_LATCH, NULL,
BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr);
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
ut_ad(lock_rec_validate_page_low(block)); ut_ad(lock_rec_validate_page(block));
mtr_commit(&mtr); mtr_commit(&mtr);
limit++; limit++;
lock_mutex_enter_kernel();
} }
} }
......
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