lp:~laurynas-biveinis/percona-server/bpage-io-fix

Created by Laurynas Biveinis and last modified
Get this branch:
bzr branch lp:~laurynas-biveinis/percona-server/bpage-io-fix
Only Laurynas Biveinis can upload to this branch. If you are Laurynas Biveinis please log in for upload directions.

Branch merges

Related bugs

Related blueprints

Branch information

Recent revisions

418. By Laurynas Biveinis

Fix:

- bug 934377 (InnoDB: Failing assertion: (buf_pool->flush_list).count
  > 0 [ in buf_flush_remove - buf0flu.c ] {Was: Crash in insert
  benchmark}),

- bug 1110102 (Failing assertion: bpage->in_flush_list in file
  buf0lru.c line 459 and in file buf0flu.c line 522 | abort in
  buf_flush_remove),

- bug 1111211 (InnoDB: Failing assertion: bpage->oldest_modification
  != 0 in file buf0flu.c and buf0lru.c),

- bug 1116447 (Buffer page I/O fix race condition in
  buf_LRU_remove_all_pages()).

All these bugs share the same root cause, introduced by upstream
changes to improve the InnoDB DROP TABLE performance for the file per
table setting.

These changes resulted in dirty buf_page_get_io_fix() calls in several
LRU- and flush-list-scanning loops. In InnoDB it is OK to read the
I/O fix state by holding either one of the buffer pool or an
individual block mutex. This newly-introduced code thus does that
with the buffer pool mutex being held.

In XtraDB the I/O fix state is protected by the block mutex only, but
it was not being held here.

The individual failures caused by this are the following.

Bug 934377 and bug 1111211. One thread is performing an LRU- or flush
list flush. Let's say it stops at buf_flush_page() for a certain page
between ut_ad(buf_flush_ready_for_flush(bpage, flush_type)) and
buf_page_set_io_fix(bpage, BUF_IO_WRITE) calls. This thread holds the
buffer pool and block mutexes, does not hold the LRU nor flush list
mutexes. Another thread is performing a DROP or TRUNCATE for a
tablespace and arrives at buf_flush_or_remove_page() for the same
page. It holds the LRU and flush list mutexes, does not hold the
buffer pool nor block mutexes. It checks the block I/O fix to be
BUF_IO_NONE and proceeds to remove the block from the flush list.
Meanwhile the first thread proceeds with flushing the same block,
resulting in flush I/O completion routine unable to remove the flushed
block from the flush list. Fix by adjusting
buf_flush_or_remove_page() to check the page I/O fix second time
after the block mutex is acquired. If the page is I/O-fixed or not
on the flush list anymore, do not remove it from the flush list and
signal to buf_flush_or_remove_pages() to restart the flush list scan.
Update buf_flush_or_remove_pages() to check if any of its subroutines
indicate flush list pointer invalidation which requires the flush list
scan restart.

Bug 1110102. Similar as above, but the DROP TABLE thread is at
buf_flush_yield(), considering whether to buffer-fix the current flush
list page and to release all the mutexes. The race condition here may
result in the current thread yielding on the same page that is being
flushed by another thread, which will cause either an assert or a
failure to remove all the dropped tablespace pages from the flush
list. Fix by moving the block mutex acquisition earlier (it was in
buf_flush_yield() before) and rechecking the page I/O fix status.
Then either proceed with the yield or signal the flush list scan
restart to buf_flush_or_remove_pages().

Bug 1116447. The dirty call is in buf_LRU_remove_all_pages(),
potentially resulting in buf_LRU_block_remove_hashed_page() call on an
I/O-fixed page, which is the opposite of what was intended. Fixed by
moving the block mutex acquisition before the I/O fix state check.

Common for all bugs, also introduce new I/O fix readers
buf_page_get_io_fix_unlocked() and buf_block_get_io_fix_unlocked()
which behave exactly like the old readers, that is, do not assert that
any mutexes are held. The old readers are adjusted to assert that the
block mutex is being held. This way any new upstream merges will
require that the mutex is held by default and will fail immediatelly
in debug builds if it's not, forcing a manual merge and fix or
replacement with the _unlocked() version. Updated all safe callers to
use _unlocked() versions as necessary.

417. By <email address hidden>

Empty merge from Percona Server 5.1

416. By <email address hidden>

Merge lp:~laurynas-biveinis/percona-server/bug1083058-5.5

415. By <email address hidden>

Merge lp:~laurynas-biveinis/percona-server/BT-16274-bug1083669-5.5

414. By <email address hidden>

Merge lp:~laurynas-biveinis/percona-server/BT-16274-bug1083596-5.5

413. By <email address hidden>

Empty merge from Percona Server 5.1

412. By <email address hidden>

Merge lp:~laurynas-biveinis/percona-server/BT-16274-bug1082437-5.5

411. By <email address hidden>

Empty merge from Percona Server 5.1

410. By <email address hidden>

Merge lp:~laurynas-biveinis/percona-server/BT-16724-xtradb-bmp-requests-5.5

409. By <email address hidden>

Empty merge from Percona Server 5.1

Branch metadata

Branch format:
Branch format 7
Repository format:
Bazaar repository format 2a (needs bzr 1.16 or later)
Stacked on:
lp:percona-server/5.5
This branch contains Public information 
Everyone can see this information.