]> git.pld-linux.org Git - packages/mysql.git/blob - innodb_split_buf_pool_mutex.patch
- up to 5.5.17
[packages/mysql.git] / innodb_split_buf_pool_mutex.patch
1 # name       : innodb_split_buf_pool_mutex.patch
2 # introduced : 11 or before
3 # maintainer : Yasufumi
4 #
5 #!!! notice !!!
6 # Any small change to this file in the main branch
7 # should be done or reviewed by the maintainer!
8 --- a/storage/innobase/btr/btr0cur.c
9 +++ b/storage/innobase/btr/btr0cur.c
10 @@ -4091,7 +4091,8 @@
11  
12         mtr_commit(mtr);
13  
14 -       buf_pool_mutex_enter(buf_pool);
15 +       //buf_pool_mutex_enter(buf_pool);
16 +       mutex_enter(&buf_pool->LRU_list_mutex);
17         mutex_enter(&block->mutex);
18  
19         /* Only free the block if it is still allocated to
20 @@ -4102,16 +4103,21 @@
21             && buf_block_get_space(block) == space
22             && buf_block_get_page_no(block) == page_no) {
23  
24 -               if (!buf_LRU_free_block(&block->page, all)
25 -                   && all && block->page.zip.data) {
26 +               if (!buf_LRU_free_block(&block->page, all, TRUE)
27 +                   && all && block->page.zip.data
28 +                   /* Now, buf_LRU_free_block() may release mutex temporarily */
29 +                   && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
30 +                   && buf_block_get_space(block) == space
31 +                   && buf_block_get_page_no(block) == page_no) {
32                         /* Attempt to deallocate the uncompressed page
33                         if the whole block cannot be deallocted. */
34  
35 -                       buf_LRU_free_block(&block->page, FALSE);
36 +                       buf_LRU_free_block(&block->page, FALSE, TRUE);
37                 }
38         }
39  
40 -       buf_pool_mutex_exit(buf_pool);
41 +       //buf_pool_mutex_exit(buf_pool);
42 +       mutex_exit(&buf_pool->LRU_list_mutex);
43         mutex_exit(&block->mutex);
44  }
45  
46 --- a/storage/innobase/btr/btr0sea.c
47 +++ b/storage/innobase/btr/btr0sea.c
48 @@ -1944,7 +1944,7 @@
49         rec_offs_init(offsets_);
50  
51         rw_lock_x_lock(&btr_search_latch);
52 -       buf_pool_mutex_enter_all();
53 +       buf_pool_page_hash_x_lock_all();
54  
55         cell_count = hash_get_n_cells(btr_search_sys->hash_index);
56  
57 @@ -1952,11 +1952,11 @@
58                 /* We release btr_search_latch every once in a while to
59                 give other queries a chance to run. */
60                 if ((i != 0) && ((i % chunk_size) == 0)) {
61 -                       buf_pool_mutex_exit_all();
62 +                       buf_pool_page_hash_x_unlock_all();
63                         rw_lock_x_unlock(&btr_search_latch);
64                         os_thread_yield();
65                         rw_lock_x_lock(&btr_search_latch);
66 -                       buf_pool_mutex_enter_all();
67 +                       buf_pool_page_hash_x_lock_all();
68                 }
69  
70                 node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
71 @@ -2067,11 +2067,11 @@
72                 /* We release btr_search_latch every once in a while to
73                 give other queries a chance to run. */
74                 if (i != 0) {
75 -                       buf_pool_mutex_exit_all();
76 +                       buf_pool_page_hash_x_unlock_all();
77                         rw_lock_x_unlock(&btr_search_latch);
78                         os_thread_yield();
79                         rw_lock_x_lock(&btr_search_latch);
80 -                       buf_pool_mutex_enter_all();
81 +                       buf_pool_page_hash_x_lock_all();
82                 }
83  
84                 if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
85 @@ -2079,7 +2079,7 @@
86                 }
87         }
88  
89 -       buf_pool_mutex_exit_all();
90 +       buf_pool_page_hash_x_unlock_all();
91         rw_lock_x_unlock(&btr_search_latch);
92         if (UNIV_LIKELY_NULL(heap)) {
93                 mem_heap_free(heap);
94 --- a/storage/innobase/buf/buf0buddy.c
95 +++ b/storage/innobase/buf/buf0buddy.c
96 @@ -58,7 +58,7 @@
97  
98  /** Validate a given zip_free list. */
99  #define BUF_BUDDY_LIST_VALIDATE(b, i)                          \
100 -       UT_LIST_VALIDATE(list, buf_page_t,                      \
101 +       UT_LIST_VALIDATE(zip_list, buf_page_t,                  \
102                          b->zip_free[i],                        \
103                          ut_ad(buf_page_get_state(              \
104                                        ut_list_node_313)        \
105 @@ -75,10 +75,11 @@
106         ulint           i)              /*!< in: index of
107                                         buf_pool->zip_free[] */
108  {
109 -       ut_ad(buf_pool_mutex_own(buf_pool));
110 +       //ut_ad(buf_pool_mutex_own(buf_pool));
111 +       ut_ad(mutex_own(&buf_pool->zip_free_mutex));
112         ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
113         ut_ad(buf_pool->zip_free[i].start != bpage);
114 -       UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
115 +       UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_free[i], bpage);
116  }
117  
118  /**********************************************************************//**
119 @@ -93,16 +94,17 @@
120                                         buf_pool->zip_free[] */
121  {
122  #ifdef UNIV_DEBUG
123 -       buf_page_t*     prev = UT_LIST_GET_PREV(list, bpage);
124 -       buf_page_t*     next = UT_LIST_GET_NEXT(list, bpage);
125 +       buf_page_t*     prev = UT_LIST_GET_PREV(zip_list, bpage);
126 +       buf_page_t*     next = UT_LIST_GET_NEXT(zip_list, bpage);
127  
128         ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE);
129         ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
130  #endif /* UNIV_DEBUG */
131  
132 -       ut_ad(buf_pool_mutex_own(buf_pool));
133 +       //ut_ad(buf_pool_mutex_own(buf_pool));
134 +       ut_ad(mutex_own(&buf_pool->zip_free_mutex));
135         ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
136 -       UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
137 +       UT_LIST_REMOVE(zip_list, buf_pool->zip_free[i], bpage);
138  }
139  
140  /**********************************************************************//**
141 @@ -117,7 +119,8 @@
142  {
143         buf_page_t*     bpage;
144  
145 -       ut_ad(buf_pool_mutex_own(buf_pool));
146 +       //ut_ad(buf_pool_mutex_own(buf_pool));
147 +       ut_ad(mutex_own(&buf_pool->zip_free_mutex));
148         ut_a(i < BUF_BUDDY_SIZES);
149         ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
150  
151 @@ -159,16 +162,19 @@
152  buf_buddy_block_free(
153  /*=================*/
154         buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
155 -       void*           buf)            /*!< in: buffer frame to deallocate */
156 +       void*           buf,            /*!< in: buffer frame to deallocate */
157 +       ibool           have_page_hash_mutex)
158  {
159         const ulint     fold    = BUF_POOL_ZIP_FOLD_PTR(buf);
160         buf_page_t*     bpage;
161         buf_block_t*    block;
162  
163 -       ut_ad(buf_pool_mutex_own(buf_pool));
164 +       //ut_ad(buf_pool_mutex_own(buf_pool));
165         ut_ad(!mutex_own(&buf_pool->zip_mutex));
166         ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE));
167  
168 +       mutex_enter(&buf_pool->zip_hash_mutex);
169 +
170         HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
171                     ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY
172                           && bpage->in_zip_hash && !bpage->in_page_hash),
173 @@ -180,12 +186,14 @@
174         ut_d(bpage->in_zip_hash = FALSE);
175         HASH_DELETE(buf_page_t, hash, buf_pool->zip_hash, fold, bpage);
176  
177 +       mutex_exit(&buf_pool->zip_hash_mutex);
178 +
179         ut_d(memset(buf, 0, UNIV_PAGE_SIZE));
180         UNIV_MEM_INVALID(buf, UNIV_PAGE_SIZE);
181  
182         block = (buf_block_t*) bpage;
183         mutex_enter(&block->mutex);
184 -       buf_LRU_block_free_non_file_page(block);
185 +       buf_LRU_block_free_non_file_page(block, have_page_hash_mutex);
186         mutex_exit(&block->mutex);
187  
188         ut_ad(buf_pool->buddy_n_frames > 0);
189 @@ -202,7 +210,7 @@
190  {
191         buf_pool_t*     buf_pool = buf_pool_from_block(block);
192         const ulint     fold = BUF_POOL_ZIP_FOLD(block);
193 -       ut_ad(buf_pool_mutex_own(buf_pool));
194 +       //ut_ad(buf_pool_mutex_own(buf_pool));
195         ut_ad(!mutex_own(&buf_pool->zip_mutex));
196         ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE);
197  
198 @@ -214,7 +222,10 @@
199         ut_ad(!block->page.in_page_hash);
200         ut_ad(!block->page.in_zip_hash);
201         ut_d(block->page.in_zip_hash = TRUE);
202 +
203 +       mutex_enter(&buf_pool->zip_hash_mutex);
204         HASH_INSERT(buf_page_t, hash, buf_pool->zip_hash, fold, &block->page);
205 +       mutex_exit(&buf_pool->zip_hash_mutex);
206  
207         ut_d(buf_pool->buddy_n_frames++);
208  }
209 @@ -268,26 +279,30 @@
210         buf_pool_t*     buf_pool,       /*!< in/out: buffer pool instance */
211         ulint           i,              /*!< in: index of buf_pool->zip_free[],
212                                         or BUF_BUDDY_SIZES */
213 -       ibool*          lru)            /*!< in: pointer to a variable that
214 +       ibool*          lru,            /*!< in: pointer to a variable that
215                                         will be assigned TRUE if storage was
216                                         allocated from the LRU list and
217                                         buf_pool->mutex was temporarily
218                                         released */
219 +       ibool           have_page_hash_mutex)
220  {
221         buf_block_t*    block;
222  
223         ut_ad(lru);
224 -       ut_ad(buf_pool_mutex_own(buf_pool));
225 +       //ut_ad(buf_pool_mutex_own(buf_pool));
226 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
227         ut_ad(!mutex_own(&buf_pool->zip_mutex));
228         ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
229  
230         if (i < BUF_BUDDY_SIZES) {
231                 /* Try to allocate from the buddy system. */
232 +               mutex_enter(&buf_pool->zip_free_mutex);
233                 block = buf_buddy_alloc_zip(buf_pool, i);
234  
235                 if (block) {
236                         goto func_exit;
237                 }
238 +               mutex_exit(&buf_pool->zip_free_mutex);
239         }
240  
241         /* Try allocating from the buf_pool->free list. */
242 @@ -299,19 +314,30 @@
243         }
244  
245         /* Try replacing an uncompressed page in the buffer pool. */
246 -       buf_pool_mutex_exit(buf_pool);
247 +       //buf_pool_mutex_exit(buf_pool);
248 +       mutex_exit(&buf_pool->LRU_list_mutex);
249 +       if (have_page_hash_mutex) {
250 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
251 +       }
252         block = buf_LRU_get_free_block(buf_pool);
253         *lru = TRUE;
254 -       buf_pool_mutex_enter(buf_pool);
255 +       //buf_pool_mutex_enter(buf_pool);
256 +       mutex_enter(&buf_pool->LRU_list_mutex);
257 +       if (have_page_hash_mutex) {
258 +               rw_lock_x_lock(&buf_pool->page_hash_latch);
259 +       }
260  
261  alloc_big:
262         buf_buddy_block_register(block);
263  
264 +       mutex_enter(&buf_pool->zip_free_mutex);
265         block = buf_buddy_alloc_from(
266                 buf_pool, block->frame, i, BUF_BUDDY_SIZES);
267  
268  func_exit:
269         buf_pool->buddy_stat[i].used++;
270 +       mutex_exit(&buf_pool->zip_free_mutex);
271 +
272         return(block);
273  }
274  
275 @@ -325,8 +351,9 @@
276         buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
277         void*           src,            /*!< in: block to relocate */
278         void*           dst,            /*!< in: free block to relocate to */
279 -       ulint           i)              /*!< in: index of
280 +       ulint           i,              /*!< in: index of
281                                         buf_pool->zip_free[] */
282 +       ibool           have_page_hash_mutex)
283  {
284         buf_page_t*     bpage;
285         const ulint     size    = BUF_BUDDY_LOW << i;
286 @@ -334,13 +361,20 @@
287         ulint           space;
288         ulint           page_no;
289  
290 -       ut_ad(buf_pool_mutex_own(buf_pool));
291 +       //ut_ad(buf_pool_mutex_own(buf_pool));
292 +       ut_ad(mutex_own(&buf_pool->zip_free_mutex));
293         ut_ad(!mutex_own(&buf_pool->zip_mutex));
294         ut_ad(!ut_align_offset(src, size));
295         ut_ad(!ut_align_offset(dst, size));
296         ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
297         UNIV_MEM_ASSERT_W(dst, size);
298  
299 +       if (!have_page_hash_mutex) {
300 +               mutex_exit(&buf_pool->zip_free_mutex);
301 +               mutex_enter(&buf_pool->LRU_list_mutex);
302 +               rw_lock_x_lock(&buf_pool->page_hash_latch);
303 +       }
304 +
305         /* We assume that all memory from buf_buddy_alloc()
306         is used for compressed page frames. */
307  
308 @@ -374,6 +408,11 @@
309                 added to buf_pool->page_hash yet.  Obviously,
310                 it cannot be relocated. */
311  
312 +               if (!have_page_hash_mutex) {
313 +                       mutex_enter(&buf_pool->zip_free_mutex);
314 +                       mutex_exit(&buf_pool->LRU_list_mutex);
315 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
316 +               }
317                 return(FALSE);
318         }
319  
320 @@ -383,18 +422,27 @@
321                 For the sake of simplicity, give up. */
322                 ut_ad(page_zip_get_size(&bpage->zip) < size);
323  
324 +               if (!have_page_hash_mutex) {
325 +                       mutex_enter(&buf_pool->zip_free_mutex);
326 +                       mutex_exit(&buf_pool->LRU_list_mutex);
327 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
328 +               }
329                 return(FALSE);
330         }
331  
332 +       /* To keep latch order */
333 +       if (have_page_hash_mutex)
334 +               mutex_exit(&buf_pool->zip_free_mutex);
335 +
336         /* The block must have been allocated, but it may
337         contain uninitialized data. */
338         UNIV_MEM_ASSERT_W(src, size);
339  
340 -       mutex = buf_page_get_mutex(bpage);
341 +       mutex = buf_page_get_mutex_enter(bpage);
342  
343 -       mutex_enter(mutex);
344 +       mutex_enter(&buf_pool->zip_free_mutex);
345  
346 -       if (buf_page_can_relocate(bpage)) {
347 +       if (mutex && buf_page_can_relocate(bpage)) {
348                 /* Relocate the compressed page. */
349                 ullint  usec    = ut_time_us(NULL);
350                 ut_a(bpage->zip.data == src);
351 @@ -409,10 +457,22 @@
352                         buddy_stat->relocated_usec
353                                 += ut_time_us(NULL) - usec;
354                 }
355 +
356 +               if (!have_page_hash_mutex) {
357 +                       mutex_exit(&buf_pool->LRU_list_mutex);
358 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
359 +               }
360                 return(TRUE);
361         }
362  
363 -       mutex_exit(mutex);
364 +       if (!have_page_hash_mutex) {
365 +               mutex_exit(&buf_pool->LRU_list_mutex);
366 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
367 +       }
368 +
369 +       if (mutex) {
370 +               mutex_exit(mutex);
371 +       }
372         return(FALSE);
373  }
374  
375 @@ -425,13 +485,15 @@
376         buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
377         void*           buf,            /*!< in: block to be freed, must not be
378                                         pointed to by the buffer pool */
379 -       ulint           i)              /*!< in: index of buf_pool->zip_free[],
380 +       ulint           i,              /*!< in: index of buf_pool->zip_free[],
381                                         or BUF_BUDDY_SIZES */
382 +       ibool           have_page_hash_mutex)
383  {
384         buf_page_t*     bpage;
385         buf_page_t*     buddy;
386  
387 -       ut_ad(buf_pool_mutex_own(buf_pool));
388 +       //ut_ad(buf_pool_mutex_own(buf_pool));
389 +       ut_ad(mutex_own(&buf_pool->zip_free_mutex));
390         ut_ad(!mutex_own(&buf_pool->zip_mutex));
391         ut_ad(i <= BUF_BUDDY_SIZES);
392         ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
393 @@ -443,7 +505,9 @@
394         ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE;
395  
396         if (i == BUF_BUDDY_SIZES) {
397 -               buf_buddy_block_free(buf_pool, buf);
398 +               mutex_exit(&buf_pool->zip_free_mutex);
399 +               buf_buddy_block_free(buf_pool, buf, have_page_hash_mutex);
400 +               mutex_enter(&buf_pool->zip_free_mutex);
401                 return;
402         }
403  
404 @@ -491,7 +555,7 @@
405  
406                 ut_a(bpage != buf);
407                 UNIV_MEM_ASSERT_W(bpage, BUF_BUDDY_LOW << i);
408 -               bpage = UT_LIST_GET_NEXT(list, bpage);
409 +               bpage = UT_LIST_GET_NEXT(zip_list, bpage);
410         }
411  
412  #ifndef UNIV_DEBUG_VALGRIND
413 @@ -501,7 +565,7 @@
414         ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
415  
416         /* The buddy is not free. Is there a free block of this size? */
417 -       bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
418 +       bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
419  
420         if (bpage) {
421  
422 @@ -510,7 +574,7 @@
423                 buf_buddy_remove_from_free(buf_pool, bpage, i);
424  
425                 /* Try to relocate the buddy of buf to the free block. */
426 -               if (buf_buddy_relocate(buf_pool, buddy, bpage, i)) {
427 +               if (buf_buddy_relocate(buf_pool, buddy, bpage, i, have_page_hash_mutex)) {
428  
429                         buddy->state = BUF_BLOCK_ZIP_FREE;
430                         goto buddy_is_free;
431 --- a/storage/innobase/buf/buf0buf.c
432 +++ b/storage/innobase/buf/buf0buf.c
433 @@ -263,6 +263,7 @@
434  #ifdef UNIV_PFS_RWLOCK
435  /* Keys to register buffer block related rwlocks and mutexes with
436  performance schema */
437 +UNIV_INTERN mysql_pfs_key_t    buf_pool_page_hash_key;
438  UNIV_INTERN mysql_pfs_key_t    buf_block_lock_key;
439  # ifdef UNIV_SYNC_DEBUG
440  UNIV_INTERN mysql_pfs_key_t    buf_block_debug_latch_key;
441 @@ -273,6 +274,10 @@
442  UNIV_INTERN mysql_pfs_key_t    buffer_block_mutex_key;
443  UNIV_INTERN mysql_pfs_key_t    buf_pool_mutex_key;
444  UNIV_INTERN mysql_pfs_key_t    buf_pool_zip_mutex_key;
445 +UNIV_INTERN mysql_pfs_key_t    buf_pool_LRU_list_mutex_key;
446 +UNIV_INTERN mysql_pfs_key_t    buf_pool_free_list_mutex_key;
447 +UNIV_INTERN mysql_pfs_key_t    buf_pool_zip_free_mutex_key;
448 +UNIV_INTERN mysql_pfs_key_t    buf_pool_zip_hash_mutex_key;
449  UNIV_INTERN mysql_pfs_key_t    flush_list_mutex_key;
450  #endif /* UNIV_PFS_MUTEX */
451  
452 @@ -882,9 +887,13 @@
453         block->page.in_zip_hash = FALSE;
454         block->page.in_flush_list = FALSE;
455         block->page.in_free_list = FALSE;
456 -       block->in_unzip_LRU_list = FALSE;
457  #endif /* UNIV_DEBUG */
458 +       block->page.flush_list.prev = NULL;
459 +       block->page.flush_list.next = NULL;
460 +       block->page.zip_list.prev = NULL;
461 +       block->page.zip_list.next = NULL;
462         block->page.in_LRU_list = FALSE;
463 +       block->in_unzip_LRU_list = FALSE;
464  #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
465         block->n_pointers = 0;
466  #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
467 @@ -982,9 +991,11 @@
468                 memset(block->frame, '\0', UNIV_PAGE_SIZE);
469  #endif
470                 /* Add the block to the free list */
471 -               UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
472 +               mutex_enter(&buf_pool->free_list_mutex);
473 +               UT_LIST_ADD_LAST(free, buf_pool->free, (&block->page));
474  
475                 ut_d(block->page.in_free_list = TRUE);
476 +               mutex_exit(&buf_pool->free_list_mutex);
477                 ut_ad(buf_pool_from_block(block) == buf_pool);
478  
479                 block++;
480 @@ -1039,7 +1050,8 @@
481         buf_chunk_t*    chunk = buf_pool->chunks;
482  
483         ut_ad(buf_pool);
484 -       ut_ad(buf_pool_mutex_own(buf_pool));
485 +       //ut_ad(buf_pool_mutex_own(buf_pool));
486 +       ut_ad(mutex_own(&buf_pool->zip_free_mutex));
487         for (n = buf_pool->n_chunks; n--; chunk++) {
488  
489                 buf_block_t* block = buf_chunk_contains_zip(chunk, data);
490 @@ -1145,9 +1157,21 @@
491         ------------------------------- */
492         mutex_create(buf_pool_mutex_key,
493                      &buf_pool->mutex, SYNC_BUF_POOL);
494 +       mutex_create(buf_pool_LRU_list_mutex_key,
495 +                    &buf_pool->LRU_list_mutex, SYNC_BUF_LRU_LIST);
496 +       rw_lock_create(buf_pool_page_hash_key,
497 +                      &buf_pool->page_hash_latch, SYNC_BUF_PAGE_HASH);
498 +       mutex_create(buf_pool_free_list_mutex_key,
499 +                    &buf_pool->free_list_mutex, SYNC_BUF_FREE_LIST);
500 +       mutex_create(buf_pool_zip_free_mutex_key,
501 +                    &buf_pool->zip_free_mutex, SYNC_BUF_ZIP_FREE);
502 +       mutex_create(buf_pool_zip_hash_mutex_key,
503 +                    &buf_pool->zip_hash_mutex, SYNC_BUF_ZIP_HASH);
504         mutex_create(buf_pool_zip_mutex_key,
505                      &buf_pool->zip_mutex, SYNC_BUF_BLOCK);
506  
507 +       mutex_enter(&buf_pool->LRU_list_mutex);
508 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
509         buf_pool_mutex_enter(buf_pool);
510  
511         if (buf_pool_size > 0) {
512 @@ -1160,6 +1184,8 @@
513                         mem_free(chunk);
514                         mem_free(buf_pool);
515  
516 +                       mutex_exit(&buf_pool->LRU_list_mutex);
517 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
518                         buf_pool_mutex_exit(buf_pool);
519  
520                         return(DB_ERROR);
521 @@ -1190,6 +1216,8 @@
522  
523         /* All fields are initialized by mem_zalloc(). */
524  
525 +       mutex_exit(&buf_pool->LRU_list_mutex);
526 +       rw_lock_x_unlock(&buf_pool->page_hash_latch);
527         buf_pool_mutex_exit(buf_pool);
528  
529         return(DB_SUCCESS);
530 @@ -1402,7 +1430,11 @@
531         ulint           fold;
532         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
533  
534 -       ut_ad(buf_pool_mutex_own(buf_pool));
535 +       //ut_ad(buf_pool_mutex_own(buf_pool));
536 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
537 +#ifdef UNIV_SYNC_DEBUG
538 +       ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
539 +#endif
540         ut_ad(mutex_own(buf_page_get_mutex(bpage)));
541         ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
542         ut_a(bpage->buf_fix_count == 0);
543 @@ -1513,21 +1545,32 @@
544         buf_page_t*     bpage;
545         ulint           i;
546         buf_pool_t*     buf_pool = buf_pool_get(space, offset);
547 +       mutex_t*        block_mutex;
548  
549 -       ut_ad(buf_pool_mutex_own(buf_pool));
550 +       //ut_ad(buf_pool_mutex_own(buf_pool));
551  
552 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
553         bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
554 +       if (bpage) {
555 +               block_mutex = buf_page_get_mutex_enter(bpage);
556 +               ut_a(block_mutex);
557 +       }
558  
559         if (UNIV_LIKELY_NULL(bpage)) {
560                 if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
561                         /* The page was loaded meanwhile. */
562 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
563                         return(bpage);
564                 }
565                 /* Add to an existing watch. */
566                 bpage->buf_fix_count++;
567 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
568 +               mutex_exit(block_mutex);
569                 return(NULL);
570         }
571  
572 +       /* buf_pool->watch is protected by zip_mutex for now */
573 +       mutex_enter(&buf_pool->zip_mutex);
574         for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
575                 bpage = &buf_pool->watch[i];
576  
577 @@ -1551,10 +1594,12 @@
578                         bpage->space = space;
579                         bpage->offset = offset;
580                         bpage->buf_fix_count = 1;
581 -
582 +                       bpage->buf_pool_index = buf_pool_index(buf_pool);
583                         ut_d(bpage->in_page_hash = TRUE);
584                         HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
585                                     fold, bpage);
586 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
587 +                       mutex_exit(&buf_pool->zip_mutex);
588                         return(NULL);
589                 case BUF_BLOCK_ZIP_PAGE:
590                         ut_ad(bpage->in_page_hash);
591 @@ -1572,6 +1617,8 @@
592         ut_error;
593  
594         /* Fix compiler warning */
595 +       rw_lock_x_unlock(&buf_pool->page_hash_latch);
596 +       mutex_exit(&buf_pool->zip_mutex);
597         return(NULL);
598  }
599  
600 @@ -1589,7 +1636,11 @@
601                                         space, offset) */
602         buf_page_t*     watch)          /*!< in/out: sentinel for watch */
603  {
604 -       ut_ad(buf_pool_mutex_own(buf_pool));
605 +       //ut_ad(buf_pool_mutex_own(buf_pool));
606 +#ifdef UNIV_SYNC_DEBUG
607 +       ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
608 +#endif
609 +       ut_ad(mutex_own(&buf_pool->zip_mutex)); /* for now */
610  
611         HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
612         ut_d(watch->in_page_hash = FALSE);
613 @@ -1611,28 +1662,31 @@
614         buf_pool_t*     buf_pool = buf_pool_get(space, offset);
615         ulint           fold = buf_page_address_fold(space, offset);
616  
617 -       buf_pool_mutex_enter(buf_pool);
618 +       //buf_pool_mutex_enter(buf_pool);
619 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
620         bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
621         /* The page must exist because buf_pool_watch_set()
622         increments buf_fix_count. */
623         ut_a(bpage);
624  
625         if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
626 -               mutex_t* mutex = buf_page_get_mutex(bpage);
627 +               mutex_t* mutex = buf_page_get_mutex_enter(bpage);
628  
629 -               mutex_enter(mutex);
630                 ut_a(bpage->buf_fix_count > 0);
631                 bpage->buf_fix_count--;
632                 mutex_exit(mutex);
633         } else {
634 +               mutex_enter(&buf_pool->zip_mutex);
635                 ut_a(bpage->buf_fix_count > 0);
636  
637                 if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
638                         buf_pool_watch_remove(buf_pool, fold, bpage);
639                 }
640 +               mutex_exit(&buf_pool->zip_mutex);
641         }
642  
643 -       buf_pool_mutex_exit(buf_pool);
644 +       //buf_pool_mutex_exit(buf_pool);
645 +       rw_lock_x_unlock(&buf_pool->page_hash_latch);
646  }
647  
648  /****************************************************************//**
649 @@ -1652,14 +1706,16 @@
650         buf_pool_t*     buf_pool = buf_pool_get(space, offset);
651         ulint           fold    = buf_page_address_fold(space, offset);
652  
653 -       buf_pool_mutex_enter(buf_pool);
654 +       //buf_pool_mutex_enter(buf_pool);
655 +       rw_lock_s_lock(&buf_pool->page_hash_latch);
656  
657         bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
658         /* The page must exist because buf_pool_watch_set()
659         increments buf_fix_count. */
660         ut_a(bpage);
661         ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
662 -       buf_pool_mutex_exit(buf_pool);
663 +       //buf_pool_mutex_exit(buf_pool);
664 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
665  
666         return(ret);
667  }
668 @@ -1676,13 +1732,15 @@
669  {
670         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
671  
672 -       buf_pool_mutex_enter(buf_pool);
673 +       //buf_pool_mutex_enter(buf_pool);
674 +       mutex_enter(&buf_pool->LRU_list_mutex);
675  
676         ut_a(buf_page_in_file(bpage));
677  
678         buf_LRU_make_block_young(bpage);
679  
680 -       buf_pool_mutex_exit(buf_pool);
681 +       //buf_pool_mutex_exit(buf_pool);
682 +       mutex_exit(&buf_pool->LRU_list_mutex);
683  }
684  
685  /********************************************************************//**
686 @@ -1706,14 +1764,20 @@
687         ut_a(buf_page_in_file(bpage));
688  
689         if (buf_page_peek_if_too_old(bpage)) {
690 -               buf_pool_mutex_enter(buf_pool);
691 +               //buf_pool_mutex_enter(buf_pool);
692 +               mutex_enter(&buf_pool->LRU_list_mutex);
693                 buf_LRU_make_block_young(bpage);
694 -               buf_pool_mutex_exit(buf_pool);
695 +               //buf_pool_mutex_exit(buf_pool);
696 +               mutex_exit(&buf_pool->LRU_list_mutex);
697         } else if (!access_time) {
698                 ulint   time_ms = ut_time_ms();
699 -               buf_pool_mutex_enter(buf_pool);
700 +               mutex_t*        block_mutex = buf_page_get_mutex_enter(bpage);
701 +               //buf_pool_mutex_enter(buf_pool);
702 +               if (block_mutex) {
703                 buf_page_set_accessed(bpage, time_ms);
704 -               buf_pool_mutex_exit(buf_pool);
705 +               mutex_exit(block_mutex);
706 +               }
707 +               //buf_pool_mutex_exit(buf_pool);
708         }
709  }
710  
711 @@ -1730,7 +1794,8 @@
712         buf_block_t*    block;
713         buf_pool_t*     buf_pool = buf_pool_get(space, offset);
714  
715 -       buf_pool_mutex_enter(buf_pool);
716 +       //buf_pool_mutex_enter(buf_pool);
717 +       rw_lock_s_lock(&buf_pool->page_hash_latch);
718  
719         block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
720  
721 @@ -1739,7 +1804,8 @@
722                 block->check_index_page_at_flush = FALSE;
723         }
724  
725 -       buf_pool_mutex_exit(buf_pool);
726 +       //buf_pool_mutex_exit(buf_pool);
727 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
728  }
729  
730  /********************************************************************//**
731 @@ -1758,7 +1824,8 @@
732         ibool           is_hashed;
733         buf_pool_t*     buf_pool = buf_pool_get(space, offset);
734  
735 -       buf_pool_mutex_enter(buf_pool);
736 +       //buf_pool_mutex_enter(buf_pool);
737 +       rw_lock_s_lock(&buf_pool->page_hash_latch);
738  
739         block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
740  
741 @@ -1769,7 +1836,8 @@
742                 is_hashed = block->is_hashed;
743         }
744  
745 -       buf_pool_mutex_exit(buf_pool);
746 +       //buf_pool_mutex_exit(buf_pool);
747 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
748  
749         return(is_hashed);
750  }
751 @@ -1791,7 +1859,8 @@
752         buf_page_t*     bpage;
753         buf_pool_t*     buf_pool = buf_pool_get(space, offset);
754  
755 -       buf_pool_mutex_enter(buf_pool);
756 +       //buf_pool_mutex_enter(buf_pool);
757 +       rw_lock_s_lock(&buf_pool->page_hash_latch);
758  
759         bpage = buf_page_hash_get(buf_pool, space, offset);
760  
761 @@ -1802,7 +1871,8 @@
762                 bpage->file_page_was_freed = TRUE;
763         }
764  
765 -       buf_pool_mutex_exit(buf_pool);
766 +       //buf_pool_mutex_exit(buf_pool);
767 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
768  
769         return(bpage);
770  }
771 @@ -1823,7 +1893,8 @@
772         buf_page_t*     bpage;
773         buf_pool_t*     buf_pool = buf_pool_get(space, offset);
774  
775 -       buf_pool_mutex_enter(buf_pool);
776 +       //buf_pool_mutex_enter(buf_pool);
777 +       rw_lock_s_lock(&buf_pool->page_hash_latch);
778  
779         bpage = buf_page_hash_get(buf_pool, space, offset);
780  
781 @@ -1832,7 +1903,8 @@
782                 bpage->file_page_was_freed = FALSE;
783         }
784  
785 -       buf_pool_mutex_exit(buf_pool);
786 +       //buf_pool_mutex_exit(buf_pool);
787 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
788  
789         return(bpage);
790  }
791 @@ -1864,8 +1936,9 @@
792         buf_pool->stat.n_page_gets++;
793  
794         for (;;) {
795 -               buf_pool_mutex_enter(buf_pool);
796 +               //buf_pool_mutex_enter(buf_pool);
797  lookup:
798 +               rw_lock_s_lock(&buf_pool->page_hash_latch);
799                 bpage = buf_page_hash_get(buf_pool, space, offset);
800                 if (bpage) {
801                         ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
802 @@ -1874,7 +1947,8 @@
803  
804                 /* Page not in buf_pool: needs to be read from file */
805  
806 -               buf_pool_mutex_exit(buf_pool);
807 +               //buf_pool_mutex_exit(buf_pool);
808 +               rw_lock_s_unlock(&buf_pool->page_hash_latch);
809  
810                 buf_read_page(space, zip_size, offset);
811  
812 @@ -1886,10 +1960,15 @@
813         if (UNIV_UNLIKELY(!bpage->zip.data)) {
814                 /* There is no compressed page. */
815  err_exit:
816 -               buf_pool_mutex_exit(buf_pool);
817 +               //buf_pool_mutex_exit(buf_pool);
818 +               rw_lock_s_unlock(&buf_pool->page_hash_latch);
819                 return(NULL);
820         }
821  
822 +       block_mutex = buf_page_get_mutex_enter(bpage);
823 +
824 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
825 +
826         ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
827  
828         switch (buf_page_get_state(bpage)) {
829 @@ -1898,24 +1977,43 @@
830         case BUF_BLOCK_MEMORY:
831         case BUF_BLOCK_REMOVE_HASH:
832         case BUF_BLOCK_ZIP_FREE:
833 +               if (block_mutex)
834 +                       mutex_exit(block_mutex);
835                 break;
836         case BUF_BLOCK_ZIP_PAGE:
837         case BUF_BLOCK_ZIP_DIRTY:
838 -               block_mutex = &buf_pool->zip_mutex;
839 -               mutex_enter(block_mutex);
840 +               ut_a(block_mutex == &buf_pool->zip_mutex);
841                 bpage->buf_fix_count++;
842                 goto got_block;
843         case BUF_BLOCK_FILE_PAGE:
844 -               block_mutex = &((buf_block_t*) bpage)->mutex;
845 +               ut_a(block_mutex == &((buf_block_t*) bpage)->mutex);
846 +
847 +               /* release mutex to obey to latch-order */
848 +               mutex_exit(block_mutex);
849 +
850 +               /* get LRU_list_mutex for buf_LRU_free_block() */
851 +               mutex_enter(&buf_pool->LRU_list_mutex);
852                 mutex_enter(block_mutex);
853  
854 -               /* Discard the uncompressed page frame if possible. */
855 -               if (buf_LRU_free_block(bpage, FALSE)) {
856 +               if (UNIV_UNLIKELY(bpage->space != space
857 +                                 || bpage->offset != offset
858 +                                 || !bpage->in_LRU_list
859 +                                 || !bpage->zip.data)) {
860 +                       /* someone should interrupt, retry */
861 +                       mutex_exit(&buf_pool->LRU_list_mutex);
862 +                       mutex_exit(block_mutex);
863 +                       goto lookup;
864 +               }
865  
866 +               /* Discard the uncompressed page frame if possible. */
867 +               if (buf_LRU_free_block(bpage, FALSE, TRUE)) {
868 +                       mutex_exit(&buf_pool->LRU_list_mutex);
869                         mutex_exit(block_mutex);
870                         goto lookup;
871                 }
872  
873 +               mutex_exit(&buf_pool->LRU_list_mutex);
874 +
875                 buf_block_buf_fix_inc((buf_block_t*) bpage,
876                                       __FILE__, __LINE__);
877                 goto got_block;
878 @@ -1928,7 +2026,7 @@
879         must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
880         access_time = buf_page_is_accessed(bpage);
881  
882 -       buf_pool_mutex_exit(buf_pool);
883 +       //buf_pool_mutex_exit(buf_pool);
884  
885         mutex_exit(block_mutex);
886  
887 @@ -2240,7 +2338,7 @@
888         const buf_block_t*      block)          /*!< in: pointer to block,
889                                                 not dereferenced */
890  {
891 -       ut_ad(buf_pool_mutex_own(buf_pool));
892 +       //ut_ad(buf_pool_mutex_own(buf_pool));
893  
894         if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
895                 /* The pointer should be aligned. */
896 @@ -2276,6 +2374,7 @@
897         ulint           fix_type;
898         ibool           must_read;
899         ulint           retries = 0;
900 +       mutex_t*        block_mutex = NULL;
901         buf_pool_t*     buf_pool = buf_pool_get(space, offset);
902  
903         ut_ad(mtr);
904 @@ -2309,18 +2408,24 @@
905         fold = buf_page_address_fold(space, offset);
906  loop:
907         block = guess;
908 -       buf_pool_mutex_enter(buf_pool);
909 +       //buf_pool_mutex_enter(buf_pool);
910  
911         if (block) {
912 +               block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
913 +
914                 /* If the guess is a compressed page descriptor that
915                 has been allocated by buf_page_alloc_descriptor(),
916                 it may have been freed by buf_relocate(). */
917  
918 -               if (!buf_block_is_uncompressed(buf_pool, block)
919 +               if (!block_mutex) {
920 +                       block = guess = NULL;
921 +               } else if (!buf_block_is_uncompressed(buf_pool, block)
922                     || offset != block->page.offset
923                     || space != block->page.space
924                     || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
925  
926 +                       mutex_exit(block_mutex);
927 +
928                         block = guess = NULL;
929                 } else {
930                         ut_ad(!block->page.in_zip_hash);
931 @@ -2329,12 +2434,19 @@
932         }
933  
934         if (block == NULL) {
935 +               rw_lock_s_lock(&buf_pool->page_hash_latch);
936                 block = (buf_block_t*) buf_page_hash_get_low(
937                         buf_pool, space, offset, fold);
938 +               if (block) {
939 +                       block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
940 +                       ut_a(block_mutex);
941 +               }
942 +               rw_lock_s_unlock(&buf_pool->page_hash_latch);
943         }
944  
945  loop2:
946         if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
947 +               mutex_exit(block_mutex);
948                 block = NULL;
949         }
950  
951 @@ -2346,12 +2458,14 @@
952                                 space, offset, fold);
953  
954                         if (UNIV_LIKELY_NULL(block)) {
955 -
956 +                               block_mutex = buf_page_get_mutex((buf_page_t*)block);
957 +                               ut_a(block_mutex);
958 +                               ut_ad(mutex_own(block_mutex));
959                                 goto got_block;
960                         }
961                 }
962  
963 -               buf_pool_mutex_exit(buf_pool);
964 +               //buf_pool_mutex_exit(buf_pool);
965  
966                 if (mode == BUF_GET_IF_IN_POOL
967                     || mode == BUF_PEEK_IF_IN_POOL
968 @@ -2404,7 +2518,8 @@
969                 /* The page is being read to buffer pool,
970                 but we cannot wait around for the read to
971                 complete. */
972 -               buf_pool_mutex_exit(buf_pool);
973 +               //buf_pool_mutex_exit(buf_pool);
974 +               mutex_exit(block_mutex);
975  
976                 return(NULL);
977         }
978 @@ -2414,38 +2529,49 @@
979                 ibool           success;
980  
981         case BUF_BLOCK_FILE_PAGE:
982 +               if (block_mutex == &buf_pool->zip_mutex) {
983 +                       /* it is wrong mutex... */
984 +                       mutex_exit(block_mutex);
985 +                       goto loop;
986 +               }
987                 break;
988  
989         case BUF_BLOCK_ZIP_PAGE:
990         case BUF_BLOCK_ZIP_DIRTY:
991 +               ut_ad(block_mutex == &buf_pool->zip_mutex);
992                 bpage = &block->page;
993                 /* Protect bpage->buf_fix_count. */
994 -               mutex_enter(&buf_pool->zip_mutex);
995 +               //mutex_enter(&buf_pool->zip_mutex);
996  
997                 if (bpage->buf_fix_count
998                     || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
999                         /* This condition often occurs when the buffer
1000                         is not buffer-fixed, but I/O-fixed by
1001                         buf_page_init_for_read(). */
1002 -                       mutex_exit(&buf_pool->zip_mutex);
1003 +                       //mutex_exit(&buf_pool->zip_mutex);
1004  wait_until_unfixed:
1005                         /* The block is buffer-fixed or I/O-fixed.
1006                         Try again later. */
1007 -                       buf_pool_mutex_exit(buf_pool);
1008 +                       //buf_pool_mutex_exit(buf_pool);
1009 +                       mutex_exit(block_mutex);
1010                         os_thread_sleep(WAIT_FOR_READ);
1011  
1012                         goto loop;
1013                 }
1014  
1015                 /* Allocate an uncompressed page. */
1016 -               buf_pool_mutex_exit(buf_pool);
1017 -               mutex_exit(&buf_pool->zip_mutex);
1018 +               //buf_pool_mutex_exit(buf_pool);
1019 +               //mutex_exit(&buf_pool->zip_mutex);
1020 +               mutex_exit(block_mutex);
1021  
1022                 block = buf_LRU_get_free_block(buf_pool);
1023                 ut_a(block);
1024 +               block_mutex = &block->mutex;
1025  
1026 -               buf_pool_mutex_enter(buf_pool);
1027 -               mutex_enter(&block->mutex);
1028 +               //buf_pool_mutex_enter(buf_pool);
1029 +               mutex_enter(&buf_pool->LRU_list_mutex);
1030 +               rw_lock_x_lock(&buf_pool->page_hash_latch);
1031 +               mutex_enter(block_mutex);
1032  
1033                 {
1034                         buf_page_t*     hash_bpage;
1035 @@ -2458,35 +2584,47 @@
1036                                 while buf_pool->mutex was released.
1037                                 Free the block that was allocated. */
1038  
1039 -                               buf_LRU_block_free_non_file_page(block);
1040 -                               mutex_exit(&block->mutex);
1041 +                               buf_LRU_block_free_non_file_page(block, TRUE);
1042 +                               mutex_exit(block_mutex);
1043  
1044                                 block = (buf_block_t*) hash_bpage;
1045 +                               if (block) {
1046 +                                       block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
1047 +                                       ut_a(block_mutex);
1048 +                               }
1049 +                               rw_lock_x_unlock(&buf_pool->page_hash_latch);
1050 +                               mutex_exit(&buf_pool->LRU_list_mutex);
1051                                 goto loop2;
1052                         }
1053                 }
1054  
1055 +               mutex_enter(&buf_pool->zip_mutex);
1056 +
1057                 if (UNIV_UNLIKELY
1058                     (bpage->buf_fix_count
1059                      || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
1060  
1061 +                       mutex_exit(&buf_pool->zip_mutex);
1062                         /* The block was buffer-fixed or I/O-fixed
1063                         while buf_pool->mutex was not held by this thread.
1064                         Free the block that was allocated and try again.
1065                         This should be extremely unlikely. */
1066  
1067 -                       buf_LRU_block_free_non_file_page(block);
1068 -                       mutex_exit(&block->mutex);
1069 +                       buf_LRU_block_free_non_file_page(block, TRUE);
1070 +                       //mutex_exit(&block->mutex);
1071  
1072 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
1073 +                       mutex_exit(&buf_pool->LRU_list_mutex);
1074                         goto wait_until_unfixed;
1075                 }
1076  
1077                 /* Move the compressed page from bpage to block,
1078                 and uncompress it. */
1079  
1080 -               mutex_enter(&buf_pool->zip_mutex);
1081 -
1082                 buf_relocate(bpage, &block->page);
1083 +
1084 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
1085 +
1086                 buf_block_init_low(block);
1087                 block->lock_hash_val = lock_rec_hash(space, offset);
1088  
1089 @@ -2496,7 +2634,7 @@
1090                 if (buf_page_get_state(&block->page)
1091                     == BUF_BLOCK_ZIP_PAGE) {
1092  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1093 -                       UT_LIST_REMOVE(list, buf_pool->zip_clean,
1094 +                       UT_LIST_REMOVE(zip_list, buf_pool->zip_clean,
1095                                        &block->page);
1096  #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1097                         ut_ad(!block->page.in_flush_list);
1098 @@ -2514,18 +2652,23 @@
1099                 /* Insert at the front of unzip_LRU list */
1100                 buf_unzip_LRU_add_block(block, FALSE);
1101  
1102 +               mutex_exit(&buf_pool->LRU_list_mutex);
1103 +
1104                 block->page.buf_fix_count = 1;
1105                 buf_block_set_io_fix(block, BUF_IO_READ);
1106                 rw_lock_x_lock_func(&block->lock, 0, file, line);
1107  
1108                 UNIV_MEM_INVALID(bpage, sizeof *bpage);
1109  
1110 -               mutex_exit(&block->mutex);
1111 +               mutex_exit(block_mutex);
1112                 mutex_exit(&buf_pool->zip_mutex);
1113 -               buf_pool->n_pend_unzip++;
1114  
1115 +               buf_pool_mutex_enter(buf_pool);
1116 +               buf_pool->n_pend_unzip++;
1117                 buf_pool_mutex_exit(buf_pool);
1118  
1119 +               //buf_pool_mutex_exit(buf_pool);
1120 +
1121                 buf_page_free_descriptor(bpage);
1122  
1123                 /* Decompress the page and apply buffered operations
1124 @@ -2539,12 +2682,15 @@
1125                 }
1126  
1127                 /* Unfix and unlatch the block. */
1128 -               buf_pool_mutex_enter(buf_pool);
1129 -               mutex_enter(&block->mutex);
1130 +               //buf_pool_mutex_enter(buf_pool);
1131 +               block_mutex = &block->mutex;
1132 +               mutex_enter(block_mutex);
1133                 block->page.buf_fix_count--;
1134                 buf_block_set_io_fix(block, BUF_IO_NONE);
1135 -               mutex_exit(&block->mutex);
1136 +
1137 +               buf_pool_mutex_enter(buf_pool);
1138                 buf_pool->n_pend_unzip--;
1139 +               buf_pool_mutex_exit(buf_pool);
1140                 rw_lock_x_unlock(&block->lock);
1141  
1142                 break;
1143 @@ -2560,7 +2706,7 @@
1144  
1145         ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
1146  
1147 -       mutex_enter(&block->mutex);
1148 +       //mutex_enter(&block->mutex);
1149  #if UNIV_WORD_SIZE == 4
1150         /* On 32-bit systems, there is no padding in buf_page_t.  On
1151         other systems, Valgrind could complain about uninitialized pad
1152 @@ -2573,8 +2719,8 @@
1153                 /* Try to evict the block from the buffer pool, to use the
1154                 insert buffer (change buffer) as much as possible. */
1155  
1156 -               if (buf_LRU_free_block(&block->page, TRUE)) {
1157 -                       mutex_exit(&block->mutex);
1158 +               if (buf_LRU_free_block(&block->page, TRUE, FALSE)) {
1159 +                       mutex_exit(block_mutex);
1160                         if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
1161                                 /* Set the watch, as it would have
1162                                 been set if the page were not in the
1163 @@ -2583,6 +2729,9 @@
1164                                         space, offset, fold);
1165  
1166                                 if (UNIV_LIKELY_NULL(block)) {
1167 +                                       block_mutex = buf_page_get_mutex((buf_page_t*)block);
1168 +                                       ut_a(block_mutex);
1169 +                                       ut_ad(mutex_own(block_mutex));
1170  
1171                                         /* The page entered the buffer
1172                                         pool for some reason. Try to
1173 @@ -2590,7 +2739,7 @@
1174                                         goto got_block;
1175                                 }
1176                         }
1177 -                       buf_pool_mutex_exit(buf_pool);
1178 +                       //buf_pool_mutex_exit(buf_pool);
1179                         fprintf(stderr,
1180                                 "innodb_change_buffering_debug evict %u %u\n",
1181                                 (unsigned) space, (unsigned) offset);
1182 @@ -2612,13 +2761,14 @@
1183         ut_a(mode == BUF_GET_POSSIBLY_FREED
1184              || !block->page.file_page_was_freed);
1185  #endif
1186 -       mutex_exit(&block->mutex);
1187 +       //mutex_exit(&block->mutex);
1188  
1189         /* Check if this is the first access to the page */
1190  
1191         access_time = buf_page_is_accessed(&block->page);
1192  
1193 -       buf_pool_mutex_exit(buf_pool);
1194 +       //buf_pool_mutex_exit(buf_pool);
1195 +       mutex_exit(block_mutex);
1196  
1197         if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL)) {
1198                 buf_page_set_accessed_make_young(&block->page, access_time);
1199 @@ -2851,9 +3001,11 @@
1200         buf_pool = buf_pool_from_block(block);
1201  
1202         if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
1203 -               buf_pool_mutex_enter(buf_pool);
1204 +               //buf_pool_mutex_enter(buf_pool);
1205 +               mutex_enter(&buf_pool->LRU_list_mutex);
1206                 buf_LRU_make_block_young(&block->page);
1207 -               buf_pool_mutex_exit(buf_pool);
1208 +               //buf_pool_mutex_exit(buf_pool);
1209 +               mutex_exit(&buf_pool->LRU_list_mutex);
1210         } else if (!buf_page_is_accessed(&block->page)) {
1211                 /* Above, we do a dirty read on purpose, to avoid
1212                 mutex contention.  The field buf_page_t::access_time
1213 @@ -2861,9 +3013,11 @@
1214                 field must be protected by mutex, however. */
1215                 ulint   time_ms = ut_time_ms();
1216  
1217 -               buf_pool_mutex_enter(buf_pool);
1218 +               //buf_pool_mutex_enter(buf_pool);
1219 +               mutex_enter(&block->mutex);
1220                 buf_page_set_accessed(&block->page, time_ms);
1221 -               buf_pool_mutex_exit(buf_pool);
1222 +               //buf_pool_mutex_exit(buf_pool);
1223 +               mutex_exit(&block->mutex);
1224         }
1225  
1226         ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
1227 @@ -2930,18 +3084,21 @@
1228         ut_ad(mtr);
1229         ut_ad(mtr->state == MTR_ACTIVE);
1230  
1231 -       buf_pool_mutex_enter(buf_pool);
1232 +       //buf_pool_mutex_enter(buf_pool);
1233 +       rw_lock_s_lock(&buf_pool->page_hash_latch);
1234         block = buf_block_hash_get(buf_pool, space_id, page_no);
1235  
1236         if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
1237 -               buf_pool_mutex_exit(buf_pool);
1238 +               //buf_pool_mutex_exit(buf_pool);
1239 +               rw_lock_s_unlock(&buf_pool->page_hash_latch);
1240                 return(NULL);
1241         }
1242  
1243         ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
1244  
1245         mutex_enter(&block->mutex);
1246 -       buf_pool_mutex_exit(buf_pool);
1247 +       //buf_pool_mutex_exit(buf_pool);
1248 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
1249  
1250  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1251         ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
1252 @@ -3031,7 +3188,10 @@
1253         buf_page_t*     hash_page;
1254  
1255         ut_ad(buf_pool == buf_pool_get(space, offset));
1256 -       ut_ad(buf_pool_mutex_own(buf_pool));
1257 +       //ut_ad(buf_pool_mutex_own(buf_pool));
1258 +#ifdef UNIV_SYNC_DEBUG
1259 +       ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
1260 +#endif
1261         ut_ad(mutex_own(&(block->mutex)));
1262         ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
1263  
1264 @@ -3060,11 +3220,14 @@
1265         if (UNIV_LIKELY(!hash_page)) {
1266         } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
1267                 /* Preserve the reference count. */
1268 -               ulint   buf_fix_count = hash_page->buf_fix_count;
1269 +               ulint   buf_fix_count;
1270  
1271 +               mutex_enter(&buf_pool->zip_mutex);
1272 +               buf_fix_count = hash_page->buf_fix_count;
1273                 ut_a(buf_fix_count > 0);
1274                 block->page.buf_fix_count += buf_fix_count;
1275                 buf_pool_watch_remove(buf_pool, fold, hash_page);
1276 +               mutex_exit(&buf_pool->zip_mutex);
1277         } else {
1278                 fprintf(stderr,
1279                         "InnoDB: Error: page %lu %lu already found"
1280 @@ -3074,7 +3237,8 @@
1281                         (const void*) hash_page, (const void*) block);
1282  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1283                 mutex_exit(&block->mutex);
1284 -               buf_pool_mutex_exit(buf_pool);
1285 +               //buf_pool_mutex_exit(buf_pool);
1286 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
1287                 buf_print();
1288                 buf_LRU_print();
1289                 buf_validate();
1290 @@ -3157,7 +3321,9 @@
1291  
1292         fold = buf_page_address_fold(space, offset);
1293  
1294 -       buf_pool_mutex_enter(buf_pool);
1295 +       //buf_pool_mutex_enter(buf_pool);
1296 +       mutex_enter(&buf_pool->LRU_list_mutex);
1297 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
1298  
1299         watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
1300         if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
1301 @@ -3166,9 +3332,15 @@
1302  err_exit:
1303                 if (block) {
1304                         mutex_enter(&block->mutex);
1305 -                       buf_LRU_block_free_non_file_page(block);
1306 +                       mutex_exit(&buf_pool->LRU_list_mutex);
1307 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
1308 +                       buf_LRU_block_free_non_file_page(block, FALSE);
1309                         mutex_exit(&block->mutex);
1310                 }
1311 +               else {
1312 +                       mutex_exit(&buf_pool->LRU_list_mutex);
1313 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
1314 +               }
1315  
1316                 bpage = NULL;
1317                 goto func_exit;
1318 @@ -3191,6 +3363,8 @@
1319  
1320                 buf_page_init(buf_pool, space, offset, fold, block);
1321  
1322 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
1323 +
1324                 /* The block must be put to the LRU list, to the old blocks */
1325                 buf_LRU_add_block(bpage, TRUE/* to old blocks */);
1326  
1327 @@ -3218,7 +3392,7 @@
1328                         been added to buf_pool->LRU and
1329                         buf_pool->page_hash. */
1330                         mutex_exit(&block->mutex);
1331 -                       data = buf_buddy_alloc(buf_pool, zip_size, &lru);
1332 +                       data = buf_buddy_alloc(buf_pool, zip_size, &lru, FALSE);
1333                         mutex_enter(&block->mutex);
1334                         block->page.zip.data = data;
1335  
1336 @@ -3231,13 +3405,14 @@
1337                         buf_unzip_LRU_add_block(block, TRUE);
1338                 }
1339  
1340 +               mutex_exit(&buf_pool->LRU_list_mutex);
1341                 mutex_exit(&block->mutex);
1342         } else {
1343                 /* The compressed page must be allocated before the
1344                 control block (bpage), in order to avoid the
1345                 invocation of buf_buddy_relocate_block() on
1346                 uninitialized data. */
1347 -               data = buf_buddy_alloc(buf_pool, zip_size, &lru);
1348 +               data = buf_buddy_alloc(buf_pool, zip_size, &lru, TRUE);
1349  
1350                 /* If buf_buddy_alloc() allocated storage from the LRU list,
1351                 it released and reacquired buf_pool->mutex.  Thus, we must
1352 @@ -3253,7 +3428,10 @@
1353  
1354                                 /* The block was added by some other thread. */
1355                                 watch_page = NULL;
1356 -                               buf_buddy_free(buf_pool, data, zip_size);
1357 +                               buf_buddy_free(buf_pool, data, zip_size, TRUE);
1358 +
1359 +                               mutex_exit(&buf_pool->LRU_list_mutex);
1360 +                               rw_lock_x_unlock(&buf_pool->page_hash_latch);
1361  
1362                                 bpage = NULL;
1363                                 goto func_exit;
1364 @@ -3301,20 +3479,26 @@
1365                 HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
1366                             bpage);
1367  
1368 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
1369 +
1370                 /* The block must be put to the LRU list, to the old blocks */
1371                 buf_LRU_add_block(bpage, TRUE/* to old blocks */);
1372  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1373                 buf_LRU_insert_zip_clean(bpage);
1374  #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1375  
1376 +               mutex_exit(&buf_pool->LRU_list_mutex);
1377 +
1378                 buf_page_set_io_fix(bpage, BUF_IO_READ);
1379  
1380                 mutex_exit(&buf_pool->zip_mutex);
1381         }
1382  
1383 +       buf_pool_mutex_enter(buf_pool);
1384         buf_pool->n_pend_reads++;
1385 -func_exit:
1386         buf_pool_mutex_exit(buf_pool);
1387 +func_exit:
1388 +       //buf_pool_mutex_exit(buf_pool);
1389  
1390         if (mode == BUF_READ_IBUF_PAGES_ONLY) {
1391  
1392 @@ -3356,7 +3540,9 @@
1393  
1394         fold = buf_page_address_fold(space, offset);
1395  
1396 -       buf_pool_mutex_enter(buf_pool);
1397 +       //buf_pool_mutex_enter(buf_pool);
1398 +       mutex_enter(&buf_pool->LRU_list_mutex);
1399 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
1400  
1401         block = (buf_block_t*) buf_page_hash_get_low(
1402                 buf_pool, space, offset, fold);
1403 @@ -3372,7 +3558,9 @@
1404  #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
1405  
1406                 /* Page can be found in buf_pool */
1407 -               buf_pool_mutex_exit(buf_pool);
1408 +               //buf_pool_mutex_exit(buf_pool);
1409 +               mutex_exit(&buf_pool->LRU_list_mutex);
1410 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
1411  
1412                 buf_block_free(free_block);
1413  
1414 @@ -3394,6 +3582,7 @@
1415         mutex_enter(&block->mutex);
1416  
1417         buf_page_init(buf_pool, space, offset, fold, block);
1418 +       rw_lock_x_unlock(&buf_pool->page_hash_latch);
1419  
1420         /* The block must be put to the LRU list */
1421         buf_LRU_add_block(&block->page, FALSE);
1422 @@ -3420,7 +3609,7 @@
1423                 the reacquisition of buf_pool->mutex.  We also must
1424                 defer this operation until after the block descriptor
1425                 has been added to buf_pool->LRU and buf_pool->page_hash. */
1426 -               data = buf_buddy_alloc(buf_pool, zip_size, &lru);
1427 +               data = buf_buddy_alloc(buf_pool, zip_size, &lru, FALSE);
1428                 mutex_enter(&block->mutex);
1429                 block->page.zip.data = data;
1430  
1431 @@ -3438,7 +3627,8 @@
1432  
1433         buf_page_set_accessed(&block->page, time_ms);
1434  
1435 -       buf_pool_mutex_exit(buf_pool);
1436 +       //buf_pool_mutex_exit(buf_pool);
1437 +       mutex_exit(&buf_pool->LRU_list_mutex);
1438  
1439         mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
1440  
1441 @@ -3493,7 +3683,9 @@
1442         ibool           ret = TRUE;
1443  
1444         /* First unfix and release lock on the bpage */
1445 -       buf_pool_mutex_enter(buf_pool);
1446 +       //buf_pool_mutex_enter(buf_pool);
1447 +       mutex_enter(&buf_pool->LRU_list_mutex);
1448 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
1449         mutex_enter(buf_page_get_mutex(bpage));
1450         ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
1451         ut_ad(bpage->buf_fix_count == 0);
1452 @@ -3514,11 +3706,15 @@
1453                 ret = FALSE;
1454         }
1455  
1456 +       buf_pool_mutex_enter(buf_pool);
1457         ut_ad(buf_pool->n_pend_reads > 0);
1458         buf_pool->n_pend_reads--;
1459 +       buf_pool_mutex_exit(buf_pool);
1460  
1461         mutex_exit(buf_page_get_mutex(bpage));
1462 -       buf_pool_mutex_exit(buf_pool);
1463 +       //buf_pool_mutex_exit(buf_pool);
1464 +       mutex_exit(&buf_pool->LRU_list_mutex);
1465 +       rw_lock_x_unlock(&buf_pool->page_hash_latch);
1466  
1467         return(ret);
1468  }
1469 @@ -3536,6 +3732,8 @@
1470         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1471         const ibool     uncompressed = (buf_page_get_state(bpage)
1472                                         == BUF_BLOCK_FILE_PAGE);
1473 +       ibool           have_LRU_mutex = FALSE;
1474 +       mutex_t*        block_mutex;
1475  
1476         ut_a(buf_page_in_file(bpage));
1477  
1478 @@ -3678,8 +3876,26 @@
1479                 }
1480         }
1481  
1482 +       if (io_type == BUF_IO_WRITE
1483 +           && (buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY
1484 +               || buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) {
1485 +               /* to keep consistency at buf_LRU_insert_zip_clean() */
1486 +               have_LRU_mutex = TRUE; /* optimistic */
1487 +       }
1488 +retry_mutex:
1489 +       if (have_LRU_mutex)
1490 +               mutex_enter(&buf_pool->LRU_list_mutex);
1491 +       block_mutex = buf_page_get_mutex_enter(bpage);
1492 +       ut_a(block_mutex);
1493 +       if (io_type == BUF_IO_WRITE
1494 +           && (buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY
1495 +               || buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)
1496 +           && !have_LRU_mutex) {
1497 +               mutex_exit(block_mutex);
1498 +               have_LRU_mutex = TRUE;
1499 +               goto retry_mutex;
1500 +       }
1501         buf_pool_mutex_enter(buf_pool);
1502 -       mutex_enter(buf_page_get_mutex(bpage));
1503  
1504  #ifdef UNIV_IBUF_COUNT_DEBUG
1505         if (io_type == BUF_IO_WRITE || uncompressed) {
1506 @@ -3702,6 +3918,7 @@
1507                 the x-latch to this OS thread: do not let this confuse you in
1508                 debugging! */
1509  
1510 +               ut_a(!have_LRU_mutex);
1511                 ut_ad(buf_pool->n_pend_reads > 0);
1512                 buf_pool->n_pend_reads--;
1513                 buf_pool->stat.n_pages_read++;
1514 @@ -3719,6 +3936,9 @@
1515  
1516                 buf_flush_write_complete(bpage);
1517  
1518 +               if (have_LRU_mutex)
1519 +                       mutex_exit(&buf_pool->LRU_list_mutex);
1520 +
1521                 if (uncompressed) {
1522                         rw_lock_s_unlock_gen(&((buf_block_t*) bpage)->lock,
1523                                              BUF_IO_WRITE);
1524 @@ -3741,8 +3961,8 @@
1525         }
1526  #endif /* UNIV_DEBUG */
1527  
1528 -       mutex_exit(buf_page_get_mutex(bpage));
1529         buf_pool_mutex_exit(buf_pool);
1530 +       mutex_exit(block_mutex);
1531  }
1532  
1533  /*********************************************************************//**
1534 @@ -3759,7 +3979,9 @@
1535  
1536         ut_ad(buf_pool);
1537  
1538 -       buf_pool_mutex_enter(buf_pool);
1539 +       //buf_pool_mutex_enter(buf_pool);
1540 +       mutex_enter(&buf_pool->LRU_list_mutex);
1541 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
1542  
1543         chunk = buf_pool->chunks;
1544  
1545 @@ -3776,7 +3998,9 @@
1546                 }
1547         }
1548  
1549 -       buf_pool_mutex_exit(buf_pool);
1550 +       //buf_pool_mutex_exit(buf_pool);
1551 +       mutex_exit(&buf_pool->LRU_list_mutex);
1552 +       rw_lock_x_unlock(&buf_pool->page_hash_latch);
1553  
1554         return(TRUE);
1555  }
1556 @@ -3824,7 +4048,8 @@
1557                 freed = buf_LRU_search_and_free_block(buf_pool, 100);
1558         }
1559  
1560 -       buf_pool_mutex_enter(buf_pool);
1561 +       //buf_pool_mutex_enter(buf_pool);
1562 +       mutex_enter(&buf_pool->LRU_list_mutex);
1563  
1564         ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
1565         ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
1566 @@ -3837,7 +4062,8 @@
1567         memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
1568         buf_refresh_io_stats(buf_pool);
1569  
1570 -       buf_pool_mutex_exit(buf_pool);
1571 +       //buf_pool_mutex_exit(buf_pool);
1572 +       mutex_exit(&buf_pool->LRU_list_mutex);
1573  }
1574  
1575  /*********************************************************************//**
1576 @@ -3879,7 +4105,10 @@
1577  
1578         ut_ad(buf_pool);
1579  
1580 -       buf_pool_mutex_enter(buf_pool);
1581 +       //buf_pool_mutex_enter(buf_pool);
1582 +       mutex_enter(&buf_pool->LRU_list_mutex);
1583 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
1584 +       /* for keep the new latch order, it cannot validate correctly... */
1585  
1586         chunk = buf_pool->chunks;
1587  
1588 @@ -3974,7 +4203,7 @@
1589         /* Check clean compressed-only blocks. */
1590  
1591         for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
1592 -            b = UT_LIST_GET_NEXT(list, b)) {
1593 +            b = UT_LIST_GET_NEXT(zip_list, b)) {
1594                 ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
1595                 switch (buf_page_get_io_fix(b)) {
1596                 case BUF_IO_NONE:
1597 @@ -4005,7 +4234,7 @@
1598  
1599         buf_flush_list_mutex_enter(buf_pool);
1600         for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1601 -            b = UT_LIST_GET_NEXT(list, b)) {
1602 +            b = UT_LIST_GET_NEXT(flush_list, b)) {
1603                 ut_ad(b->in_flush_list);
1604                 ut_a(b->oldest_modification);
1605                 n_flush++;
1606 @@ -4064,6 +4293,8 @@
1607         }
1608  
1609         ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == n_lru);
1610 +       /* because of latching order with block->mutex, we cannot get needed mutexes before that */
1611 +/*
1612         if (UT_LIST_GET_LEN(buf_pool->free) != n_free) {
1613                 fprintf(stderr, "Free list len %lu, free blocks %lu\n",
1614                         (ulong) UT_LIST_GET_LEN(buf_pool->free),
1615 @@ -4074,8 +4305,11 @@
1616         ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
1617         ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
1618         ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
1619 +*/
1620  
1621 -       buf_pool_mutex_exit(buf_pool);
1622 +       //buf_pool_mutex_exit(buf_pool);
1623 +       mutex_exit(&buf_pool->LRU_list_mutex);
1624 +       rw_lock_x_unlock(&buf_pool->page_hash_latch);
1625  
1626         ut_a(buf_LRU_validate());
1627         ut_a(buf_flush_validate(buf_pool));
1628 @@ -4131,7 +4365,9 @@
1629         index_ids = mem_alloc(size * sizeof *index_ids);
1630         counts = mem_alloc(sizeof(ulint) * size);
1631  
1632 -       buf_pool_mutex_enter(buf_pool);
1633 +       //buf_pool_mutex_enter(buf_pool);
1634 +       mutex_enter(&buf_pool->LRU_list_mutex);
1635 +       mutex_enter(&buf_pool->free_list_mutex);
1636         buf_flush_list_mutex_enter(buf_pool);
1637  
1638         fprintf(stderr,
1639 @@ -4200,7 +4436,9 @@
1640                 }
1641         }
1642  
1643 -       buf_pool_mutex_exit(buf_pool);
1644 +       //buf_pool_mutex_exit(buf_pool);
1645 +       mutex_exit(&buf_pool->LRU_list_mutex);
1646 +       mutex_exit(&buf_pool->free_list_mutex);
1647  
1648         for (i = 0; i < n_found; i++) {
1649                 index = dict_index_get_if_in_cache(index_ids[i]);
1650 @@ -4257,7 +4495,7 @@
1651         buf_chunk_t*    chunk;
1652         ulint           fixed_pages_number = 0;
1653  
1654 -       buf_pool_mutex_enter(buf_pool);
1655 +       //buf_pool_mutex_enter(buf_pool);
1656  
1657         chunk = buf_pool->chunks;
1658  
1659 @@ -4291,7 +4529,7 @@
1660         /* Traverse the lists of clean and dirty compressed-only blocks. */
1661  
1662         for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
1663 -            b = UT_LIST_GET_NEXT(list, b)) {
1664 +            b = UT_LIST_GET_NEXT(zip_list, b)) {
1665                 ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
1666                 ut_a(buf_page_get_io_fix(b) != BUF_IO_WRITE);
1667  
1668 @@ -4303,7 +4541,7 @@
1669  
1670         buf_flush_list_mutex_enter(buf_pool);
1671         for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1672 -            b = UT_LIST_GET_NEXT(list, b)) {
1673 +            b = UT_LIST_GET_NEXT(flush_list, b)) {
1674                 ut_ad(b->in_flush_list);
1675  
1676                 switch (buf_page_get_state(b)) {
1677 @@ -4329,7 +4567,7 @@
1678  
1679         buf_flush_list_mutex_exit(buf_pool);
1680         mutex_exit(&buf_pool->zip_mutex);
1681 -       buf_pool_mutex_exit(buf_pool);
1682 +       //buf_pool_mutex_exit(buf_pool);
1683  
1684         return(fixed_pages_number);
1685  }
1686 @@ -4487,6 +4725,8 @@
1687         /* Find appropriate pool_info to store stats for this buffer pool */
1688         pool_info = &all_pool_info[pool_id];
1689  
1690 +       mutex_enter(&buf_pool->LRU_list_mutex);
1691 +       mutex_enter(&buf_pool->free_list_mutex);
1692         buf_pool_mutex_enter(buf_pool);
1693         buf_flush_list_mutex_enter(buf_pool);
1694  
1695 @@ -4602,6 +4842,8 @@
1696         pool_info->unzip_cur = buf_LRU_stat_cur.unzip;
1697  
1698         buf_refresh_io_stats(buf_pool);
1699 +       mutex_exit(&buf_pool->LRU_list_mutex);
1700 +       mutex_exit(&buf_pool->free_list_mutex);
1701         buf_pool_mutex_exit(buf_pool);
1702  }
1703  
1704 @@ -4846,11 +5088,13 @@
1705  {
1706         ulint   len;
1707  
1708 -       buf_pool_mutex_enter(buf_pool);
1709 +       //buf_pool_mutex_enter(buf_pool);
1710 +       mutex_enter(&buf_pool->free_list_mutex);
1711  
1712         len = UT_LIST_GET_LEN(buf_pool->free);
1713  
1714 -       buf_pool_mutex_exit(buf_pool);
1715 +       //buf_pool_mutex_exit(buf_pool);
1716 +       mutex_exit(&buf_pool->free_list_mutex);
1717  
1718         return(len);
1719  }
1720 --- a/storage/innobase/buf/buf0flu.c
1721 +++ b/storage/innobase/buf/buf0flu.c
1722 @@ -307,7 +307,7 @@
1723  
1724         ut_d(block->page.in_flush_list = TRUE);
1725         block->page.oldest_modification = lsn;
1726 -       UT_LIST_ADD_FIRST(list, buf_pool->flush_list, &block->page);
1727 +       UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, &block->page);
1728  
1729  #ifdef UNIV_DEBUG_VALGRIND
1730         {
1731 @@ -401,14 +401,14 @@
1732                        > block->page.oldest_modification) {
1733                         ut_ad(b->in_flush_list);
1734                         prev_b = b;
1735 -                       b = UT_LIST_GET_NEXT(list, b);
1736 +                       b = UT_LIST_GET_NEXT(flush_list, b);
1737                 }
1738         }
1739  
1740         if (prev_b == NULL) {
1741 -               UT_LIST_ADD_FIRST(list, buf_pool->flush_list, &block->page);
1742 +               UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, &block->page);
1743         } else {
1744 -               UT_LIST_INSERT_AFTER(list, buf_pool->flush_list,
1745 +               UT_LIST_INSERT_AFTER(flush_list, buf_pool->flush_list,
1746                                      prev_b, &block->page);
1747         }
1748  
1749 @@ -434,7 +434,7 @@
1750         //buf_pool_t*   buf_pool = buf_pool_from_bpage(bpage);
1751         //ut_ad(buf_pool_mutex_own(buf_pool));
1752  #endif
1753 -       //ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1754 +       ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1755         //ut_ad(bpage->in_LRU_list);
1756  
1757         if (UNIV_LIKELY(bpage->in_LRU_list && buf_page_in_file(bpage))) {
1758 @@ -470,14 +470,14 @@
1759         enum buf_flush  flush_type)/*!< in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */
1760  {
1761  #ifdef UNIV_DEBUG
1762 -       buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1763 -       ut_ad(buf_pool_mutex_own(buf_pool));
1764 +       //buf_pool_t*   buf_pool = buf_pool_from_bpage(bpage);
1765 +       //ut_ad(buf_pool_mutex_own(buf_pool));
1766  #endif
1767 -       ut_a(buf_page_in_file(bpage));
1768 +       //ut_a(buf_page_in_file(bpage));
1769         ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1770         ut_ad(flush_type == BUF_FLUSH_LRU || BUF_FLUSH_LIST);
1771  
1772 -       if (bpage->oldest_modification != 0
1773 +       if (buf_page_in_file(bpage) && bpage->oldest_modification != 0
1774             && buf_page_get_io_fix(bpage) == BUF_IO_NONE) {
1775                 ut_ad(bpage->in_flush_list);
1776  
1777 @@ -508,7 +508,7 @@
1778  {
1779         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1780  
1781 -       ut_ad(buf_pool_mutex_own(buf_pool));
1782 +       //ut_ad(buf_pool_mutex_own(buf_pool));
1783         ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1784         ut_ad(bpage->in_flush_list);
1785  
1786 @@ -526,13 +526,13 @@
1787                 return;
1788         case BUF_BLOCK_ZIP_DIRTY:
1789                 buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE);
1790 -               UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
1791 +               UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
1792  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1793                 buf_LRU_insert_zip_clean(bpage);
1794  #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1795                 break;
1796         case BUF_BLOCK_FILE_PAGE:
1797 -               UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
1798 +               UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
1799                 break;
1800         }
1801  
1802 @@ -576,7 +576,7 @@
1803         buf_page_t*     prev_b = NULL;
1804         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1805  
1806 -       ut_ad(buf_pool_mutex_own(buf_pool));
1807 +       //ut_ad(buf_pool_mutex_own(buf_pool));
1808         /* Must reside in the same buffer pool. */
1809         ut_ad(buf_pool == buf_pool_from_bpage(dpage));
1810  
1811 @@ -605,18 +605,18 @@
1812         because we assert on in_flush_list in comparison function. */
1813         ut_d(bpage->in_flush_list = FALSE);
1814  
1815 -       prev = UT_LIST_GET_PREV(list, bpage);
1816 -       UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
1817 +       prev = UT_LIST_GET_PREV(flush_list, bpage);
1818 +       UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
1819  
1820         if (prev) {
1821                 ut_ad(prev->in_flush_list);
1822                 UT_LIST_INSERT_AFTER(
1823 -                       list,
1824 +                       flush_list,
1825                         buf_pool->flush_list,
1826                         prev, dpage);
1827         } else {
1828                 UT_LIST_ADD_FIRST(
1829 -                       list,
1830 +                       flush_list,
1831                         buf_pool->flush_list,
1832                         dpage);
1833         }
1834 @@ -1085,7 +1085,7 @@
1835  
1836  #ifdef UNIV_DEBUG
1837         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1838 -       ut_ad(!buf_pool_mutex_own(buf_pool));
1839 +       //ut_ad(!buf_pool_mutex_own(buf_pool));
1840  #endif
1841  
1842  #ifdef UNIV_LOG_DEBUG
1843 @@ -1099,7 +1099,8 @@
1844         io_fixed and oldest_modification != 0.  Thus, it cannot be
1845         relocated in the buffer pool or removed from flush_list or
1846         LRU_list. */
1847 -       ut_ad(!buf_pool_mutex_own(buf_pool));
1848 +       //ut_ad(!buf_pool_mutex_own(buf_pool));
1849 +       ut_ad(!mutex_own(&buf_pool->LRU_list_mutex));
1850         ut_ad(!buf_flush_list_mutex_own(buf_pool));
1851         ut_ad(!mutex_own(buf_page_get_mutex(bpage)));
1852         ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_WRITE);
1853 @@ -1179,7 +1180,7 @@
1854         buf_pool_t*     buf_pool,       /*!< in/out: buffer pool instance */
1855         buf_block_t*    block)          /*!< in/out: buffer control block */
1856  {
1857 -       ut_ad(buf_pool_mutex_own(buf_pool));
1858 +       //ut_ad(buf_pool_mutex_own(buf_pool));
1859         ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
1860         ut_ad(mutex_own(&block->mutex));
1861  
1862 @@ -1187,8 +1188,11 @@
1863                 return(FALSE);
1864         }
1865  
1866 +       buf_pool_mutex_enter(buf_pool);
1867 +
1868         if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0
1869             || buf_pool->init_flush[BUF_FLUSH_LRU]) {
1870 +               buf_pool_mutex_exit(buf_pool);
1871                 /* There is already a flush batch of the same type running */
1872                 return(FALSE);
1873         }
1874 @@ -1262,12 +1266,18 @@
1875         ibool           is_uncompressed;
1876  
1877         ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
1878 -       ut_ad(buf_pool_mutex_own(buf_pool));
1879 +       //ut_ad(buf_pool_mutex_own(buf_pool));
1880 +#ifdef UNIV_SYNC_DEBUG
1881 +       ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_SHARED));
1882 +#endif
1883         ut_ad(buf_page_in_file(bpage));
1884  
1885         block_mutex = buf_page_get_mutex(bpage);
1886         ut_ad(mutex_own(block_mutex));
1887  
1888 +       buf_pool_mutex_enter(buf_pool);
1889 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
1890 +
1891         ut_ad(buf_flush_ready_for_flush(bpage, flush_type));
1892  
1893         buf_page_set_io_fix(bpage, BUF_IO_WRITE);
1894 @@ -1429,14 +1439,16 @@
1895  
1896                 buf_pool = buf_pool_get(space, i);
1897  
1898 -               buf_pool_mutex_enter(buf_pool);
1899 +               //buf_pool_mutex_enter(buf_pool);
1900 +               rw_lock_s_lock(&buf_pool->page_hash_latch);
1901  
1902                 /* We only want to flush pages from this buffer pool. */
1903                 bpage = buf_page_hash_get(buf_pool, space, i);
1904  
1905                 if (!bpage) {
1906  
1907 -                       buf_pool_mutex_exit(buf_pool);
1908 +                       //buf_pool_mutex_exit(buf_pool);
1909 +                       rw_lock_s_unlock(&buf_pool->page_hash_latch);
1910                         continue;
1911                 }
1912  
1913 @@ -1448,11 +1460,9 @@
1914                 if (flush_type != BUF_FLUSH_LRU
1915                     || i == offset
1916                     || buf_page_is_old(bpage)) {
1917 -                       mutex_t* block_mutex = buf_page_get_mutex(bpage);
1918 +                       mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
1919  
1920 -                       mutex_enter(block_mutex);
1921 -
1922 -                       if (buf_flush_ready_for_flush(bpage, flush_type)
1923 +                       if (block_mutex && buf_flush_ready_for_flush(bpage, flush_type)
1924                             && (i == offset || !bpage->buf_fix_count)) {
1925                                 /* We only try to flush those
1926                                 neighbors != offset where the buf fix
1927 @@ -1468,11 +1478,12 @@
1928                                 ut_ad(!buf_pool_mutex_own(buf_pool));
1929                                 count++;
1930                                 continue;
1931 -                       } else {
1932 +                       } else if (block_mutex) {
1933                                 mutex_exit(block_mutex);
1934                         }
1935                 }
1936 -               buf_pool_mutex_exit(buf_pool);
1937 +               //buf_pool_mutex_exit(buf_pool);
1938 +               rw_lock_s_unlock(&buf_pool->page_hash_latch);
1939         }
1940  
1941         return(count);
1942 @@ -1505,21 +1516,25 @@
1943         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1944  #endif /* UNIV_DEBUG */
1945  
1946 -       ut_ad(buf_pool_mutex_own(buf_pool));
1947 +       //ut_ad(buf_pool_mutex_own(buf_pool));
1948 +       ut_ad(flush_type != BUF_FLUSH_LRU
1949 +             || mutex_own(&buf_pool->LRU_list_mutex));
1950  
1951 -       block_mutex = buf_page_get_mutex(bpage);
1952 -       mutex_enter(block_mutex);
1953 +       block_mutex = buf_page_get_mutex_enter(bpage);
1954  
1955 -       ut_a(buf_page_in_file(bpage));
1956 +       //ut_a(buf_page_in_file(bpage));
1957  
1958 -       if (buf_flush_ready_for_flush(bpage, flush_type)) {
1959 +       if (block_mutex && buf_flush_ready_for_flush(bpage, flush_type)) {
1960                 ulint           space;
1961                 ulint           offset;
1962                 buf_pool_t*     buf_pool;
1963  
1964                 buf_pool = buf_pool_from_bpage(bpage);
1965  
1966 -               buf_pool_mutex_exit(buf_pool);
1967 +               //buf_pool_mutex_exit(buf_pool);
1968 +               if (flush_type == BUF_FLUSH_LRU) {
1969 +                       mutex_exit(&buf_pool->LRU_list_mutex);
1970 +               }
1971  
1972                 /* These fields are protected by both the
1973                 buffer pool mutex and block mutex. */
1974 @@ -1535,13 +1550,18 @@
1975                                                   *count,
1976                                                   n_to_flush);
1977  
1978 -               buf_pool_mutex_enter(buf_pool);
1979 +               //buf_pool_mutex_enter(buf_pool);
1980 +               if (flush_type == BUF_FLUSH_LRU) {
1981 +                       mutex_enter(&buf_pool->LRU_list_mutex);
1982 +               }
1983                 flushed = TRUE;
1984 -       } else {
1985 +       } else if (block_mutex) {
1986                 mutex_exit(block_mutex);
1987         }
1988  
1989 -       ut_ad(buf_pool_mutex_own(buf_pool));
1990 +       //ut_ad(buf_pool_mutex_own(buf_pool));
1991 +       ut_ad(flush_type != BUF_FLUSH_LRU
1992 +             || mutex_own(&buf_pool->LRU_list_mutex));
1993  
1994         return(flushed);
1995  }
1996 @@ -1562,7 +1582,8 @@
1997         buf_page_t*     bpage;
1998         ulint           count = 0;
1999  
2000 -       ut_ad(buf_pool_mutex_own(buf_pool));
2001 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2002 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2003  
2004         do {
2005                 /* Start from the end of the list looking for a
2006 @@ -1584,7 +1605,8 @@
2007         should be flushed, we factor in this value. */
2008         buf_lru_flush_page_count += count;
2009  
2010 -       ut_ad(buf_pool_mutex_own(buf_pool));
2011 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2012 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2013  
2014         return(count);
2015  }
2016 @@ -1612,9 +1634,10 @@
2017  {
2018         ulint           len;
2019         buf_page_t*     bpage;
2020 +       buf_page_t*     prev_bpage = NULL;
2021         ulint           count = 0;
2022  
2023 -       ut_ad(buf_pool_mutex_own(buf_pool));
2024 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2025  
2026         /* If we have flushed enough, leave the loop */
2027         do {
2028 @@ -1633,6 +1656,7 @@
2029  
2030                 if (bpage) {
2031                         ut_a(bpage->oldest_modification > 0);
2032 +                       prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
2033                 }
2034  
2035                 if (!bpage || bpage->oldest_modification >= lsn_limit) {
2036 @@ -1674,9 +1698,17 @@
2037                                 break;
2038                         }
2039  
2040 -                       bpage = UT_LIST_GET_PREV(list, bpage);
2041 +                       bpage = UT_LIST_GET_PREV(flush_list, bpage);
2042  
2043 -                       ut_ad(!bpage || bpage->in_flush_list);
2044 +                       //ut_ad(!bpage || bpage->in_flush_list);
2045 +                       if (bpage != prev_bpage) {
2046 +                               /* the search might warp.. retrying */
2047 +                               buf_flush_list_mutex_exit(buf_pool);
2048 +                               break;
2049 +                       }
2050 +                       if (bpage) {
2051 +                               prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
2052 +                       }
2053  
2054                         buf_flush_list_mutex_exit(buf_pool);
2055  
2056 @@ -1685,7 +1717,7 @@
2057  
2058         } while (count < min_n && bpage != NULL && len > 0);
2059  
2060 -       ut_ad(buf_pool_mutex_own(buf_pool));
2061 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2062  
2063         return(count);
2064  }
2065 @@ -1724,13 +1756,15 @@
2066               || sync_thread_levels_empty_except_dict());
2067  #endif /* UNIV_SYNC_DEBUG */
2068  
2069 -       buf_pool_mutex_enter(buf_pool);
2070 +       //buf_pool_mutex_enter(buf_pool);
2071  
2072         /* Note: The buffer pool mutex is released and reacquired within
2073         the flush functions. */
2074         switch(flush_type) {
2075         case BUF_FLUSH_LRU:
2076 +               mutex_enter(&buf_pool->LRU_list_mutex);
2077                 count = buf_flush_LRU_list_batch(buf_pool, min_n);
2078 +               mutex_exit(&buf_pool->LRU_list_mutex);
2079                 break;
2080         case BUF_FLUSH_LIST:
2081                 count = buf_flush_flush_list_batch(buf_pool, min_n, lsn_limit);
2082 @@ -1739,7 +1773,7 @@
2083                 ut_error;
2084         }
2085  
2086 -       buf_pool_mutex_exit(buf_pool);
2087 +       //buf_pool_mutex_exit(buf_pool);
2088  
2089         buf_flush_buffered_writes();
2090  
2091 @@ -1995,7 +2029,7 @@
2092  retry:
2093         //buf_pool_mutex_enter(buf_pool);
2094         if (have_LRU_mutex)
2095 -               buf_pool_mutex_enter(buf_pool);
2096 +               mutex_enter(&buf_pool->LRU_list_mutex);
2097  
2098         n_replaceable = UT_LIST_GET_LEN(buf_pool->free);
2099  
2100 @@ -2012,15 +2046,15 @@
2101                         bpage = UT_LIST_GET_LAST(buf_pool->LRU);
2102                         continue;
2103                 }
2104 -               block_mutex = buf_page_get_mutex(bpage);
2105 -
2106 -               mutex_enter(block_mutex);
2107 +               block_mutex = buf_page_get_mutex_enter(bpage);
2108  
2109 -               if (buf_flush_ready_for_replace(bpage)) {
2110 +               if (block_mutex && buf_flush_ready_for_replace(bpage)) {
2111                         n_replaceable++;
2112                 }
2113  
2114 -               mutex_exit(block_mutex);
2115 +               if (block_mutex) {
2116 +                       mutex_exit(block_mutex);
2117 +               }
2118  
2119                 distance++;
2120  
2121 @@ -2029,7 +2063,7 @@
2122  
2123         //buf_pool_mutex_exit(buf_pool);
2124         if (have_LRU_mutex)
2125 -               buf_pool_mutex_exit(buf_pool);
2126 +               mutex_exit(&buf_pool->LRU_list_mutex);
2127  
2128         if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN(buf_pool)) {
2129  
2130 @@ -2228,7 +2262,7 @@
2131  
2132         ut_ad(buf_flush_list_mutex_own(buf_pool));
2133  
2134 -       UT_LIST_VALIDATE(list, buf_page_t, buf_pool->flush_list,
2135 +       UT_LIST_VALIDATE(flush_list, buf_page_t, buf_pool->flush_list,
2136                          ut_ad(ut_list_node_313->in_flush_list));
2137  
2138         bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
2139 @@ -2268,7 +2302,7 @@
2140                         rnode = rbt_next(buf_pool->flush_rbt, rnode);
2141                 }
2142  
2143 -               bpage = UT_LIST_GET_NEXT(list, bpage);
2144 +               bpage = UT_LIST_GET_NEXT(flush_list, bpage);
2145  
2146                 ut_a(!bpage || om >= bpage->oldest_modification);
2147         }
2148 --- a/storage/innobase/buf/buf0lru.c
2149 +++ b/storage/innobase/buf/buf0lru.c
2150 @@ -143,8 +143,9 @@
2151  void
2152  buf_LRU_block_free_hashed_page(
2153  /*===========================*/
2154 -       buf_block_t*    block); /*!< in: block, must contain a file page and
2155 +       buf_block_t*    block,  /*!< in: block, must contain a file page and
2156                                 be in a state where it can be freed */
2157 +       ibool           have_page_hash_mutex);
2158  
2159  /******************************************************************//**
2160  Determines if the unzip_LRU list should be used for evicting a victim
2161 @@ -154,15 +155,20 @@
2162  ibool
2163  buf_LRU_evict_from_unzip_LRU(
2164  /*=========================*/
2165 -       buf_pool_t*     buf_pool)
2166 +       buf_pool_t*     buf_pool,
2167 +       ibool           have_LRU_mutex)
2168  {
2169         ulint   io_avg;
2170         ulint   unzip_avg;
2171  
2172 -       ut_ad(buf_pool_mutex_own(buf_pool));
2173 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2174  
2175 +       if (!have_LRU_mutex)
2176 +               mutex_enter(&buf_pool->LRU_list_mutex);
2177         /* If the unzip_LRU list is empty, we can only use the LRU. */
2178         if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0) {
2179 +               if (!have_LRU_mutex)
2180 +                       mutex_exit(&buf_pool->LRU_list_mutex);
2181                 return(FALSE);
2182         }
2183  
2184 @@ -171,14 +177,20 @@
2185         decompressed pages in the buffer pool. */
2186         if (UT_LIST_GET_LEN(buf_pool->unzip_LRU)
2187             <= UT_LIST_GET_LEN(buf_pool->LRU) / 10) {
2188 +               if (!have_LRU_mutex)
2189 +                       mutex_exit(&buf_pool->LRU_list_mutex);
2190                 return(FALSE);
2191         }
2192  
2193         /* If eviction hasn't started yet, we assume by default
2194         that a workload is disk bound. */
2195         if (buf_pool->freed_page_clock == 0) {
2196 +               if (!have_LRU_mutex)
2197 +                       mutex_exit(&buf_pool->LRU_list_mutex);
2198                 return(TRUE);
2199         }
2200 +       if (!have_LRU_mutex)
2201 +               mutex_exit(&buf_pool->LRU_list_mutex);
2202  
2203         /* Calculate the average over past intervals, and add the values
2204         of the current interval. */
2205 @@ -246,18 +258,25 @@
2206         page_arr = ut_malloc(
2207                 sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE);
2208  
2209 -       buf_pool_mutex_enter(buf_pool);
2210 +       //buf_pool_mutex_enter(buf_pool);
2211 +       mutex_enter(&buf_pool->LRU_list_mutex);
2212         num_entries = 0;
2213  
2214  scan_again:
2215         bpage = UT_LIST_GET_LAST(buf_pool->LRU);
2216  
2217         while (bpage != NULL) {
2218 +               /* bpage->state,space,io_fix,buf_fix_count are protected by block_mutex at XtraDB */
2219 +               mutex_t*        block_mutex = buf_page_get_mutex_enter(bpage);
2220                 buf_page_t*     prev_bpage;
2221                 ibool           is_fixed;
2222  
2223                 prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
2224  
2225 +               if (UNIV_UNLIKELY(!block_mutex)) {
2226 +                       goto next_page;
2227 +               }
2228 +
2229                 ut_a(buf_page_in_file(bpage));
2230  
2231                 if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
2232 @@ -266,23 +285,27 @@
2233                         /* Compressed pages are never hashed.
2234                         Skip blocks of other tablespaces.
2235                         Skip I/O-fixed blocks (to be dealt with later). */
2236 +                       mutex_exit(block_mutex);
2237  next_page:
2238                         bpage = prev_bpage;
2239                         continue;
2240                 }
2241  
2242 -               mutex_enter(&((buf_block_t*) bpage)->mutex);
2243 +               //mutex_enter(&((buf_block_t*) bpage)->mutex);
2244                 is_fixed = bpage->buf_fix_count > 0
2245                         || !((buf_block_t*) bpage)->is_hashed;
2246 -               mutex_exit(&((buf_block_t*) bpage)->mutex);
2247 +               //mutex_exit(&((buf_block_t*) bpage)->mutex);
2248  
2249                 if (is_fixed) {
2250 +                       mutex_exit(block_mutex);
2251                         goto next_page;
2252                 }
2253  
2254                 /* Store the page number so that we can drop the hash
2255                 index in a batch later. */
2256                 page_arr[num_entries] = bpage->offset;
2257 +               mutex_exit(block_mutex);
2258 +
2259                 ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
2260                 ++num_entries;
2261  
2262 @@ -292,14 +315,16 @@
2263  
2264                 /* Array full. We release the buf_pool->mutex to obey
2265                 the latching order. */
2266 -               buf_pool_mutex_exit(buf_pool);
2267 +               //buf_pool_mutex_exit(buf_pool);
2268 +               mutex_exit(&buf_pool->LRU_list_mutex);
2269  
2270                 buf_LRU_drop_page_hash_batch(
2271                         id, zip_size, page_arr, num_entries);
2272  
2273                 num_entries = 0;
2274  
2275 -               buf_pool_mutex_enter(buf_pool);
2276 +               //buf_pool_mutex_enter(buf_pool);
2277 +               mutex_enter(&buf_pool->LRU_list_mutex);
2278  
2279                 /* Note that we released the buf_pool mutex above
2280                 after reading the prev_bpage during processing of a
2281 @@ -317,13 +342,23 @@
2282                 /* If, however, bpage has been removed from LRU list
2283                 to the free list then we should restart the scan.
2284                 bpage->state is protected by buf_pool mutex. */
2285 +
2286 +               /* obtain block_mutex again to avoid race condition of bpage->state */
2287 +               block_mutex = buf_page_get_mutex_enter(bpage);
2288 +               if (!block_mutex) {
2289 +                       goto scan_again;
2290 +               }
2291 +
2292                 if (bpage
2293                     && buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
2294 +                       mutex_exit(block_mutex);
2295                         goto scan_again;
2296                 }
2297 +               mutex_exit(block_mutex);
2298         }
2299  
2300 -       buf_pool_mutex_exit(buf_pool);
2301 +       //buf_pool_mutex_exit(buf_pool);
2302 +       mutex_exit(&buf_pool->LRU_list_mutex);
2303  
2304         /* Drop any remaining batch of search hashed pages. */
2305         buf_LRU_drop_page_hash_batch(id, zip_size, page_arr, num_entries);
2306 @@ -345,7 +380,9 @@
2307         ibool           all_freed;
2308  
2309  scan_again:
2310 -       buf_pool_mutex_enter(buf_pool);
2311 +       //buf_pool_mutex_enter(buf_pool);
2312 +       mutex_enter(&buf_pool->LRU_list_mutex);
2313 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
2314  
2315         all_freed = TRUE;
2316  
2317 @@ -375,8 +412,15 @@
2318                         all_freed = FALSE;
2319                         goto next_page;
2320                 } else {
2321 -                       block_mutex = buf_page_get_mutex(bpage);
2322 -                       mutex_enter(block_mutex);
2323 +                       block_mutex = buf_page_get_mutex_enter(bpage);
2324 +
2325 +                       if (!block_mutex) {
2326 +                               /* It may be impossible case...
2327 +                               Something wrong, so will be scan_again */
2328 +
2329 +                               all_freed = FALSE;
2330 +                               goto next_page;
2331 +                       }
2332  
2333                         if (bpage->buf_fix_count > 0) {
2334  
2335 @@ -409,7 +453,9 @@
2336                         ulint   page_no;
2337                         ulint   zip_size;
2338  
2339 -                       buf_pool_mutex_exit(buf_pool);
2340 +                       //buf_pool_mutex_exit(buf_pool);
2341 +                       mutex_exit(&buf_pool->LRU_list_mutex);
2342 +                       rw_lock_x_unlock(&buf_pool->page_hash_latch);
2343  
2344                         zip_size = buf_page_get_zip_size(bpage);
2345                         page_no = buf_page_get_page_no(bpage);
2346 @@ -433,7 +479,7 @@
2347  
2348                 if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
2349                     != BUF_BLOCK_ZIP_FREE) {
2350 -                       buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
2351 +                       buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
2352                         mutex_exit(block_mutex);
2353                 } else {
2354                         /* The block_mutex should have been released
2355 @@ -446,7 +492,9 @@
2356                 bpage = prev_bpage;
2357         }
2358  
2359 -       buf_pool_mutex_exit(buf_pool);
2360 +       //buf_pool_mutex_exit(buf_pool);
2361 +       mutex_exit(&buf_pool->LRU_list_mutex);
2362 +       rw_lock_x_unlock(&buf_pool->page_hash_latch);
2363  
2364         if (!all_freed) {
2365                 os_thread_sleep(20000);
2366 @@ -493,7 +541,9 @@
2367         buf_page_t*     b;
2368         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2369  
2370 -       ut_ad(buf_pool_mutex_own(buf_pool));
2371 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2372 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2373 +       ut_ad(mutex_own(&buf_pool->zip_mutex));
2374         ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
2375  
2376         /* Find the first successor of bpage in the LRU list
2377 @@ -501,17 +551,17 @@
2378         b = bpage;
2379         do {
2380                 b = UT_LIST_GET_NEXT(LRU, b);
2381 -       } while (b && buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE);
2382 +       } while (b && (buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE || !b->in_LRU_list));
2383  
2384         /* Insert bpage before b, i.e., after the predecessor of b. */
2385         if (b) {
2386 -               b = UT_LIST_GET_PREV(list, b);
2387 +               b = UT_LIST_GET_PREV(zip_list, b);
2388         }
2389  
2390         if (b) {
2391 -               UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, bpage);
2392 +               UT_LIST_INSERT_AFTER(zip_list, buf_pool->zip_clean, b, bpage);
2393         } else {
2394 -               UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, bpage);
2395 +               UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, bpage);
2396         }
2397  }
2398  #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
2399 @@ -525,18 +575,19 @@
2400  buf_LRU_free_from_unzip_LRU_list(
2401  /*=============================*/
2402         buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
2403 -       ulint           n_iterations)   /*!< in: how many times this has
2404 +       ulint           n_iterations,   /*!< in: how many times this has
2405                                         been called repeatedly without
2406                                         result: a high value means that
2407                                         we should search farther; we will
2408                                         search n_iterations / 5 of the
2409                                         unzip_LRU list, or nothing if
2410                                         n_iterations >= 5 */
2411 +       ibool           have_LRU_mutex)
2412  {
2413         buf_block_t*    block;
2414         ulint           distance;
2415  
2416 -       ut_ad(buf_pool_mutex_own(buf_pool));
2417 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2418  
2419         /* Theoratically it should be much easier to find a victim
2420         from unzip_LRU as we can choose even a dirty block (as we'll
2421 @@ -546,7 +597,7 @@
2422         if we have done five iterations so far. */
2423  
2424         if (UNIV_UNLIKELY(n_iterations >= 5)
2425 -           || !buf_LRU_evict_from_unzip_LRU(buf_pool)) {
2426 +           || !buf_LRU_evict_from_unzip_LRU(buf_pool, have_LRU_mutex)) {
2427  
2428                 return(FALSE);
2429         }
2430 @@ -554,18 +605,25 @@
2431         distance = 100 + (n_iterations
2432                           * UT_LIST_GET_LEN(buf_pool->unzip_LRU)) / 5;
2433  
2434 +restart:
2435         for (block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
2436              UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
2437              block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
2438  
2439                 ibool freed;
2440  
2441 +               mutex_enter(&block->mutex);
2442 +               if (!block->in_unzip_LRU_list || !block->page.in_LRU_list
2443 +                   || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2444 +                       mutex_exit(&block->mutex);
2445 +                       goto restart;
2446 +               }
2447 +
2448                 ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2449                 ut_ad(block->in_unzip_LRU_list);
2450                 ut_ad(block->page.in_LRU_list);
2451  
2452 -               mutex_enter(&block->mutex);
2453 -               freed = buf_LRU_free_block(&block->page, FALSE);
2454 +               freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex);
2455                 mutex_exit(&block->mutex);
2456  
2457                 if (freed) {
2458 @@ -584,35 +642,46 @@
2459  buf_LRU_free_from_common_LRU_list(
2460  /*==============================*/
2461         buf_pool_t*     buf_pool,
2462 -       ulint           n_iterations)
2463 +       ulint           n_iterations,
2464                                 /*!< in: how many times this has been called
2465                                 repeatedly without result: a high value means
2466                                 that we should search farther; if
2467                                 n_iterations < 10, then we search
2468                                 n_iterations / 10 * buf_pool->curr_size
2469                                 pages from the end of the LRU list */
2470 +       ibool           have_LRU_mutex)
2471  {
2472         buf_page_t*     bpage;
2473         ulint           distance;
2474  
2475 -       ut_ad(buf_pool_mutex_own(buf_pool));
2476 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2477  
2478         distance = 100 + (n_iterations * buf_pool->curr_size) / 10;
2479  
2480 +restart:
2481         for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
2482              UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
2483              bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
2484  
2485                 ibool           freed;
2486                 unsigned        accessed;
2487 -               mutex_t*        block_mutex = buf_page_get_mutex(bpage);
2488 +               mutex_t*        block_mutex = buf_page_get_mutex_enter(bpage);
2489 +
2490 +               if (!block_mutex) {
2491 +                       goto restart;
2492 +               }
2493 +
2494 +               if (!bpage->in_LRU_list
2495 +                   || !buf_page_in_file(bpage)) {
2496 +                       mutex_exit(block_mutex);
2497 +                       goto restart;
2498 +               }
2499  
2500                 ut_ad(buf_page_in_file(bpage));
2501                 ut_ad(bpage->in_LRU_list);
2502  
2503 -               mutex_enter(block_mutex);
2504                 accessed = buf_page_is_accessed(bpage);
2505 -               freed = buf_LRU_free_block(bpage, TRUE);
2506 +               freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex);
2507                 mutex_exit(block_mutex);
2508  
2509                 if (freed) {
2510 @@ -649,16 +718,23 @@
2511                                 n_iterations / 5 of the unzip_LRU list. */
2512  {
2513         ibool   freed = FALSE;
2514 +       ibool   have_LRU_mutex = FALSE;
2515  
2516 -       buf_pool_mutex_enter(buf_pool);
2517 +       if (UT_LIST_GET_LEN(buf_pool->unzip_LRU))
2518 +               have_LRU_mutex = TRUE;
2519  
2520 -       freed = buf_LRU_free_from_unzip_LRU_list(buf_pool, n_iterations);
2521 +       //buf_pool_mutex_enter(buf_pool);
2522 +       if (have_LRU_mutex)
2523 +               mutex_enter(&buf_pool->LRU_list_mutex);
2524 +
2525 +       freed = buf_LRU_free_from_unzip_LRU_list(buf_pool, n_iterations, have_LRU_mutex);
2526  
2527         if (!freed) {
2528                 freed = buf_LRU_free_from_common_LRU_list(
2529 -                       buf_pool, n_iterations);
2530 +                       buf_pool, n_iterations, have_LRU_mutex);
2531         }
2532  
2533 +       buf_pool_mutex_enter(buf_pool);
2534         if (!freed) {
2535                 buf_pool->LRU_flush_ended = 0;
2536         } else if (buf_pool->LRU_flush_ended > 0) {
2537 @@ -666,6 +742,8 @@
2538         }
2539  
2540         buf_pool_mutex_exit(buf_pool);
2541 +       if (have_LRU_mutex)
2542 +               mutex_exit(&buf_pool->LRU_list_mutex);
2543  
2544         return(freed);
2545  }
2546 @@ -726,7 +804,9 @@
2547  
2548                 buf_pool = buf_pool_from_array(i);
2549  
2550 -               buf_pool_mutex_enter(buf_pool);
2551 +               //buf_pool_mutex_enter(buf_pool);
2552 +               mutex_enter(&buf_pool->LRU_list_mutex);
2553 +               mutex_enter(&buf_pool->free_list_mutex);
2554  
2555                 if (!recv_recovery_on
2556                     && UT_LIST_GET_LEN(buf_pool->free)
2557 @@ -736,7 +816,9 @@
2558                         ret = TRUE;
2559                 }
2560  
2561 -               buf_pool_mutex_exit(buf_pool);
2562 +               //buf_pool_mutex_exit(buf_pool);
2563 +               mutex_exit(&buf_pool->LRU_list_mutex);
2564 +               mutex_exit(&buf_pool->free_list_mutex);
2565         }
2566  
2567         return(ret);
2568 @@ -754,9 +836,10 @@
2569  {
2570         buf_block_t*    block;
2571  
2572 -       ut_ad(buf_pool_mutex_own(buf_pool));
2573 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2574  
2575 -       block = (buf_block_t*) UT_LIST_GET_FIRST(buf_pool->free);
2576 +       mutex_enter(&buf_pool->free_list_mutex);
2577 +       block = (buf_block_t*) UT_LIST_GET_LAST(buf_pool->free);
2578  
2579         if (block) {
2580  
2581 @@ -765,7 +848,9 @@
2582                 ut_ad(!block->page.in_flush_list);
2583                 ut_ad(!block->page.in_LRU_list);
2584                 ut_a(!buf_page_in_file(&block->page));
2585 -               UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
2586 +               UT_LIST_REMOVE(free, buf_pool->free, (&block->page));
2587 +
2588 +               mutex_exit(&buf_pool->free_list_mutex);
2589  
2590                 mutex_enter(&block->mutex);
2591  
2592 @@ -775,6 +860,8 @@
2593                 ut_ad(buf_pool_from_block(block) == buf_pool);
2594  
2595                 mutex_exit(&block->mutex);
2596 +       } else {
2597 +               mutex_exit(&buf_pool->free_list_mutex);
2598         }
2599  
2600         return(block);
2601 @@ -797,7 +884,7 @@
2602         ibool           mon_value_was   = FALSE;
2603         ibool           started_monitor = FALSE;
2604  loop:
2605 -       buf_pool_mutex_enter(buf_pool);
2606 +       //buf_pool_mutex_enter(buf_pool);
2607  
2608         if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
2609             + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 20) {
2610 @@ -865,7 +952,7 @@
2611  
2612         /* If there is a block in the free list, take it */
2613         block = buf_LRU_get_free_only(buf_pool);
2614 -       buf_pool_mutex_exit(buf_pool);
2615 +       //buf_pool_mutex_exit(buf_pool);
2616  
2617         if (block) {
2618                 ut_ad(buf_pool_from_block(block) == buf_pool);
2619 @@ -965,7 +1052,8 @@
2620         ulint   new_len;
2621  
2622         ut_a(buf_pool->LRU_old);
2623 -       ut_ad(buf_pool_mutex_own(buf_pool));
2624 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2625 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2626         ut_ad(buf_pool->LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN);
2627         ut_ad(buf_pool->LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX);
2628  #if BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)
2629 @@ -1031,7 +1119,8 @@
2630  {
2631         buf_page_t*     bpage;
2632  
2633 -       ut_ad(buf_pool_mutex_own(buf_pool));
2634 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2635 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2636         ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
2637  
2638         /* We first initialize all blocks in the LRU list as old and then use
2639 @@ -1066,13 +1155,14 @@
2640         ut_ad(buf_pool);
2641         ut_ad(bpage);
2642         ut_ad(buf_page_in_file(bpage));
2643 -       ut_ad(buf_pool_mutex_own(buf_pool));
2644 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2645 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2646  
2647         if (buf_page_belongs_to_unzip_LRU(bpage)) {
2648                 buf_block_t*    block = (buf_block_t*) bpage;
2649  
2650                 ut_ad(block->in_unzip_LRU_list);
2651 -               ut_d(block->in_unzip_LRU_list = FALSE);
2652 +               block->in_unzip_LRU_list = FALSE;
2653  
2654                 UT_LIST_REMOVE(unzip_LRU, buf_pool->unzip_LRU, block);
2655         }
2656 @@ -1090,7 +1180,8 @@
2657  
2658         ut_ad(buf_pool);
2659         ut_ad(bpage);
2660 -       ut_ad(buf_pool_mutex_own(buf_pool));
2661 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2662 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2663  
2664         ut_a(buf_page_in_file(bpage));
2665  
2666 @@ -1167,12 +1258,13 @@
2667  
2668         ut_ad(buf_pool);
2669         ut_ad(block);
2670 -       ut_ad(buf_pool_mutex_own(buf_pool));
2671 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2672 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2673  
2674         ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
2675  
2676         ut_ad(!block->in_unzip_LRU_list);
2677 -       ut_d(block->in_unzip_LRU_list = TRUE);
2678 +       block->in_unzip_LRU_list = TRUE;
2679  
2680         if (old) {
2681                 UT_LIST_ADD_LAST(unzip_LRU, buf_pool->unzip_LRU, block);
2682 @@ -1193,7 +1285,8 @@
2683  
2684         ut_ad(buf_pool);
2685         ut_ad(bpage);
2686 -       ut_ad(buf_pool_mutex_own(buf_pool));
2687 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2688 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2689  
2690         ut_a(buf_page_in_file(bpage));
2691  
2692 @@ -1244,7 +1337,8 @@
2693  
2694         ut_ad(buf_pool);
2695         ut_ad(bpage);
2696 -       ut_ad(buf_pool_mutex_own(buf_pool));
2697 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2698 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2699  
2700         ut_a(buf_page_in_file(bpage));
2701         ut_ad(!bpage->in_LRU_list);
2702 @@ -1323,7 +1417,8 @@
2703  {
2704         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2705  
2706 -       ut_ad(buf_pool_mutex_own(buf_pool));
2707 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2708 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2709  
2710         if (bpage->old) {
2711                 buf_pool->stat.n_pages_made_young++;
2712 @@ -1362,17 +1457,18 @@
2713  buf_LRU_free_block(
2714  /*===============*/
2715         buf_page_t*     bpage,  /*!< in: block to be freed */
2716 -       ibool           zip)    /*!< in: TRUE if should remove also the
2717 +       ibool           zip,    /*!< in: TRUE if should remove also the
2718                                 compressed page of an uncompressed page */
2719 +       ibool           have_LRU_mutex)
2720  {
2721         buf_page_t*     b = NULL;
2722         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2723         mutex_t*        block_mutex = buf_page_get_mutex(bpage);
2724  
2725 -       ut_ad(buf_pool_mutex_own(buf_pool));
2726 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2727         ut_ad(mutex_own(block_mutex));
2728         ut_ad(buf_page_in_file(bpage));
2729 -       ut_ad(bpage->in_LRU_list);
2730 +       //ut_ad(bpage->in_LRU_list);
2731         ut_ad(!bpage->in_flush_list == !bpage->oldest_modification);
2732  #if UNIV_WORD_SIZE == 4
2733         /* On 32-bit systems, there is no padding in buf_page_t.  On
2734 @@ -1381,7 +1477,7 @@
2735         UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
2736  #endif
2737  
2738 -       if (!buf_page_can_relocate(bpage)) {
2739 +       if (!bpage->in_LRU_list || !block_mutex || !buf_page_can_relocate(bpage)) {
2740  
2741                 /* Do not free buffer-fixed or I/O-fixed blocks. */
2742                 return(FALSE);
2743 @@ -1415,7 +1511,7 @@
2744  alloc:
2745                 b = buf_page_alloc_descriptor();
2746                 ut_a(b);
2747 -               memcpy(b, bpage, sizeof *b);
2748 +               //memcpy(b, bpage, sizeof *b);
2749         }
2750  
2751  #ifdef UNIV_DEBUG
2752 @@ -1426,6 +1522,39 @@
2753         }
2754  #endif /* UNIV_DEBUG */
2755  
2756 +       /* not to break latch order, must re-enter block_mutex */
2757 +       mutex_exit(block_mutex);
2758 +
2759 +       if (!have_LRU_mutex)
2760 +               mutex_enter(&buf_pool->LRU_list_mutex); /* optimistic */
2761 +       rw_lock_x_lock(&buf_pool->page_hash_latch);
2762 +       mutex_enter(block_mutex);
2763 +
2764 +       /* recheck states of block */
2765 +       if (!bpage->in_LRU_list || block_mutex != buf_page_get_mutex(bpage)
2766 +           || !buf_page_can_relocate(bpage)) {
2767 +not_freed:
2768 +               if (b) {
2769 +                       buf_buddy_free(buf_pool, b, sizeof *b, TRUE);
2770 +               }
2771 +               if (!have_LRU_mutex)
2772 +                       mutex_exit(&buf_pool->LRU_list_mutex);
2773 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
2774 +               return(FALSE);
2775 +       } else if (zip || !bpage->zip.data) {
2776 +               if (bpage->oldest_modification)
2777 +                       goto not_freed;
2778 +       } else if (bpage->oldest_modification) {
2779 +               if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
2780 +                       ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY);
2781 +                       goto not_freed;
2782 +               }
2783 +       }
2784 +
2785 +       if (b) {
2786 +               memcpy(b, bpage, sizeof *b);
2787 +       }
2788 +
2789         if (buf_LRU_block_remove_hashed_page(bpage, zip)
2790             != BUF_BLOCK_ZIP_FREE) {
2791                 ut_a(bpage->buf_fix_count == 0);
2792 @@ -1442,6 +1571,10 @@
2793  
2794                         ut_a(!hash_b);
2795  
2796 +                       while (prev_b && !prev_b->in_LRU_list) {
2797 +                               prev_b = UT_LIST_GET_PREV(LRU, prev_b);
2798 +                       }
2799 +
2800                         b->state = b->oldest_modification
2801                                 ? BUF_BLOCK_ZIP_DIRTY
2802                                 : BUF_BLOCK_ZIP_PAGE;
2803 @@ -1517,6 +1650,7 @@
2804                                 buf_LRU_add_block_low(b, buf_page_is_old(b));
2805                         }
2806  
2807 +                       mutex_enter(&buf_pool->zip_mutex);
2808                         if (b->state == BUF_BLOCK_ZIP_PAGE) {
2809  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2810                                 buf_LRU_insert_zip_clean(b);
2811 @@ -1534,9 +1668,12 @@
2812                         buf_pool->mutex and block_mutex. */
2813                         b->buf_fix_count++;
2814                         b->io_fix = BUF_IO_READ;
2815 +                       mutex_exit(&buf_pool->zip_mutex);
2816                 }
2817  
2818 -               buf_pool_mutex_exit(buf_pool);
2819 +               //buf_pool_mutex_exit(buf_pool);
2820 +               mutex_exit(&buf_pool->LRU_list_mutex);
2821 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
2822                 mutex_exit(block_mutex);
2823  
2824                 /* Remove possible adaptive hash index on the page.
2825 @@ -1568,7 +1705,9 @@
2826                                 : BUF_NO_CHECKSUM_MAGIC);
2827                 }
2828  
2829 -               buf_pool_mutex_enter(buf_pool);
2830 +               //buf_pool_mutex_enter(buf_pool);
2831 +               if (have_LRU_mutex)
2832 +                       mutex_enter(&buf_pool->LRU_list_mutex);
2833                 mutex_enter(block_mutex);
2834  
2835                 if (b) {
2836 @@ -1578,13 +1717,17 @@
2837                         mutex_exit(&buf_pool->zip_mutex);
2838                 }
2839  
2840 -               buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
2841 +               buf_LRU_block_free_hashed_page((buf_block_t*) bpage, FALSE);
2842         } else {
2843                 /* The block_mutex should have been released by
2844                 buf_LRU_block_remove_hashed_page() when it returns
2845                 BUF_BLOCK_ZIP_FREE. */
2846                 ut_ad(block_mutex == &buf_pool->zip_mutex);
2847                 mutex_enter(block_mutex);
2848 +
2849 +               if (!have_LRU_mutex)
2850 +                       mutex_exit(&buf_pool->LRU_list_mutex);
2851 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
2852         }
2853  
2854         return(TRUE);
2855 @@ -1596,13 +1739,14 @@
2856  void
2857  buf_LRU_block_free_non_file_page(
2858  /*=============================*/
2859 -       buf_block_t*    block)  /*!< in: block, must not contain a file page */
2860 +       buf_block_t*    block,  /*!< in: block, must not contain a file page */
2861 +       ibool           have_page_hash_mutex)
2862  {
2863         void*           data;
2864         buf_pool_t*     buf_pool = buf_pool_from_block(block);
2865  
2866         ut_ad(block);
2867 -       ut_ad(buf_pool_mutex_own(buf_pool));
2868 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2869         ut_ad(mutex_own(&block->mutex));
2870  
2871         switch (buf_block_get_state(block)) {
2872 @@ -1636,18 +1780,21 @@
2873         if (data) {
2874                 block->page.zip.data = NULL;
2875                 mutex_exit(&block->mutex);
2876 -               buf_pool_mutex_exit_forbid(buf_pool);
2877 +               //buf_pool_mutex_exit_forbid(buf_pool);
2878  
2879                 buf_buddy_free(
2880 -                       buf_pool, data, page_zip_get_size(&block->page.zip));
2881 +                       buf_pool, data, page_zip_get_size(&block->page.zip),
2882 +                       have_page_hash_mutex);
2883  
2884 -               buf_pool_mutex_exit_allow(buf_pool);
2885 +               //buf_pool_mutex_exit_allow(buf_pool);
2886                 mutex_enter(&block->mutex);
2887                 page_zip_set_size(&block->page.zip, 0);
2888         }
2889  
2890 -       UT_LIST_ADD_FIRST(list, buf_pool->free, (&block->page));
2891 +       mutex_enter(&buf_pool->free_list_mutex);
2892 +       UT_LIST_ADD_FIRST(free, buf_pool->free, (&block->page));
2893         ut_d(block->page.in_free_list = TRUE);
2894 +       mutex_exit(&buf_pool->free_list_mutex);
2895  
2896         UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE);
2897  }
2898 @@ -1677,7 +1824,11 @@
2899         buf_pool_t*             buf_pool = buf_pool_from_bpage(bpage);
2900  
2901         ut_ad(bpage);
2902 -       ut_ad(buf_pool_mutex_own(buf_pool));
2903 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2904 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
2905 +#ifdef UNIV_SYNC_DEBUG
2906 +       ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
2907 +#endif
2908         ut_ad(mutex_own(buf_page_get_mutex(bpage)));
2909  
2910         ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
2911 @@ -1785,7 +1936,9 @@
2912  
2913  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2914                 mutex_exit(buf_page_get_mutex(bpage));
2915 -               buf_pool_mutex_exit(buf_pool);
2916 +               //buf_pool_mutex_exit(buf_pool);
2917 +               mutex_exit(&buf_pool->LRU_list_mutex);
2918 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
2919                 buf_print();
2920                 buf_LRU_print();
2921                 buf_validate();
2922 @@ -1807,17 +1960,17 @@
2923                 ut_a(buf_page_get_zip_size(bpage));
2924  
2925  #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2926 -               UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
2927 +               UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, bpage);
2928  #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
2929  
2930                 mutex_exit(&buf_pool->zip_mutex);
2931 -               buf_pool_mutex_exit_forbid(buf_pool);
2932 +               //buf_pool_mutex_exit_forbid(buf_pool);
2933  
2934                 buf_buddy_free(
2935                         buf_pool, bpage->zip.data,
2936 -                       page_zip_get_size(&bpage->zip));
2937 +                       page_zip_get_size(&bpage->zip), TRUE);
2938  
2939 -               buf_pool_mutex_exit_allow(buf_pool);
2940 +               //buf_pool_mutex_exit_allow(buf_pool);
2941                 buf_page_free_descriptor(bpage);
2942                 return(BUF_BLOCK_ZIP_FREE);
2943  
2944 @@ -1839,13 +1992,13 @@
2945                         ut_ad(!bpage->in_flush_list);
2946                         ut_ad(!bpage->in_LRU_list);
2947                         mutex_exit(&((buf_block_t*) bpage)->mutex);
2948 -                       buf_pool_mutex_exit_forbid(buf_pool);
2949 +                       //buf_pool_mutex_exit_forbid(buf_pool);
2950  
2951                         buf_buddy_free(
2952                                 buf_pool, data,
2953 -                               page_zip_get_size(&bpage->zip));
2954 +                               page_zip_get_size(&bpage->zip), TRUE);
2955  
2956 -                       buf_pool_mutex_exit_allow(buf_pool);
2957 +                       //buf_pool_mutex_exit_allow(buf_pool);
2958                         mutex_enter(&((buf_block_t*) bpage)->mutex);
2959                         page_zip_set_size(&bpage->zip, 0);
2960                 }
2961 @@ -1871,18 +2024,19 @@
2962  void
2963  buf_LRU_block_free_hashed_page(
2964  /*===========================*/
2965 -       buf_block_t*    block)  /*!< in: block, must contain a file page and
2966 +       buf_block_t*    block,  /*!< in: block, must contain a file page and
2967                                 be in a state where it can be freed */
2968 +       ibool           have_page_hash_mutex)
2969  {
2970  #ifdef UNIV_DEBUG
2971 -       buf_pool_t*     buf_pool = buf_pool_from_block(block);
2972 -       ut_ad(buf_pool_mutex_own(buf_pool));
2973 +       //buf_pool_t*   buf_pool = buf_pool_from_block(block);
2974 +       //ut_ad(buf_pool_mutex_own(buf_pool));
2975  #endif
2976         ut_ad(mutex_own(&block->mutex));
2977  
2978         buf_block_set_state(block, BUF_BLOCK_MEMORY);
2979  
2980 -       buf_LRU_block_free_non_file_page(block);
2981 +       buf_LRU_block_free_non_file_page(block, have_page_hash_mutex);
2982  }
2983  
2984  /******************************************************************//**
2985 @@ -1897,7 +2051,7 @@
2986  {
2987         if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
2988             != BUF_BLOCK_ZIP_FREE) {
2989 -               buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
2990 +               buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
2991         }
2992  }
2993  
2994 @@ -1925,7 +2079,8 @@
2995         }
2996  
2997         if (adjust) {
2998 -               buf_pool_mutex_enter(buf_pool);
2999 +               //buf_pool_mutex_enter(buf_pool);
3000 +               mutex_enter(&buf_pool->LRU_list_mutex);
3001  
3002                 if (ratio != buf_pool->LRU_old_ratio) {
3003                         buf_pool->LRU_old_ratio = ratio;
3004 @@ -1937,7 +2092,8 @@
3005                         }
3006                 }
3007  
3008 -               buf_pool_mutex_exit(buf_pool);
3009 +               //buf_pool_mutex_exit(buf_pool);
3010 +               mutex_exit(&buf_pool->LRU_list_mutex);
3011         } else {
3012                 buf_pool->LRU_old_ratio = ratio;
3013         }
3014 @@ -2042,7 +2198,8 @@
3015         ulint           new_len;
3016  
3017         ut_ad(buf_pool);
3018 -       buf_pool_mutex_enter(buf_pool);
3019 +       //buf_pool_mutex_enter(buf_pool);
3020 +       mutex_enter(&buf_pool->LRU_list_mutex);
3021  
3022         if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
3023  
3024 @@ -2103,16 +2260,22 @@
3025  
3026         ut_a(buf_pool->LRU_old_len == old_len);
3027  
3028 -       UT_LIST_VALIDATE(list, buf_page_t, buf_pool->free,
3029 +       mutex_exit(&buf_pool->LRU_list_mutex);
3030 +       mutex_enter(&buf_pool->free_list_mutex);
3031 +
3032 +       UT_LIST_VALIDATE(free, buf_page_t, buf_pool->free,
3033                          ut_ad(ut_list_node_313->in_free_list));
3034  
3035         for (bpage = UT_LIST_GET_FIRST(buf_pool->free);
3036              bpage != NULL;
3037 -            bpage = UT_LIST_GET_NEXT(list, bpage)) {
3038 +            bpage = UT_LIST_GET_NEXT(free, bpage)) {
3039  
3040                 ut_a(buf_page_get_state(bpage) == BUF_BLOCK_NOT_USED);
3041         }
3042  
3043 +       mutex_exit(&buf_pool->free_list_mutex);
3044 +       mutex_enter(&buf_pool->LRU_list_mutex);
3045 +
3046         UT_LIST_VALIDATE(unzip_LRU, buf_block_t, buf_pool->unzip_LRU,
3047                          ut_ad(ut_list_node_313->in_unzip_LRU_list
3048                                && ut_list_node_313->page.in_LRU_list));
3049 @@ -2126,7 +2289,8 @@
3050                 ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
3051         }
3052  
3053 -       buf_pool_mutex_exit(buf_pool);
3054 +       //buf_pool_mutex_exit(buf_pool);
3055 +       mutex_exit(&buf_pool->LRU_list_mutex);
3056  }
3057  
3058  /**********************************************************************//**
3059 @@ -2162,7 +2326,8 @@
3060         const buf_page_t*       bpage;
3061  
3062         ut_ad(buf_pool);
3063 -       buf_pool_mutex_enter(buf_pool);
3064 +       //buf_pool_mutex_enter(buf_pool);
3065 +       mutex_enter(&buf_pool->LRU_list_mutex);
3066  
3067         bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
3068  
3069 @@ -2219,7 +2384,8 @@
3070                 bpage = UT_LIST_GET_NEXT(LRU, bpage);
3071         }
3072  
3073 -       buf_pool_mutex_exit(buf_pool);
3074 +       //buf_pool_mutex_exit(buf_pool);
3075 +       mutex_exit(&buf_pool->LRU_list_mutex);
3076  }
3077  
3078  /**********************************************************************//**
3079 --- a/storage/innobase/buf/buf0rea.c
3080 +++ b/storage/innobase/buf/buf0rea.c
3081 @@ -478,6 +478,7 @@
3082  
3083                 return(0);
3084         }
3085 +       buf_pool_mutex_exit(buf_pool);
3086  
3087         /* Check that almost all pages in the area have been accessed; if
3088         offset == low, the accesses must be in a descending order, otherwise,
3089 @@ -496,6 +497,7 @@
3090  
3091         fail_count = 0;
3092  
3093 +       rw_lock_s_lock(&buf_pool->page_hash_latch);
3094         for (i = low; i < high; i++) {
3095                 bpage = buf_page_hash_get(buf_pool, space, i);
3096  
3097 @@ -523,7 +525,8 @@
3098  
3099                 if (fail_count > threshold) {
3100                         /* Too many failures: return */
3101 -                       buf_pool_mutex_exit(buf_pool);
3102 +                       //buf_pool_mutex_exit(buf_pool);
3103 +                       rw_lock_s_unlock(&buf_pool->page_hash_latch);
3104                         return(0);
3105                 }
3106  
3107 @@ -538,7 +541,8 @@
3108         bpage = buf_page_hash_get(buf_pool, space, offset);
3109  
3110         if (bpage == NULL) {
3111 -               buf_pool_mutex_exit(buf_pool);
3112 +               //buf_pool_mutex_exit(buf_pool);
3113 +               rw_lock_s_unlock(&buf_pool->page_hash_latch);
3114  
3115                 return(0);
3116         }
3117 @@ -564,7 +568,8 @@
3118         pred_offset = fil_page_get_prev(frame);
3119         succ_offset = fil_page_get_next(frame);
3120  
3121 -       buf_pool_mutex_exit(buf_pool);
3122 +       //buf_pool_mutex_exit(buf_pool);
3123 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
3124  
3125         if ((offset == low) && (succ_offset == offset + 1)) {
3126  
3127 --- a/storage/innobase/handler/ha_innodb.cc
3128 +++ b/storage/innobase/handler/ha_innodb.cc
3129 @@ -265,6 +265,10 @@
3130  #  endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
3131         {&buf_pool_mutex_key, "buf_pool_mutex", 0},
3132         {&buf_pool_zip_mutex_key, "buf_pool_zip_mutex", 0},
3133 +       {&buf_pool_LRU_list_mutex_key, "buf_pool_LRU_list_mutex", 0},
3134 +       {&buf_pool_free_list_mutex_key, "buf_pool_free_list_mutex", 0},
3135 +       {&buf_pool_zip_free_mutex_key, "buf_pool_zip_free_mutex", 0},
3136 +       {&buf_pool_zip_hash_mutex_key, "buf_pool_zip_hash_mutex", 0},
3137         {&cache_last_read_mutex_key, "cache_last_read_mutex", 0},
3138         {&dict_foreign_err_mutex_key, "dict_foreign_err_mutex", 0},
3139         {&dict_sys_mutex_key, "dict_sys_mutex", 0},
3140 @@ -314,6 +318,7 @@
3141         {&archive_lock_key, "archive_lock", 0},
3142  #  endif /* UNIV_LOG_ARCHIVE */
3143         {&btr_search_latch_key, "btr_search_latch", 0},
3144 +       {&buf_pool_page_hash_key, "buf_pool_page_hash_latch", 0},
3145  #  ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
3146         {&buf_block_lock_key, "buf_block_lock", 0},
3147  #  endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
3148 --- a/storage/innobase/handler/i_s.cc
3149 +++ b/storage/innobase/handler/i_s.cc
3150 @@ -1583,7 +1583,8 @@
3151  
3152                 buf_pool = buf_pool_from_array(i);
3153  
3154 -               buf_pool_mutex_enter(buf_pool);
3155 +               //buf_pool_mutex_enter(buf_pool);
3156 +               mutex_enter(&buf_pool->zip_free_mutex);
3157  
3158                 for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
3159                         buf_buddy_stat_t*       buddy_stat;
3160 @@ -1613,7 +1614,8 @@
3161                         }
3162                 }
3163  
3164 -               buf_pool_mutex_exit(buf_pool);
3165 +               //buf_pool_mutex_exit(buf_pool);
3166 +               mutex_exit(&buf_pool->zip_free_mutex);
3167  
3168                 if (status) {
3169                         break;
3170 --- a/storage/innobase/ibuf/ibuf0ibuf.c
3171 +++ b/storage/innobase/ibuf/ibuf0ibuf.c
3172 @@ -3821,9 +3821,11 @@
3173                 ulint           fold = buf_page_address_fold(space, page_no);
3174                 buf_pool_t*     buf_pool = buf_pool_get(space, page_no);
3175  
3176 -               buf_pool_mutex_enter(buf_pool);
3177 +               //buf_pool_mutex_enter(buf_pool);
3178 +               rw_lock_s_lock(&buf_pool->page_hash_latch);
3179                 bpage = buf_page_hash_get_low(buf_pool, space, page_no, fold);
3180 -               buf_pool_mutex_exit(buf_pool);
3181 +               //buf_pool_mutex_exit(buf_pool);
3182 +               rw_lock_s_unlock(&buf_pool->page_hash_latch);
3183  
3184                 if (UNIV_LIKELY_NULL(bpage)) {
3185                         /* A buffer pool watch has been set or the
3186 --- a/storage/innobase/include/buf0buddy.h
3187 +++ b/storage/innobase/include/buf0buddy.h
3188 @@ -49,11 +49,12 @@
3189         ulint           size,           /*!< in: compressed page size
3190                                         (between PAGE_ZIP_MIN_SIZE and
3191                                         UNIV_PAGE_SIZE) */
3192 -       ibool*          lru)            /*!< in: pointer to a variable
3193 +       ibool*          lru,            /*!< in: pointer to a variable
3194                                         that will be assigned TRUE if
3195                                         storage was allocated from the
3196                                         LRU list and buf_pool->mutex was
3197                                         temporarily released */
3198 +       ibool           have_page_hash_mutex)
3199         __attribute__((malloc, nonnull));
3200  
3201  /**********************************************************************//**
3202 @@ -66,8 +67,9 @@
3203                                         the block resides */
3204         void*           buf,            /*!< in: block to be freed, must not
3205                                         be pointed to by the buffer pool */
3206 -       ulint           size)           /*!< in: block size,
3207 +       ulint           size,           /*!< in: block size,
3208                                         up to UNIV_PAGE_SIZE */
3209 +       ibool           have_page_hash_mutex)
3210         __attribute__((nonnull));
3211  
3212  #ifndef UNIV_NONINL
3213 --- a/storage/innobase/include/buf0buddy.ic
3214 +++ b/storage/innobase/include/buf0buddy.ic
3215 @@ -45,11 +45,12 @@
3216         buf_pool_t*     buf_pool,       /*!< in/out: buffer pool instance */
3217         ulint           i,              /*!< in: index of buf_pool->zip_free[],
3218                                         or BUF_BUDDY_SIZES */
3219 -       ibool*          lru)            /*!< in: pointer to a variable that
3220 +       ibool*          lru,            /*!< in: pointer to a variable that
3221                                         will be assigned TRUE if storage was
3222                                         allocated from the LRU list and
3223                                         buf_pool->mutex was temporarily
3224                                         released */
3225 +       ibool           have_page_hash_mutex)
3226         __attribute__((malloc, nonnull));
3227  
3228  /**********************************************************************//**
3229 @@ -61,8 +62,9 @@
3230         buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
3231         void*           buf,            /*!< in: block to be freed, must not be
3232                                         pointed to by the buffer pool */
3233 -       ulint           i)              /*!< in: index of buf_pool->zip_free[],
3234 +       ulint           i,              /*!< in: index of buf_pool->zip_free[],
3235                                         or BUF_BUDDY_SIZES */
3236 +       ibool           have_page_hash_mutex)
3237         __attribute__((nonnull));
3238  
3239  /**********************************************************************//**
3240 @@ -101,19 +103,20 @@
3241         ulint           size,           /*!< in: compressed page size
3242                                         (between PAGE_ZIP_MIN_SIZE and
3243                                         UNIV_PAGE_SIZE) */
3244 -       ibool*          lru)            /*!< in: pointer to a variable
3245 +       ibool*          lru,            /*!< in: pointer to a variable
3246                                         that will be assigned TRUE if
3247                                         storage was allocated from the
3248                                         LRU list and buf_pool->mutex was
3249                                         temporarily released */
3250 +       ibool           have_page_hash_mutex)
3251  {
3252 -       ut_ad(buf_pool_mutex_own(buf_pool));
3253 +       //ut_ad(buf_pool_mutex_own(buf_pool));
3254         ut_ad(ut_is_2pow(size));
3255         ut_ad(size >= PAGE_ZIP_MIN_SIZE);
3256         ut_ad(size <= UNIV_PAGE_SIZE);
3257  
3258         return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size),
3259 -                                          lru));
3260 +                                          lru, have_page_hash_mutex));
3261  }
3262  
3263  /**********************************************************************//**
3264 @@ -126,15 +129,28 @@
3265                                         the block resides */
3266         void*           buf,            /*!< in: block to be freed, must not
3267                                         be pointed to by the buffer pool */
3268 -       ulint           size)           /*!< in: block size,
3269 +       ulint           size,           /*!< in: block size,
3270                                         up to UNIV_PAGE_SIZE */
3271 +       ibool           have_page_hash_mutex)
3272  {
3273 -       ut_ad(buf_pool_mutex_own(buf_pool));
3274 +       //ut_ad(buf_pool_mutex_own(buf_pool));
3275         ut_ad(ut_is_2pow(size));
3276         ut_ad(size >= PAGE_ZIP_MIN_SIZE);
3277         ut_ad(size <= UNIV_PAGE_SIZE);
3278  
3279 -       buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size));
3280 +       if (!have_page_hash_mutex) {
3281 +               mutex_enter(&buf_pool->LRU_list_mutex);
3282 +               rw_lock_x_lock(&buf_pool->page_hash_latch);
3283 +       }
3284 +
3285 +       mutex_enter(&buf_pool->zip_free_mutex);
3286 +       buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size), TRUE);
3287 +       mutex_exit(&buf_pool->zip_free_mutex);
3288 +
3289 +       if (!have_page_hash_mutex) {
3290 +               mutex_exit(&buf_pool->LRU_list_mutex);
3291 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
3292 +       }
3293  }
3294  
3295  #ifdef UNIV_MATERIALIZE
3296 --- a/storage/innobase/include/buf0buf.h
3297 +++ b/storage/innobase/include/buf0buf.h
3298 @@ -212,6 +212,20 @@
3299  /*==========================*/
3300  
3301  /********************************************************************//**
3302 +*/
3303 +UNIV_INLINE
3304 +void
3305 +buf_pool_page_hash_x_lock_all(void);
3306 +/*================================*/
3307 +
3308 +/********************************************************************//**
3309 +*/
3310 +UNIV_INLINE
3311 +void
3312 +buf_pool_page_hash_x_unlock_all(void);
3313 +/*==================================*/
3314 +
3315 +/********************************************************************//**
3316  Creates the buffer pool.
3317  @return        own: buf_pool object, NULL if not enough memory or error */
3318  UNIV_INTERN
3319 @@ -864,6 +878,15 @@
3320         const buf_page_t*       bpage)  /*!< in: pointer to control block */
3321         __attribute__((pure));
3322  
3323 +/*************************************************************************
3324 +Gets the mutex of a block and enter the mutex with consistency. */
3325 +UNIV_INLINE
3326 +mutex_t*
3327 +buf_page_get_mutex_enter(
3328 +/*=========================*/
3329 +       const buf_page_t*       bpage)  /*!< in: pointer to control block */
3330 +       __attribute__((pure));
3331 +
3332  /*********************************************************************//**
3333  Get the flush type of a page.
3334  @return        flush type */
3335 @@ -1345,7 +1368,7 @@
3336         All these are protected by buf_pool->mutex. */
3337         /* @{ */
3338  
3339 -       UT_LIST_NODE_T(buf_page_t) list;
3340 +       /* UT_LIST_NODE_T(buf_page_t) list; */
3341                                         /*!< based on state, this is a
3342                                         list node, protected either by
3343                                         buf_pool->mutex or by
3344 @@ -1373,6 +1396,10 @@
3345                                         BUF_BLOCK_REMOVE_HASH or
3346                                         BUF_BLOCK_READY_IN_USE. */
3347  
3348 +       /* resplit for optimistic use */
3349 +       UT_LIST_NODE_T(buf_page_t) free;
3350 +       UT_LIST_NODE_T(buf_page_t) flush_list;
3351 +       UT_LIST_NODE_T(buf_page_t) zip_list; /* zip_clean or zip_free[] */
3352  #ifdef UNIV_DEBUG
3353         ibool           in_flush_list;  /*!< TRUE if in buf_pool->flush_list;
3354                                         when buf_pool->flush_list_mutex is
3355 @@ -1465,11 +1492,11 @@
3356                                         a block is in the unzip_LRU list
3357                                         if page.state == BUF_BLOCK_FILE_PAGE
3358                                         and page.zip.data != NULL */
3359 -#ifdef UNIV_DEBUG
3360 +//#ifdef UNIV_DEBUG
3361         ibool           in_unzip_LRU_list;/*!< TRUE if the page is in the
3362                                         decompressed LRU list;
3363                                         used in debugging */
3364 -#endif /* UNIV_DEBUG */
3365 +//#endif /* UNIV_DEBUG */
3366         mutex_t         mutex;          /*!< mutex protecting this block:
3367                                         state (also protected by the buffer
3368                                         pool mutex), io_fix, buf_fix_count,
3369 @@ -1646,6 +1673,11 @@
3370                                         pool instance, protects compressed
3371                                         only pages (of type buf_page_t, not
3372                                         buf_block_t */
3373 +       mutex_t         LRU_list_mutex;
3374 +       rw_lock_t       page_hash_latch;
3375 +       mutex_t         free_list_mutex;
3376 +       mutex_t         zip_free_mutex;
3377 +       mutex_t         zip_hash_mutex;
3378         ulint           instance_no;    /*!< Array index of this buffer
3379                                         pool instance */
3380         ulint           old_pool_size;  /*!< Old pool size in bytes */
3381 @@ -1799,8 +1831,8 @@
3382  /** Test if a buffer pool mutex is owned. */
3383  #define buf_pool_mutex_own(b) mutex_own(&b->mutex)
3384  /** Acquire a buffer pool mutex. */
3385 +/* the buf_pool_mutex is changed the latch order */
3386  #define buf_pool_mutex_enter(b) do {           \
3387 -       ut_ad(!mutex_own(&b->zip_mutex));       \
3388         mutex_enter(&b->mutex);         \
3389  } while (0)
3390  
3391 --- a/storage/innobase/include/buf0buf.ic
3392 +++ b/storage/innobase/include/buf0buf.ic
3393 @@ -292,7 +292,7 @@
3394         case BUF_BLOCK_ZIP_FREE:
3395                 /* This is a free page in buf_pool->zip_free[].
3396                 Such pages should only be accessed by the buddy allocator. */
3397 -               ut_error;
3398 +               /* ut_error; */ /* optimistic */
3399                 break;
3400         case BUF_BLOCK_ZIP_PAGE:
3401         case BUF_BLOCK_ZIP_DIRTY:
3402 @@ -335,9 +335,16 @@
3403  {
3404         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3405  
3406 +       if (/*equivalent to buf_pool_watch_is_sentinel(buf_pool, bpage)*/
3407 +           bpage >= &buf_pool->watch[0]
3408 +           && bpage < &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
3409 +               /* TODO: this code is the interim. should be confirmed later. */
3410 +               return(&buf_pool->zip_mutex);
3411 +       }
3412 +
3413         switch (buf_page_get_state(bpage)) {
3414         case BUF_BLOCK_ZIP_FREE:
3415 -               ut_error;
3416 +               /* ut_error; */ /* optimistic */
3417                 return(NULL);
3418         case BUF_BLOCK_ZIP_PAGE:
3419         case BUF_BLOCK_ZIP_DIRTY:
3420 @@ -347,6 +354,28 @@
3421         }
3422  }
3423  
3424 +/*************************************************************************
3425 +Gets the mutex of a block and enter the mutex with consistency. */
3426 +UNIV_INLINE
3427 +mutex_t*
3428 +buf_page_get_mutex_enter(
3429 +/*=========================*/
3430 +       const buf_page_t*       bpage)  /*!< in: pointer to control block */
3431 +{
3432 +       mutex_t*        block_mutex;
3433 +
3434 +       while(1) {
3435 +               block_mutex = buf_page_get_mutex(bpage);
3436 +               if (!block_mutex)
3437 +                       return block_mutex;
3438 +
3439 +               mutex_enter(block_mutex);
3440 +               if (block_mutex == buf_page_get_mutex(bpage))
3441 +                       return block_mutex;
3442 +               mutex_exit(block_mutex);
3443 +       }
3444 +}
3445 +
3446  /*********************************************************************//**
3447  Get the flush type of a page.
3448  @return        flush type */
3449 @@ -443,8 +472,8 @@
3450         enum buf_io_fix io_fix) /*!< in: io_fix state */
3451  {
3452  #ifdef UNIV_DEBUG
3453 -       buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3454 -       ut_ad(buf_pool_mutex_own(buf_pool));
3455 +       //buf_pool_t*   buf_pool = buf_pool_from_bpage(bpage);
3456 +       //ut_ad(buf_pool_mutex_own(buf_pool));
3457  #endif
3458         ut_ad(mutex_own(buf_page_get_mutex(bpage)));
3459  
3460 @@ -474,14 +503,14 @@
3461         const buf_page_t*       bpage)  /*!< control block being relocated */
3462  {
3463  #ifdef UNIV_DEBUG
3464 -       buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3465 -       ut_ad(buf_pool_mutex_own(buf_pool));
3466 +       //buf_pool_t*   buf_pool = buf_pool_from_bpage(bpage);
3467 +       //ut_ad(buf_pool_mutex_own(buf_pool));
3468  #endif
3469         ut_ad(mutex_own(buf_page_get_mutex(bpage)));
3470         ut_ad(buf_page_in_file(bpage));
3471 -       ut_ad(bpage->in_LRU_list);
3472 +       //ut_ad(bpage->in_LRU_list);
3473  
3474 -       return(buf_page_get_io_fix(bpage) == BUF_IO_NONE
3475 +       return(bpage->in_LRU_list && bpage->io_fix == BUF_IO_NONE
3476                && bpage->buf_fix_count == 0);
3477  }
3478  
3479 @@ -495,8 +524,8 @@
3480         const buf_page_t*       bpage)  /*!< in: control block */
3481  {
3482  #ifdef UNIV_DEBUG
3483 -       buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3484 -       ut_ad(buf_pool_mutex_own(buf_pool));
3485 +       //buf_pool_t*   buf_pool = buf_pool_from_bpage(bpage);
3486 +       //ut_ad(buf_pool_mutex_own(buf_pool));
3487  #endif
3488         ut_ad(buf_page_in_file(bpage));
3489  
3490 @@ -516,7 +545,8 @@
3491         buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3492  #endif /* UNIV_DEBUG */
3493         ut_a(buf_page_in_file(bpage));
3494 -       ut_ad(buf_pool_mutex_own(buf_pool));
3495 +       //ut_ad(buf_pool_mutex_own(buf_pool));
3496 +       ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
3497         ut_ad(bpage->in_LRU_list);
3498  
3499  #ifdef UNIV_LRU_DEBUG
3500 @@ -563,9 +593,10 @@
3501         ulint           time_ms)        /*!< in: ut_time_ms() */
3502  {
3503  #ifdef UNIV_DEBUG
3504 -       buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3505 -       ut_ad(buf_pool_mutex_own(buf_pool));
3506 +       //buf_pool_t*   buf_pool = buf_pool_from_bpage(bpage);
3507 +       //ut_ad(buf_pool_mutex_own(buf_pool));
3508  #endif
3509 +       ut_ad(mutex_own(buf_page_get_mutex(bpage)));
3510         ut_a(buf_page_in_file(bpage));
3511  
3512         if (!bpage->access_time) {
3513 @@ -808,19 +839,19 @@
3514  /*===========*/
3515         buf_block_t*    block)  /*!< in, own: block to be freed */
3516  {
3517 -       buf_pool_t*     buf_pool = buf_pool_from_bpage((buf_page_t*)block);
3518 +       //buf_pool_t*   buf_pool = buf_pool_from_bpage((buf_page_t*)block);
3519  
3520 -       buf_pool_mutex_enter(buf_pool);
3521 +       //buf_pool_mutex_enter(buf_pool);
3522  
3523         mutex_enter(&block->mutex);
3524  
3525         ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
3526  
3527 -       buf_LRU_block_free_non_file_page(block);
3528 +       buf_LRU_block_free_non_file_page(block, FALSE);
3529  
3530         mutex_exit(&block->mutex);
3531  
3532 -       buf_pool_mutex_exit(buf_pool);
3533 +       //buf_pool_mutex_exit(buf_pool);
3534  }
3535  #endif /* !UNIV_HOTBACKUP */
3536  
3537 @@ -868,17 +899,17 @@
3538                                         page frame */
3539  {
3540         ib_uint64_t     lsn;
3541 -       mutex_t*        block_mutex = buf_page_get_mutex(bpage);
3542 -
3543 -       mutex_enter(block_mutex);
3544 +       mutex_t*        block_mutex = buf_page_get_mutex_enter(bpage);
3545  
3546 -       if (buf_page_in_file(bpage)) {
3547 +       if (block_mutex && buf_page_in_file(bpage)) {
3548                 lsn = bpage->newest_modification;
3549         } else {
3550                 lsn = 0;
3551         }
3552  
3553 -       mutex_exit(block_mutex);
3554 +       if (block_mutex) {
3555 +               mutex_exit(block_mutex);
3556 +       }
3557  
3558         return(lsn);
3559  }
3560 @@ -896,7 +927,7 @@
3561  #ifdef UNIV_SYNC_DEBUG
3562         buf_pool_t*     buf_pool = buf_pool_from_bpage((buf_page_t*)block);
3563  
3564 -       ut_ad((buf_pool_mutex_own(buf_pool)
3565 +       ut_ad((mutex_own(&buf_pool->LRU_list_mutex)
3566                && (block->page.buf_fix_count == 0))
3567               || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
3568  #endif /* UNIV_SYNC_DEBUG */
3569 @@ -1026,7 +1057,11 @@
3570         buf_page_t*     bpage;
3571  
3572         ut_ad(buf_pool);
3573 -       ut_ad(buf_pool_mutex_own(buf_pool));
3574 +       //ut_ad(buf_pool_mutex_own(buf_pool));
3575 +#ifdef UNIV_SYNC_DEBUG
3576 +       ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX)
3577 +             || rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_SHARED));
3578 +#endif
3579         ut_ad(fold == buf_page_address_fold(space, offset));
3580  
3581         /* Look for the page in the hash table */
3582 @@ -1111,11 +1146,13 @@
3583         const buf_page_t*       bpage;
3584         buf_pool_t*             buf_pool = buf_pool_get(space, offset);
3585  
3586 -       buf_pool_mutex_enter(buf_pool);
3587 +       //buf_pool_mutex_enter(buf_pool);
3588 +       rw_lock_s_lock(&buf_pool->page_hash_latch);
3589  
3590         bpage = buf_page_hash_get(buf_pool, space, offset);
3591  
3592 -       buf_pool_mutex_exit(buf_pool);
3593 +       //buf_pool_mutex_exit(buf_pool);
3594 +       rw_lock_s_unlock(&buf_pool->page_hash_latch);
3595  
3596         return(bpage != NULL);
3597  }
3598 @@ -1243,4 +1280,38 @@
3599                 buf_pool_mutex_exit(buf_pool);
3600         }
3601  }
3602 +
3603 +/********************************************************************//**
3604 +*/
3605 +UNIV_INLINE
3606 +void
3607 +buf_pool_page_hash_x_lock_all(void)
3608 +/*===============================*/
3609 +{
3610 +       ulint   i;
3611 +
3612 +       for (i = 0; i < srv_buf_pool_instances; i++) {
3613 +               buf_pool_t*     buf_pool;
3614 +
3615 +               buf_pool = buf_pool_from_array(i);
3616 +               rw_lock_x_lock(&buf_pool->page_hash_latch);
3617 +       }
3618 +}
3619 +
3620 +/********************************************************************//**
3621 +*/
3622 +UNIV_INLINE
3623 +void
3624 +buf_pool_page_hash_x_unlock_all(void)
3625 +/*=================================*/
3626 +{
3627 +       ulint   i;
3628 +
3629 +       for (i = 0; i < srv_buf_pool_instances; i++) {
3630 +               buf_pool_t*     buf_pool;
3631 +
3632 +               buf_pool = buf_pool_from_array(i);
3633 +               rw_lock_x_unlock(&buf_pool->page_hash_latch);
3634 +       }
3635 +}
3636  #endif /* !UNIV_HOTBACKUP */
3637 --- a/storage/innobase/include/buf0lru.h
3638 +++ b/storage/innobase/include/buf0lru.h
3639 @@ -100,8 +100,9 @@
3640  buf_LRU_free_block(
3641  /*===============*/
3642         buf_page_t*     bpage,  /*!< in: block to be freed */
3643 -       ibool           zip)    /*!< in: TRUE if should remove also the
3644 +       ibool           zip,    /*!< in: TRUE if should remove also the
3645                                 compressed page of an uncompressed page */
3646 +       ibool           have_LRU_mutex)
3647         __attribute__((nonnull));
3648  /******************************************************************//**
3649  Try to free a replaceable block.
3650 @@ -148,7 +149,8 @@
3651  void
3652  buf_LRU_block_free_non_file_page(
3653  /*=============================*/
3654 -       buf_block_t*    block); /*!< in: block, must not contain a file page */
3655 +       buf_block_t*    block,  /*!< in: block, must not contain a file page */
3656 +       ibool           have_page_hash_mutex);
3657  /******************************************************************//**
3658  Adds a block to the LRU list. */
3659  UNIV_INTERN
3660 --- a/storage/innobase/include/sync0rw.h
3661 +++ b/storage/innobase/include/sync0rw.h
3662 @@ -112,6 +112,7 @@
3663  extern mysql_pfs_key_t archive_lock_key;
3664  # endif /* UNIV_LOG_ARCHIVE */
3665  extern mysql_pfs_key_t btr_search_latch_key;
3666 +extern mysql_pfs_key_t buf_pool_page_hash_key;
3667  extern mysql_pfs_key_t buf_block_lock_key;
3668  # ifdef UNIV_SYNC_DEBUG
3669  extern mysql_pfs_key_t buf_block_debug_latch_key;
3670 --- a/storage/innobase/include/sync0sync.h
3671 +++ b/storage/innobase/include/sync0sync.h
3672 @@ -75,6 +75,10 @@
3673  extern mysql_pfs_key_t buffer_block_mutex_key;
3674  extern mysql_pfs_key_t buf_pool_mutex_key;
3675  extern mysql_pfs_key_t buf_pool_zip_mutex_key;
3676 +extern mysql_pfs_key_t buf_pool_LRU_list_mutex_key;
3677 +extern mysql_pfs_key_t buf_pool_free_list_mutex_key;
3678 +extern mysql_pfs_key_t buf_pool_zip_free_mutex_key;
3679 +extern mysql_pfs_key_t buf_pool_zip_hash_mutex_key;
3680  extern mysql_pfs_key_t cache_last_read_mutex_key;
3681  extern mysql_pfs_key_t dict_foreign_err_mutex_key;
3682  extern mysql_pfs_key_t dict_sys_mutex_key;
3683 @@ -667,7 +671,7 @@
3684  #define SYNC_TRX_SYS_HEADER    290
3685  #define        SYNC_PURGE_QUEUE        200
3686  #define SYNC_LOG               170
3687 -#define SYNC_LOG_FLUSH_ORDER   147
3688 +#define SYNC_LOG_FLUSH_ORDER   156
3689  #define SYNC_RECV              168
3690  #define        SYNC_WORK_QUEUE         162
3691  #define        SYNC_SEARCH_SYS_CONF    161     /* for assigning btr_search_enabled */
3692 @@ -677,8 +681,13 @@
3693                                         SYNC_SEARCH_SYS, as memory allocation
3694                                         can call routines there! Otherwise
3695                                         the level is SYNC_MEM_HASH. */
3696 +#define        SYNC_BUF_LRU_LIST       158
3697 +#define        SYNC_BUF_PAGE_HASH      157
3698 +#define        SYNC_BUF_BLOCK          155     /* Block mutex */
3699 +#define        SYNC_BUF_FREE_LIST      153
3700 +#define        SYNC_BUF_ZIP_FREE       152
3701 +#define        SYNC_BUF_ZIP_HASH       151
3702  #define        SYNC_BUF_POOL           150     /* Buffer pool mutex */
3703 -#define        SYNC_BUF_BLOCK          146     /* Block mutex */
3704  #define        SYNC_BUF_FLUSH_LIST     145     /* Buffer flush list mutex */
3705  #define SYNC_DOUBLEWRITE       140
3706  #define        SYNC_ANY_LATCH          135
3707 @@ -709,7 +718,7 @@
3708                 os_fast_mutex;  /*!< We use this OS mutex in place of lock_word
3709                                 when atomic operations are not enabled */
3710  #endif
3711 -       ulint   waiters;        /*!< This ulint is set to 1 if there are (or
3712 +       volatile ulint  waiters;        /*!< This ulint is set to 1 if there are (or
3713                                 may be) threads waiting in the global wait
3714                                 array for this mutex to be released.
3715                                 Otherwise, this is 0. */
3716 --- a/storage/innobase/srv/srv0srv.c
3717 +++ b/storage/innobase/srv/srv0srv.c
3718 @@ -3102,7 +3102,7 @@
3719                                                                 level += log_sys->max_checkpoint_age
3720                                                                          - (lsn - oldest_modification);
3721                                                         }
3722 -                                                       bpage = UT_LIST_GET_NEXT(list, bpage);
3723 +                                                       bpage = UT_LIST_GET_NEXT(flush_list, bpage);
3724                                                         n_blocks++;
3725                                                 }
3726  
3727 @@ -3188,7 +3188,7 @@
3728                                                         found = TRUE;
3729                                                         break;
3730                                                 }
3731 -                                               bpage = UT_LIST_GET_NEXT(list, bpage);
3732 +                                               bpage = UT_LIST_GET_NEXT(flush_list, bpage);
3733                                                 new_blocks_num++;
3734                                         }
3735                                         if (!found) {
3736 --- a/storage/innobase/sync/sync0sync.c
3737 +++ b/storage/innobase/sync/sync0sync.c
3738 @@ -285,7 +285,7 @@
3739         mutex->lock_word = 0;
3740  #endif
3741         mutex->event = os_event_create(NULL);
3742 -       mutex_set_waiters(mutex, 0);
3743 +       mutex->waiters = 0;
3744  #ifdef UNIV_DEBUG
3745         mutex->magic_n = MUTEX_MAGIC_N;
3746  #endif /* UNIV_DEBUG */
3747 @@ -464,6 +464,15 @@
3748         mutex_t*        mutex,  /*!< in: mutex */
3749         ulint           n)      /*!< in: value to set */
3750  {
3751 +#ifdef INNODB_RW_LOCKS_USE_ATOMICS
3752 +       ut_ad(mutex);
3753 +
3754 +       if (n) {
3755 +               os_compare_and_swap_ulint(&mutex->waiters, 0, 1);
3756 +       } else {
3757 +               os_compare_and_swap_ulint(&mutex->waiters, 1, 0);
3758 +       }
3759 +#else
3760         volatile ulint* ptr;            /* declared volatile to ensure that
3761                                         the value is stored to memory */
3762         ut_ad(mutex);
3763 @@ -472,6 +481,7 @@
3764  
3765         *ptr = n;               /* Here we assume that the write of a single
3766                                 word in memory is atomic */
3767 +#endif
3768  }
3769  
3770  /******************************************************************//**
3771 @@ -1234,7 +1244,12 @@
3772                         ut_error;
3773                 }
3774                 break;
3775 +       case SYNC_BUF_LRU_LIST:
3776         case SYNC_BUF_FLUSH_LIST:
3777 +       case SYNC_BUF_PAGE_HASH:
3778 +       case SYNC_BUF_FREE_LIST:
3779 +       case SYNC_BUF_ZIP_FREE:
3780 +       case SYNC_BUF_ZIP_HASH:
3781         case SYNC_BUF_POOL:
3782                 /* We can have multiple mutexes of this type therefore we
3783                 can only check whether the greater than condition holds. */
3784 @@ -1252,7 +1267,8 @@
3785                 buffer block (block->mutex or buf_pool->zip_mutex). */
3786                 if (!sync_thread_levels_g(array, level, FALSE)) {
3787                         ut_a(sync_thread_levels_g(array, level - 1, TRUE));
3788 -                       ut_a(sync_thread_levels_contain(array, SYNC_BUF_POOL));
3789 +                       /* the exact rule is not fixed yet, for now */
3790 +                       //ut_a(sync_thread_levels_contain(array, SYNC_BUF_LRU_LIST));
3791                 }
3792                 break;
3793         case SYNC_REC_LOCK:
This page took 0.357163 seconds and 4 git commands to generate.