summaryrefslogtreecommitdiff
path: root/storage/innobase/buf/buf0dblwr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/buf/buf0dblwr.cc')
-rw-r--r--storage/innobase/buf/buf0dblwr.cc275
1 files changed, 114 insertions, 161 deletions
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index ff1d2057e6a..4f83921a553 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -40,8 +40,6 @@ Created 2011/12/19
#include "fil0crypt.h"
#include "fil0pagecompress.h"
-#ifndef UNIV_HOTBACKUP
-
/** The doublewrite buffer */
buf_dblwr_t* buf_dblwr = NULL;
@@ -382,8 +380,6 @@ buf_dblwr_init_or_load_pages(
IORequest read_request(IORequest::READ);
- read_request.disable_compression();
-
err = os_file_read(
read_request,
file, read_buf, TRX_SYS_PAGE_NO * UNIV_PAGE_SIZE,
@@ -498,11 +494,6 @@ buf_dblwr_init_or_load_pages(
IORequest write_request(IORequest::WRITE);
- /* Recovered data file pages are written out
- as uncompressed. */
-
- write_request.disable_compression();
-
err = os_file_write(
write_request, path, file, page,
source_page_no * UNIV_PAGE_SIZE,
@@ -518,8 +509,9 @@ buf_dblwr_init_or_load_pages(
return(err);
}
- } else {
-
+ } else if (memcmp(field_ref_zero, page + FIL_PAGE_LSN, 8)) {
+ /* Each valid page header must contain
+ a nonzero FIL_PAGE_LSN field. */
recv_dblwr.add(page);
}
@@ -553,11 +545,9 @@ buf_dblwr_process(void)
for (recv_dblwr_t::list::iterator i = recv_dblwr.pages.begin();
i != recv_dblwr.pages.end();
++i, ++page_no_dblwr) {
- bool is_compressed = false;
-
- const byte* page = *i;
- ulint page_no = page_get_page_no(page);
- ulint space_id = page_get_space_id(page);
+ byte* page = *i;
+ ulint page_no = page_get_page_no(page);
+ ulint space_id = page_get_space_id(page);
fil_space_t* space = fil_space_get(space_id);
@@ -569,163 +559,130 @@ buf_dblwr_process(void)
fil_space_open_if_needed(space);
+ const page_id_t page_id(space_id, page_no);
+
if (page_no >= space->size) {
- /* Do not report the warning if the tablespace is
- schedule for truncate or was truncated and we have live
- MLOG_TRUNCATE record in redo. */
- bool skip_warning =
- srv_is_tablespace_truncated(space_id)
- || srv_was_tablespace_truncated(space);
-
- if (!skip_warning) {
- ib::warn() << "Page " << page_no_dblwr
- << " in the doublewrite buffer is"
- " not within space bounds: page "
- << page_id_t(space_id, page_no);
+ /* Do not report the warning if the tablespace
+ is scheduled for truncation or was truncated
+ and we have parsed an MLOG_TRUNCATE record. */
+ if (!srv_is_tablespace_truncated(space_id)
+ && !srv_was_tablespace_truncated(space)) {
+ ib::warn() << "A copy of page " << page_id
+ << " in the doublewrite buffer slot "
+ << page_no_dblwr
+ << " is not within space bounds";
}
- } else {
- const page_size_t page_size(space->flags);
- const page_id_t page_id(space_id, page_no);
+ continue;
+ }
- /* We want to ensure that for partial reads the
- unread portion of the page is NUL. */
- memset(read_buf, 0x0, page_size.physical());
+ const page_size_t page_size(space->flags);
+ ut_ad(!buf_page_is_zeroes(page, page_size));
- IORequest request;
+ /* We want to ensure that for partial reads the
+ unread portion of the page is NUL. */
+ memset(read_buf, 0x0, page_size.physical());
- request.dblwr_recover();
+ IORequest request;
- /* Read in the actual page from the file */
- dberr_t err = fil_io(
- request, true,
- page_id, page_size,
- 0, page_size.physical(), read_buf, NULL, NULL);
+ request.dblwr_recover();
- if (err != DB_SUCCESS) {
+ /* Read in the actual page from the file */
+ dberr_t err = fil_io(
+ request, true,
+ page_id, page_size,
+ 0, page_size.physical(), read_buf, NULL);
- ib::warn()
- << "Double write buffer recovery: "
- << page_id << " read failed with "
- << "error: " << ut_strerr(err);
- }
+ if (err != DB_SUCCESS) {
+ ib::warn()
+ << "Double write buffer recovery: "
+ << page_id << " read failed with "
+ << "error: " << ut_strerr(err);
+ }
- /* Is page compressed ? */
- is_compressed = fil_page_is_compressed_encrypted(read_buf) |
- fil_page_is_compressed(read_buf);
+ const bool is_all_zero = buf_page_is_zeroes(
+ read_buf, page_size);
- /* If page was compressed, decompress it before we
- check checksum. */
- if (is_compressed) {
- fil_decompress_page(NULL, read_buf, UNIV_PAGE_SIZE, NULL, true);
+ if (is_all_zero) {
+ /* We will check if the copy in the
+ doublewrite buffer is valid. If not, we will
+ ignore this page (there should be redo log
+ records to initialize it). */
+ } else {
+ if (fil_page_is_compressed_encrypted(read_buf) ||
+ fil_page_is_compressed(read_buf)) {
+ /* Decompress the page before
+ validating the checksum. */
+ fil_decompress_page(
+ NULL, read_buf, UNIV_PAGE_SIZE,
+ NULL, true);
}
- if (err != DB_SUCCESS) {
- ib::warn()
- << "Double write buffer recovery: "
- << page_id << " read failed with "
- << "error: " << ut_strerr(err);
+ if (fil_space_verify_crypt_checksum(
+ read_buf, page_size)
+ || !buf_page_is_corrupted(
+ true, read_buf, page_size, false)) {
+ /* The page is good; there is no need
+ to consult the doublewrite buffer. */
+ continue;
}
- if (fil_space_verify_crypt_checksum(read_buf, page_size)) {
-
- /* page is encrypted and checksum is OK */
- } else if (buf_page_is_corrupted(
- true, read_buf, page_size,
- fsp_is_checksum_disabled(space_id))) {
-
- ib::warn() << "Database page corruption or"
- << " a failed file read of page "
- << page_id
- << ". Trying to recover it from the"
- << " doublewrite buffer.";
-
- /* Is page compressed ? */
- is_compressed = fil_page_is_compressed_encrypted(page) |
- fil_page_is_compressed(page);
-
- /* If page was compressed, decompress it before we
- check checksum. */
- if (is_compressed) {
- fil_decompress_page(NULL, (byte*)page, UNIV_PAGE_SIZE, NULL, true);
- }
-
- if (fil_space_verify_crypt_checksum(page, page_size)) {
- /* the doublewrite buffer page is encrypted and OK */
- } else if (buf_page_is_corrupted(
- true, page, page_size,
- fsp_is_checksum_disabled(space_id))) {
-
- ib::error() << "Dump of the page:";
-
- buf_page_print(
- read_buf, page_size,
- BUF_PAGE_PRINT_NO_CRASH);
- ib::error() << "Dump of corresponding"
- " page in doublewrite buffer:";
-
- buf_page_print(
- page, page_size,
- BUF_PAGE_PRINT_NO_CRASH);
-
- ib::fatal() << "The page in the"
- " doublewrite buffer is"
- " corrupt. Cannot continue"
- " operation. You can try to"
- " recover the database with"
- " innodb_force_recovery=6";
- }
- } else if (buf_page_is_zeroes(read_buf, page_size)
- && !buf_page_is_zeroes(page, page_size)
- && !buf_page_is_corrupted(
- true, page, page_size,
- fsp_is_checksum_disabled(space_id))) {
-
- /* Database page contained only zeroes, while
- a valid copy is available in dblwr buffer. */
-
- } else {
-
- bool t1 = buf_page_is_zeroes(
- read_buf, page_size);
-
- bool t2 = buf_page_is_zeroes(page, page_size);
-
- bool t3 = buf_page_is_corrupted(
- true, page, page_size,
- fsp_is_checksum_disabled(space_id));
-
- if (t1 && !(t2 || t3)) {
+ /* We intentionally skip this message for
+ is_all_zero pages. */
+ ib::info()
+ << "Trying to recover page " << page_id
+ << " from the doublewrite buffer.";
+ }
- /* Database page contained only
- zeroes, while a valid copy is
- available in dblwr buffer. */
+ /* Next, validate the doublewrite page. */
+ if (fil_page_is_compressed_encrypted(page) ||
+ fil_page_is_compressed(page)) {
+ /* Decompress the page before
+ validating the checksum. */
+ fil_decompress_page(
+ NULL, page, UNIV_PAGE_SIZE, NULL, true);
+ }
- } else {
- continue;
- }
+ if (!fil_space_verify_crypt_checksum(page, page_size)
+ && buf_page_is_corrupted(true, page, page_size, false)) {
+ if (!is_all_zero) {
+ ib::warn() << "A doublewrite copy of page "
+ << page_id << " is corrupted.";
}
+ /* Theoretically we could have another good
+ copy for this page in the doublewrite
+ buffer. If not, we will report a fatal error
+ for a corrupted page somewhere else if that
+ page was truly needed. */
+ continue;
+ }
- /* Recovered data file pages are written out
- as uncompressed. */
-
- IORequest write_request(IORequest::WRITE);
+ if (page_no == 0) {
+ /* Check the FSP_SPACE_FLAGS. */
+ ulint flags = fsp_header_get_flags(page);
+ if (!fsp_flags_is_valid(flags)
+ && fsp_flags_convert_from_101(flags)
+ == ULINT_UNDEFINED) {
+ ib::warn() << "Ignoring a doublewrite copy"
+ " of page " << page_id
+ << " due to invalid flags "
+ << ib::hex(flags);
+ continue;
+ }
+ /* The flags on the page should be converted later. */
+ }
- write_request.disable_compression();
+ /* Write the good page from the doublewrite buffer to
+ the intended position. */
- /* Write the good page from the doublewrite
- buffer to the intended position. */
+ IORequest write_request(IORequest::WRITE);
- fil_io(write_request, true,
- page_id, page_size,
- 0, page_size.physical(),
- const_cast<byte*>(page), NULL, NULL);
+ fil_io(write_request, true, page_id, page_size,
+ 0, page_size.physical(),
+ const_cast<byte*>(page), NULL);
- ib::info()
- << "Recovered page "
- << page_id
- << " from the doublewrite buffer.";
- }
+ ib::info() << "Recovered page " << page_id
+ << " from the doublewrite buffer.";
}
recv_dblwr.pages.clear();
@@ -955,7 +912,7 @@ buf_dblwr_write_block_to_datafile(
type |= IORequest::DO_NOT_WAKE;
}
- IORequest request(type);
+ IORequest request(type, const_cast<buf_page_t*>(bpage));
/* We request frame here to get correct buffer in case of
encryption and/or page compression */
@@ -967,7 +924,7 @@ buf_dblwr_write_block_to_datafile(
fil_io(request, sync, bpage->id, bpage->size, 0,
bpage->size.physical(),
(void*) frame,
- (void*) bpage, NULL);
+ (void*) bpage);
} else {
ut_ad(!bpage->size.is_compressed());
@@ -981,8 +938,8 @@ buf_dblwr_write_block_to_datafile(
buf_dblwr_check_page_lsn(block->frame);
fil_io(request,
- sync, bpage->id, bpage->size, 0, bpage->size.physical(),
- frame, block, (ulint *)&bpage->write_size);
+ sync, bpage->id, bpage->size, 0, bpage->real_size,
+ frame, block);
}
}
@@ -1084,7 +1041,7 @@ try_again:
fil_io(IORequestWrite, true,
page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), univ_page_size,
- 0, len, (void*) write_buf, NULL, NULL);
+ 0, len, (void*) write_buf, NULL);
if (buf_dblwr->first_free <= TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
/* No unwritten pages in the second block. */
@@ -1100,7 +1057,7 @@ try_again:
fil_io(IORequestWrite, true,
page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), univ_page_size,
- 0, len, (void*) write_buf, NULL, NULL);
+ 0, len, (void*) write_buf, NULL);
flush:
/* increment the doublewrite flushed pages counter */
@@ -1195,7 +1152,6 @@ try_again:
} else {
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
-
UNIV_MEM_ASSERT_RW(frame,
bpage->size.logical());
@@ -1336,7 +1292,6 @@ retry:
0,
univ_page_size.physical(),
(void *)(buf_dblwr->write_buf + univ_page_size.physical() * i),
- NULL,
NULL);
} else {
/* It is a regular page. Write it directly to the
@@ -1348,7 +1303,6 @@ retry:
0,
univ_page_size.physical(),
(void*) frame,
- NULL,
NULL);
}
@@ -1360,4 +1314,3 @@ retry:
blocks. Next do the write to the intended position. */
buf_dblwr_write_block_to_datafile(bpage, sync);
}
-#endif /* !UNIV_HOTBACKUP */