[Draft] buf_page_get_mutex_enter() is used either redundantly, either dangerously

Bug #1220191 reported by Laurynas Biveinis
10
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Percona Server moved to https://jira.percona.com/projects/PS
Invalid
High
Unassigned
5.1
Won't Fix
High
Unassigned
5.5
Triaged
High
Unassigned
5.6
Invalid
High
Unassigned

Bug Description

This is a draft description for further analysis.

A port of buf_page_get_mutex_enter() from 5.5 to 5.6 showed that it is used either redundantly, either dangerously, and the port removed it. It needs to be seen whether that applies to it in 5.5 as well.

In 5.5 it is defined as

/*********************************************************************//**
Gets the mutex of a block.
@return pointer to mutex protecting bpage */
UNIV_INLINE
mutex_t*
buf_page_get_mutex(
/*===============*/
 const buf_page_t* bpage) /*!< in: pointer to control block */
{
 buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);

 if (/*equivalent to buf_pool_watch_is_sentinel(buf_pool, bpage)*/
     bpage >= &buf_pool->watch[0]
     && bpage < &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
  /* TODO: this code is the interim. should be confirmed later. */
  return(&buf_pool->zip_mutex);
 }

 switch (buf_page_get_state(bpage)) {
 case BUF_BLOCK_ZIP_FREE:
  /* ut_error; */ /* optimistic */
  return(NULL);
 case BUF_BLOCK_ZIP_PAGE:
 case BUF_BLOCK_ZIP_DIRTY:
  return(&buf_pool->zip_mutex);
 default:
  return(&((buf_block_t*) bpage)->mutex);
 }
}

/*************************************************************************
Gets the mutex of a block and enter the mutex with consistency. */
UNIV_INLINE
mutex_t*
buf_page_get_mutex_enter(
/*=========================*/
 const buf_page_t* bpage) /*!< in: pointer to control block */
{
 mutex_t* block_mutex;

 while(1) {
  block_mutex = buf_page_get_mutex(bpage);
  if (!block_mutex)
   return block_mutex;

  mutex_enter(block_mutex);
  if (block_mutex == buf_page_get_mutex(bpage))
   return block_mutex;
  mutex_exit(block_mutex);
 }
}

It hard to say what "consistency" in "enter the mutex with consistency" means.

It appears to protect from the buffer page state transition race conditions, namely, from the page moving between BUF_POOL_BLOCK_WATCH|BUF_BLOCK_ZIP_PAGE|BUF_BLOCK_ZIP_DIRTY and BUF_BLOCK_ZIP_FREE and all the remaining states. The sets of these states is defined by the patched-in-XtraDB buf_page_get_mutex(). Were it not patched, then the sets of the states would be BUF_BLOCK_ZIP_PAGE|BUF_BLOCK_ZIP_DIRTY and everything else, with BUF_BLOCK_ZIP_FREE forbidden.

The buffer page state transitions are protected by buffer pool mutexes, thus this appears to handle the situation where none are held. But then, depending on where the bpage pointer was taken from, the pointer itself may become invalid if it points not to a buffer pool frame but to a compressed page descriptor that might get freed. Then the protection offered by buf_page_get_mutex_enter() is useless too. If it can be proven that bpage may not become invalid, then most probably its state may not change neither and simple buf_page_get_mutex/mutex_enter call pair is enough. In the worst case (this is why this bug is here), the bpage may indeed become invalid and the correct locking must be ensured.

tags: added: bp-split xtradb
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

buf_page_get_mutex() patch to handle BUF_BLOCK_ZIP_FREE and BUF_BLOCK_POOL_WATCH is suspicious on its own too.

Revision history for this message
Roel Van de Paar (roel11) wrote :

Confirmed not a 5.6 issue as per email Laurynas

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Bug 1250762 might be related.

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Bug 1250762 not related.

Revision history for this message
Shahriyar Rzayev (rzayev-sehriyar) wrote :

Percona now uses JIRA for bug reports so this bug report is migrated to: https://jira.percona.com/browse/PS-717

Changed in percona-server:
assignee: Laurynas Biveinis (laurynas-biveinis) → nobody
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Related blueprints

Remote bug watches

Bug watches keep track of this bug in other bug trackers.