ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
switch (buf_page_get_state(bpage)) {
-@@ -2355,19 +2449,19 @@
+@@ -2355,24 +2449,43 @@
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
case BUF_BLOCK_ZIP_FREE:
goto got_block;
case BUF_BLOCK_FILE_PAGE:
- block_mutex = &((buf_block_t*) bpage)->mutex;
-- mutex_enter(block_mutex);
+ ut_a(block_mutex == &((buf_block_t*) bpage)->mutex);
++
++ /* release mutex to obey to latch-order */
++ mutex_exit(block_mutex);
++
++ /* get LRU_list_mutex for buf_LRU_free_block() */
++ mutex_enter(&buf_pool->LRU_list_mutex);
+ mutex_enter(block_mutex);
- /* Discard the uncompressed page frame if possible. */
+- /* Discard the uncompressed page frame if possible. */
- if (buf_LRU_free_block(bpage, FALSE) == BUF_LRU_FREED) {
-+ if (buf_LRU_free_block(bpage, FALSE, FALSE) == BUF_LRU_FREED) {
++ if (UNIV_UNLIKELY(bpage->space != space
++ || bpage->offset != offset
++ || !bpage->in_LRU_list
++ || !bpage->zip.data)) {
++ /* someone should interrupt, retry */
++ mutex_exit(&buf_pool->LRU_list_mutex);
++ mutex_exit(block_mutex);
++ goto lookup;
++ }
++ /* Discard the uncompressed page frame if possible. */
++ if (buf_LRU_free_block(bpage, FALSE, TRUE) == BUF_LRU_FREED) {
++ mutex_exit(&buf_pool->LRU_list_mutex);
mutex_exit(block_mutex);
goto lookup;
-@@ -2385,7 +2479,7 @@
+ }
+
++ mutex_exit(&buf_pool->LRU_list_mutex);
++
+ buf_block_buf_fix_inc((buf_block_t*) bpage,
+ __FILE__, __LINE__);
+ goto got_block;
+@@ -2385,7 +2498,7 @@
must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
access_time = buf_page_is_accessed(bpage);
mutex_exit(block_mutex);
-@@ -2697,7 +2791,7 @@
+@@ -2697,7 +2810,7 @@
const buf_block_t* block) /*!< in: pointer to block,
not dereferenced */
{
if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
/* The pointer should be aligned. */
-@@ -2733,6 +2827,7 @@
+@@ -2733,6 +2846,7 @@
ulint fix_type;
ibool must_read;
ulint retries = 0;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ut_ad(mtr);
-@@ -2765,9 +2860,11 @@
+@@ -2765,9 +2879,11 @@
fold = buf_page_address_fold(space, offset);
loop:
block = guess;
/* If the guess is a compressed page descriptor that
has been allocated by buf_buddy_alloc(), it may have
been invalidated by buf_buddy_relocate(). In that
-@@ -2776,11 +2873,15 @@
+@@ -2776,11 +2892,15 @@
the guess may be pointing to a buffer pool chunk that
has been released when resizing the buffer pool. */
block = guess = NULL;
} else {
ut_ad(!block->page.in_zip_hash);
-@@ -2789,12 +2890,19 @@
+@@ -2789,12 +2909,19 @@
}
if (block == NULL) {
block = NULL;
}
-@@ -2806,12 +2914,14 @@
+@@ -2806,12 +2933,14 @@
space, offset, fold);
if (UNIV_LIKELY_NULL(block)) {
if (mode == BUF_GET_IF_IN_POOL
|| mode == BUF_PEEK_IF_IN_POOL
-@@ -2861,7 +2971,8 @@
+@@ -2861,7 +2990,8 @@
/* The page is being read to buffer pool,
but we cannot wait around for the read to
complete. */
return(NULL);
}
-@@ -2871,38 +2982,49 @@
+@@ -2871,38 +3001,49 @@
ibool success;
case BUF_BLOCK_FILE_PAGE:
{
buf_page_t* hash_bpage;
-@@ -2915,35 +3037,47 @@
+@@ -2915,35 +3056,47 @@
while buf_pool->mutex was released.
Free the block that was allocated. */
buf_block_init_low(block);
block->lock_hash_val = lock_rec_hash(space, offset);
-@@ -2952,7 +3086,7 @@
+@@ -2952,7 +3105,7 @@
if (buf_page_get_state(&block->page)
== BUF_BLOCK_ZIP_PAGE) {
&block->page);
ut_ad(!block->page.in_flush_list);
} else {
-@@ -2969,20 +3103,25 @@
+@@ -2969,20 +3122,25 @@
/* Insert at the front of unzip_LRU list */
buf_unzip_LRU_add_block(block, FALSE);
/* Decompress the page and apply buffered operations
while not holding buf_pool->mutex or block->mutex. */
-@@ -2995,12 +3134,15 @@
+@@ -2995,12 +3153,15 @@
}
/* Unfix and unlatch the block. */
rw_lock_x_unlock(&block->lock);
break;
-@@ -3016,7 +3158,7 @@
+@@ -3016,7 +3177,7 @@
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#if UNIV_WORD_SIZE == 4
/* On 32-bit systems, there is no padding in buf_page_t. On
other systems, Valgrind could complain about uninitialized pad
-@@ -3029,8 +3171,8 @@
+@@ -3029,8 +3190,8 @@
/* Try to evict the block from the buffer pool, to use the
insert buffer (change buffer) as much as possible. */
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
/* Set the watch, as it would have
been set if the page were not in the
-@@ -3039,6 +3181,9 @@
+@@ -3039,6 +3200,9 @@
space, offset, fold);
if (UNIV_LIKELY_NULL(block)) {
/* The page entered the buffer
pool for some reason. Try to
-@@ -3046,7 +3191,7 @@
+@@ -3046,7 +3210,7 @@
goto got_block;
}
}
fprintf(stderr,
"innodb_change_buffering_debug evict %u %u\n",
(unsigned) space, (unsigned) offset);
-@@ -3065,13 +3210,14 @@
+@@ -3065,13 +3229,14 @@
buf_block_buf_fix_inc(block, file, line);
if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL)) {
buf_page_set_accessed_make_young(&block->page, access_time);
-@@ -3308,9 +3454,11 @@
+@@ -3308,9 +3473,11 @@
buf_pool = buf_pool_from_block(block);
if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
} else if (!buf_page_is_accessed(&block->page)) {
/* Above, we do a dirty read on purpose, to avoid
mutex contention. The field buf_page_t::access_time
-@@ -3318,9 +3466,11 @@
+@@ -3318,9 +3485,11 @@
field must be protected by mutex, however. */
ulint time_ms = ut_time_ms();
}
ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
-@@ -3387,18 +3537,21 @@
+@@ -3387,18 +3556,21 @@
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
-@@ -3487,7 +3640,10 @@
+@@ -3487,7 +3659,10 @@
buf_page_t* hash_page;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ut_ad(mutex_own(&(block->mutex)));
ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
-@@ -3516,11 +3672,14 @@
+@@ -3516,11 +3691,14 @@
if (UNIV_LIKELY(!hash_page)) {
} else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
/* Preserve the reference count. */
} else {
fprintf(stderr,
"InnoDB: Error: page %lu %lu already found"
-@@ -3530,7 +3689,8 @@
+@@ -3530,7 +3708,8 @@
(const void*) hash_page, (const void*) block);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
mutex_exit(&block->mutex);
buf_print();
buf_LRU_print();
buf_validate();
-@@ -3613,7 +3773,9 @@
+@@ -3613,7 +3792,9 @@
fold = buf_page_address_fold(space, offset);
watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
-@@ -3622,9 +3784,15 @@
+@@ -3622,9 +3803,15 @@
err_exit:
if (block) {
mutex_enter(&block->mutex);
bpage = NULL;
goto func_exit;
-@@ -3647,6 +3815,8 @@
+@@ -3647,6 +3834,8 @@
buf_page_init(space, offset, fold, block);
/* The block must be put to the LRU list, to the old blocks */
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
-@@ -3674,7 +3844,7 @@
+@@ -3674,7 +3863,7 @@
been added to buf_pool->LRU and
buf_pool->page_hash. */
mutex_exit(&block->mutex);
mutex_enter(&block->mutex);
block->page.zip.data = data;
-@@ -3687,6 +3857,7 @@
+@@ -3687,6 +3876,7 @@
buf_unzip_LRU_add_block(block, TRUE);
}
mutex_exit(&block->mutex);
} else {
/* Defer buf_buddy_alloc() until after the block has
-@@ -3698,8 +3869,8 @@
+@@ -3698,8 +3888,8 @@
control block (bpage), in order to avoid the
invocation of buf_buddy_relocate_block() on
uninitialized data. */
/* Initialize the buf_pool pointer. */
bpage->buf_pool_index = buf_pool_index(buf_pool);
-@@ -3719,8 +3890,11 @@
+@@ -3719,8 +3909,11 @@
/* The block was added by some other thread. */
watch_page = NULL;
bpage->state = BUF_BLOCK_ZIP_FREE;
bpage = NULL;
goto func_exit;
-@@ -3764,18 +3938,24 @@
+@@ -3764,18 +3957,24 @@
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
bpage);
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
-@@ -3817,7 +3997,9 @@
+@@ -3817,7 +4016,9 @@
fold = buf_page_address_fold(space, offset);
block = (buf_block_t*) buf_page_hash_get_low(
buf_pool, space, offset, fold);
-@@ -3833,7 +4015,9 @@
+@@ -3833,7 +4034,9 @@
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/* Page can be found in buf_pool */
buf_block_free(free_block);
-@@ -3855,6 +4039,7 @@
+@@ -3855,6 +4058,7 @@
mutex_enter(&block->mutex);
buf_page_init(space, offset, fold, block);
/* The block must be put to the LRU list */
buf_LRU_add_block(&block->page, FALSE);
-@@ -3881,7 +4066,7 @@
+@@ -3881,7 +4085,7 @@
the reacquisition of buf_pool->mutex. We also must
defer this operation until after the block descriptor
has been added to buf_pool->LRU and buf_pool->page_hash. */
mutex_enter(&block->mutex);
block->page.zip.data = data;
-@@ -3899,7 +4084,8 @@
+@@ -3899,7 +4103,8 @@
buf_page_set_accessed(&block->page, time_ms);
mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
-@@ -3950,6 +4136,8 @@
+@@ -3950,6 +4155,8 @@
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
const ibool uncompressed = (buf_page_get_state(bpage)
== BUF_BLOCK_FILE_PAGE);
ut_a(buf_page_in_file(bpage));
-@@ -4083,8 +4271,26 @@
+@@ -4083,8 +4290,26 @@
}
}
#ifdef UNIV_IBUF_COUNT_DEBUG
if (io_type == BUF_IO_WRITE || uncompressed) {
-@@ -4107,6 +4313,7 @@
+@@ -4107,6 +4332,7 @@
the x-latch to this OS thread: do not let this confuse you in
debugging! */
ut_ad(buf_pool->n_pend_reads > 0);
buf_pool->n_pend_reads--;
buf_pool->stat.n_pages_read++;
-@@ -4124,6 +4331,9 @@
+@@ -4124,6 +4350,9 @@
buf_flush_write_complete(bpage);
if (uncompressed) {
rw_lock_s_unlock_gen(&((buf_block_t*) bpage)->lock,
BUF_IO_WRITE);
-@@ -4146,8 +4356,8 @@
+@@ -4146,8 +4375,8 @@
}
#endif /* UNIV_DEBUG */
}
/*********************************************************************//**
-@@ -4164,7 +4374,9 @@
+@@ -4164,7 +4393,9 @@
ut_ad(buf_pool);
chunk = buf_pool->chunks;
-@@ -4181,7 +4393,9 @@
+@@ -4181,7 +4412,9 @@
}
}
return(TRUE);
}
-@@ -4229,7 +4443,8 @@
+@@ -4229,7 +4462,8 @@
freed = buf_LRU_search_and_free_block(buf_pool, 100);
}
ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
-@@ -4242,7 +4457,8 @@
+@@ -4242,7 +4476,8 @@
memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
buf_refresh_io_stats(buf_pool);
}
/*********************************************************************//**
-@@ -4284,7 +4500,10 @@
+@@ -4284,7 +4519,10 @@
ut_ad(buf_pool);
chunk = buf_pool->chunks;
-@@ -4379,7 +4598,7 @@
+@@ -4379,7 +4617,7 @@
/* Check clean compressed-only blocks. */
for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
switch (buf_page_get_io_fix(b)) {
case BUF_IO_NONE:
-@@ -4410,7 +4629,7 @@
+@@ -4410,7 +4648,7 @@
buf_flush_list_mutex_enter(buf_pool);
for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
ut_ad(b->in_flush_list);
ut_a(b->oldest_modification);
n_flush++;
-@@ -4469,6 +4688,8 @@
+@@ -4469,6 +4707,8 @@
}
ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == n_lru);
if (UT_LIST_GET_LEN(buf_pool->free) != n_free) {
fprintf(stderr, "Free list len %lu, free blocks %lu\n",
(ulong) UT_LIST_GET_LEN(buf_pool->free),
-@@ -4479,8 +4700,11 @@
+@@ -4479,8 +4719,11 @@
ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
ut_a(buf_LRU_validate());
ut_a(buf_flush_validate(buf_pool));
-@@ -4536,7 +4760,9 @@
+@@ -4536,7 +4779,9 @@
index_ids = mem_alloc(size * sizeof *index_ids);
counts = mem_alloc(sizeof(ulint) * size);
buf_flush_list_mutex_enter(buf_pool);
fprintf(stderr,
-@@ -4605,7 +4831,9 @@
+@@ -4605,7 +4850,9 @@
}
}
for (i = 0; i < n_found; i++) {
index = dict_index_get_if_in_cache(index_ids[i]);
-@@ -4662,7 +4890,7 @@
+@@ -4662,7 +4909,7 @@
buf_chunk_t* chunk;
ulint fixed_pages_number = 0;
chunk = buf_pool->chunks;
-@@ -4696,7 +4924,7 @@
+@@ -4696,7 +4943,7 @@
/* Traverse the lists of clean and dirty compressed-only blocks. */
for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
ut_a(buf_page_get_io_fix(b) != BUF_IO_WRITE);
-@@ -4708,7 +4936,7 @@
+@@ -4708,7 +4955,7 @@
buf_flush_list_mutex_enter(buf_pool);
for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
ut_ad(b->in_flush_list);
switch (buf_page_get_state(b)) {
-@@ -4734,7 +4962,7 @@
+@@ -4734,7 +4981,7 @@
buf_flush_list_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_mutex);
return(fixed_pages_number);
}
-@@ -4890,6 +5118,8 @@
+@@ -4890,6 +5137,8 @@
/* Find appropriate pool_info to store stats for this buffer pool */
pool_info = &all_pool_info[pool_id];
buf_pool_mutex_enter(buf_pool);
buf_flush_list_mutex_enter(buf_pool);
-@@ -5000,6 +5230,8 @@
+@@ -5000,6 +5249,8 @@
pool_info->unzip_cur = buf_LRU_stat_cur.unzip;
buf_refresh_io_stats(buf_pool);
buf_pool_mutex_exit(buf_pool);
}
-@@ -5241,11 +5473,13 @@
+@@ -5241,11 +5492,13 @@
{
ulint len;