Introduce a reduced doublewrite mode, handling error detection only

Summary:
Feature: Reduced Double-Write Mode

Introduce a new double write mode where only the page ids and space ids
are written to the double write buffer but not the entire page. We can
use these page numbers and space ids to determine whether any pages that
were written to the disk (or flash) were torn. If there are torn pages,
crash recovery fails and the server must be recovered from some other
source.

The implementation makes innodb_doublewrite a dynamic sysvar that may
be set to 0, 1, or 2.

* innodb_doublewrite=0 and innodb_doublewrite=1 work the same way as
before. The former disables the doublewrite buffer while the latter
writes each page twice (plus extra overhead for compressed pages).

* When innodb_doublewrite=2, only the space ids and the page numbers of
flushed pages are written to the doublewrite buffer, in a single page.

* We disallow changing innodb_doublewrite between nonzero values and
zero dynamically. In order to turn the doublewrite buffer on or off,
the user must do a clean shutdown and then change the variable, just
as before. This is done to avoid changing innodb_doublewrite to zero
by accident.

* When innodb_doublewrite is changed from 1 to 2 or 2 to 1, a clean
version of the doublewrite buffer will be written to the disk before the
next batch doublewrite flush. This is done to make sure that the stale
pages do not override a corrupt page on disk in case the user changes
innodb_doublewrite from 1 to 2.

Note that the implementation doesn't really change anything about the
in-memory representation of the doublewrite buffer (buf_dblwr) aside
from adding a new field called 'header'. This field is used to serially
write the space_id s and page_no s of the pages that are flushed.

Because we read the value of innodb_doublewrite only in one place
(during batch flushing), we do not need to do anything special if the
user changes the value of innodb_doublewrite while the server is
running.  It will be consistent through the course of each write/flush.

During recovery, we determine which mode of doublewrite was used based
on the page type of the first doublewrite page. If the first page seems
to be a doublewrite header page then this page includes the space_ids
and page_nos of the recently flushed pages. In this case we simply
validate those pages based on their checksums.

5.6 introduced a new type of flush operation which flushes single pages
from the doublewrite buffer as opposed to flushing all of them.
Single-flushing seems to be rare so we still do double-writing in case
of a single-flush. This means that when mysqld starts, doublewrite
buffer may contain pages from both batch-flushes and single-flushes. For
this reason, we always scan the entire doublewrite buffer even when we
detect that the first double write page is a doublwrite header page.

Test Plan:
Introduced innodb_doublewrite.test (and ..._odirect.test) which calls
innodb_corrupt_doublewrite_pages.py. The latter intentionally corrupts a
random page that it finds in the doublewrite buffer, and starts mysqld.

* If innodb_doublewrite=1 we expect mysqld to successfully start after
recovering the corrupt page from the doublewrite buffer.

* if innodb_doublewrite=2 we expect mysqld to fail to recover.

For both cases, we check that the appropriate messages in the error log
appear to make sure mysqld behaved as expected.

These all pass:

mysqltest.sh --repeat=16 --parallel=4 \
	innodb.innodb_doublewrite \
	innodb.innodb_doublewrite_odirect \
	innodb.innodb_doublewrite \
	innodb.innodb_doublewrite_odirect

mysqltest.sh --release --repeat=16 --parallel=4 \
	innodb.innodb_doublewrite \
	innodb.innodb_doublewrite_odirect \
	innodb.innodb_doublewrite \
	innodb.innodb_doublewrite_odirect

mysqltest.sh --valgrind innodb.innodb_doublewrite

mysqltest.sh --valgrind innodb.innodb_doublewrite_odirect

Reviewers: pivanof, inaam-rana

Reviewed By: inaam-rana

Subscribers: WebScaleSQL, jtolmer

Differential Revision: https://reviews.facebook.net/D18939