Commit 6058319d authored by Yasufumi Kinoshita's avatar Yasufumi Kinoshita

Bug#14251529 : FIX FOR BUG 13704145 CREATES POSSIBLE RACE CONDITION

make buf_read_page_low() to treat DB_TABLESPACE_DELETED error correctly
rb#1129 approved by Inaam
parent 24726234
...@@ -3470,9 +3470,10 @@ buf_mark_space_corrupt( ...@@ -3470,9 +3470,10 @@ buf_mark_space_corrupt(
/********************************************************************//** /********************************************************************//**
Completes an asynchronous read or write request of a file page to or from Completes an asynchronous read or write request of a file page to or from
the buffer pool. */ the buffer pool.
@return TRUE if successful */
UNIV_INTERN UNIV_INTERN
void ibool
buf_page_io_complete( buf_page_io_complete(
/*=================*/ /*=================*/
buf_page_t* bpage) /*!< in: pointer to the block in question */ buf_page_t* bpage) /*!< in: pointer to the block in question */
...@@ -3599,7 +3600,7 @@ corrupt: ...@@ -3599,7 +3600,7 @@ corrupt:
table as corrupted instead of crashing server */ table as corrupted instead of crashing server */
if (bpage->space > TRX_SYS_SPACE if (bpage->space > TRX_SYS_SPACE
&& buf_mark_space_corrupt(bpage)) { && buf_mark_space_corrupt(bpage)) {
return; return(FALSE);
} else { } else {
fputs("InnoDB: Ending processing" fputs("InnoDB: Ending processing"
" because of" " because of"
...@@ -3689,6 +3690,8 @@ corrupt: ...@@ -3689,6 +3690,8 @@ corrupt:
mutex_exit(buf_page_get_mutex(bpage)); mutex_exit(buf_page_get_mutex(bpage));
buf_pool_mutex_exit(buf_pool); buf_pool_mutex_exit(buf_pool);
return(TRUE);
} }
/*********************************************************************//** /*********************************************************************//**
......
...@@ -2164,9 +2164,23 @@ buf_LRU_free_one_page( ...@@ -2164,9 +2164,23 @@ buf_LRU_free_one_page(
be in a state where it can be freed; there be in a state where it can be freed; there
may or may not be a hash index to the page */ may or may not be a hash index to the page */
{ {
#ifdef UNIV_DEBUG
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
#endif
mutex_t* block_mutex = buf_page_get_mutex(bpage);
ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(block_mutex));
if (buf_LRU_block_remove_hashed_page(bpage, TRUE) if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
!= BUF_BLOCK_ZIP_FREE) { != BUF_BLOCK_ZIP_FREE) {
buf_LRU_block_free_hashed_page((buf_block_t*) bpage); buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
} else {
/* The block_mutex should have been released by
buf_LRU_block_remove_hashed_page() when it returns
BUF_BLOCK_ZIP_FREE. */
ut_ad(block_mutex == &buf_pool->zip_mutex);
mutex_enter(block_mutex);
} }
} }
......
...@@ -50,6 +50,44 @@ read-ahead is not done: this is to prevent flooding the buffer pool with ...@@ -50,6 +50,44 @@ read-ahead is not done: this is to prevent flooding the buffer pool with
i/o-fixed buffer blocks */ i/o-fixed buffer blocks */
#define BUF_READ_AHEAD_PEND_LIMIT 2 #define BUF_READ_AHEAD_PEND_LIMIT 2
/********************************************************************//**
Unfixes the pages, unlatches the page,
removes it from page_hash and removes it from LRU. */
static
void
buf_read_page_handle_error(
/*=======================*/
buf_page_t* bpage) /*!< in: pointer to the block */
{
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
const ibool uncompressed = (buf_page_get_state(bpage)
== BUF_BLOCK_FILE_PAGE);
/* First unfix and release lock on the bpage */
buf_pool_mutex_enter(buf_pool);
mutex_enter(buf_page_get_mutex(bpage));
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
ut_ad(bpage->buf_fix_count == 0);
/* Set BUF_IO_NONE before we remove the block from LRU list */
buf_page_set_io_fix(bpage, BUF_IO_NONE);
if (uncompressed) {
rw_lock_x_unlock_gen(
&((buf_block_t*) bpage)->lock,
BUF_IO_READ);
}
/* remove the block from LRU list */
buf_LRU_free_one_page(bpage);
ut_ad(buf_pool->n_pend_reads > 0);
buf_pool->n_pend_reads--;
mutex_exit(buf_page_get_mutex(bpage));
buf_pool_mutex_exit(buf_pool);
}
/********************************************************************//** /********************************************************************//**
Low-level function which reads a page asynchronously from a file to the Low-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there, in which case does nothing. buffer buf_pool if it is not already there, in which case does nothing.
...@@ -152,12 +190,20 @@ buf_read_page_low( ...@@ -152,12 +190,20 @@ buf_read_page_low(
((buf_block_t*) bpage)->frame, bpage); ((buf_block_t*) bpage)->frame, bpage);
} }
thd_wait_end(NULL); thd_wait_end(NULL);
if (*err == DB_TABLESPACE_DELETED) {
buf_read_page_handle_error(bpage);
return(0);
}
ut_a(*err == DB_SUCCESS); ut_a(*err == DB_SUCCESS);
if (sync) { if (sync) {
/* The i/o is already completed when we arrive from /* The i/o is already completed when we arrive from
fil_read */ fil_read */
buf_page_io_complete(bpage); if (!buf_page_io_complete(bpage)) {
return(0);
}
} }
return(1); return(1);
......
...@@ -1162,9 +1162,10 @@ buf_page_init_for_read( ...@@ -1162,9 +1162,10 @@ buf_page_init_for_read(
ulint offset);/*!< in: page number */ ulint offset);/*!< in: page number */
/********************************************************************//** /********************************************************************//**
Completes an asynchronous read or write request of a file page to or from Completes an asynchronous read or write request of a file page to or from
the buffer pool. */ the buffer pool.
@return TRUE if successful */
UNIV_INTERN UNIV_INTERN
void ibool
buf_page_io_complete( buf_page_io_complete(
/*=================*/ /*=================*/
buf_page_t* bpage); /*!< in: pointer to the block in question */ buf_page_t* bpage); /*!< in: pointer to the block in question */
......
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