Bug#12560151 61132: infinite loop in buf_page_get_gen() when handling
compressed pages After loading a compressed-only page in buf_page_get_gen() we allocate a new block for decompression. The problem is that the compressed page is neither buffer-fixed nor I/O-fixed by the time we call buf_LRU_get_free_block(), so it may end up being evicted and returned back as a new block. buf_page_get_gen(): Temporarily buffer-fix the compressed-only block while allocating memory for an uncompressed page frame. This should prevent this form of the infinite loop, which is more likely with a small innodb_buffer_pool_size. rb#2511 approved by Jimmy Yang, Sunny Bains
This commit is contained in:
parent
55129f676a
commit
6a3bb3c07c
@ -1,3 +1,9 @@
|
|||||||
|
2013-08-21 The InnoDB Team
|
||||||
|
|
||||||
|
* buf/buf0buf.c:
|
||||||
|
Fix Bug#12560151 61132: infinite loop in buf_page_get_gen()
|
||||||
|
when handling compressed pages
|
||||||
|
|
||||||
2013-08-16 The InnoDB Team
|
2013-08-16 The InnoDB Team
|
||||||
|
|
||||||
* row/row0sel.c:
|
* row/row0sel.c:
|
||||||
|
@ -1615,7 +1615,6 @@ loop:
|
|||||||
block = (buf_block_t*) buf_page_hash_get(space, offset);
|
block = (buf_block_t*) buf_page_hash_get(space, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop2:
|
|
||||||
if (block == NULL) {
|
if (block == NULL) {
|
||||||
/* Page not in buf_pool: needs to be read from file */
|
/* Page not in buf_pool: needs to be read from file */
|
||||||
|
|
||||||
@ -1706,6 +1705,11 @@ wait_until_unfixed:
|
|||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Buffer-fix the block so that it cannot be evicted
|
||||||
|
or relocated while we are attempting to allocate an
|
||||||
|
uncompressed page. */
|
||||||
|
bpage->buf_fix_count++;
|
||||||
|
|
||||||
/* Allocate an uncompressed page. */
|
/* Allocate an uncompressed page. */
|
||||||
buf_pool_mutex_exit();
|
buf_pool_mutex_exit();
|
||||||
mutex_exit(&buf_pool_zip_mutex);
|
mutex_exit(&buf_pool_zip_mutex);
|
||||||
@ -1715,32 +1719,19 @@ wait_until_unfixed:
|
|||||||
|
|
||||||
buf_pool_mutex_enter();
|
buf_pool_mutex_enter();
|
||||||
mutex_enter(&block->mutex);
|
mutex_enter(&block->mutex);
|
||||||
|
mutex_enter(&buf_pool_zip_mutex);
|
||||||
|
/* Buffer-fixing prevents the page_hash from changing. */
|
||||||
|
ut_ad(bpage == buf_page_hash_get(space, offset));
|
||||||
|
|
||||||
{
|
if (--bpage->buf_fix_count
|
||||||
buf_page_t* hash_bpage
|
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
|
||||||
= buf_page_hash_get(space, offset);
|
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(bpage != hash_bpage)) {
|
mutex_exit(&buf_pool_zip_mutex);
|
||||||
/* The buf_pool->page_hash was modified
|
/* The block was buffer-fixed or I/O-fixed while
|
||||||
while buf_pool_mutex was released.
|
buf_pool_mutex was not held by this thread.
|
||||||
Free the block that was allocated. */
|
Free the block that was allocated and retry.
|
||||||
|
This should be extremely unlikely, for example,
|
||||||
buf_LRU_block_free_non_file_page(block);
|
if buf_page_get_zip() was invoked. */
|
||||||
mutex_exit(&block->mutex);
|
|
||||||
|
|
||||||
block = (buf_block_t*) hash_bpage;
|
|
||||||
goto loop2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UNIV_UNLIKELY
|
|
||||||
(bpage->buf_fix_count
|
|
||||||
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
|
|
||||||
|
|
||||||
/* The block was buffer-fixed or I/O-fixed
|
|
||||||
while buf_pool_mutex was not held by this thread.
|
|
||||||
Free the block that was allocated and try again.
|
|
||||||
This should be extremely unlikely. */
|
|
||||||
|
|
||||||
buf_LRU_block_free_non_file_page(block);
|
buf_LRU_block_free_non_file_page(block);
|
||||||
mutex_exit(&block->mutex);
|
mutex_exit(&block->mutex);
|
||||||
@ -1751,8 +1742,6 @@ wait_until_unfixed:
|
|||||||
/* Move the compressed page from bpage to block,
|
/* Move the compressed page from bpage to block,
|
||||||
and uncompress it. */
|
and uncompress it. */
|
||||||
|
|
||||||
mutex_enter(&buf_pool_zip_mutex);
|
|
||||||
|
|
||||||
buf_relocate(bpage, &block->page);
|
buf_relocate(bpage, &block->page);
|
||||||
buf_block_init_low(block);
|
buf_block_init_low(block);
|
||||||
block->lock_hash_val = lock_rec_hash(space, offset);
|
block->lock_hash_val = lock_rec_hash(space, offset);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user