]> git.pld-linux.org Git - packages/mysql.git/blobdiff - innodb_split_buf_pool_mutex.patch
- updated to 5.5.32
[packages/mysql.git] / innodb_split_buf_pool_mutex.patch
index d2a872750352bc277f70b85e56cacff28a3a2daf..dd69aee8e416ff22e7f0322857923d47be3434c3 100644 (file)
@@ -5,10 +5,9 @@
 #!!! notice !!!
 # Any small change to this file in the main branch
 # should be done or reviewed by the maintainer!
-diff -ruN a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
---- a/storage/innobase/btr/btr0cur.c   2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/btr/btr0cur.c   2010-12-03 15:48:29.268957148 +0900
-@@ -3935,7 +3935,8 @@
+--- a/storage/innobase/btr/btr0cur.c
++++ b/storage/innobase/btr/btr0cur.c
+@@ -4070,7 +4070,8 @@
  
        mtr_commit(mtr);
  
@@ -18,14 +17,13 @@ diff -ruN a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
        mutex_enter(&block->mutex);
  
        /* Only free the block if it is still allocated to
-@@ -3946,17 +3947,22 @@
+@@ -4081,16 +4082,21 @@
            && buf_block_get_space(block) == space
            && buf_block_get_page_no(block) == page_no) {
  
--              if (buf_LRU_free_block(&block->page, all, NULL)
-+              if (buf_LRU_free_block(&block->page, all, NULL, TRUE)
-                   != BUF_LRU_FREED
+-              if (!buf_LRU_free_block(&block->page, all)
 -                  && all && block->page.zip.data) {
++              if (!buf_LRU_free_block(&block->page, all, TRUE)
 +                  && all && block->page.zip.data
 +                  /* Now, buf_LRU_free_block() may release mutex temporarily */
 +                  && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
@@ -34,8 +32,8 @@ diff -ruN a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
                        /* Attempt to deallocate the uncompressed page
                        if the whole block cannot be deallocted. */
  
--                      buf_LRU_free_block(&block->page, FALSE, NULL);
-+                      buf_LRU_free_block(&block->page, FALSE, NULL, TRUE);
+-                      buf_LRU_free_block(&block->page, FALSE);
++                      buf_LRU_free_block(&block->page, FALSE, TRUE);
                }
        }
  
@@ -45,10 +43,9 @@ diff -ruN a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
        mutex_exit(&block->mutex);
  }
  
-diff -ruN a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
---- a/storage/innobase/btr/btr0sea.c   2010-12-03 15:48:03.033037049 +0900
-+++ b/storage/innobase/btr/btr0sea.c   2010-12-03 15:48:29.271024260 +0900
-@@ -1943,7 +1943,7 @@
+--- a/storage/innobase/btr/btr0sea.c
++++ b/storage/innobase/btr/btr0sea.c
+@@ -1972,7 +1972,7 @@
        rec_offs_init(offsets_);
  
        rw_lock_x_lock(&btr_search_latch);
@@ -57,7 +54,7 @@ diff -ruN a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
  
        cell_count = hash_get_n_cells(btr_search_sys->hash_index);
  
-@@ -1951,11 +1951,11 @@
+@@ -1980,11 +1980,11 @@
                /* We release btr_search_latch every once in a while to
                give other queries a chance to run. */
                if ((i != 0) && ((i % chunk_size) == 0)) {
@@ -71,7 +68,7 @@ diff -ruN a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
                }
  
                node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
-@@ -2066,11 +2066,11 @@
+@@ -2093,11 +2093,11 @@
                /* We release btr_search_latch every once in a while to
                give other queries a chance to run. */
                if (i != 0) {
@@ -85,7 +82,7 @@ diff -ruN a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
                }
  
                if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
-@@ -2078,7 +2078,7 @@
+@@ -2105,7 +2105,7 @@
                }
        }
  
@@ -94,13 +91,21 @@ diff -ruN a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
        rw_lock_x_unlock(&btr_search_latch);
        if (UNIV_LIKELY_NULL(heap)) {
                mem_heap_free(heap);
-diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
---- a/storage/innobase/buf/buf0buddy.c 2010-12-03 15:22:36.307986907 +0900
-+++ b/storage/innobase/buf/buf0buddy.c 2010-12-03 15:48:29.275025723 +0900
-@@ -73,10 +73,11 @@
-       if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
- #endif /* UNIV_DEBUG_VALGRIND */
+--- a/storage/innobase/buf/buf0buddy.c
++++ b/storage/innobase/buf/buf0buddy.c
+@@ -58,7 +58,7 @@
+ /** Validate a given zip_free list. */
+ #define BUF_BUDDY_LIST_VALIDATE(b, i)                         \
+-      UT_LIST_VALIDATE(list, buf_page_t,                      \
++      UT_LIST_VALIDATE(zip_list, buf_page_t,                  \
+                        b->zip_free[i],                        \
+                        ut_ad(buf_page_get_state(              \
+                                      ut_list_node_313)        \
+@@ -75,10 +75,11 @@
+       ulint           i)              /*!< in: index of
+                                       buf_pool->zip_free[] */
+ {
 -      ut_ad(buf_pool_mutex_own(buf_pool));
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
 +      ut_ad(mutex_own(&buf_pool->zip_free_mutex));
@@ -108,23 +113,21 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
        ut_ad(buf_pool->zip_free[i].start != bpage);
 -      UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
 +      UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_free[i], bpage);
+ }
  
- #ifdef UNIV_DEBUG_VALGRIND
-       if (b) UNIV_MEM_FREE(b, BUF_BUDDY_LOW << i);
-@@ -96,8 +97,8 @@
+ /**********************************************************************//**
+@@ -93,16 +94,17 @@
                                        buf_pool->zip_free[] */
  {
- #ifdef UNIV_DEBUG_VALGRIND
+ #ifdef UNIV_DEBUG
 -      buf_page_t*     prev = UT_LIST_GET_PREV(list, bpage);
 -      buf_page_t*     next = UT_LIST_GET_NEXT(list, bpage);
 +      buf_page_t*     prev = UT_LIST_GET_PREV(zip_list, bpage);
 +      buf_page_t*     next = UT_LIST_GET_NEXT(zip_list, bpage);
  
-       if (prev) UNIV_MEM_VALID(prev, BUF_BUDDY_LOW << i);
-       if (next) UNIV_MEM_VALID(next, BUF_BUDDY_LOW << i);
-@@ -106,9 +107,10 @@
+       ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE);
        ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
- #endif /* UNIV_DEBUG_VALGRIND */
+ #endif /* UNIV_DEBUG */
  
 -      ut_ad(buf_pool_mutex_own(buf_pool));
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
@@ -132,10 +135,10 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
 -      UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
 +      UT_LIST_REMOVE(zip_list, buf_pool->zip_free[i], bpage);
+ }
  
- #ifdef UNIV_DEBUG_VALGRIND
-       if (prev) UNIV_MEM_FREE(prev, BUF_BUDDY_LOW << i);
-@@ -128,12 +130,13 @@
+ /**********************************************************************//**
+@@ -117,7 +119,8 @@
  {
        buf_page_t*     bpage;
  
@@ -143,15 +146,9 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
 +      ut_ad(mutex_own(&buf_pool->zip_free_mutex));
        ut_a(i < BUF_BUDDY_SIZES);
+       ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
  
- #ifndef UNIV_DEBUG_VALGRIND
-       /* Valgrind would complain about accessing free memory. */
--      ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
-+      ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
-                             ut_ad(buf_page_get_state(ut_list_node_313)
-                                   == BUF_BLOCK_ZIP_FREE)));
- #endif /* !UNIV_DEBUG_VALGRIND */
-@@ -177,16 +180,19 @@
+@@ -159,16 +162,19 @@
  buf_buddy_block_free(
  /*=================*/
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
@@ -173,7 +170,7 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
        HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
                    ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY
                          && bpage->in_zip_hash && !bpage->in_page_hash),
-@@ -198,12 +204,14 @@
+@@ -180,12 +186,14 @@
        ut_d(bpage->in_zip_hash = FALSE);
        HASH_DELETE(buf_page_t, hash, buf_pool->zip_hash, fold, bpage);
  
@@ -189,7 +186,7 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
        mutex_exit(&block->mutex);
  
        ut_ad(buf_pool->buddy_n_frames > 0);
-@@ -220,7 +228,7 @@
+@@ -202,7 +210,7 @@
  {
        buf_pool_t*     buf_pool = buf_pool_from_block(block);
        const ulint     fold = BUF_POOL_ZIP_FOLD(block);
@@ -198,7 +195,7 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE);
  
-@@ -232,7 +240,10 @@
+@@ -214,7 +222,10 @@
        ut_ad(!block->page.in_page_hash);
        ut_ad(!block->page.in_zip_hash);
        ut_d(block->page.in_zip_hash = TRUE);
@@ -209,17 +206,8 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
  
        ut_d(buf_pool->buddy_n_frames++);
  }
-@@ -268,7 +279,7 @@
-               bpage->state = BUF_BLOCK_ZIP_FREE;
- #ifndef UNIV_DEBUG_VALGRIND
-               /* Valgrind would complain about accessing free memory. */
--              ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
-+              ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
-                                     ut_ad(buf_page_get_state(
-                                                   ut_list_node_313)
-                                           == BUF_BLOCK_ZIP_FREE)));
-@@ -291,25 +302,29 @@
-       buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
+@@ -268,26 +279,30 @@
+       buf_pool_t*     buf_pool,       /*!< in/out: buffer pool instance */
        ulint           i,              /*!< in: index of buf_pool->zip_free[],
                                        or BUF_BUDDY_SIZES */
 -      ibool*          lru)            /*!< in: pointer to a variable that
@@ -227,16 +215,17 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
                                        will be assigned TRUE if storage was
                                        allocated from the LRU list and
                                        buf_pool->mutex was temporarily
-                                       released, or NULL if the LRU list
-                                       should not be used */
+                                       released */
 +      ibool           have_page_hash_mutex)
  {
        buf_block_t*    block;
  
+       ut_ad(lru);
 -      ut_ad(buf_pool_mutex_own(buf_pool));
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
 +      ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
+       ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
  
        if (i < BUF_BUDDY_SIZES) {
                /* Try to allocate from the buddy system. */
@@ -250,7 +239,7 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
        }
  
        /* Try allocating from the buf_pool->free list. */
-@@ -326,19 +341,30 @@
+@@ -299,19 +314,30 @@
        }
  
        /* Try replacing an uncompressed page in the buffer pool. */
@@ -260,7 +249,7 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
 +      if (have_page_hash_mutex) {
 +              rw_lock_x_unlock(&buf_pool->page_hash_latch);
 +      }
-       block = buf_LRU_get_free_block(buf_pool, 0);
+       block = buf_LRU_get_free_block(buf_pool);
        *lru = TRUE;
 -      buf_pool_mutex_enter(buf_pool);
 +      //buf_pool_mutex_enter(buf_pool);
@@ -283,71 +272,7 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
        return(block);
  }
  
-@@ -355,7 +381,10 @@
-       buf_page_t*     b;
-       buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
--      ut_ad(buf_pool_mutex_own(buf_pool));
-+      //ut_ad(buf_pool_mutex_own(buf_pool));
-+#ifdef UNIV_SYNC_DEBUG
-+      ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
-+#endif
-       switch (buf_page_get_state(bpage)) {
-       case BUF_BLOCK_ZIP_FREE:
-@@ -364,7 +393,7 @@
-       case BUF_BLOCK_FILE_PAGE:
-       case BUF_BLOCK_MEMORY:
-       case BUF_BLOCK_REMOVE_HASH:
--              ut_error;
-+              /* ut_error; */ /* optimistic */
-       case BUF_BLOCK_ZIP_DIRTY:
-               /* Cannot relocate dirty pages. */
-               return(FALSE);
-@@ -374,9 +403,18 @@
-       }
-       mutex_enter(&buf_pool->zip_mutex);
-+      mutex_enter(&buf_pool->zip_free_mutex);
-       if (!buf_page_can_relocate(bpage)) {
-               mutex_exit(&buf_pool->zip_mutex);
-+              mutex_exit(&buf_pool->zip_free_mutex);
-+              return(FALSE);
-+      }
-+
-+      if (bpage != buf_page_hash_get(buf_pool,
-+                                     bpage->space, bpage->offset)) {
-+              mutex_exit(&buf_pool->zip_mutex);
-+              mutex_exit(&buf_pool->zip_free_mutex);
-               return(FALSE);
-       }
-@@ -384,18 +422,19 @@
-       ut_d(bpage->state = BUF_BLOCK_ZIP_FREE);
-       /* relocate buf_pool->zip_clean */
--      b = UT_LIST_GET_PREV(list, dpage);
--      UT_LIST_REMOVE(list, buf_pool->zip_clean, dpage);
-+      b = UT_LIST_GET_PREV(zip_list, dpage);
-+      UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, dpage);
-       if (b) {
--              UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, dpage);
-+              UT_LIST_INSERT_AFTER(zip_list, buf_pool->zip_clean, b, dpage);
-       } else {
--              UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, dpage);
-+              UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, dpage);
-       }
-       UNIV_MEM_INVALID(bpage, sizeof *bpage);
-       mutex_exit(&buf_pool->zip_mutex);
-+      mutex_exit(&buf_pool->zip_free_mutex);
-       return(TRUE);
- }
-@@ -409,14 +448,16 @@
+@@ -325,8 +351,9 @@
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
        void*           src,            /*!< in: block to relocate */
        void*           dst,            /*!< in: free block to relocate to */
@@ -358,7 +283,9 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
  {
        buf_page_t*     bpage;
        const ulint     size    = BUF_BUDDY_LOW << i;
-       ullint          usec    = ut_time_us(NULL);
+@@ -334,13 +361,20 @@
+       ulint           space;
+       ulint           page_no;
  
 -      ut_ad(buf_pool_mutex_own(buf_pool));
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
@@ -366,132 +293,86 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
        ut_ad(!ut_align_offset(src, size));
        ut_ad(!ut_align_offset(dst, size));
-@@ -437,6 +478,13 @@
-       if (size >= PAGE_ZIP_MIN_SIZE) {
-               /* This is a compressed page. */
-               mutex_t*        mutex;
-+              ulint           space, page_no;
-+
-+              if (!have_page_hash_mutex) {
-+                      mutex_exit(&buf_pool->zip_free_mutex);
-+                      mutex_enter(&buf_pool->LRU_list_mutex);
-+                      rw_lock_x_lock(&buf_pool->page_hash_latch);
-+              }
+       ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
+       UNIV_MEM_ASSERT_W(dst, size);
  
-               /* The src block may be split into smaller blocks,
-               some of which may be free.  Thus, the
-@@ -446,9 +494,9 @@
-               pool), so there is nothing wrong about this.  The
-               mach_read_from_4() calls here will only trigger bogus
-               Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
--              ulint           space   = mach_read_from_4(
-+              space   = mach_read_from_4(
-                       (const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
--              ulint           page_no = mach_read_from_4(
-+              page_no = mach_read_from_4(
-                       (const byte*) src + FIL_PAGE_OFFSET);
-               /* Suppress Valgrind warnings about conditional jump
-               on uninitialized value. */
-@@ -462,6 +510,11 @@
-                       added to buf_pool->page_hash yet.  Obviously,
-                       it cannot be relocated. */
-+                      if (!have_page_hash_mutex) {
-+                              mutex_enter(&buf_pool->zip_free_mutex);
-+                              mutex_exit(&buf_pool->LRU_list_mutex);
-+                              rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+                      }
-                       return(FALSE);
-               }
-@@ -473,18 +526,27 @@
-                       For the sake of simplicity, give up. */
-                       ut_ad(page_zip_get_size(&bpage->zip) < size);
-+                      if (!have_page_hash_mutex) {
-+                              mutex_enter(&buf_pool->zip_free_mutex);
-+                              mutex_exit(&buf_pool->LRU_list_mutex);
-+                              rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+                      }
-                       return(FALSE);
-               }
-+              /* To keep latch order */
-+              if (have_page_hash_mutex)
-+                      mutex_exit(&buf_pool->zip_free_mutex);
++      if (!have_page_hash_mutex) {
++              mutex_exit(&buf_pool->zip_free_mutex);
++              mutex_enter(&buf_pool->LRU_list_mutex);
++              rw_lock_x_lock(&buf_pool->page_hash_latch);
++      }
 +
-               /* The block must have been allocated, but it may
-               contain uninitialized data. */
-               UNIV_MEM_ASSERT_W(src, size);
+       /* We assume that all memory from buf_buddy_alloc()
+       is used for compressed page frames. */
  
--              mutex = buf_page_get_mutex(bpage);
-+              mutex = buf_page_get_mutex_enter(bpage);
+@@ -374,6 +408,11 @@
+               added to buf_pool->page_hash yet.  Obviously,
+               it cannot be relocated. */
  
--              mutex_enter(mutex);
-+              mutex_enter(&buf_pool->zip_free_mutex);
++              if (!have_page_hash_mutex) {
++                      mutex_enter(&buf_pool->zip_free_mutex);
++                      mutex_exit(&buf_pool->LRU_list_mutex);
++                      rw_lock_x_unlock(&buf_pool->page_hash_latch);
++              }
+               return(FALSE);
+       }
  
--              if (buf_page_can_relocate(bpage)) {
-+              if (mutex && buf_page_can_relocate(bpage)) {
-                       /* Relocate the compressed page. */
-                       ut_a(bpage->zip.data == src);
-                       memcpy(dst, src, size);
-@@ -499,10 +561,22 @@
-                               buddy_stat->relocated_usec
-                                       += ut_time_us(NULL) - usec;
-                       }
-+
-+                      if (!have_page_hash_mutex) {
-+                              mutex_exit(&buf_pool->LRU_list_mutex);
-+                              rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+                      }
-                       return(TRUE);
-               }
+@@ -383,18 +422,27 @@
+               For the sake of simplicity, give up. */
+               ut_ad(page_zip_get_size(&bpage->zip) < size);
  
--              mutex_exit(mutex);
 +              if (!have_page_hash_mutex) {
++                      mutex_enter(&buf_pool->zip_free_mutex);
 +                      mutex_exit(&buf_pool->LRU_list_mutex);
 +                      rw_lock_x_unlock(&buf_pool->page_hash_latch);
 +              }
-+
-+              if (mutex) {
-+                      mutex_exit(mutex);
-+              }
-       } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
-               /* This must be a buf_page_t object. */
- #if UNIV_WORD_SIZE == 4
-@@ -511,10 +585,31 @@
-               about uninitialized pad bytes. */
-               UNIV_MEM_ASSERT_RW(src, size);
- #endif
-+
+               return(FALSE);
+       }
++      /* To keep latch order */
++      if (have_page_hash_mutex)
 +              mutex_exit(&buf_pool->zip_free_mutex);
 +
-+              if (!have_page_hash_mutex) {
-+                      mutex_enter(&buf_pool->LRU_list_mutex);
-+                      rw_lock_x_lock(&buf_pool->page_hash_latch);
-+              }
-+
-               if (buf_buddy_relocate_block(src, dst)) {
-+                      mutex_enter(&buf_pool->zip_free_mutex);
-+
-+                      if (!have_page_hash_mutex) {
-+                              mutex_exit(&buf_pool->LRU_list_mutex);
-+                              rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+                      }
+       /* The block must have been allocated, but it may
+       contain uninitialized data. */
+       UNIV_MEM_ASSERT_W(src, size);
+-      mutex = buf_page_get_mutex(bpage);
++      mutex = buf_page_get_mutex_enter(bpage);
  
-                       goto success;
+-      mutex_enter(mutex);
++      mutex_enter(&buf_pool->zip_free_mutex);
+-      if (buf_page_can_relocate(bpage)) {
++      if (mutex && buf_page_can_relocate(bpage)) {
+               /* Relocate the compressed page. */
+               ullint  usec    = ut_time_us(NULL);
+               ut_a(bpage->zip.data == src);
+@@ -409,10 +457,22 @@
+                       buddy_stat->relocated_usec
+                               += ut_time_us(NULL) - usec;
                }
 +
-+              mutex_enter(&buf_pool->zip_free_mutex);
-+
 +              if (!have_page_hash_mutex) {
 +                      mutex_exit(&buf_pool->LRU_list_mutex);
 +                      rw_lock_x_unlock(&buf_pool->page_hash_latch);
 +              }
+               return(TRUE);
        }
  
+-      mutex_exit(mutex);
++      if (!have_page_hash_mutex) {
++              mutex_exit(&buf_pool->LRU_list_mutex);
++              rw_lock_x_unlock(&buf_pool->page_hash_latch);
++      }
++
++      if (mutex) {
++              mutex_exit(mutex);
++      }
        return(FALSE);
-@@ -529,13 +624,15 @@
+ }
+@@ -425,13 +485,15 @@
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
        void*           buf,            /*!< in: block to be freed, must not be
                                        pointed to by the buffer pool */
@@ -508,9 +389,9 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
 +      ut_ad(mutex_own(&buf_pool->zip_free_mutex));
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
        ut_ad(i <= BUF_BUDDY_SIZES);
-       ut_ad(buf_pool->buddy_stat[i].used > 0);
-@@ -546,7 +643,9 @@
-       ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
+       ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
+@@ -443,7 +505,9 @@
+       ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE;
  
        if (i == BUF_BUDDY_SIZES) {
 -              buf_buddy_block_free(buf_pool, buf);
@@ -520,60 +401,35 @@ diff -ruN a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
                return;
        }
  
-@@ -591,7 +690,7 @@
+@@ -491,7 +555,7 @@
                ut_a(bpage != buf);
+               UNIV_MEM_ASSERT_W(bpage, BUF_BUDDY_LOW << i);
+-              bpage = UT_LIST_GET_NEXT(list, bpage);
++              bpage = UT_LIST_GET_NEXT(zip_list, bpage);
+       }
  
-               {
--                      buf_page_t*     next = UT_LIST_GET_NEXT(list, bpage);
-+                      buf_page_t*     next = UT_LIST_GET_NEXT(zip_list, bpage);
-                       UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
-                       bpage = next;
-               }
-@@ -600,13 +699,13 @@
  #ifndef UNIV_DEBUG_VALGRIND
- buddy_nonfree:
-       /* Valgrind would complain about accessing free memory. */
--      ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
-+      ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
-                             ut_ad(buf_page_get_state(ut_list_node_313)
-                                   == BUF_BLOCK_ZIP_FREE)));
- #endif /* UNIV_DEBUG_VALGRIND */
+@@ -501,7 +565,7 @@
+       ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
  
        /* The buddy is not free. Is there a free block of this size? */
 -      bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
 +      bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
  
        if (bpage) {
-               /* Remove the block from the free list, because a successful
-@@ -616,7 +715,7 @@
+@@ -510,7 +574,7 @@
                buf_buddy_remove_from_free(buf_pool, bpage, i);
  
                /* Try to relocate the buddy of buf to the free block. */
 -              if (buf_buddy_relocate(buf_pool, buddy, bpage, i)) {
 +              if (buf_buddy_relocate(buf_pool, buddy, bpage, i, have_page_hash_mutex)) {
  
-                       ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
-                       goto buddy_free2;
-@@ -636,14 +735,14 @@
-               (Parts of the buddy can be free in
-               buf_pool->zip_free[j] with j < i.) */
--              ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
-+              ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
-                                     ut_ad(buf_page_get_state(
-                                                   ut_list_node_313)
-                                           == BUF_BLOCK_ZIP_FREE
-                                           && ut_list_node_313 != buddy)));
- #endif /* !UNIV_DEBUG_VALGRIND */
--              if (buf_buddy_relocate(buf_pool, buddy, buf, i)) {
-+              if (buf_buddy_relocate(buf_pool, buddy, buf, i, have_page_hash_mutex)) {
-                       buf = bpage;
-                       UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
-diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
---- a/storage/innobase/buf/buf0buf.c   2010-12-03 15:22:36.314943336 +0900
-+++ b/storage/innobase/buf/buf0buf.c   2010-12-03 15:48:29.282947357 +0900
+                       buddy->state = BUF_BLOCK_ZIP_FREE;
+                       goto buddy_is_free;
+--- a/storage/innobase/buf/buf0buf.c
++++ b/storage/innobase/buf/buf0buf.c
 @@ -263,6 +263,7 @@
  #ifdef UNIV_PFS_RWLOCK
  /* Keys to register buffer block related rwlocks and mutexes with
@@ -593,18 +449,22 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  UNIV_INTERN mysql_pfs_key_t   flush_list_mutex_key;
  #endif /* UNIV_PFS_MUTEX */
  
-@@ -881,9 +886,9 @@
+@@ -890,9 +895,13 @@
        block->page.in_zip_hash = FALSE;
        block->page.in_flush_list = FALSE;
        block->page.in_free_list = FALSE;
 -      block->in_unzip_LRU_list = FALSE;
  #endif /* UNIV_DEBUG */
++      block->page.flush_list.prev = NULL;
++      block->page.flush_list.next = NULL;
++      block->page.zip_list.prev = NULL;
++      block->page.zip_list.next = NULL;
        block->page.in_LRU_list = FALSE;
 +      block->in_unzip_LRU_list = FALSE;
  #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
        block->n_pointers = 0;
  #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-@@ -981,9 +986,11 @@
+@@ -997,9 +1006,11 @@
                memset(block->frame, '\0', UNIV_PAGE_SIZE);
  #endif
                /* Add the block to the free list */
@@ -617,7 +477,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                ut_ad(buf_pool_from_block(block) == buf_pool);
  
                block++;
-@@ -1038,7 +1045,8 @@
+@@ -1054,7 +1065,8 @@
        buf_chunk_t*    chunk = buf_pool->chunks;
  
        ut_ad(buf_pool);
@@ -627,28 +487,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        for (n = buf_pool->n_chunks; n--; chunk++) {
  
                buf_block_t* block = buf_chunk_contains_zip(chunk, data);
-@@ -1138,7 +1146,7 @@
-       buf_block_t*            block;
-       const buf_block_t*      block_end;
--      ut_ad(buf_pool_mutex_own(buf_pool));
-+      //ut_ad(buf_pool_mutex_own(buf_pool)); /* but we need all mutex here */
-       block_end = chunk->blocks + chunk->size;
-@@ -1150,8 +1158,10 @@
-               ut_ad(!block->in_unzip_LRU_list);
-               ut_ad(!block->page.in_flush_list);
-               /* Remove the block from the free list. */
-+              mutex_enter(&buf_pool->free_list_mutex);
-               ut_ad(block->page.in_free_list);
--              UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
-+              UT_LIST_REMOVE(free, buf_pool->free, (&block->page));
-+              mutex_exit(&buf_pool->free_list_mutex);
-               /* Free the latches. */
-               mutex_free(&block->mutex);
-@@ -1208,9 +1218,21 @@
+@@ -1160,9 +1172,21 @@
        ------------------------------- */
        mutex_create(buf_pool_mutex_key,
                     &buf_pool->mutex, SYNC_BUF_POOL);
@@ -670,7 +509,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        buf_pool_mutex_enter(buf_pool);
  
        if (buf_pool_size > 0) {
-@@ -1223,6 +1245,8 @@
+@@ -1175,6 +1199,8 @@
                        mem_free(chunk);
                        mem_free(buf_pool);
  
@@ -679,7 +518,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                        buf_pool_mutex_exit(buf_pool);
  
                        return(DB_ERROR);
-@@ -1253,6 +1277,8 @@
+@@ -1205,6 +1231,8 @@
  
        /* All fields are initialized by mem_zalloc(). */
  
@@ -688,7 +527,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        buf_pool_mutex_exit(buf_pool);
  
        return(DB_SUCCESS);
-@@ -1467,7 +1493,11 @@
+@@ -1376,7 +1404,11 @@
        ulint           fold;
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
  
@@ -701,92 +540,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
        ut_a(bpage->buf_fix_count == 0);
-@@ -1554,7 +1584,8 @@
- try_again:
-       btr_search_disable(); /* Empty the adaptive hash index again */
--      buf_pool_mutex_enter(buf_pool);
-+      //buf_pool_mutex_enter(buf_pool);
-+      mutex_enter(&buf_pool->LRU_list_mutex);
- shrink_again:
-       if (buf_pool->n_chunks <= 1) {
-@@ -1625,7 +1656,7 @@
-                               buf_LRU_make_block_old(&block->page);
-                               dirty++;
--                      } else if (buf_LRU_free_block(&block->page, TRUE, NULL)
-+                      } else if (buf_LRU_free_block(&block->page, TRUE, NULL, TRUE)
-                                  != BUF_LRU_FREED) {
-                               nonfree++;
-                       }
-@@ -1633,7 +1664,8 @@
-                       mutex_exit(&block->mutex);
-               }
--              buf_pool_mutex_exit(buf_pool);
-+              //buf_pool_mutex_exit(buf_pool);
-+              mutex_exit(&buf_pool->LRU_list_mutex);
-               /* Request for a flush of the chunk if it helps.
-               Do not flush if there are non-free blocks, since
-@@ -1683,7 +1715,8 @@
- func_done:
-       buf_pool->old_pool_size = buf_pool->curr_pool_size;
- func_exit:
--      buf_pool_mutex_exit(buf_pool);
-+      //buf_pool_mutex_exit(buf_pool);
-+      mutex_exit(&buf_pool->LRU_list_mutex);
-       btr_search_enable();
- }
-@@ -1724,7 +1757,9 @@
-       hash_table_t*   zip_hash;
-       hash_table_t*   page_hash;
--      buf_pool_mutex_enter(buf_pool);
-+      //buf_pool_mutex_enter(buf_pool);
-+      mutex_enter(&buf_pool->LRU_list_mutex);
-+      rw_lock_x_lock(&buf_pool->page_hash_latch);
-       /* Free, create, and populate the hash table. */
-       hash_table_free(buf_pool->page_hash);
-@@ -1765,8 +1800,9 @@
-       All such blocks are either in buf_pool->zip_clean or
-       in buf_pool->flush_list. */
-+      mutex_enter(&buf_pool->zip_mutex);
-       for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
--           b = UT_LIST_GET_NEXT(list, b)) {
-+           b = UT_LIST_GET_NEXT(zip_list, b)) {
-               ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
-               ut_ad(!b->in_flush_list);
-               ut_ad(b->in_LRU_list);
-@@ -1776,10 +1812,11 @@
-               HASH_INSERT(buf_page_t, hash, page_hash,
-                           buf_page_address_fold(b->space, b->offset), b);
-       }
-+      mutex_exit(&buf_pool->zip_mutex);
-       buf_flush_list_mutex_enter(buf_pool);
-       for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
--           b = UT_LIST_GET_NEXT(list, b)) {
-+           b = UT_LIST_GET_NEXT(flush_list, b)) {
-               ut_ad(b->in_flush_list);
-               ut_ad(b->in_LRU_list);
-               ut_ad(b->in_page_hash);
-@@ -1806,7 +1843,9 @@
-       }
-       buf_flush_list_mutex_exit(buf_pool);
--      buf_pool_mutex_exit(buf_pool);
-+      //buf_pool_mutex_exit(buf_pool);
-+      mutex_exit(&buf_pool->LRU_list_mutex);
-+      rw_lock_x_unlock(&buf_pool->page_hash_latch);
- }
- /********************************************************************
-@@ -1853,21 +1892,32 @@
+@@ -1487,21 +1519,32 @@
        buf_page_t*     bpage;
        ulint           i;
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
@@ -797,12 +551,12 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
 +      rw_lock_x_lock(&buf_pool->page_hash_latch);
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
-+      if (bpage) {
-+              block_mutex = buf_page_get_mutex_enter(bpage);
-+              ut_a(block_mutex);
-+      }
  
        if (UNIV_LIKELY_NULL(bpage)) {
++
++              block_mutex = buf_page_get_mutex_enter(bpage);
++              ut_a(block_mutex);
++
                if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
                        /* The page was loaded meanwhile. */
 +                      rw_lock_x_unlock(&buf_pool->page_hash_latch);
@@ -820,7 +574,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
                bpage = &buf_pool->watch[i];
  
-@@ -1891,10 +1941,12 @@
+@@ -1525,10 +1568,12 @@
                        bpage->space = space;
                        bpage->offset = offset;
                        bpage->buf_fix_count = 1;
@@ -834,7 +588,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                        return(NULL);
                case BUF_BLOCK_ZIP_PAGE:
                        ut_ad(bpage->in_page_hash);
-@@ -1912,6 +1964,8 @@
+@@ -1546,6 +1591,8 @@
        ut_error;
  
        /* Fix compiler warning */
@@ -843,25 +597,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        return(NULL);
  }
  
-@@ -1941,6 +1995,8 @@
-       buf_chunk_t*    chunks;
-       buf_chunk_t*    chunk;
-+      mutex_enter(&buf_pool->LRU_list_mutex);
-+      rw_lock_x_lock(&buf_pool->page_hash_latch);
-       buf_pool_mutex_enter(buf_pool);
-       chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
-@@ -1959,6 +2015,8 @@
-               buf_pool->n_chunks++;
-       }
-+      mutex_exit(&buf_pool->LRU_list_mutex);
-+      rw_lock_x_unlock(&buf_pool->page_hash_latch);
-       buf_pool_mutex_exit(buf_pool);
- }
-@@ -2046,7 +2104,11 @@
+@@ -1563,7 +1610,11 @@
                                        space, offset) */
        buf_page_t*     watch)          /*!< in/out: sentinel for watch */
  {
@@ -874,7 +610,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
        ut_d(watch->in_page_hash = FALSE);
-@@ -2068,28 +2130,31 @@
+@@ -1585,28 +1636,31 @@
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
        ulint           fold = buf_page_address_fold(space, offset);
  
@@ -910,7 +646,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  }
  
  /****************************************************************//**
-@@ -2109,14 +2174,16 @@
+@@ -1626,14 +1680,16 @@
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
        ulint           fold    = buf_page_address_fold(space, offset);
  
@@ -929,7 +665,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        return(ret);
  }
-@@ -2133,13 +2200,15 @@
+@@ -1650,13 +1706,15 @@
  {
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
  
@@ -947,7 +683,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  }
  
  /********************************************************************//**
-@@ -2163,14 +2232,20 @@
+@@ -1680,14 +1738,20 @@
        ut_a(buf_page_in_file(bpage));
  
        if (buf_page_peek_if_too_old(bpage)) {
@@ -972,7 +708,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        }
  }
  
-@@ -2187,7 +2262,8 @@
+@@ -1704,7 +1768,8 @@
        buf_block_t*    block;
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
  
@@ -982,7 +718,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
  
-@@ -2196,7 +2272,8 @@
+@@ -1713,7 +1778,8 @@
                block->check_index_page_at_flush = FALSE;
        }
  
@@ -991,28 +727,8 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 +      rw_lock_s_unlock(&buf_pool->page_hash_latch);
  }
  
- /********************************************************************//**
-@@ -2215,7 +2292,8 @@
-       ibool           is_hashed;
-       buf_pool_t*     buf_pool = buf_pool_get(space, offset);
--      buf_pool_mutex_enter(buf_pool);
-+      //buf_pool_mutex_enter(buf_pool);
-+      rw_lock_s_lock(&buf_pool->page_hash_latch);
-       block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
-@@ -2226,7 +2304,8 @@
-               is_hashed = block->is_hashed;
-       }
--      buf_pool_mutex_exit(buf_pool);
-+      //buf_pool_mutex_exit(buf_pool);
-+      rw_lock_s_unlock(&buf_pool->page_hash_latch);
-       return(is_hashed);
- }
-@@ -2248,7 +2327,8 @@
+ #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
+@@ -1733,7 +1799,8 @@
        buf_page_t*     bpage;
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
  
@@ -1022,7 +738,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        bpage = buf_page_hash_get(buf_pool, space, offset);
  
-@@ -2257,7 +2337,8 @@
+@@ -1744,7 +1811,8 @@
                bpage->file_page_was_freed = TRUE;
        }
  
@@ -1032,7 +748,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        return(bpage);
  }
-@@ -2278,7 +2359,8 @@
+@@ -1765,7 +1833,8 @@
        buf_page_t*     bpage;
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
  
@@ -1042,7 +758,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        bpage = buf_page_hash_get(buf_pool, space, offset);
  
-@@ -2287,7 +2369,8 @@
+@@ -1774,7 +1843,8 @@
                bpage->file_page_was_freed = FALSE;
        }
  
@@ -1052,7 +768,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        return(bpage);
  }
-@@ -2322,8 +2405,9 @@
+@@ -1806,8 +1876,9 @@
        buf_pool->stat.n_page_gets++;
  
        for (;;) {
@@ -1063,7 +779,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                bpage = buf_page_hash_get(buf_pool, space, offset);
                if (bpage) {
                        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
-@@ -2332,7 +2416,8 @@
+@@ -1816,7 +1887,8 @@
  
                /* Page not in buf_pool: needs to be read from file */
  
@@ -1073,7 +789,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
                buf_read_page(space, zip_size, offset);
  
-@@ -2344,10 +2429,15 @@
+@@ -1828,10 +1900,15 @@
        if (UNIV_UNLIKELY(!bpage->zip.data)) {
                /* There is no compressed page. */
  err_exit:
@@ -1090,7 +806,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
  
        switch (buf_page_get_state(bpage)) {
-@@ -2356,19 +2446,19 @@
+@@ -1840,24 +1917,43 @@
        case BUF_BLOCK_MEMORY:
        case BUF_BLOCK_REMOVE_HASH:
        case BUF_BLOCK_ZIP_FREE:
@@ -1106,16 +822,40 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                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. */
--              if (buf_LRU_free_block(bpage, FALSE, NULL)
-+              if (buf_LRU_free_block(bpage, FALSE, NULL, FALSE)
-                   == BUF_LRU_FREED) {
+-              /* Discard the uncompressed page frame if possible. */
+-              if (buf_LRU_free_block(bpage, FALSE)) {
++              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)) {
++                      mutex_exit(&buf_pool->LRU_list_mutex);
                        mutex_exit(block_mutex);
-@@ -2387,7 +2477,7 @@
+                       goto lookup;
+               }
++              mutex_exit(&buf_pool->LRU_list_mutex);
++
+               buf_block_buf_fix_inc((buf_block_t*) bpage,
+                                     __FILE__, __LINE__);
+               goto got_block;
+@@ -1870,7 +1966,7 @@
        must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
        access_time = buf_page_is_accessed(bpage);
  
@@ -1124,7 +864,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        mutex_exit(block_mutex);
  
-@@ -2696,7 +2786,7 @@
+@@ -2181,7 +2277,7 @@
        const buf_block_t*      block)          /*!< in: pointer to block,
                                                not dereferenced */
  {
@@ -1133,7 +873,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
                /* The pointer should be aligned. */
-@@ -2732,6 +2822,7 @@
+@@ -2217,6 +2313,7 @@
        ulint           fix_type;
        ibool           must_read;
        ulint           retries = 0;
@@ -1141,7 +881,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
  
        ut_ad(mtr);
-@@ -2754,9 +2845,11 @@
+@@ -2250,18 +2347,24 @@
        fold = buf_page_address_fold(space, offset);
  loop:
        block = guess;
@@ -1152,11 +892,8 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 +              block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
 +
                /* 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
-@@ -2765,11 +2858,15 @@
-               the guess may be pointing to a buffer pool chunk that
-               has been released when resizing the buffer pool. */
+               has been allocated by buf_page_alloc_descriptor(),
+               it may have been freed by buf_relocate(). */
  
 -              if (!buf_block_is_uncompressed(buf_pool, block)
 +              if (!block_mutex) {
@@ -1171,7 +908,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                        block = guess = NULL;
                } else {
                        ut_ad(!block->page.in_zip_hash);
-@@ -2778,12 +2875,19 @@
+@@ -2270,12 +2373,19 @@
        }
  
        if (block == NULL) {
@@ -1191,7 +928,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                block = NULL;
        }
  
-@@ -2795,12 +2899,14 @@
+@@ -2287,12 +2397,14 @@
                                space, offset, fold);
  
                        if (UNIV_LIKELY_NULL(block)) {
@@ -1207,8 +944,8 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 +              //buf_pool_mutex_exit(buf_pool);
  
                if (mode == BUF_GET_IF_IN_POOL
-                   || mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
-@@ -2848,7 +2954,8 @@
+                   || mode == BUF_PEEK_IF_IN_POOL
+@@ -2345,7 +2457,8 @@
                /* The page is being read to buffer pool,
                but we cannot wait around for the read to
                complete. */
@@ -1218,7 +955,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
                return(NULL);
        }
-@@ -2858,38 +2965,49 @@
+@@ -2355,38 +2468,49 @@
                ibool           success;
  
        case BUF_BLOCK_FILE_PAGE:
@@ -1251,7 +988,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 +                      //buf_pool_mutex_exit(buf_pool);
 +                      mutex_exit(block_mutex);
                        os_thread_sleep(WAIT_FOR_READ);
-   
                        goto loop;
                }
  
@@ -1262,7 +999,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 +              //mutex_exit(&buf_pool->zip_mutex);
 +              mutex_exit(block_mutex);
  
-               block = buf_LRU_get_free_block(buf_pool, 0);
+               block = buf_LRU_get_free_block(buf_pool);
                ut_a(block);
 +              block_mutex = &block->mutex;
  
@@ -1275,7 +1012,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
                {
                        buf_page_t*     hash_bpage;
-@@ -2902,35 +3020,47 @@
+@@ -2399,35 +2523,47 @@
                                while buf_pool->mutex was released.
                                Free the block that was allocated. */
  
@@ -1329,16 +1066,16 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                buf_block_init_low(block);
                block->lock_hash_val = lock_rec_hash(space, offset);
  
-@@ -2939,7 +3069,7 @@
+@@ -2437,7 +2573,7 @@
                if (buf_page_get_state(&block->page)
                    == BUF_BLOCK_ZIP_PAGE) {
+ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 -                      UT_LIST_REMOVE(list, buf_pool->zip_clean,
 +                      UT_LIST_REMOVE(zip_list, buf_pool->zip_clean,
                                       &block->page);
+ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
                        ut_ad(!block->page.in_flush_list);
-               } else {
-@@ -2956,19 +3086,24 @@
+@@ -2455,18 +2591,23 @@
                /* Insert at the front of unzip_LRU list */
                buf_unzip_LRU_add_block(block, FALSE);
  
@@ -1353,20 +1090,18 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 -              mutex_exit(&block->mutex);
 +              mutex_exit(block_mutex);
                mutex_exit(&buf_pool->zip_mutex);
-+
-+              buf_pool_mutex_enter(buf_pool);
-               buf_pool->n_pend_unzip++;
-+              buf_pool_mutex_exit(buf_pool);
+-              buf_pool->n_pend_unzip++;
  
--              buf_buddy_free(buf_pool, bpage, sizeof *bpage);
-+              buf_buddy_free(buf_pool, bpage, sizeof *bpage, FALSE);
++              buf_pool_mutex_enter(buf_pool);
++              buf_pool->n_pend_unzip++;
+               buf_pool_mutex_exit(buf_pool);
  
--              buf_pool_mutex_exit(buf_pool);
 +              //buf_pool_mutex_exit(buf_pool);
++
+               buf_page_free_descriptor(bpage);
  
                /* Decompress the page and apply buffered operations
-               while not holding buf_pool->mutex or block->mutex. */
-@@ -2981,12 +3116,15 @@
+@@ -2480,12 +2621,15 @@
                }
  
                /* Unfix and unlatch the block. */
@@ -1385,7 +1120,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                rw_lock_x_unlock(&block->lock);
  
                break;
-@@ -3002,7 +3140,7 @@
+@@ -2501,7 +2645,7 @@
  
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
  
@@ -1394,19 +1129,40 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  #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
-@@ -3015,7 +3153,7 @@
+@@ -2514,8 +2658,8 @@
                /* Try to evict the block from the buffer pool, to use the
                insert buffer (change buffer) as much as possible. */
  
--              if (buf_LRU_free_block(&block->page, TRUE, NULL)
-+              if (buf_LRU_free_block(&block->page, TRUE, NULL, FALSE)
-                   == BUF_LRU_FREED) {
-                       mutex_exit(&block->mutex);
+-              if (buf_LRU_free_block(&block->page, TRUE)) {
+-                      mutex_exit(&block->mutex);
++              if (buf_LRU_free_block(&block->page, TRUE, FALSE)) {
++                      mutex_exit(block_mutex);
                        if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
-@@ -3052,13 +3190,14 @@
+                               /* Set the watch, as it would have
+                               been set if the page were not in the
+@@ -2524,6 +2668,9 @@
+                                       space, offset, fold);
  
-       buf_block_buf_fix_inc(block, file, line);
+                               if (UNIV_LIKELY_NULL(block)) {
++                                      block_mutex = buf_page_get_mutex((buf_page_t*)block);
++                                      ut_a(block_mutex);
++                                      ut_ad(mutex_own(block_mutex));
  
+                                       /* The page entered the buffer
+                                       pool for some reason. Try to
+@@ -2531,7 +2678,7 @@
+                                       goto got_block;
+                               }
+                       }
+-                      buf_pool_mutex_exit(buf_pool);
++                      //buf_pool_mutex_exit(buf_pool);
+                       fprintf(stderr,
+                               "innodb_change_buffering_debug evict %u %u\n",
+                               (unsigned) space, (unsigned) offset);
+@@ -2553,13 +2700,14 @@
+       ut_a(mode == BUF_GET_POSSIBLY_FREED
+            || !block->page.file_page_was_freed);
+ #endif
 -      mutex_exit(&block->mutex);
 +      //mutex_exit(&block->mutex);
  
@@ -1418,9 +1174,9 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 +      //buf_pool_mutex_exit(buf_pool);
 +      mutex_exit(block_mutex);
  
-       buf_page_set_accessed_make_young(&block->page, access_time);
-@@ -3291,9 +3430,11 @@
+       if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL)) {
+               buf_page_set_accessed_make_young(&block->page, access_time);
+@@ -2792,9 +2940,11 @@
        buf_pool = buf_pool_from_block(block);
  
        if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
@@ -1434,7 +1190,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        } 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
-@@ -3301,9 +3442,11 @@
+@@ -2802,9 +2952,11 @@
                field must be protected by mutex, however. */
                ulint   time_ms = ut_time_ms();
  
@@ -1447,8 +1203,8 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 +              mutex_exit(&block->mutex);
        }
  
-       ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
-@@ -3370,18 +3513,21 @@
+       ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
+@@ -2871,18 +3023,21 @@
        ut_ad(mtr);
        ut_ad(mtr->state == MTR_ACTIVE);
  
@@ -1473,10 +1229,10 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
-@@ -3470,7 +3616,10 @@
+@@ -2972,7 +3127,10 @@
        buf_page_t*     hash_page;
-       buf_pool_t*     buf_pool = buf_pool_get(space, offset);
  
+       ut_ad(buf_pool == buf_pool_get(space, offset));
 -      ut_ad(buf_pool_mutex_own(buf_pool));
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
 +#ifdef UNIV_SYNC_DEBUG
@@ -1485,7 +1241,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        ut_ad(mutex_own(&(block->mutex)));
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
  
-@@ -3499,11 +3648,14 @@
+@@ -3001,11 +3159,14 @@
        if (UNIV_LIKELY(!hash_page)) {
        } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
                /* Preserve the reference count. */
@@ -1501,7 +1257,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        } else {
                fprintf(stderr,
                        "InnoDB: Error: page %lu %lu already found"
-@@ -3513,7 +3665,8 @@
+@@ -3015,7 +3176,8 @@
                        (const void*) hash_page, (const void*) block);
  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
                mutex_exit(&block->mutex);
@@ -1511,7 +1267,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                buf_print();
                buf_LRU_print();
                buf_validate();
-@@ -3597,7 +3750,9 @@
+@@ -3098,7 +3260,9 @@
  
        fold = buf_page_address_fold(space, offset);
  
@@ -1522,7 +1278,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
        if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
-@@ -3606,9 +3761,15 @@
+@@ -3107,9 +3271,15 @@
  err_exit:
                if (block) {
                        mutex_enter(&block->mutex);
@@ -1539,16 +1295,16 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
                bpage = NULL;
                goto func_exit;
-@@ -3631,6 +3792,8 @@
+@@ -3132,6 +3302,8 @@
  
-               buf_page_init(space, offset, fold, block);
+               buf_page_init(buf_pool, space, offset, fold, block);
  
 +              rw_lock_x_unlock(&buf_pool->page_hash_latch);
 +
                /* The block must be put to the LRU list, to the old blocks */
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
  
-@@ -3658,7 +3821,7 @@
+@@ -3159,7 +3331,7 @@
                        been added to buf_pool->LRU and
                        buf_pool->page_hash. */
                        mutex_exit(&block->mutex);
@@ -1557,32 +1313,27 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                        mutex_enter(&block->mutex);
                        block->page.zip.data = data;
  
-@@ -3671,6 +3834,7 @@
+@@ -3172,13 +3344,14 @@
                        buf_unzip_LRU_add_block(block, TRUE);
                }
  
 +              mutex_exit(&buf_pool->LRU_list_mutex);
                mutex_exit(&block->mutex);
        } else {
-               /* Defer buf_buddy_alloc() until after the block has
-@@ -3682,8 +3846,8 @@
+               /* The compressed page must be allocated before the
                control block (bpage), in order to avoid the
                invocation of buf_buddy_relocate_block() on
                uninitialized data. */
 -              data = buf_buddy_alloc(buf_pool, zip_size, &lru);
--              bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
 +              data = buf_buddy_alloc(buf_pool, zip_size, &lru, TRUE);
-+              bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru, TRUE);
  
-               /* Initialize the buf_pool pointer. */
-               bpage->buf_pool_index = buf_pool_index(buf_pool);
-@@ -3702,8 +3866,11 @@
+               /* If buf_buddy_alloc() allocated storage from the LRU list,
+               it released and reacquired buf_pool->mutex.  Thus, we must
+@@ -3194,7 +3367,10 @@
  
                                /* The block was added by some other thread. */
                                watch_page = NULL;
--                              buf_buddy_free(buf_pool, bpage, sizeof *bpage);
 -                              buf_buddy_free(buf_pool, data, zip_size);
-+                              buf_buddy_free(buf_pool, bpage, sizeof *bpage, TRUE);
 +                              buf_buddy_free(buf_pool, data, zip_size, TRUE);
 +
 +                              mutex_exit(&buf_pool->LRU_list_mutex);
@@ -1590,7 +1341,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
                                bpage = NULL;
                                goto func_exit;
-@@ -3747,18 +3914,24 @@
+@@ -3242,20 +3418,26 @@
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
                            bpage);
  
@@ -1598,7 +1349,9 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
 +
                /* The block must be put to the LRU list, to the old blocks */
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
+ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
                buf_LRU_insert_zip_clean(bpage);
+ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
  
 +              mutex_exit(&buf_pool->LRU_list_mutex);
 +
@@ -1616,7 +1369,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
  
-@@ -3800,7 +3973,9 @@
+@@ -3297,7 +3479,9 @@
  
        fold = buf_page_address_fold(space, offset);
  
@@ -1627,8 +1380,8 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        block = (buf_block_t*) buf_page_hash_get_low(
                buf_pool, space, offset, fold);
-@@ -3816,7 +3991,9 @@
- #endif /* UNIV_DEBUG_FILE_ACCESSES */
+@@ -3313,7 +3497,9 @@
+ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
  
                /* Page can be found in buf_pool */
 -              buf_pool_mutex_exit(buf_pool);
@@ -1638,15 +1391,15 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
                buf_block_free(free_block);
  
-@@ -3838,6 +4015,7 @@
+@@ -3335,6 +3521,7 @@
        mutex_enter(&block->mutex);
  
-       buf_page_init(space, offset, fold, block);
+       buf_page_init(buf_pool, space, offset, fold, block);
 +      rw_lock_x_unlock(&buf_pool->page_hash_latch);
  
        /* The block must be put to the LRU list */
        buf_LRU_add_block(&block->page, FALSE);
-@@ -3864,7 +4042,7 @@
+@@ -3361,7 +3548,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. */
@@ -1655,7 +1408,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                mutex_enter(&block->mutex);
                block->page.zip.data = data;
  
-@@ -3882,7 +4060,8 @@
+@@ -3379,7 +3566,8 @@
  
        buf_page_set_accessed(&block->page, time_ms);
  
@@ -1665,7 +1418,35 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
  
-@@ -3933,6 +4112,8 @@
+@@ -3434,7 +3622,9 @@
+       ibool           ret = TRUE;
+       /* First unfix and release lock on the bpage */
+-      buf_pool_mutex_enter(buf_pool);
++      //buf_pool_mutex_enter(buf_pool);
++      mutex_enter(&buf_pool->LRU_list_mutex);
++      rw_lock_x_lock(&buf_pool->page_hash_latch);
+       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);
+@@ -3455,11 +3645,15 @@
+               ret = FALSE;
+       }
++      buf_pool_mutex_enter(buf_pool);
+       ut_ad(buf_pool->n_pend_reads > 0);
+       buf_pool->n_pend_reads--;
++      buf_pool_mutex_exit(buf_pool);
+       mutex_exit(buf_page_get_mutex(bpage));
+-      buf_pool_mutex_exit(buf_pool);
++      //buf_pool_mutex_exit(buf_pool);
++      mutex_exit(&buf_pool->LRU_list_mutex);
++      rw_lock_x_unlock(&buf_pool->page_hash_latch);
+       return(ret);
+ }
+@@ -3477,6 +3671,8 @@
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
        const ibool     uncompressed = (buf_page_get_state(bpage)
                                        == BUF_BLOCK_FILE_PAGE);
@@ -1674,7 +1455,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        ut_a(buf_page_in_file(bpage));
  
-@@ -4066,8 +4247,26 @@
+@@ -3619,8 +3815,26 @@
                }
        }
  
@@ -1702,7 +1483,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
  #ifdef UNIV_IBUF_COUNT_DEBUG
        if (io_type == BUF_IO_WRITE || uncompressed) {
-@@ -4090,6 +4289,7 @@
+@@ -3643,6 +3857,7 @@
                the x-latch to this OS thread: do not let this confuse you in
                debugging! */
  
@@ -1710,7 +1491,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                ut_ad(buf_pool->n_pend_reads > 0);
                buf_pool->n_pend_reads--;
                buf_pool->stat.n_pages_read++;
-@@ -4107,6 +4307,9 @@
+@@ -3660,6 +3875,9 @@
  
                buf_flush_write_complete(bpage);
  
@@ -1720,7 +1501,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                if (uncompressed) {
                        rw_lock_s_unlock_gen(&((buf_block_t*) bpage)->lock,
                                             BUF_IO_WRITE);
-@@ -4129,8 +4332,8 @@
+@@ -3682,8 +3900,8 @@
        }
  #endif /* UNIV_DEBUG */
  
@@ -1730,7 +1511,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  }
  
  /*********************************************************************//**
-@@ -4147,7 +4350,9 @@
+@@ -3700,7 +3918,9 @@
  
        ut_ad(buf_pool);
  
@@ -1741,7 +1522,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        chunk = buf_pool->chunks;
  
-@@ -4164,7 +4369,9 @@
+@@ -3717,7 +3937,9 @@
                }
        }
  
@@ -1752,7 +1533,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        return(TRUE);
  }
-@@ -4212,7 +4419,8 @@
+@@ -3765,7 +3987,8 @@
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
        }
  
@@ -1762,7 +1543,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
-@@ -4225,7 +4433,8 @@
+@@ -3778,7 +4001,8 @@
        memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
        buf_refresh_io_stats(buf_pool);
  
@@ -1772,7 +1553,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  }
  
  /*********************************************************************//**
-@@ -4267,7 +4476,10 @@
+@@ -3820,7 +4044,10 @@
  
        ut_ad(buf_pool);
  
@@ -1784,7 +1565,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        chunk = buf_pool->chunks;
  
-@@ -4362,7 +4574,7 @@
+@@ -3918,7 +4145,7 @@
        /* Check clean compressed-only blocks. */
  
        for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
@@ -1793,7 +1574,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
                switch (buf_page_get_io_fix(b)) {
                case BUF_IO_NONE:
-@@ -4393,7 +4605,7 @@
+@@ -3950,7 +4177,7 @@
  
        buf_flush_list_mutex_enter(buf_pool);
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
@@ -1802,7 +1583,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                ut_ad(b->in_flush_list);
                ut_a(b->oldest_modification);
                n_flush++;
-@@ -4452,6 +4664,8 @@
+@@ -4010,6 +4237,8 @@
        }
  
        ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == n_lru);
@@ -1811,7 +1592,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        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),
-@@ -4462,8 +4676,11 @@
+@@ -4020,8 +4249,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);
@@ -1824,7 +1605,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        ut_a(buf_LRU_validate());
        ut_a(buf_flush_validate(buf_pool));
-@@ -4519,7 +4736,9 @@
+@@ -4077,7 +4309,9 @@
        index_ids = mem_alloc(size * sizeof *index_ids);
        counts = mem_alloc(sizeof(ulint) * size);
  
@@ -1835,7 +1616,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        buf_flush_list_mutex_enter(buf_pool);
  
        fprintf(stderr,
-@@ -4588,7 +4807,9 @@
+@@ -4146,7 +4380,9 @@
                }
        }
  
@@ -1846,7 +1627,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        for (i = 0; i < n_found; i++) {
                index = dict_index_get_if_in_cache(index_ids[i]);
-@@ -4645,7 +4866,7 @@
+@@ -4203,7 +4439,7 @@
        buf_chunk_t*    chunk;
        ulint           fixed_pages_number = 0;
  
@@ -1855,7 +1636,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        chunk = buf_pool->chunks;
  
-@@ -4679,7 +4900,7 @@
+@@ -4237,7 +4473,7 @@
        /* Traverse the lists of clean and dirty compressed-only blocks. */
  
        for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
@@ -1864,7 +1645,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
                ut_a(buf_page_get_io_fix(b) != BUF_IO_WRITE);
  
-@@ -4691,7 +4912,7 @@
+@@ -4249,7 +4485,7 @@
  
        buf_flush_list_mutex_enter(buf_pool);
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
@@ -1873,7 +1654,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
                ut_ad(b->in_flush_list);
  
                switch (buf_page_get_state(b)) {
-@@ -4717,7 +4938,7 @@
+@@ -4275,7 +4511,7 @@
  
        buf_flush_list_mutex_exit(buf_pool);
        mutex_exit(&buf_pool->zip_mutex);
@@ -1882,7 +1663,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        return(fixed_pages_number);
  }
-@@ -4873,6 +5094,8 @@
+@@ -4433,6 +4669,8 @@
        /* Find appropriate pool_info to store stats for this buffer pool */
        pool_info = &all_pool_info[pool_id];
  
@@ -1891,7 +1672,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        buf_pool_mutex_enter(buf_pool);
        buf_flush_list_mutex_enter(buf_pool);
  
-@@ -4983,6 +5206,8 @@
+@@ -4548,6 +4786,8 @@
        pool_info->unzip_cur = buf_LRU_stat_cur.unzip;
  
        buf_refresh_io_stats(buf_pool);
@@ -1900,7 +1681,7 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
        buf_pool_mutex_exit(buf_pool);
  }
  
-@@ -5224,11 +5449,13 @@
+@@ -4792,11 +5032,13 @@
  {
        ulint   len;
  
@@ -1916,9 +1697,8 @@ diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
  
        return(len);
  }
-diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
---- a/storage/innobase/buf/buf0flu.c   2010-12-03 15:22:36.318955693 +0900
-+++ b/storage/innobase/buf/buf0flu.c   2010-12-03 15:48:29.289024083 +0900
+--- a/storage/innobase/buf/buf0flu.c
++++ b/storage/innobase/buf/buf0flu.c
 @@ -307,7 +307,7 @@
  
        ut_d(block->page.in_flush_list = TRUE);
@@ -1983,13 +1763,15 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
        ut_ad(bpage->in_flush_list);
  
-@@ -526,11 +526,11 @@
+@@ -526,13 +526,13 @@
                return;
        case BUF_BLOCK_ZIP_DIRTY:
                buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE);
 -              UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
 +              UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
+ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
                buf_LRU_insert_zip_clean(bpage);
+ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
                break;
        case BUF_BLOCK_FILE_PAGE:
 -              UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
@@ -1997,7 +1779,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
                break;
        }
  
-@@ -574,7 +574,7 @@
+@@ -576,7 +576,7 @@
        buf_page_t*     prev_b = NULL;
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
  
@@ -2006,7 +1788,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
        /* Must reside in the same buffer pool. */
        ut_ad(buf_pool == buf_pool_from_bpage(dpage));
  
-@@ -603,18 +603,18 @@
+@@ -605,18 +605,18 @@
        because we assert on in_flush_list in comparison function. */
        ut_d(bpage->in_flush_list = FALSE);
  
@@ -2029,7 +1811,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
                        buf_pool->flush_list,
                        dpage);
        }
-@@ -1083,7 +1083,7 @@
+@@ -1085,7 +1085,7 @@
  
  #ifdef UNIV_DEBUG
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
@@ -2038,7 +1820,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  #endif
  
  #ifdef UNIV_LOG_DEBUG
-@@ -1097,7 +1097,8 @@
+@@ -1099,7 +1099,8 @@
        io_fixed and oldest_modification != 0.  Thus, it cannot be
        relocated in the buffer pool or removed from flush_list or
        LRU_list. */
@@ -2048,7 +1830,28 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
        ut_ad(!buf_flush_list_mutex_own(buf_pool));
        ut_ad(!mutex_own(buf_page_get_mutex(bpage)));
        ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_WRITE);
-@@ -1260,12 +1261,18 @@
+@@ -1179,7 +1180,7 @@
+       buf_pool_t*     buf_pool,       /*!< in/out: buffer pool instance */
+       buf_block_t*    block)          /*!< in/out: buffer control block */
+ {
+-      ut_ad(buf_pool_mutex_own(buf_pool));
++      //ut_ad(buf_pool_mutex_own(buf_pool));
+       ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
+       ut_ad(mutex_own(&block->mutex));
+@@ -1187,8 +1188,11 @@
+               return(FALSE);
+       }
++      buf_pool_mutex_enter(buf_pool);
++
+       if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0
+           || buf_pool->init_flush[BUF_FLUSH_LRU]) {
++              buf_pool_mutex_exit(buf_pool);
+               /* There is already a flush batch of the same type running */
+               return(FALSE);
+       }
+@@ -1262,12 +1266,18 @@
        ibool           is_uncompressed;
  
        ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
@@ -2068,7 +1871,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
        ut_ad(buf_flush_ready_for_flush(bpage, flush_type));
  
        buf_page_set_io_fix(bpage, BUF_IO_WRITE);
-@@ -1427,14 +1434,16 @@
+@@ -1455,14 +1465,16 @@
  
                buf_pool = buf_pool_get(space, i);
  
@@ -2084,24 +1887,24 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
 -                      buf_pool_mutex_exit(buf_pool);
 +                      //buf_pool_mutex_exit(buf_pool);
 +                      rw_lock_s_unlock(&buf_pool->page_hash_latch);
-                       continue;
-               }
+                       if (srv_flush_neighbor_pages == 2) {
  
-@@ -1446,11 +1455,9 @@
+                               /* This is contiguous neighbor page flush and
+@@ -1480,11 +1492,9 @@
                if (flush_type != BUF_FLUSH_LRU
                    || i == offset
                    || buf_page_is_old(bpage)) {
 -                      mutex_t* block_mutex = buf_page_get_mutex(bpage);
--
--                      mutex_enter(block_mutex);
 +                      mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
  
+-                      mutex_enter(block_mutex);
+-
 -                      if (buf_flush_ready_for_flush(bpage, flush_type)
 +                      if (block_mutex && buf_flush_ready_for_flush(bpage, flush_type)
                            && (i == offset || !bpage->buf_fix_count)) {
                                /* We only try to flush those
                                neighbors != offset where the buf fix
-@@ -1466,11 +1473,12 @@
+@@ -1500,11 +1510,12 @@
                                ut_ad(!buf_pool_mutex_own(buf_pool));
                                count++;
                                continue;
@@ -2113,10 +1916,10 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
 -              buf_pool_mutex_exit(buf_pool);
 +              //buf_pool_mutex_exit(buf_pool);
 +              rw_lock_s_unlock(&buf_pool->page_hash_latch);
-       }
  
-       return(count);
-@@ -1503,21 +1511,25 @@
+               if (srv_flush_neighbor_pages == 2) {
+@@ -1553,21 +1564,25 @@
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
  #endif /* UNIV_DEBUG */
  
@@ -2148,7 +1951,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
                /* These fields are protected by both the
                buffer pool mutex and block mutex. */
-@@ -1533,13 +1545,18 @@
+@@ -1583,13 +1598,18 @@
                                                  *count,
                                                  n_to_flush);
  
@@ -2170,7 +1973,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
        return(flushed);
  }
-@@ -1560,7 +1577,8 @@
+@@ -1610,7 +1630,8 @@
        buf_page_t*     bpage;
        ulint           count = 0;
  
@@ -2180,7 +1983,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
        do {
                /* Start from the end of the list looking for a
-@@ -1582,7 +1600,8 @@
+@@ -1632,7 +1653,8 @@
        should be flushed, we factor in this value. */
        buf_lru_flush_page_count += count;
  
@@ -2190,7 +1993,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
        return(count);
  }
-@@ -1610,9 +1629,10 @@
+@@ -1660,9 +1682,10 @@
  {
        ulint           len;
        buf_page_t*     bpage;
@@ -2202,7 +2005,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
        /* If we have flushed enough, leave the loop */
        do {
-@@ -1631,6 +1651,7 @@
+@@ -1681,6 +1704,7 @@
  
                if (bpage) {
                        ut_a(bpage->oldest_modification > 0);
@@ -2210,7 +2013,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
                }
  
                if (!bpage || bpage->oldest_modification >= lsn_limit) {
-@@ -1672,9 +1693,17 @@
+@@ -1722,9 +1746,17 @@
                                break;
                        }
  
@@ -2230,7 +2033,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
                        buf_flush_list_mutex_exit(buf_pool);
  
-@@ -1683,7 +1712,7 @@
+@@ -1733,7 +1765,7 @@
  
        } while (count < min_n && bpage != NULL && len > 0);
  
@@ -2239,8 +2042,8 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
        return(count);
  }
-@@ -1722,13 +1751,15 @@
-             || sync_thread_levels_empty_gen(TRUE));
+@@ -1772,13 +1804,15 @@
+             || sync_thread_levels_empty_except_dict());
  #endif /* UNIV_SYNC_DEBUG */
  
 -      buf_pool_mutex_enter(buf_pool);
@@ -2256,7 +2059,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
                break;
        case BUF_FLUSH_LIST:
                count = buf_flush_flush_list_batch(buf_pool, min_n, lsn_limit);
-@@ -1737,7 +1768,7 @@
+@@ -1787,7 +1821,7 @@
                ut_error;
        }
  
@@ -2265,7 +2068,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
        buf_flush_buffered_writes();
  
-@@ -1993,7 +2024,7 @@
+@@ -2059,7 +2093,7 @@
  retry:
        //buf_pool_mutex_enter(buf_pool);
        if (have_LRU_mutex)
@@ -2274,7 +2077,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
        n_replaceable = UT_LIST_GET_LEN(buf_pool->free);
  
-@@ -2010,15 +2041,15 @@
+@@ -2076,15 +2110,15 @@
                        bpage = UT_LIST_GET_LAST(buf_pool->LRU);
                        continue;
                }
@@ -2295,7 +2098,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
                distance++;
  
-@@ -2027,7 +2058,7 @@
+@@ -2093,7 +2127,7 @@
  
        //buf_pool_mutex_exit(buf_pool);
        if (have_LRU_mutex)
@@ -2304,7 +2107,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
        if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN(buf_pool)) {
  
-@@ -2226,7 +2257,7 @@
+@@ -2292,7 +2326,7 @@
  
        ut_ad(buf_flush_list_mutex_own(buf_pool));
  
@@ -2313,7 +2116,7 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
                         ut_ad(ut_list_node_313->in_flush_list));
  
        bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-@@ -2266,7 +2297,7 @@
+@@ -2332,7 +2366,7 @@
                        rnode = rbt_next(buf_pool->flush_rbt, rnode);
                }
  
@@ -2322,10 +2125,9 @@ diff -ruN a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
  
                ut_a(!bpage || om >= bpage->oldest_modification);
        }
-diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
---- a/storage/innobase/buf/buf0lru.c   2010-12-03 15:22:36.321987250 +0900
-+++ b/storage/innobase/buf/buf0lru.c   2010-12-03 15:48:29.293023197 +0900
-@@ -143,8 +143,9 @@
+--- a/storage/innobase/buf/buf0lru.c
++++ b/storage/innobase/buf/buf0lru.c
+@@ -147,8 +147,9 @@
  void
  buf_LRU_block_free_hashed_page(
  /*===========================*/
@@ -2336,7 +2138,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
  /******************************************************************//**
  Determines if the unzip_LRU list should be used for evicting a victim
-@@ -154,15 +155,20 @@
+@@ -158,15 +159,20 @@
  ibool
  buf_LRU_evict_from_unzip_LRU(
  /*=========================*/
@@ -2359,7 +2161,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
                return(FALSE);
        }
  
-@@ -171,14 +177,20 @@
+@@ -175,14 +181,20 @@
        decompressed pages in the buffer pool. */
        if (UT_LIST_GET_LEN(buf_pool->unzip_LRU)
            <= UT_LIST_GET_LEN(buf_pool->LRU) / 10) {
@@ -2380,54 +2182,102 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        /* Calculate the average over past intervals, and add the values
        of the current interval. */
-@@ -246,19 +258,23 @@
+@@ -250,18 +262,25 @@
        page_arr = ut_malloc(
-               sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE);
+               sizeof(ulint) * BUF_LRU_DROP_SEARCH_SIZE);
  
 -      buf_pool_mutex_enter(buf_pool);
 +      //buf_pool_mutex_enter(buf_pool);
 +      mutex_enter(&buf_pool->LRU_list_mutex);
+       num_entries = 0;
  
  scan_again:
-       num_entries = 0;
        bpage = UT_LIST_GET_LAST(buf_pool->LRU);
  
        while (bpage != NULL) {
--              mutex_t*        block_mutex = buf_page_get_mutex(bpage);
++              /* bpage->state,space,io_fix,buf_fix_count are protected by block_mutex at XtraDB */
 +              mutex_t*        block_mutex = buf_page_get_mutex_enter(bpage);
                buf_page_t*     prev_bpage;
+               ibool           is_fixed;
  
--              mutex_enter(block_mutex);
                prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
  
-+              if (!block_mutex) {
++              if (UNIV_UNLIKELY(!block_mutex)) {
 +                      goto next_page;
 +              }
 +
                ut_a(buf_page_in_file(bpage));
  
                if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
-@@ -287,14 +303,16 @@
+@@ -270,24 +289,30 @@
+                       /* Compressed pages are never hashed.
+                       Skip blocks of other tablespaces.
+                       Skip I/O-fixed blocks (to be dealt with later). */
++                      mutex_exit(block_mutex);
+ next_page:
+                       bpage = prev_bpage;
+                       continue;
+               }
  
-                       /* Array full. We release the buf_pool->mutex to
-                       obey the latching order. */
--                      buf_pool_mutex_exit(buf_pool);
-+                      //buf_pool_mutex_exit(buf_pool);
-+                      mutex_exit(&buf_pool->LRU_list_mutex);
+-              mutex_enter(&((buf_block_t*) bpage)->mutex);
++              //mutex_enter(&((buf_block_t*) bpage)->mutex);
+               is_fixed = bpage->buf_fix_count > 0
+                       || !((buf_block_t*) bpage)->index;
+-              mutex_exit(&((buf_block_t*) bpage)->mutex);
++              //mutex_exit(&((buf_block_t*) bpage)->mutex);
+               if (is_fixed) {
++                      mutex_exit(block_mutex);
+                       goto next_page;
+               }
  
-                       buf_LRU_drop_page_hash_batch(
-                               id, zip_size, page_arr, num_entries);
+               /* Store the page number so that we can drop the hash
+               index in a batch later. */
+               page_arr[num_entries] = bpage->offset;
++
++              mutex_exit(block_mutex);
++
+               ut_a(num_entries < BUF_LRU_DROP_SEARCH_SIZE);
++
+               ++num_entries;
  
-                       num_entries = 0;
+               if (num_entries < BUF_LRU_DROP_SEARCH_SIZE) {
+@@ -296,14 +321,16 @@
  
--                      buf_pool_mutex_enter(buf_pool);
-+                      //buf_pool_mutex_enter(buf_pool);
-+                      mutex_enter(&buf_pool->LRU_list_mutex);
-               } else {
-                       mutex_exit(block_mutex);
-               }
-@@ -319,7 +337,8 @@
+               /* Array full. We release the buf_pool->mutex to obey
+               the latching order. */
+-              buf_pool_mutex_exit(buf_pool);
++              //buf_pool_mutex_exit(buf_pool);
++              mutex_exit(&buf_pool->LRU_list_mutex);
+               buf_LRU_drop_page_hash_batch(
+                       id, zip_size, page_arr, num_entries);
+               num_entries = 0;
+-              buf_pool_mutex_enter(buf_pool);
++              //buf_pool_mutex_enter(buf_pool);
++              mutex_enter(&buf_pool->LRU_list_mutex);
+               /* Note that we released the buf_pool mutex above
+               after reading the prev_bpage during processing of a
+@@ -321,13 +348,23 @@
+               /* If, however, bpage has been removed from LRU list
+               to the free list then we should restart the scan.
+               bpage->state is protected by buf_pool mutex. */
++
++              /* obtain block_mutex again to avoid race condition of bpage->state */
++              block_mutex = buf_page_get_mutex_enter(bpage);
++              if (!block_mutex) {
++                      goto scan_again;
++              }
++
+               if (bpage
+                   && buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
++                      mutex_exit(block_mutex);
+                       goto scan_again;
                }
++              mutex_exit(block_mutex);
        }
  
 -      buf_pool_mutex_exit(buf_pool);
@@ -2436,79 +2286,84 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        /* Drop any remaining batch of search hashed pages. */
        buf_LRU_drop_page_hash_batch(id, zip_size, page_arr, num_entries);
-@@ -341,7 +360,9 @@
-       ibool           all_freed;
+@@ -351,7 +388,9 @@
+       ulint           i;
  
  scan_again:
 -      buf_pool_mutex_enter(buf_pool);
 +      //buf_pool_mutex_enter(buf_pool);
 +      mutex_enter(&buf_pool->LRU_list_mutex);
 +      rw_lock_x_lock(&buf_pool->page_hash_latch);
+       buf_flush_list_mutex_enter(buf_pool);
  
        all_freed = TRUE;
+@@ -364,7 +403,7 @@
  
-@@ -369,8 +390,16 @@
+               ut_a(buf_page_in_file(bpage));
  
-                       all_freed = FALSE;
-               } else {
--                      mutex_t* block_mutex = buf_page_get_mutex(bpage);
--                      mutex_enter(block_mutex);
-+                      mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
-+
-+                      if (!block_mutex) {
-+                              /* It may be impossible case...
-+                              Something wrong, so will be scan_again */
-+
-+                              all_freed = FALSE;
-+
-+                              goto next_page_no_mutex;
-+                      }
+-              prev_bpage = UT_LIST_GET_PREV(list, bpage);
++              prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
  
-                       if (bpage->buf_fix_count > 0) {
+               /* bpage->space and bpage->io_fix are protected by
+               buf_pool->mutex and block_mutex. It is safe to check
+@@ -388,8 +427,14 @@
+               will stay in the flush_list because buf_flush_remove()
+               needs buf_pool->mutex as well. */
+               buf_flush_list_mutex_exit(buf_pool);
+-              block_mutex = buf_page_get_mutex(bpage);
+-              mutex_enter(block_mutex);
++              block_mutex = buf_page_get_mutex_enter(bpage);
++
++              if (!block_mutex) {
++                      /* It may be impossible case...
++                      Something wrong, so will be scan_again */
++                      all_freed = FALSE;
++                      goto next_page;
++              }
  
-@@ -429,7 +458,9 @@
-                               ulint   page_no;
-                               ulint   zip_size;
+               if (bpage->buf_fix_count > 0) {
+                       mutex_exit(block_mutex);
+@@ -440,9 +485,15 @@
+               mutex_exit(block_mutex);
  
--                              buf_pool_mutex_exit(buf_pool);
-+                              //buf_pool_mutex_exit(buf_pool);
-+                              mutex_exit(&buf_pool->LRU_list_mutex);
-+                              rw_lock_x_unlock(&buf_pool->page_hash_latch);
+               /* Now it is safe to release the buf_pool->mutex. */
+-              buf_pool_mutex_exit(buf_pool);
++              //buf_pool_mutex_exit(buf_pool);
++              mutex_exit(&buf_pool->LRU_list_mutex);
++              rw_lock_x_unlock(&buf_pool->page_hash_latch);
++
+               os_thread_yield();
+-              buf_pool_mutex_enter(buf_pool);
++              //buf_pool_mutex_enter(buf_pool);
++              mutex_enter(&buf_pool->LRU_list_mutex);
++              rw_lock_x_lock(&buf_pool->page_hash_latch);
++
  
-                               zip_size = buf_page_get_zip_size(bpage);
-                               page_no = buf_page_get_page_no(bpage);
-@@ -454,7 +485,7 @@
-                       if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
-                           != BUF_BLOCK_ZIP_FREE) {
-                               buf_LRU_block_free_hashed_page((buf_block_t*)
--                                                             bpage);
-+                                                             bpage, TRUE);
-                       } else {
-                               /* The block_mutex should have been
-                               released by buf_LRU_block_remove_hashed_page()
-@@ -486,7 +517,9 @@
-               bpage = prev_bpage;
+               mutex_enter(block_mutex);
+               buf_page_unset_sticky(bpage);
+@@ -454,7 +505,9 @@
+               i = 0;
        }
  
 -      buf_pool_mutex_exit(buf_pool);
-+      //buf_pool_mutex_exit(buf_pool);
++//    buf_pool_mutex_exit(buf_pool);
 +      mutex_exit(&buf_pool->LRU_list_mutex);
 +      rw_lock_x_unlock(&buf_pool->page_hash_latch);
+       buf_flush_list_mutex_exit(buf_pool);
  
-       if (!all_freed) {
-               os_thread_sleep(20000);
-@@ -532,7 +565,9 @@
+       ut_ad(buf_flush_validate(buf_pool));
+@@ -504,7 +557,9 @@
        buf_page_t*     b;
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
  
 -      ut_ad(buf_pool_mutex_own(buf_pool));
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
 +      ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-+      ut_ad(mutex_own(&buf_pool->flush_list_mutex));
++      ut_ad(mutex_own(&buf_pool->zip_mutex));
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
  
        /* Find the first successor of bpage in the LRU list
-@@ -540,17 +575,17 @@
+@@ -512,17 +567,17 @@
        b = bpage;
        do {
                b = UT_LIST_GET_NEXT(LRU, b);
@@ -2529,8 +2384,8 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
 +              UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, bpage);
        }
  }
-@@ -563,18 +598,19 @@
+ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
+@@ -536,18 +591,19 @@
  buf_LRU_free_from_unzip_LRU_list(
  /*=============================*/
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
@@ -2552,7 +2407,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        /* Theoratically it should be much easier to find a victim
        from unzip_LRU as we can choose even a dirty block (as we'll
-@@ -584,7 +620,7 @@
+@@ -557,7 +613,7 @@
        if we have done five iterations so far. */
  
        if (UNIV_UNLIKELY(n_iterations >= 5)
@@ -2561,7 +2416,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
                return(FALSE);
        }
-@@ -592,18 +628,25 @@
+@@ -565,18 +621,25 @@
        distance = 100 + (n_iterations
                          * UT_LIST_GET_LEN(buf_pool->unzip_LRU)) / 5;
  
@@ -2570,7 +2425,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
             UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
             block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
  
-               enum buf_lru_free_block_status  freed;
+               ibool freed;
  
 +              mutex_enter(&block->mutex);
 +              if (!block->in_unzip_LRU_list || !block->page.in_LRU_list
@@ -2584,12 +2439,12 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
                ut_ad(block->page.in_LRU_list);
  
 -              mutex_enter(&block->mutex);
--              freed = buf_LRU_free_block(&block->page, FALSE, NULL);
-+              freed = buf_LRU_free_block(&block->page, FALSE, NULL, have_LRU_mutex);
+-              freed = buf_LRU_free_block(&block->page, FALSE);
++              freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex);
                mutex_exit(&block->mutex);
  
-               switch (freed) {
-@@ -637,21 +680,23 @@
+               if (freed) {
+@@ -595,35 +658,46 @@
  buf_LRU_free_from_common_LRU_list(
  /*==============================*/
        buf_pool_t*     buf_pool,
@@ -2615,12 +2470,11 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
             UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
             bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
-@@ -659,14 +704,23 @@
-               enum buf_lru_free_block_status  freed;
-               unsigned                        accessed;
-               mutex_t*                        block_mutex
--                      = buf_page_get_mutex(bpage);
-+                      = buf_page_get_mutex_enter(bpage);
+               ibool           freed;
+               unsigned        accessed;
+-              mutex_t*        block_mutex = buf_page_get_mutex(bpage);
++              mutex_t*        block_mutex = buf_page_get_mutex_enter(bpage);
 +
 +              if (!block_mutex) {
 +                      goto restart;
@@ -2637,12 +2491,12 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
 -              mutex_enter(block_mutex);
                accessed = buf_page_is_accessed(bpage);
--              freed = buf_LRU_free_block(bpage, TRUE, NULL);
-+              freed = buf_LRU_free_block(bpage, TRUE, NULL, have_LRU_mutex);
+-              freed = buf_LRU_free_block(bpage, TRUE);
++              freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex);
                mutex_exit(block_mutex);
  
-               switch (freed) {
-@@ -718,16 +772,23 @@
+               if (freed) {
+@@ -660,16 +734,23 @@
                                n_iterations / 5 of the unzip_LRU list. */
  {
        ibool   freed = FALSE;
@@ -2669,7 +2523,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        if (!freed) {
                buf_pool->LRU_flush_ended = 0;
        } else if (buf_pool->LRU_flush_ended > 0) {
-@@ -735,6 +796,8 @@
+@@ -677,6 +758,8 @@
        }
  
        buf_pool_mutex_exit(buf_pool);
@@ -2678,7 +2532,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        return(freed);
  }
-@@ -795,7 +858,9 @@
+@@ -737,7 +820,9 @@
  
                buf_pool = buf_pool_from_array(i);
  
@@ -2689,7 +2543,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
                if (!recv_recovery_on
                    && UT_LIST_GET_LEN(buf_pool->free)
-@@ -805,7 +870,9 @@
+@@ -747,7 +832,9 @@
                        ret = TRUE;
                }
  
@@ -2700,7 +2554,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        }
  
        return(ret);
-@@ -823,9 +890,10 @@
+@@ -765,9 +852,10 @@
  {
        buf_block_t*    block;
  
@@ -2713,7 +2567,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        if (block) {
  
-@@ -834,7 +902,9 @@
+@@ -776,7 +864,9 @@
                ut_ad(!block->page.in_flush_list);
                ut_ad(!block->page.in_LRU_list);
                ut_a(!buf_page_in_file(&block->page));
@@ -2724,7 +2578,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
                mutex_enter(&block->mutex);
  
-@@ -844,6 +914,8 @@
+@@ -786,6 +876,8 @@
                ut_ad(buf_pool_from_block(block) == buf_pool);
  
                mutex_exit(&block->mutex);
@@ -2733,7 +2587,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        }
  
        return(block);
-@@ -868,7 +940,7 @@
+@@ -808,7 +900,7 @@
        ibool           mon_value_was   = FALSE;
        ibool           started_monitor = FALSE;
  loop:
@@ -2742,37 +2596,16 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
            + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 20) {
-@@ -951,8 +1023,10 @@
-                       ibool   lru;
-                       page_zip_set_size(&block->page.zip, zip_size);
-+                      mutex_enter(&buf_pool->LRU_list_mutex);
-                       block->page.zip.data = buf_buddy_alloc(
--                              buf_pool, zip_size, &lru);
-+                              buf_pool, zip_size, &lru, FALSE);
-+                      mutex_exit(&buf_pool->LRU_list_mutex);
-                       UNIV_MEM_DESC(block->page.zip.data, zip_size, block);
-               } else {
-@@ -960,7 +1034,7 @@
-                       block->page.zip.data = NULL;
-               }
--              buf_pool_mutex_exit(buf_pool);
-+              //buf_pool_mutex_exit(buf_pool);
-               if (started_monitor) {
-                       srv_print_innodb_monitor = mon_value_was;
-@@ -972,7 +1046,7 @@
-       /* If no block was in the free list, search from the end of the LRU
-       list and try to free a block there */
+@@ -876,7 +968,7 @@
  
+       /* If there is a block in the free list, take it */
+       block = buf_LRU_get_free_only(buf_pool);
 -      buf_pool_mutex_exit(buf_pool);
 +      //buf_pool_mutex_exit(buf_pool);
  
-       freed = buf_LRU_search_and_free_block(buf_pool, n_iterations);
-@@ -1058,7 +1132,8 @@
+       if (block) {
+               ut_ad(buf_pool_from_block(block) == buf_pool);
+@@ -976,7 +1068,8 @@
        ulint   new_len;
  
        ut_a(buf_pool->LRU_old);
@@ -2782,7 +2615,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        ut_ad(buf_pool->LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN);
        ut_ad(buf_pool->LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX);
  #if BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)
-@@ -1124,7 +1199,8 @@
+@@ -1042,7 +1135,8 @@
  {
        buf_page_t*     bpage;
  
@@ -2792,7 +2625,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
  
        /* We first initialize all blocks in the LRU list as old and then use
-@@ -1159,13 +1235,14 @@
+@@ -1077,13 +1171,14 @@
        ut_ad(buf_pool);
        ut_ad(bpage);
        ut_ad(buf_page_in_file(bpage));
@@ -2809,7 +2642,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
                UT_LIST_REMOVE(unzip_LRU, buf_pool->unzip_LRU, block);
        }
-@@ -1183,7 +1260,8 @@
+@@ -1101,7 +1196,8 @@
  
        ut_ad(buf_pool);
        ut_ad(bpage);
@@ -2819,7 +2652,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        ut_a(buf_page_in_file(bpage));
  
-@@ -1260,12 +1338,13 @@
+@@ -1178,12 +1274,13 @@
  
        ut_ad(buf_pool);
        ut_ad(block);
@@ -2835,7 +2668,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        if (old) {
                UT_LIST_ADD_LAST(unzip_LRU, buf_pool->unzip_LRU, block);
-@@ -1286,7 +1365,8 @@
+@@ -1204,7 +1301,8 @@
  
        ut_ad(buf_pool);
        ut_ad(bpage);
@@ -2845,7 +2678,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        ut_a(buf_page_in_file(bpage));
  
-@@ -1337,7 +1417,8 @@
+@@ -1255,7 +1353,8 @@
  
        ut_ad(buf_pool);
        ut_ad(bpage);
@@ -2855,7 +2688,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        ut_a(buf_page_in_file(bpage));
        ut_ad(!bpage->in_LRU_list);
-@@ -1416,7 +1497,8 @@
+@@ -1334,7 +1433,8 @@
  {
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
  
@@ -2865,15 +2698,13 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        if (bpage->old) {
                buf_pool->stat.n_pages_made_young++;
-@@ -1458,19 +1540,20 @@
+@@ -1373,17 +1473,18 @@
+ buf_LRU_free_block(
+ /*===============*/
        buf_page_t*     bpage,  /*!< in: block to be freed */
-       ibool           zip,    /*!< in: TRUE if should remove also the
+-      ibool           zip)    /*!< in: TRUE if should remove also the
++      ibool           zip,    /*!< in: TRUE if should remove also the
                                compressed page of an uncompressed page */
--      ibool*          buf_pool_mutex_released)
-+      ibool*          buf_pool_mutex_released,
-                               /*!< in: pointer to a variable that will
-                               be assigned TRUE if buf_pool_mutex
-                               was temporarily released, or NULL */
 +      ibool           have_LRU_mutex)
  {
        buf_page_t*     b = NULL;
@@ -2889,7 +2720,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        ut_ad(!bpage->in_flush_list == !bpage->oldest_modification);
  #if UNIV_WORD_SIZE == 4
        /* On 32-bit systems, there is no padding in buf_page_t.  On
-@@ -1479,7 +1562,7 @@
+@@ -1392,7 +1493,7 @@
        UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
  #endif
  
@@ -2897,28 +2728,17 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
 +      if (!bpage->in_LRU_list || !block_mutex || !buf_page_can_relocate(bpage)) {
  
                /* Do not free buffer-fixed or I/O-fixed blocks. */
-               return(BUF_LRU_NOT_FREED);
-@@ -1511,15 +1594,15 @@
-               If it cannot be allocated (without freeing a block
-               from the LRU list), refuse to free bpage. */
+               return(FALSE);
+@@ -1426,7 +1527,7 @@
  alloc:
--              buf_pool_mutex_exit_forbid(buf_pool);
--              b = buf_buddy_alloc(buf_pool, sizeof *b, NULL);
--              buf_pool_mutex_exit_allow(buf_pool);
-+              //buf_pool_mutex_exit_forbid(buf_pool);
-+              b = buf_buddy_alloc(buf_pool, sizeof *b, NULL, FALSE);
-+              //buf_pool_mutex_exit_allow(buf_pool);
-               if (UNIV_UNLIKELY(!b)) {
-                       return(BUF_LRU_CANNOT_RELOCATE);
-               }
+               b = buf_page_alloc_descriptor();
+               ut_a(b);
 -              memcpy(b, bpage, sizeof *b);
 +              //memcpy(b, bpage, sizeof *b);
        }
  
  #ifdef UNIV_DEBUG
-@@ -1530,6 +1613,39 @@
+@@ -1437,6 +1538,39 @@
        }
  #endif /* UNIV_DEBUG */
  
@@ -2940,7 +2760,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
 +              if (!have_LRU_mutex)
 +                      mutex_exit(&buf_pool->LRU_list_mutex);
 +              rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+              return(BUF_LRU_NOT_FREED);
++              return(FALSE);
 +      } else if (zip || !bpage->zip.data) {
 +              if (bpage->oldest_modification)
 +                      goto not_freed;
@@ -2958,7 +2778,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        if (buf_LRU_block_remove_hashed_page(bpage, zip)
            != BUF_BLOCK_ZIP_FREE) {
                ut_a(bpage->buf_fix_count == 0);
-@@ -1546,6 +1662,10 @@
+@@ -1453,6 +1587,10 @@
  
                        ut_a(!hash_b);
  
@@ -2969,8 +2789,21 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
                        b->state = b->oldest_modification
                                ? BUF_BLOCK_ZIP_DIRTY
                                : BUF_BLOCK_ZIP_PAGE;
-@@ -1642,7 +1762,9 @@
-                       *buf_pool_mutex_released = TRUE;
+@@ -1528,6 +1666,7 @@
+                               buf_LRU_add_block_low(b, buf_page_is_old(b));
+                       }
++                      mutex_enter(&buf_pool->zip_mutex);
+                       if (b->state == BUF_BLOCK_ZIP_PAGE) {
+ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
+                               buf_LRU_insert_zip_clean(b);
+@@ -1543,12 +1682,13 @@
+                       /* Prevent buf_page_get_gen() from
+                       decompressing the block while we release
+                       buf_pool->mutex and block_mutex. */
+-                      mutex_enter(&buf_pool->zip_mutex);
+                       buf_page_set_sticky(b);
+                       mutex_exit(&buf_pool->zip_mutex);
                }
  
 -              buf_pool_mutex_exit(buf_pool);
@@ -2980,7 +2813,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
                mutex_exit(block_mutex);
  
                /* Remove possible adaptive hash index on the page.
-@@ -1674,7 +1796,9 @@
+@@ -1580,7 +1720,9 @@
                                : BUF_NO_CHECKSUM_MAGIC);
                }
  
@@ -2991,7 +2824,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
                mutex_enter(block_mutex);
  
                if (b) {
-@@ -1684,13 +1808,17 @@
+@@ -1589,13 +1731,17 @@
                        mutex_exit(&buf_pool->zip_mutex);
                }
  
@@ -3009,8 +2842,8 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
 +              rw_lock_x_unlock(&buf_pool->page_hash_latch);
        }
  
-       return(BUF_LRU_FREED);
-@@ -1702,13 +1830,14 @@
+       return(TRUE);
+@@ -1607,13 +1753,14 @@
  void
  buf_LRU_block_free_non_file_page(
  /*=============================*/
@@ -3027,7 +2860,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        ut_ad(mutex_own(&block->mutex));
  
        switch (buf_block_get_state(block)) {
-@@ -1742,18 +1871,21 @@
+@@ -1647,18 +1794,21 @@
        if (data) {
                block->page.zip.data = NULL;
                mutex_exit(&block->mutex);
@@ -3053,7 +2886,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE);
  }
-@@ -1783,7 +1915,11 @@
+@@ -1688,7 +1838,11 @@
        buf_pool_t*             buf_pool = buf_pool_from_bpage(bpage);
  
        ut_ad(bpage);
@@ -3066,7 +2899,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
  
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
-@@ -1891,7 +2027,9 @@
+@@ -1796,7 +1950,9 @@
  
  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
                mutex_exit(buf_page_get_mutex(bpage));
@@ -3077,12 +2910,13 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
                buf_print();
                buf_LRU_print();
                buf_validate();
-@@ -1912,17 +2050,17 @@
-               ut_a(bpage->zip.data);
+@@ -1818,17 +1974,17 @@
                ut_a(buf_page_get_zip_size(bpage));
  
+ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 -              UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
 +              UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, bpage);
+ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
  
                mutex_exit(&buf_pool->zip_mutex);
 -              buf_pool_mutex_exit_forbid(buf_pool);
@@ -3093,14 +2927,12 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
 -                      page_zip_get_size(&bpage->zip));
 +                      page_zip_get_size(&bpage->zip), TRUE);
  
--              buf_buddy_free(buf_pool, bpage, sizeof(*bpage));
 -              buf_pool_mutex_exit_allow(buf_pool);
-+              buf_buddy_free(buf_pool, bpage, sizeof(*bpage), TRUE);
 +              //buf_pool_mutex_exit_allow(buf_pool);
-               UNIV_MEM_UNDESC(bpage);
+               buf_page_free_descriptor(bpage);
                return(BUF_BLOCK_ZIP_FREE);
-@@ -1945,13 +2083,13 @@
+@@ -1850,13 +2006,13 @@
                        ut_ad(!bpage->in_flush_list);
                        ut_ad(!bpage->in_LRU_list);
                        mutex_exit(&((buf_block_t*) bpage)->mutex);
@@ -3117,7 +2949,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
                        mutex_enter(&((buf_block_t*) bpage)->mutex);
                        page_zip_set_size(&bpage->zip, 0);
                }
-@@ -1977,18 +2115,19 @@
+@@ -1882,18 +2038,19 @@
  void
  buf_LRU_block_free_hashed_page(
  /*===========================*/
@@ -3140,8 +2972,17 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
 +      buf_LRU_block_free_non_file_page(block, have_page_hash_mutex);
  }
  
- /**********************************************************************//**
-@@ -2015,7 +2154,8 @@
+ /******************************************************************//**
+@@ -1908,7 +2065,7 @@
+ {
+       if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
+           != BUF_BLOCK_ZIP_FREE) {
+-              buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
++              buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
+       }
+ }
+@@ -1936,7 +2093,8 @@
        }
  
        if (adjust) {
@@ -3151,7 +2992,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
                if (ratio != buf_pool->LRU_old_ratio) {
                        buf_pool->LRU_old_ratio = ratio;
-@@ -2027,7 +2167,8 @@
+@@ -1948,7 +2106,8 @@
                        }
                }
  
@@ -3161,7 +3002,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        } else {
                buf_pool->LRU_old_ratio = ratio;
        }
-@@ -2132,7 +2273,8 @@
+@@ -2053,7 +2212,8 @@
        ulint           new_len;
  
        ut_ad(buf_pool);
@@ -3171,7 +3012,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
  
-@@ -2193,16 +2335,22 @@
+@@ -2114,16 +2274,22 @@
  
        ut_a(buf_pool->LRU_old_len == old_len);
  
@@ -3196,7 +3037,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
        UT_LIST_VALIDATE(unzip_LRU, buf_block_t, buf_pool->unzip_LRU,
                         ut_ad(ut_list_node_313->in_unzip_LRU_list
                               && ut_list_node_313->page.in_LRU_list));
-@@ -2216,7 +2364,8 @@
+@@ -2137,7 +2303,8 @@
                ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
        }
  
@@ -3206,7 +3047,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  }
  
  /**********************************************************************//**
-@@ -2252,7 +2401,8 @@
+@@ -2173,7 +2340,8 @@
        const buf_page_t*       bpage;
  
        ut_ad(buf_pool);
@@ -3216,7 +3057,7 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  
        bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
  
-@@ -2309,7 +2459,8 @@
+@@ -2230,7 +2398,8 @@
                bpage = UT_LIST_GET_NEXT(LRU, bpage);
        }
  
@@ -3226,10 +3067,9 @@ diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
  }
  
  /**********************************************************************//**
-diff -ruN a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
---- a/storage/innobase/buf/buf0rea.c   2010-12-03 15:22:36.323977308 +0900
-+++ b/storage/innobase/buf/buf0rea.c   2010-12-03 15:48:29.296024468 +0900
-@@ -311,6 +311,7 @@
+--- a/storage/innobase/buf/buf0rea.c
++++ b/storage/innobase/buf/buf0rea.c
+@@ -478,6 +478,7 @@
  
                return(0);
        }
@@ -3237,7 +3077,7 @@ diff -ruN a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
  
        /* Check that almost all pages in the area have been accessed; if
        offset == low, the accesses must be in a descending order, otherwise,
-@@ -329,6 +330,7 @@
+@@ -496,6 +497,7 @@
  
        fail_count = 0;
  
@@ -3245,7 +3085,7 @@ diff -ruN a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
        for (i = low; i < high; i++) {
                bpage = buf_page_hash_get(buf_pool, space, i);
  
-@@ -356,7 +358,8 @@
+@@ -523,7 +525,8 @@
  
                if (fail_count > threshold) {
                        /* Too many failures: return */
@@ -3255,7 +3095,7 @@ diff -ruN a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
                        return(0);
                }
  
-@@ -371,7 +374,8 @@
+@@ -538,7 +541,8 @@
        bpage = buf_page_hash_get(buf_pool, space, offset);
  
        if (bpage == NULL) {
@@ -3265,7 +3105,7 @@ diff -ruN a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
  
                return(0);
        }
-@@ -397,7 +401,8 @@
+@@ -564,7 +568,8 @@
        pred_offset = fil_page_get_prev(frame);
        succ_offset = fil_page_get_next(frame);
  
@@ -3275,10 +3115,9 @@ diff -ruN a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
  
        if ((offset == low) && (succ_offset == offset + 1)) {
  
-diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
---- a/storage/innobase/handler/ha_innodb.cc    2010-12-03 15:48:03.048955897 +0900
-+++ b/storage/innobase/handler/ha_innodb.cc    2010-12-03 15:48:29.304024564 +0900
-@@ -245,6 +245,10 @@
+--- a/storage/innobase/handler/ha_innodb.cc
++++ b/storage/innobase/handler/ha_innodb.cc
+@@ -265,6 +265,10 @@
  #  endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
        {&buf_pool_mutex_key, "buf_pool_mutex", 0},
        {&buf_pool_zip_mutex_key, "buf_pool_zip_mutex", 0},
@@ -3289,7 +3128,7 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
        {&cache_last_read_mutex_key, "cache_last_read_mutex", 0},
        {&dict_foreign_err_mutex_key, "dict_foreign_err_mutex", 0},
        {&dict_sys_mutex_key, "dict_sys_mutex", 0},
-@@ -295,6 +299,7 @@
+@@ -314,6 +318,7 @@
        {&archive_lock_key, "archive_lock", 0},
  #  endif /* UNIV_LOG_ARCHIVE */
        {&btr_search_latch_key, "btr_search_latch", 0},
@@ -3297,10 +3136,9 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
  #  ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
        {&buf_block_lock_key, "buf_block_lock", 0},
  #  endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
-diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
---- a/storage/innobase/handler/i_s.cc  2010-12-03 15:37:45.517105700 +0900
-+++ b/storage/innobase/handler/i_s.cc  2010-12-03 15:48:29.331024462 +0900
-@@ -1565,7 +1565,8 @@
+--- a/storage/innobase/handler/i_s.cc
++++ b/storage/innobase/handler/i_s.cc
+@@ -1583,7 +1583,8 @@
  
                buf_pool = buf_pool_from_array(i);
  
@@ -3310,7 +3148,7 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
  
                for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
                        buf_buddy_stat_t*       buddy_stat;
-@@ -1595,7 +1596,8 @@
+@@ -1613,7 +1614,8 @@
                        }
                }
  
@@ -3320,10 +3158,9 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
  
                if (status) {
                        break;
-diff -ruN a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
---- a/storage/innobase/ibuf/ibuf0ibuf.c        2010-12-03 15:48:03.068954202 +0900
-+++ b/storage/innobase/ibuf/ibuf0ibuf.c        2010-12-03 15:48:29.335988682 +0900
-@@ -3783,9 +3783,11 @@
+--- a/storage/innobase/ibuf/ibuf0ibuf.c
++++ b/storage/innobase/ibuf/ibuf0ibuf.c
+@@ -3760,9 +3760,11 @@
                ulint           fold = buf_page_address_fold(space, page_no);
                buf_pool_t*     buf_pool = buf_pool_get(space, page_no);
  
@@ -3337,46 +3174,47 @@ diff -ruN a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.
  
                if (UNIV_LIKELY_NULL(bpage)) {
                        /* A buffer pool watch has been set or the
-diff -ruN a/storage/innobase/include/buf0buddy.h b/storage/innobase/include/buf0buddy.h
---- a/storage/innobase/include/buf0buddy.h     2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/buf0buddy.h     2010-12-03 15:48:29.338023826 +0900
-@@ -51,10 +51,11 @@
-       buf_pool_t*     buf_pool,
-                       /*!< buffer pool in which the block resides */
-       ulint   size,   /*!< in: block size, up to UNIV_PAGE_SIZE */
--      ibool*  lru)    /*!< in: pointer to a variable that will be assigned
-+      ibool*  lru,    /*!< in: pointer to a variable that will be assigned
-                       TRUE if storage was allocated from the LRU list
-                       and buf_pool->mutex was temporarily released,
-                       or NULL if the LRU list should not be used */
-+      ibool   have_page_hash_mutex)
-       __attribute__((malloc));
+--- a/storage/innobase/include/buf0buddy.h
++++ b/storage/innobase/include/buf0buddy.h
+@@ -49,11 +49,12 @@
+       ulint           size,           /*!< in: compressed page size
+                                       (between PAGE_ZIP_MIN_SIZE and
+                                       UNIV_PAGE_SIZE) */
+-      ibool*          lru)            /*!< in: pointer to a variable
++      ibool*          lru,            /*!< in: pointer to a variable
+                                       that will be assigned TRUE if
+                                       storage was allocated from the
+                                       LRU list and buf_pool->mutex was
+                                       temporarily released */
++      ibool           have_page_hash_mutex)
+       __attribute__((malloc, nonnull));
  
  /**********************************************************************//**
-@@ -67,7 +68,8 @@
-                       /*!< buffer pool in which the block resides */
-       void*   buf,    /*!< in: block to be freed, must not be
-                       pointed to by the buffer pool */
--      ulint   size)   /*!< in: block size, up to UNIV_PAGE_SIZE */
-+      ulint   size,   /*!< in: block size, up to UNIV_PAGE_SIZE */
-+      ibool   have_page_hash_mutex)
+@@ -66,8 +67,9 @@
+                                       the block resides */
+       void*           buf,            /*!< in: block to be freed, must not
+                                       be pointed to by the buffer pool */
+-      ulint           size)           /*!< in: block size,
++      ulint           size,           /*!< in: block size,
+                                       up to UNIV_PAGE_SIZE */
++      ibool           have_page_hash_mutex)
        __attribute__((nonnull));
  
  #ifndef UNIV_NONINL
-diff -ruN a/storage/innobase/include/buf0buddy.ic b/storage/innobase/include/buf0buddy.ic
---- a/storage/innobase/include/buf0buddy.ic    2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/buf0buddy.ic    2010-12-03 15:48:29.339040413 +0900
-@@ -46,10 +46,11 @@
-                       /*!< in: buffer pool in which the page resides */
-       ulint   i,      /*!< in: index of buf_pool->zip_free[],
-                       or BUF_BUDDY_SIZES */
--      ibool*  lru)    /*!< in: pointer to a variable that will be assigned
-+      ibool*  lru,    /*!< in: pointer to a variable that will be assigned
-                       TRUE if storage was allocated from the LRU list
-                       and buf_pool->mutex was temporarily released,
-                       or NULL if the LRU list should not be used */
-+      ibool   have_page_hash_mutex)
-       __attribute__((malloc));
+--- a/storage/innobase/include/buf0buddy.ic
++++ b/storage/innobase/include/buf0buddy.ic
+@@ -45,11 +45,12 @@
+       buf_pool_t*     buf_pool,       /*!< in/out: buffer pool instance */
+       ulint           i,              /*!< in: index of buf_pool->zip_free[],
+                                       or BUF_BUDDY_SIZES */
+-      ibool*          lru)            /*!< in: pointer to a variable that
++      ibool*          lru,            /*!< in: pointer to a variable that
+                                       will be assigned TRUE if storage was
+                                       allocated from the LRU list and
+                                       buf_pool->mutex was temporarily
+                                       released */
++      ibool           have_page_hash_mutex)
+       __attribute__((malloc, nonnull));
  
  /**********************************************************************//**
 @@ -61,8 +62,9 @@
@@ -3390,45 +3228,51 @@ diff -ruN a/storage/innobase/include/buf0buddy.ic b/storage/innobase/include/buf
        __attribute__((nonnull));
  
  /**********************************************************************//**
-@@ -102,16 +104,17 @@
-                                       the page resides */
-       ulint           size,           /*!< in: block size, up to
-                                       UNIV_PAGE_SIZE */
+@@ -101,19 +103,20 @@
+       ulint           size,           /*!< in: compressed page size
+                                       (between PAGE_ZIP_MIN_SIZE and
+                                       UNIV_PAGE_SIZE) */
 -      ibool*          lru)            /*!< in: pointer to a variable
 +      ibool*          lru,            /*!< in: pointer to a variable
                                        that will be assigned TRUE if
                                        storage was allocated from the
                                        LRU list and buf_pool->mutex was
-                                       temporarily released, or NULL if
-                                       the LRU list should not be used */
+                                       temporarily released */
 +      ibool           have_page_hash_mutex)
  {
 -      ut_ad(buf_pool_mutex_own(buf_pool));
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
+       ut_ad(ut_is_2pow(size));
+       ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+       ut_ad(size <= UNIV_PAGE_SIZE);
  
--      return(buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru));
-+      return(buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru, have_page_hash_mutex));
+       return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size),
+-                                         lru));
++                                         lru, have_page_hash_mutex));
  }
  
  /**********************************************************************//**
-@@ -123,12 +126,25 @@
-       buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
-       void*           buf,            /*!< in: block to be freed, must not be
-                                       pointed to by the buffer pool */
--      ulint           size)           /*!< in: block size, up to
-+      ulint           size,           /*!< in: block size, up to
-                                       UNIV_PAGE_SIZE */
+@@ -126,15 +129,28 @@
+                                       the block resides */
+       void*           buf,            /*!< in: block to be freed, must not
+                                       be pointed to by the buffer pool */
+-      ulint           size)           /*!< in: block size,
++      ulint           size,           /*!< in: block size,
+                                       up to UNIV_PAGE_SIZE */
 +      ibool           have_page_hash_mutex)
  {
 -      ut_ad(buf_pool_mutex_own(buf_pool));
 +      //ut_ad(buf_pool_mutex_own(buf_pool));
-+
+       ut_ad(ut_is_2pow(size));
+       ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+       ut_ad(size <= UNIV_PAGE_SIZE);
+-      buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size));
 +      if (!have_page_hash_mutex) {
 +              mutex_enter(&buf_pool->LRU_list_mutex);
 +              rw_lock_x_lock(&buf_pool->page_hash_latch);
 +      }
--      buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size));
++
 +      mutex_enter(&buf_pool->zip_free_mutex);
 +      buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size), TRUE);
 +      mutex_exit(&buf_pool->zip_free_mutex);
@@ -3440,10 +3284,9 @@ diff -ruN a/storage/innobase/include/buf0buddy.ic b/storage/innobase/include/buf
  }
  
  #ifdef UNIV_MATERIALIZE
-diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
---- a/storage/innobase/include/buf0buf.h       2010-12-03 15:22:36.327954660 +0900
-+++ b/storage/innobase/include/buf0buf.h       2010-12-03 15:48:29.343024683 +0900
-@@ -203,6 +203,20 @@
+--- a/storage/innobase/include/buf0buf.h
++++ b/storage/innobase/include/buf0buf.h
+@@ -212,6 +212,20 @@
  /*==========================*/
  
  /********************************************************************//**
@@ -3464,7 +3307,7 @@ diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0bu
  Creates the buffer pool.
  @return       own: buf_pool object, NULL if not enough memory or error */
  UNIV_INTERN
-@@ -832,6 +846,15 @@
+@@ -851,6 +865,15 @@
        const buf_page_t*       bpage)  /*!< in: pointer to control block */
        __attribute__((pure));
  
@@ -3480,7 +3323,7 @@ diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0bu
  /*********************************************************************//**
  Get the flush type of a page.
  @return       flush type */
-@@ -1313,7 +1336,7 @@
+@@ -1352,7 +1375,7 @@
        All these are protected by buf_pool->mutex. */
        /* @{ */
  
@@ -3489,7 +3332,7 @@ diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0bu
                                        /*!< based on state, this is a
                                        list node, protected either by
                                        buf_pool->mutex or by
-@@ -1341,6 +1364,10 @@
+@@ -1380,6 +1403,10 @@
                                        BUF_BLOCK_REMOVE_HASH or
                                        BUF_BLOCK_READY_IN_USE. */
  
@@ -3500,7 +3343,7 @@ diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0bu
  #ifdef UNIV_DEBUG
        ibool           in_flush_list;  /*!< TRUE if in buf_pool->flush_list;
                                        when buf_pool->flush_list_mutex is
-@@ -1433,11 +1460,11 @@
+@@ -1472,11 +1499,11 @@
                                        a block is in the unzip_LRU list
                                        if page.state == BUF_BLOCK_FILE_PAGE
                                        and page.zip.data != NULL */
@@ -3514,7 +3357,7 @@ diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0bu
        mutex_t         mutex;          /*!< mutex protecting this block:
                                        state (also protected by the buffer
                                        pool mutex), io_fix, buf_fix_count,
-@@ -1612,6 +1639,11 @@
+@@ -1656,6 +1683,11 @@
                                        pool instance, protects compressed
                                        only pages (of type buf_page_t, not
                                        buf_block_t */
@@ -3526,10 +3369,19 @@ diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0bu
        ulint           instance_no;    /*!< Array index of this buffer
                                        pool instance */
        ulint           old_pool_size;  /*!< Old pool size in bytes */
-diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
---- a/storage/innobase/include/buf0buf.ic      2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/buf0buf.ic      2010-12-03 15:48:29.345024524 +0900
-@@ -274,7 +274,7 @@
+@@ -1809,8 +1841,8 @@
+ /** Test if a buffer pool mutex is owned. */
+ #define buf_pool_mutex_own(b) mutex_own(&b->mutex)
+ /** Acquire a buffer pool mutex. */
++/* the buf_pool_mutex is changed the latch order */
+ #define buf_pool_mutex_enter(b) do {          \
+-      ut_ad(!mutex_own(&b->zip_mutex));       \
+       mutex_enter(&b->mutex);         \
+ } while (0)
+--- a/storage/innobase/include/buf0buf.ic
++++ b/storage/innobase/include/buf0buf.ic
+@@ -292,7 +292,7 @@
        case BUF_BLOCK_ZIP_FREE:
                /* This is a free page in buf_pool->zip_free[].
                Such pages should only be accessed by the buddy allocator. */
@@ -3538,11 +3390,13 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
                break;
        case BUF_BLOCK_ZIP_PAGE:
        case BUF_BLOCK_ZIP_DIRTY:
-@@ -317,9 +317,14 @@
+@@ -335,9 +335,16 @@
  {
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
  
-+      if (buf_pool_watch_is_sentinel(buf_pool, bpage)) {
++      if (/*equivalent to buf_pool_watch_is_sentinel(buf_pool, bpage)*/
++          bpage >= &buf_pool->watch[0]
++          && bpage < &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
 +              /* TODO: this code is the interim. should be confirmed later. */
 +              return(&buf_pool->zip_mutex);
 +      }
@@ -3554,7 +3408,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
                return(NULL);
        case BUF_BLOCK_ZIP_PAGE:
        case BUF_BLOCK_ZIP_DIRTY:
-@@ -329,6 +334,28 @@
+@@ -347,6 +354,28 @@
        }
  }
  
@@ -3583,7 +3437,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
  /*********************************************************************//**
  Get the flush type of a page.
  @return       flush type */
-@@ -425,8 +452,8 @@
+@@ -444,8 +473,8 @@
        enum buf_io_fix io_fix) /*!< in: io_fix state */
  {
  #ifdef UNIV_DEBUG
@@ -3594,7 +3448,25 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
  #endif
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
  
-@@ -456,14 +483,14 @@
+@@ -482,7 +511,7 @@
+ {
+ #ifdef UNIV_DEBUG
+       buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
+-      ut_ad(buf_pool_mutex_own(buf_pool));
++      ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
+ #endif
+       ut_ad(mutex_own(buf_page_get_mutex(bpage)));
+       ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
+@@ -500,7 +529,7 @@
+ {
+ #ifdef UNIV_DEBUG
+       buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
+-      ut_ad(buf_pool_mutex_own(buf_pool));
++      ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
+ #endif
+       ut_ad(mutex_own(buf_page_get_mutex(bpage)));
+       ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN);
+@@ -518,14 +547,14 @@
        const buf_page_t*       bpage)  /*!< control block being relocated */
  {
  #ifdef UNIV_DEBUG
@@ -3613,7 +3485,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
               && bpage->buf_fix_count == 0);
  }
  
-@@ -477,8 +504,8 @@
+@@ -539,8 +568,8 @@
        const buf_page_t*       bpage)  /*!< in: control block */
  {
  #ifdef UNIV_DEBUG
@@ -3624,7 +3496,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
  #endif
        ut_ad(buf_page_in_file(bpage));
  
-@@ -498,7 +525,8 @@
+@@ -560,7 +589,8 @@
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
  #endif /* UNIV_DEBUG */
        ut_a(buf_page_in_file(bpage));
@@ -3634,7 +3506,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
        ut_ad(bpage->in_LRU_list);
  
  #ifdef UNIV_LRU_DEBUG
-@@ -545,9 +573,10 @@
+@@ -607,9 +637,10 @@
        ulint           time_ms)        /*!< in: ut_time_ms() */
  {
  #ifdef UNIV_DEBUG
@@ -3647,7 +3519,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
        ut_a(buf_page_in_file(bpage));
  
        if (!bpage->access_time) {
-@@ -761,19 +790,19 @@
+@@ -852,19 +883,19 @@
  /*===========*/
        buf_block_t*    block)  /*!< in, own: block to be freed */
  {
@@ -3671,7 +3543,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
  }
  #endif /* !UNIV_HOTBACKUP */
  
-@@ -821,17 +850,17 @@
+@@ -912,17 +943,17 @@
                                        page frame */
  {
        ib_uint64_t     lsn;
@@ -3694,7 +3566,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
  
        return(lsn);
  }
-@@ -849,7 +878,7 @@
+@@ -940,7 +971,7 @@
  #ifdef UNIV_SYNC_DEBUG
        buf_pool_t*     buf_pool = buf_pool_from_bpage((buf_page_t*)block);
  
@@ -3703,7 +3575,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
               && (block->page.buf_fix_count == 0))
              || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
  #endif /* UNIV_SYNC_DEBUG */
-@@ -979,7 +1008,11 @@
+@@ -1070,7 +1101,11 @@
        buf_page_t*     bpage;
  
        ut_ad(buf_pool);
@@ -3716,7 +3588,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
        ut_ad(fold == buf_page_address_fold(space, offset));
  
        /* Look for the page in the hash table */
-@@ -1064,11 +1097,13 @@
+@@ -1155,11 +1190,13 @@
        const buf_page_t*       bpage;
        buf_pool_t*             buf_pool = buf_pool_get(space, offset);
  
@@ -3732,7 +3604,7 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
  
        return(bpage != NULL);
  }
-@@ -1196,4 +1231,38 @@
+@@ -1287,4 +1324,38 @@
                buf_pool_mutex_exit(buf_pool);
        }
  }
@@ -3771,23 +3643,20 @@ diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0b
 +      }
 +}
  #endif /* !UNIV_HOTBACKUP */
-diff -ruN a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h
---- a/storage/innobase/include/buf0lru.h       2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/buf0lru.h       2010-12-03 15:48:29.349024701 +0900
-@@ -113,10 +113,11 @@
+--- a/storage/innobase/include/buf0lru.h
++++ b/storage/innobase/include/buf0lru.h
+@@ -100,8 +100,9 @@
+ buf_LRU_free_block(
+ /*===============*/
        buf_page_t*     bpage,  /*!< in: block to be freed */
-       ibool           zip,    /*!< in: TRUE if should remove also the
+-      ibool           zip)    /*!< in: TRUE if should remove also the
++      ibool           zip,    /*!< in: TRUE if should remove also the
                                compressed page of an uncompressed page */
--      ibool*          buf_pool_mutex_released);
-+      ibool*          buf_pool_mutex_released,
-                               /*!< in: pointer to a variable that will
-                               be assigned TRUE if buf_pool->mutex
-                               was temporarily released, or NULL */
-+      ibool           have_LRU_mutex);
++      ibool           have_LRU_mutex)
+       __attribute__((nonnull));
  /******************************************************************//**
  Try to free a replaceable block.
- @return       TRUE if found and freed */
-@@ -163,7 +164,8 @@
+@@ -148,7 +149,8 @@
  void
  buf_LRU_block_free_non_file_page(
  /*=============================*/
@@ -3797,9 +3666,8 @@ diff -ruN a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lr
  /******************************************************************//**
  Adds a block to the LRU list. */
  UNIV_INTERN
-diff -ruN a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
---- a/storage/innobase/include/sync0rw.h       2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/sync0rw.h       2010-12-03 15:48:29.349942993 +0900
+--- a/storage/innobase/include/sync0rw.h
++++ b/storage/innobase/include/sync0rw.h
 @@ -112,6 +112,7 @@
  extern        mysql_pfs_key_t archive_lock_key;
  # endif /* UNIV_LOG_ARCHIVE */
@@ -3808,9 +3676,8 @@ diff -ruN a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0r
  extern        mysql_pfs_key_t buf_block_lock_key;
  # ifdef UNIV_SYNC_DEBUG
  extern        mysql_pfs_key_t buf_block_debug_latch_key;
-diff -ruN a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
---- a/storage/innobase/include/sync0sync.h     2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/sync0sync.h     2010-12-03 15:48:29.352024614 +0900
+--- a/storage/innobase/include/sync0sync.h
++++ b/storage/innobase/include/sync0sync.h
 @@ -75,6 +75,10 @@
  extern mysql_pfs_key_t        buffer_block_mutex_key;
  extern mysql_pfs_key_t        buf_pool_mutex_key;
@@ -3822,16 +3689,16 @@ diff -ruN a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync
  extern mysql_pfs_key_t        cache_last_read_mutex_key;
  extern mysql_pfs_key_t        dict_foreign_err_mutex_key;
  extern mysql_pfs_key_t        dict_sys_mutex_key;
-@@ -660,7 +664,7 @@
- #define       SYNC_TRX_LOCK_HEAP      298
+@@ -667,7 +671,7 @@
  #define SYNC_TRX_SYS_HEADER   290
+ #define       SYNC_PURGE_QUEUE        200
  #define SYNC_LOG              170
 -#define SYNC_LOG_FLUSH_ORDER  147
 +#define SYNC_LOG_FLUSH_ORDER  156
  #define SYNC_RECV             168
  #define       SYNC_WORK_QUEUE         162
- #define       SYNC_SEARCH_SYS_CONF    161     /* for assigning btr_search_enabled */
-@@ -670,8 +674,13 @@
+ #define       SYNC_SEARCH_SYS         160     /* NOTE that if we have a memory
+@@ -676,8 +680,13 @@
                                        SYNC_SEARCH_SYS, as memory allocation
                                        can call routines there! Otherwise
                                        the level is SYNC_MEM_HASH. */
@@ -3846,7 +3713,7 @@ diff -ruN a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync
  #define       SYNC_BUF_FLUSH_LIST     145     /* Buffer flush list mutex */
  #define SYNC_DOUBLEWRITE      140
  #define       SYNC_ANY_LATCH          135
-@@ -703,7 +712,7 @@
+@@ -708,7 +717,7 @@
                os_fast_mutex;  /*!< We use this OS mutex in place of lock_word
                                when atomic operations are not enabled */
  #endif
@@ -3855,10 +3722,9 @@ diff -ruN a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync
                                may be) threads waiting in the global wait
                                array for this mutex to be released.
                                Otherwise, this is 0. */
-diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
---- a/storage/innobase/srv/srv0srv.c   2010-12-03 15:48:03.080956216 +0900
-+++ b/storage/innobase/srv/srv0srv.c   2010-12-03 15:48:29.355023766 +0900
-@@ -3094,7 +3094,7 @@
+--- a/storage/innobase/srv/srv0srv.c
++++ b/storage/innobase/srv/srv0srv.c
+@@ -3105,7 +3105,7 @@
                                                                level += log_sys->max_checkpoint_age
                                                                         - (lsn - oldest_modification);
                                                        }
@@ -3867,7 +3733,7 @@ diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
                                                        n_blocks++;
                                                }
  
-@@ -3180,7 +3180,7 @@
+@@ -3191,7 +3191,7 @@
                                                        found = TRUE;
                                                        break;
                                                }
@@ -3876,10 +3742,9 @@ diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
                                                new_blocks_num++;
                                        }
                                        if (!found) {
-diff -ruN a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c
---- a/storage/innobase/sync/sync0sync.c        2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/sync/sync0sync.c        2010-12-03 15:48:29.358023890 +0900
-@@ -265,7 +265,7 @@
+--- a/storage/innobase/sync/sync0sync.c
++++ b/storage/innobase/sync/sync0sync.c
+@@ -285,7 +285,7 @@
        mutex->lock_word = 0;
  #endif
        mutex->event = os_event_create(NULL);
@@ -3888,7 +3753,7 @@ diff -ruN a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.
  #ifdef UNIV_DEBUG
        mutex->magic_n = MUTEX_MAGIC_N;
  #endif /* UNIV_DEBUG */
-@@ -444,6 +444,15 @@
+@@ -464,6 +464,15 @@
        mutex_t*        mutex,  /*!< in: mutex */
        ulint           n)      /*!< in: value to set */
  {
@@ -3904,7 +3769,7 @@ diff -ruN a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.
        volatile ulint* ptr;            /* declared volatile to ensure that
                                        the value is stored to memory */
        ut_ad(mutex);
-@@ -452,6 +461,7 @@
+@@ -472,6 +481,7 @@
  
        *ptr = n;               /* Here we assume that the write of a single
                                word in memory is atomic */
@@ -3912,7 +3777,7 @@ diff -ruN a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.
  }
  
  /******************************************************************//**
-@@ -1193,7 +1203,12 @@
+@@ -1233,7 +1243,12 @@
                        ut_error;
                }
                break;
@@ -3925,7 +3790,7 @@ diff -ruN a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.
        case SYNC_BUF_POOL:
                /* We can have multiple mutexes of this type therefore we
                can only check whether the greater than condition holds. */
-@@ -1211,7 +1226,8 @@
+@@ -1251,7 +1266,8 @@
                buffer block (block->mutex or buf_pool->zip_mutex). */
                if (!sync_thread_levels_g(array, level, FALSE)) {
                        ut_a(sync_thread_levels_g(array, level - 1, TRUE));
This page took 0.287142 seconds and 4 git commands to generate.