diff options
Diffstat (limited to 'storage/innobase/buf/buf0dblwr.cc')
-rw-r--r-- | storage/innobase/buf/buf0dblwr.cc | 275 |
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 */ |