summaryrefslogtreecommitdiff
path: root/storage/xtradb/buf/buf0buf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/buf/buf0buf.cc')
-rw-r--r--storage/xtradb/buf/buf0buf.cc713
1 files changed, 322 insertions, 391 deletions
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 6d5776dc726..c9a3f6aa6ec 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -65,26 +65,9 @@ Created 11/5/1995 Heikki Tuuri
#include "fil0pagecompress.h"
#include "ha_prototypes.h"
-/* Enable this for checksum error messages. */
-//#ifdef UNIV_DEBUG
-//#define UNIV_DEBUG_LEVEL2 1
-//#endif
-
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
-/********************************************************************//**
-Check if page is maybe compressed, encrypted or both when we encounter
-corrupted page. Note that we can't be 100% sure if page is corrupted
-or decrypt/decompress just failed.
-*/
-static
-ibool
-buf_page_check_corrupt(
-/*===================*/
- buf_page_t* bpage); /*!< in/out: buffer page read from
- disk */
-
static inline
void
_increment_page_get_statistics(buf_block_t* block, trx_t* trx)
@@ -568,6 +551,7 @@ buf_block_alloc(
/********************************************************************//**
Checks if a page is all zeroes.
@return TRUE if the page is all zeroes */
+UNIV_INTERN
bool
buf_page_is_zeroes(
/*===============*/
@@ -590,7 +574,7 @@ buf_page_is_zeroes(
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
@return true if the page is in crc32 checksum format */
-UNIV_INLINE
+UNIV_INTERN
bool
buf_page_is_checksum_valid_crc32(
const byte* read_buf,
@@ -599,15 +583,15 @@ buf_page_is_checksum_valid_crc32(
{
ib_uint32_t crc32 = buf_calc_page_crc32(read_buf);
-#ifdef UNIV_DEBUG_LEVEL2
if (!(checksum_field1 == crc32 && checksum_field2 == crc32)) {
- ib_logf(IB_LOG_LEVEL_INFO,
- "Page checksum crc32 not valid field1 %lu field2 %lu crc32 %lu.",
- checksum_field1, checksum_field2, (ulint)crc32);
+ DBUG_PRINT("buf_checksum",
+ ("Page checksum crc32 not valid field1 " ULINTPF
+ " field2 " ULINTPF " crc32 %u.",
+ checksum_field1, checksum_field2, crc32));
+ return (false);
}
-#endif
- return(checksum_field1 == crc32 && checksum_field2 == crc32);
+ return (true);
}
/** Checks if the page is in innodb checksum format.
@@ -615,7 +599,7 @@ buf_page_is_checksum_valid_crc32(
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
@return true if the page is in innodb checksum format */
-UNIV_INLINE
+UNIV_INTERN
bool
buf_page_is_checksum_valid_innodb(
const byte* read_buf,
@@ -634,13 +618,13 @@ buf_page_is_checksum_valid_innodb(
if (checksum_field2 != mach_read_from_4(read_buf + FIL_PAGE_LSN)
&& checksum_field2 != buf_calc_page_old_checksum(read_buf)) {
-#ifdef UNIV_DEBUG_LEVEL2
- ib_logf(IB_LOG_LEVEL_INFO,
- "Page checksum innodb not valid field1 %lu field2 %lu crc32 %lu lsn %lu.",
+
+ DBUG_PRINT("buf_checksum",
+ ("Page checksum innodb not valid field1 " ULINTPF
+ " field2 " ULINTPF "crc32 " ULINTPF " lsn " ULINTPF ".",
checksum_field1, checksum_field2, buf_calc_page_old_checksum(read_buf),
- mach_read_from_4(read_buf + FIL_PAGE_LSN)
- );
-#endif
+ mach_read_from_4(read_buf + FIL_PAGE_LSN)));
+
return(false);
}
@@ -651,13 +635,13 @@ buf_page_is_checksum_valid_innodb(
if (checksum_field1 != 0
&& checksum_field1 != buf_calc_page_new_checksum(read_buf)) {
-#ifdef UNIV_DEBUG_LEVEL2
- ib_logf(IB_LOG_LEVEL_INFO,
- "Page checksum innodb not valid field1 %lu field2 %lu crc32 %lu lsn %lu.",
+
+ DBUG_PRINT("buf_checksum",
+ ("Page checksum innodb not valid field1 " ULINTPF
+ " field2 " ULINTPF "crc32 " ULINTPF " lsn " ULINTPF ".",
checksum_field1, checksum_field2, buf_calc_page_new_checksum(read_buf),
- mach_read_from_4(read_buf + FIL_PAGE_LSN)
- );
-#endif
+ mach_read_from_4(read_buf + FIL_PAGE_LSN)));
+
return(false);
}
@@ -669,22 +653,21 @@ buf_page_is_checksum_valid_innodb(
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
@return true if the page is in none checksum format */
-UNIV_INLINE
+UNIV_INTERN
bool
buf_page_is_checksum_valid_none(
const byte* read_buf,
ulint checksum_field1,
ulint checksum_field2)
{
-#ifdef UNIV_DEBUG_LEVEL2
- if (!(checksum_field1 == checksum_field2 || checksum_field1 == BUF_NO_CHECKSUM_MAGIC)) {
- ib_logf(IB_LOG_LEVEL_INFO,
- "Page checksum none not valid field1 %lu field2 %lu crc32 %lu lsn %lu.",
+
+ if (!(checksum_field1 == checksum_field2 && checksum_field1 == BUF_NO_CHECKSUM_MAGIC)) {
+ DBUG_PRINT("buf_checksum",
+ ("Page checksum none not valid field1 " ULINTPF
+ " field2 " ULINTPF "crc32 " ULINTPF " lsn " ULINTPF ".",
checksum_field1, checksum_field2, BUF_NO_CHECKSUM_MAGIC,
- mach_read_from_4(read_buf + FIL_PAGE_LSN)
- );
+ mach_read_from_4(read_buf + FIL_PAGE_LSN)));
}
-#endif
return(checksum_field1 == checksum_field2
&& checksum_field1 == BUF_NO_CHECKSUM_MAGIC);
@@ -692,43 +675,42 @@ buf_page_is_checksum_valid_none(
/********************************************************************//**
Checks if a page is corrupt.
-@return TRUE if corrupted */
+@param[in] check_lsn true if LSN should be checked
+@param[in] read_buf Page to be checked
+@param[in] zip_size compressed size or 0
+@param[in] space Pointer to tablespace
+@return true if corrupted, false if not */
UNIV_INTERN
-ibool
+bool
buf_page_is_corrupted(
-/*==================*/
- bool check_lsn, /*!< in: true if we need to check
- and complain about the LSN */
- const byte* read_buf, /*!< in: a database page */
- ulint zip_size) /*!< in: size of compressed page;
- 0 for uncompressed pages */
+ bool check_lsn,
+ const byte* read_buf,
+ ulint zip_size,
+ const fil_space_t* space)
{
ulint checksum_field1;
ulint checksum_field2;
ulint space_id = mach_read_from_4(
read_buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- ulint page_type = mach_read_from_4(
+ ulint page_type = mach_read_from_2(
read_buf + FIL_PAGE_TYPE);
- bool no_checksum = (page_type == FIL_PAGE_PAGE_COMPRESSED ||
- page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
- fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
-
-
- /* Page is encrypted if encryption information is found from
- tablespace and page contains used key_version. This is true
- also for pages first compressed and then encrypted. */
- if (crypt_data &&
- crypt_data->type != CRYPT_SCHEME_UNENCRYPTED &&
- fil_page_is_encrypted(read_buf)) {
- no_checksum = true;
- }
- /* Return early if there is no checksum or END_LSN */
- if (no_checksum) {
- return (FALSE);
- }
-
- if (!no_checksum && !zip_size
+ /* We can trust page type if page compression is set on tablespace
+ flags because page compression flag means file must have been
+ created with 10.1 (later than 5.5 code base). In 10.1 page
+ compressed tables do not contain post compression checksum and
+ FIL_PAGE_END_LSN_OLD_CHKSUM field stored. Note that space can
+ be null if we are in fil_check_first_page() and first page
+ is not compressed or encrypted. Page checksum is verified
+ after decompression (i.e. normally pages are already
+ decompressed at this stage). */
+ if ((page_type == FIL_PAGE_PAGE_COMPRESSED ||
+ page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED)
+ && space && FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags)) {
+ return (false);
+ }
+
+ if (!zip_size
&& memcmp(read_buf + FIL_PAGE_LSN + 4,
read_buf + UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
@@ -780,7 +762,7 @@ buf_page_is_corrupted(
/* Check whether the checksum fields have correct values */
if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_NONE) {
- return(FALSE);
+ return(false);
}
if (zip_size) {
@@ -807,14 +789,14 @@ buf_page_is_corrupted(
ib_logf(IB_LOG_LEVEL_INFO,
"Checksum fields zero but page is not empty.");
- return(TRUE);
+ return(true);
}
}
- return(FALSE);
+ return(false);
}
- DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); );
+ DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(true); );
ulint page_no = mach_read_from_4(read_buf + FIL_PAGE_OFFSET);
@@ -827,7 +809,7 @@ buf_page_is_corrupted(
if (buf_page_is_checksum_valid_crc32(read_buf,
checksum_field1, checksum_field2)) {
- return(FALSE);
+ return(false);
}
if (buf_page_is_checksum_valid_none(read_buf,
@@ -840,7 +822,7 @@ buf_page_is_corrupted(
space_id, page_no);
}
- return(FALSE);
+ return(false);
}
if (buf_page_is_checksum_valid_innodb(read_buf,
@@ -853,17 +835,17 @@ buf_page_is_corrupted(
space_id, page_no);
}
- return(FALSE);
+ return(false);
}
- return(TRUE);
+ return(true);
case SRV_CHECKSUM_ALGORITHM_INNODB:
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
if (buf_page_is_checksum_valid_innodb(read_buf,
checksum_field1, checksum_field2)) {
- return(FALSE);
+ return(false);
}
if (buf_page_is_checksum_valid_none(read_buf,
@@ -876,7 +858,7 @@ buf_page_is_corrupted(
space_id, page_no);
}
- return(FALSE);
+ return(false);
}
if (buf_page_is_checksum_valid_crc32(read_buf,
@@ -889,16 +871,16 @@ buf_page_is_corrupted(
space_id, page_no);
}
- return(FALSE);
+ return(false);
}
- return(TRUE);
+ return(true);
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
if (buf_page_is_checksum_valid_none(read_buf,
checksum_field1, checksum_field2)) {
- return(FALSE);
+ return(false);
}
if (buf_page_is_checksum_valid_crc32(read_buf,
@@ -907,7 +889,7 @@ buf_page_is_corrupted(
curr_algo,
SRV_CHECKSUM_ALGORITHM_CRC32,
space_id, page_no);
- return(FALSE);
+ return(false);
}
if (buf_page_is_checksum_valid_innodb(read_buf,
@@ -916,10 +898,10 @@ buf_page_is_corrupted(
curr_algo,
SRV_CHECKSUM_ALGORITHM_INNODB,
space_id, page_no);
- return(FALSE);
+ return(false);
}
- return(TRUE);
+ return(true);
case SRV_CHECKSUM_ALGORITHM_NONE:
/* should have returned FALSE earlier */
@@ -929,7 +911,7 @@ buf_page_is_corrupted(
}
ut_error;
- return(FALSE);
+ return(false);
}
/********************************************************************//**
@@ -1198,12 +1180,8 @@ buf_block_init(
block->page.state = BUF_BLOCK_NOT_USED;
block->page.buf_fix_count = 0;
block->page.io_fix = BUF_IO_NONE;
- block->page.key_version = 0;
- block->page.page_encrypted = false;
- block->page.page_compressed = false;
block->page.encrypted = false;
- block->page.stored_checksum = BUF_NO_CHECKSUM_MAGIC;
- block->page.calculated_checksum = BUF_NO_CHECKSUM_MAGIC;
+ block->page.key_version = 0;
block->page.real_size = 0;
block->page.write_size = 0;
block->modify_clock = 0;
@@ -3026,14 +3004,14 @@ loop:
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
++retries;
- bool corrupted = true;
+ bool corrupted = false;
if (bpage) {
corrupted = buf_page_check_corrupt(bpage);
}
/* Do not try again for encrypted pages */
- if (!corrupted) {
+ if (corrupted && bpage->encrypted) {
ib_mutex_t* pmutex = buf_page_get_mutex(bpage);
mutex_enter(&buf_pool->LRU_list_mutex);
mutex_enter(pmutex);
@@ -3062,14 +3040,14 @@ loop:
retries = BUF_PAGE_READ_MAX_RETRIES;
);
} else {
- bool corrupted = true;
+ bool corrupted = false;
if (bpage) {
corrupted = buf_page_check_corrupt(bpage);
}
- if (corrupted) {
- fprintf(stderr, "InnoDB: Error: Unable"
+ if (corrupted && !bpage->encrypted) {
+ ib_logf(IB_LOG_LEVEL_ERROR, "Unable"
" to read tablespace %lu page no"
" %lu into the buffer pool after"
" %lu attempts\n"
@@ -3880,12 +3858,8 @@ buf_page_init_low(
bpage->newest_modification = 0;
bpage->oldest_modification = 0;
bpage->write_size = 0;
- bpage->key_version = 0;
- bpage->stored_checksum = BUF_NO_CHECKSUM_MAGIC;
- bpage->calculated_checksum = BUF_NO_CHECKSUM_MAGIC;
- bpage->page_encrypted = false;
- bpage->page_compressed = false;
bpage->encrypted = false;
+ bpage->key_version = 0;
bpage->real_size = 0;
HASH_INVALIDATE(bpage, hash);
@@ -3924,15 +3898,6 @@ buf_page_init(
/* Set the state of the block */
buf_block_set_file_page(block, space, offset);
-#ifdef UNIV_DEBUG_VALGRIND
- if (!space) {
- /* Silence valid Valgrind warnings about uninitialized
- data being written to data files. There are some unused
- bytes on some pages that InnoDB does not initialize. */
- UNIV_MEM_VALID(block->frame, UNIV_PAGE_SIZE);
- }
-#endif /* UNIV_DEBUG_VALGRIND */
-
buf_block_init_low(block);
block->lock_hash_val = lock_rec_hash(space, offset);
@@ -4598,78 +4563,80 @@ buf_mark_space_corrupt(
Check if page is maybe compressed, encrypted or both when we encounter
corrupted page. Note that we can't be 100% sure if page is corrupted
or decrypt/decompress just failed.
-*/
-static
-ibool
+@param[in,out] bpage Page
+@return true if page corrupted, false if not */
+UNIV_INTERN
+bool
buf_page_check_corrupt(
-/*===================*/
- buf_page_t* bpage) /*!< in/out: buffer page read from disk */
+ buf_page_t* bpage)
{
ulint zip_size = buf_page_get_zip_size(bpage);
byte* dst_frame = (zip_size) ? bpage->zip.data :
((buf_block_t*) bpage)->frame;
- bool page_compressed = bpage->page_encrypted;
- ulint stored_checksum = bpage->stored_checksum;
- ulint calculated_checksum = bpage->calculated_checksum;
- bool page_compressed_encrypted = bpage->page_compressed;
- ulint space_id = mach_read_from_4(
- dst_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
- fil_space_t* space = fil_space_found_by_id(space_id);
- bool corrupted = true;
- ulint key_version = bpage->key_version;
-
- if (key_version != 0 || page_compressed_encrypted) {
- bpage->encrypted = true;
+ ulint space_id = bpage->space;
+ fil_space_t* space = fil_space_acquire_silent(space_id);
+ bool still_encrypted = false;
+ bool corrupted = false;
+ ulint page_type = mach_read_from_2(dst_frame + FIL_PAGE_TYPE);
+ fil_space_crypt_t* crypt_data = NULL;
+
+ ut_ad(space);
+ crypt_data = space->crypt_data;
+
+ /* In buf_decrypt_after_read we have either decrypted the page if
+ page post encryption checksum matches and used key_id is found
+ from the encryption plugin. If checksum did not match page was
+ not decrypted and it could be either encrypted and corrupted
+ or corrupted or good page. If we decrypted, there page could
+ still be corrupted if used key does not match. */
+ still_encrypted = (crypt_data &&
+ crypt_data->type != CRYPT_SCHEME_UNENCRYPTED &&
+ !bpage->encrypted &&
+ fil_space_verify_crypt_checksum(dst_frame, zip_size,
+ space, bpage->offset));
+
+ if (!still_encrypted) {
+ /* If traditional checksums match, we assume that page is
+ not anymore encrypted. */
+ corrupted = buf_page_is_corrupted(true, dst_frame, zip_size, space);
+
+ if (!corrupted) {
+ bpage->encrypted = false;
+ }
}
- if (key_version != 0 ||
- (crypt_data && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED) ||
- page_compressed || page_compressed_encrypted) {
-
- /* Page is really corrupted if post encryption stored
- checksum does not match calculated checksum after page was
- read. For pages compressed and then encrypted, there is no
- checksum. */
- corrupted = (!page_compressed_encrypted && stored_checksum != calculated_checksum);
+ /* Pages that we think are unencrypted but do not match the checksum
+ checks could be corrupted or encrypted or both. */
+ if (corrupted && !bpage->encrypted) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "%s: Block in space_id " ULINTPF " in file %s corrupted.",
+ page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED ? "Maybe corruption" : "Corruption",
+ space_id, (space && space->name) ? space->name : "NULL");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Based on page type %s (" ULINTPF ")",
+ fil_get_page_type_name(page_type), page_type);
+ } else if (still_encrypted || (bpage->encrypted && corrupted)) {
+ bpage->encrypted = true;
+ corrupted = true;
- if (corrupted) {
- ib_logf(IB_LOG_LEVEL_ERROR,
- "%s: Block in space_id %lu in file %s corrupted.",
- page_compressed_encrypted ? "Maybe corruption" : "Corruption",
- space_id, space ? space->name : "NULL");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Page based on contents %s encrypted.",
- (key_version == 0 && page_compressed_encrypted == false) ? "not" : "maybe");
- if (stored_checksum != BUF_NO_CHECKSUM_MAGIC || calculated_checksum != BUF_NO_CHECKSUM_MAGIC) {
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Page stored checksum %lu but calculated checksum %lu.",
- stored_checksum, calculated_checksum);
- }
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Reason could be that key_version %lu in page "
- "or in crypt_data %p could not be found.",
- key_version, crypt_data);
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Reason could be also that key management plugin is not found or"
- " used encryption algorithm or method does not match.");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Based on page page compressed %d, compressed and encrypted %d.",
- page_compressed, page_compressed_encrypted);
- } else {
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Block in space_id %lu in file %s encrypted.",
- space_id, space ? space->name : "NULL");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "However key management plugin or used key_id %lu is not found or"
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Block in space_id " ULINTPF " in file %s encrypted.",
+ space_id, (space && space->name) ? space->name : "NULL");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "However key management plugin or used key_version %u is not found or"
" used encryption algorithm or method does not match.",
- key_version);
+ bpage->key_version);
+ if (space_id > TRX_SYS_SPACE) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Marking tablespace as missing. You may drop this table or"
" install correct key management plugin and key file.");
}
}
+ if (space) {
+ fil_space_release(space);
+ }
+
return corrupted;
}
@@ -4689,6 +4656,8 @@ buf_page_io_complete(
== BUF_BLOCK_FILE_PAGE);
bool have_LRU_mutex = false;
fil_space_t* space = NULL;
+ byte* frame = NULL;
+ bool corrupted = false;
ut_a(buf_page_in_file(bpage));
@@ -4704,21 +4673,13 @@ buf_page_io_complete(
if (io_type == BUF_IO_READ) {
ulint read_page_no;
ulint read_space_id;
- byte* frame;
- if (!buf_page_decrypt_after_read(bpage)) {
- /* encryption error! */
- if (buf_page_get_zip_size(bpage)) {
- frame = bpage->zip.data;
- } else {
- frame = ((buf_block_t*) bpage)->frame;
- }
-
- ib_logf(IB_LOG_LEVEL_INFO,
- "Page %u in tablespace %u encryption error key_version %u.",
- bpage->offset, bpage->space, bpage->key_version);
+ buf_page_decrypt_after_read(bpage);
- goto database_corrupted;
+ if (buf_page_get_zip_size(bpage)) {
+ frame = bpage->zip.data;
+ } else {
+ frame = ((buf_block_t*) bpage)->frame;
}
if (buf_page_get_zip_size(bpage)) {
@@ -4735,6 +4696,8 @@ buf_page_io_complete(
"Page %u in tablespace %u zip_decompress failure.",
bpage->offset, bpage->space);
+ corrupted = true;
+
goto database_corrupted;
}
os_atomic_decrement_ulint(&buf_pool->n_pend_unzip, 1);
@@ -4773,7 +4736,7 @@ buf_page_io_complete(
fprintf(stderr,
" InnoDB: Error: space id and page n:o"
" stored in the page\n"
- "InnoDB: read in are %lu:%lu,"
+ "InnoDB: read in are " ULINTPF ":" ULINTPF ","
" should be %u:%u!\n",
read_space_id,
read_page_no,
@@ -4783,121 +4746,116 @@ buf_page_io_complete(
if (UNIV_LIKELY(!bpage->is_corrupt ||
!srv_pass_corrupt_table)) {
- /* From version 3.23.38 up we store the page checksum
- to the 4 first bytes of the page end lsn field */
-
- if (buf_page_is_corrupted(true, frame,
- buf_page_get_zip_size(bpage))) {
-
- /* Not a real corruption if it was triggered by
- error injection */
- DBUG_EXECUTE_IF("buf_page_is_corrupt_failure",
- if (bpage->space > TRX_SYS_SPACE
- && buf_mark_space_corrupt(bpage)) {
- ib_logf(IB_LOG_LEVEL_INFO,
- "Simulated page corruption");
- return(true);
- }
- goto page_not_corrupt;
- ;);
+ corrupted = buf_page_check_corrupt(bpage);
+
+ }
+
database_corrupted:
- bool corrupted = buf_page_check_corrupt(bpage);
+ if (corrupted) {
+ /* Not a real corruption if it was triggered by
+ error injection */
+
+ DBUG_EXECUTE_IF("buf_page_is_corrupt_failure",
+ if (bpage->space > TRX_SYS_SPACE
+ && buf_mark_space_corrupt(bpage)) {
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Simulated page corruption");
+ return(true);
+ }
+ goto page_not_corrupt;
+ );
- if (corrupted) {
- fil_system_enter();
- space = fil_space_get_by_id(bpage->space);
- fil_system_exit();
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Database page corruption on disk"
- " or a failed");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Space %u file %s read of page %u.",
- bpage->space,
- space ? space->name : "NULL",
- bpage->offset);
- ib_logf(IB_LOG_LEVEL_ERROR,
- "You may have to recover"
- " from a backup.");
+ if (!bpage->encrypted) {
+ fil_system_enter();
+ space = fil_space_get_by_id(bpage->space);
+ fil_system_exit();
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Database page corruption on disk"
+ " or a failed");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Space %u file %s read of page %u.",
+ bpage->space,
+ space->name ? space->name : "NULL",
+ bpage->offset);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "You may have to recover"
+ " from a backup.");
+ buf_page_print(frame, buf_page_get_zip_size(bpage),
+ BUF_PAGE_PRINT_NO_CRASH);
- buf_page_print(frame, buf_page_get_zip_size(bpage),
- BUF_PAGE_PRINT_NO_CRASH);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "It is also possible that your operating"
+ "system has corrupted its own file cache.");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "and rebooting your computer removes the error.");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "If the corrupt page is an index page you can also try to");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "fix the corruption by dumping, dropping, and reimporting");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "the corrupt table. You can use CHECK");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "TABLE to scan your table for corruption.");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "See also "
+ REFMAN "forcing-innodb-recovery.html"
+ " about forcing recovery.");
+ }
- ib_logf(IB_LOG_LEVEL_ERROR,
- "It is also possible that your operating"
- "system has corrupted its own file cache.");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "and rebooting your computer removes the error.");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "If the corrupt page is an index page you can also try to");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "fix the corruption by dumping, dropping, and reimporting");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "the corrupt table. You can use CHECK");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "TABLE to scan your table for corruption.");
- ib_logf(IB_LOG_LEVEL_ERROR,
- "See also "
- REFMAN "forcing-innodb-recovery.html"
- " about forcing recovery.");
+ if (srv_pass_corrupt_table && bpage->space != 0
+ && bpage->space < SRV_LOG_SPACE_FIRST_ID) {
+ trx_t* trx;
+
+ fprintf(stderr,
+ "InnoDB: space %u will be treated as corrupt.\n",
+ bpage->space);
+ fil_space_set_corrupt(bpage->space);
+
+ trx = innobase_get_trx();
+
+ if (trx && trx->dict_operation_lock_mode == RW_X_LATCH) {
+ dict_table_set_corrupt_by_space(bpage->space, FALSE);
+ } else {
+ dict_table_set_corrupt_by_space(bpage->space, TRUE);
}
- if (srv_pass_corrupt_table && bpage->space != 0
- && bpage->space < SRV_LOG_SPACE_FIRST_ID) {
- trx_t* trx;
+ bpage->is_corrupt = TRUE;
+ }
- fprintf(stderr,
- "InnoDB: space %u will be treated as corrupt.\n",
- bpage->space);
- fil_space_set_corrupt(bpage->space);
+ if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
+ /* If page space id is larger than TRX_SYS_SPACE
+ (0), we will attempt to mark the corresponding
+ table as corrupted instead of crashing server */
+ if (bpage->space > TRX_SYS_SPACE
+ && buf_mark_space_corrupt(bpage)) {
+ return(false);
+ } else {
+ if (!bpage->encrypted) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Ending processing because of a corrupt database page.");
- trx = innobase_get_trx();
- if (trx && trx->dict_operation_lock_mode == RW_X_LATCH) {
- dict_table_set_corrupt_by_space(bpage->space, FALSE);
- } else {
- dict_table_set_corrupt_by_space(bpage->space, TRUE);
+ ut_error;
}
- bpage->is_corrupt = TRUE;
- }
- if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
- /* If page space id is larger than TRX_SYS_SPACE
- (0), we will attempt to mark the corresponding
- table as corrupted instead of crashing server */
- if (bpage->space > TRX_SYS_SPACE
- && buf_mark_space_corrupt(bpage)) {
- return(false);
+ ib_push_warning(innobase_get_trx(), DB_DECRYPTION_FAILED,
+ "Table in tablespace %lu encrypted."
+ "However key management plugin or used key_id %lu is not found or"
+ " used encryption algorithm or method does not match."
+ " Can't continue opening the table.",
+ bpage->space, bpage->key_version);
+
+ if (bpage->encrypted && bpage->space > TRX_SYS_SPACE) {
+ buf_mark_space_corrupt(bpage);
} else {
- corrupted = buf_page_check_corrupt(bpage);
- ulint key_version = bpage->key_version;
-
- if (corrupted) {
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Ending processing because of a corrupt database page.");
-
- ut_error;
- }
-
- ib_push_warning(innobase_get_trx(), DB_DECRYPTION_FAILED,
- "Table in tablespace %lu encrypted."
- "However key management plugin or used key_id %lu is not found or"
- " used encryption algorithm or method does not match."
- " Can't continue opening the table.",
- (ulint)bpage->space, key_version);
-
- if (bpage->space > TRX_SYS_SPACE) {
- if (corrupted) {
- buf_mark_space_corrupt(bpage);
- }
- } else {
- ut_error;
- }
- return(false);
+ ut_error;
}
+
+ return(false);
}
}
- } /**/
+ }
DBUG_EXECUTE_IF("buf_page_is_corrupt_failure",
page_not_corrupt: bpage = bpage; );
@@ -4912,32 +4870,19 @@ database_corrupted:
&& fil_page_get_type(frame) == FIL_PAGE_INDEX
&& page_is_leaf(frame)) {
- buf_block_t* block;
- ibool update_ibuf_bitmap;
-
- if (UNIV_UNLIKELY(bpage->is_corrupt &&
- srv_pass_corrupt_table)) {
-
- block = NULL;
- update_ibuf_bitmap = FALSE;
- } else {
-
- block = (buf_block_t *) bpage;
- update_ibuf_bitmap = TRUE;
- }
-
if (bpage && bpage->encrypted) {
- fprintf(stderr,
- "InnoDB: Warning: Table in tablespace %lu encrypted."
- "However key management plugin or used key_id %u is not found or"
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Table in tablespace %lu encrypted."
+ "However key management plugin or used key_version %u is not found or"
" used encryption algorithm or method does not match."
" Can't continue opening the table.\n",
(ulint)bpage->space, bpage->key_version);
} else {
+
ibuf_merge_or_delete_for_page(
- block, bpage->space,
+ (buf_block_t*)bpage, bpage->space,
bpage->offset, buf_page_get_zip_size(bpage),
- update_ibuf_bitmap);
+ TRUE);
}
}
@@ -5081,24 +5026,22 @@ buf_all_freed_instance(
mutex_exit(&buf_pool->LRU_list_mutex);
- if (UNIV_LIKELY_NULL(block)) {
- if (block->page.key_version == 0) {
- fil_space_t* space = fil_space_get(block->page.space);
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Page %u %u still fixed or dirty.",
- block->page.space,
- block->page.offset);
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Page oldest_modification %lu fix_count %d io_fix %d.",
- (ulong) block->page.oldest_modification,
- block->page.buf_fix_count,
- buf_page_get_io_fix(&block->page));
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Page space_id %u name %s.",
- block->page.space,
- (space && space->name) ? space->name : "NULL");
- ut_error;
- }
+ if (UNIV_LIKELY_NULL(block) && block->page.key_version == 0) {
+ fil_space_t* space = fil_space_get(block->page.space);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Page %u %u still fixed or dirty.",
+ block->page.space,
+ block->page.offset);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Page oldest_modification " LSN_PF
+ " fix_count %d io_fix %d.",
+ block->page.oldest_modification,
+ block->page.buf_fix_count,
+ buf_page_get_io_fix(&block->page));
+ ib_logf(IB_LOG_LEVEL_FATAL,
+ "Page space_id %u name %s.",
+ block->page.space,
+ (space && space->name) ? space->name : "NULL");
}
}
@@ -6304,21 +6247,17 @@ buf_pool_reserve_tmp_slot(
/********************************************************************//**
Encrypts a buffer page right before it's flushed to disk
+@param[in,out] bpage Page control block
+@param[in,out] src_frame Source page
+@param[in] space_id Tablespace id
+@return either unencrypted source page or decrypted page.
*/
byte*
buf_page_encrypt_before_write(
-/*==========================*/
- buf_page_t* bpage, /*!< in/out: buffer page to be flushed */
- byte* src_frame, /*!< in: src frame */
- ulint space_id) /*!< in: space id */
+ buf_page_t* bpage,
+ byte* src_frame,
+ ulint space_id)
{
- fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
- ulint zip_size = buf_page_get_zip_size(bpage);
- ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
- bool page_compressed = fil_space_is_page_compressed(bpage->space);
- bool encrypted = true;
-
bpage->real_size = UNIV_PAGE_SIZE;
fil_page_type_validate(src_frame);
@@ -6335,7 +6274,20 @@ buf_page_encrypt_before_write(
return src_frame;
}
- if (crypt_data != NULL && crypt_data->not_encrypted()) {
+ fil_space_t* space = fil_space_acquire_silent(space_id);
+
+ /* Tablespace must exist during write operation */
+ if (!space) {
+ /* This could be true on discard if we have injected a error
+ case e.g. in innodb.innodb-wl5522-debug-zip so that space
+ is already marked as stop_new_ops = true. */
+ return src_frame;
+ }
+
+ fil_space_crypt_t* crypt_data = space->crypt_data;
+ bool encrypted = true;
+
+ if (space->crypt_data != NULL && space->crypt_data->not_encrypted()) {
/* Encryption is disabled */
encrypted = false;
}
@@ -6352,11 +6304,17 @@ buf_page_encrypt_before_write(
encrypted = false;
}
+ bool page_compressed = fil_space_is_page_compressed(bpage->space);
+
if (!encrypted && !page_compressed) {
/* No need to encrypt or page compress the page */
+ fil_space_release(space);
return src_frame;
}
+ ulint zip_size = buf_page_get_zip_size(bpage);
+ ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
+ buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
/* Find free slot from temporary memory array */
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed);
slot->out_buf = NULL;
@@ -6366,11 +6324,10 @@ buf_page_encrypt_before_write(
if (!page_compressed) {
/* Encrypt page content */
- byte* tmp = fil_space_encrypt(bpage->space,
+ byte* tmp = fil_space_encrypt(space,
bpage->offset,
bpage->newest_modification,
src_frame,
- zip_size,
dst_frame);
ulint key_version = mach_read_from_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
@@ -6408,11 +6365,10 @@ buf_page_encrypt_before_write(
if(encrypted) {
/* And then we encrypt the page content */
- tmp = fil_space_encrypt(bpage->space,
+ tmp = fil_space_encrypt(space,
bpage->offset,
bpage->newest_modification,
tmp,
- zip_size,
dst_frame);
}
@@ -6423,17 +6379,20 @@ buf_page_encrypt_before_write(
fil_page_type_validate(dst_frame);
#endif
+ fil_space_release(space);
// return dst_frame which will be written
return dst_frame;
}
/********************************************************************//**
Decrypt page after it has been read from disk
+@param[in,out] bpage Page control block
+@return true if successfull, false if something went wrong
*/
-ibool
+UNIV_INTERN
+bool
buf_page_decrypt_after_read(
-/*========================*/
- buf_page_t* bpage) /*!< in/out: buffer page read from disk */
+ buf_page_t* bpage)
{
ulint zip_size = buf_page_get_zip_size(bpage);
ulint size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
@@ -6446,53 +6405,25 @@ buf_page_decrypt_after_read(
bool page_compressed_encrypted = fil_page_is_compressed_encrypted(dst_frame);
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
bool success = true;
- ulint space_id = mach_read_from_4(
- dst_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
- /* Page is encrypted if encryption information is found from
- tablespace and page contains used key_version. This is true
- also for pages first compressed and then encrypted. */
- if (!crypt_data ||
- (crypt_data &&
- crypt_data->type == CRYPT_SCHEME_UNENCRYPTED &&
- key_version != 0)) {
- byte* frame = NULL;
-
- if (buf_page_get_zip_size(bpage)) {
- frame = bpage->zip.data;
- } else {
- frame = ((buf_block_t*) bpage)->frame;
- }
+ bpage->key_version = key_version;
- /* If page is not corrupted at this point, page can't be
- encrypted, thus set key_version to 0. If page is corrupted,
- we assume at this point that it is encrypted as page
- contained key_version != 0. Note that page could still be
- really corrupted. This we will find out after decrypt by
- checking page checksums. */
- if (!buf_page_is_corrupted(false, frame, buf_page_get_zip_size(bpage))) {
- key_version = 0;
- }
+ if (bpage->offset == 0) {
+ /* File header pages are not encrypted/compressed */
+ return (true);
}
- /* If page is encrypted read post-encryption checksum */
- if (!page_compressed_encrypted && key_version != 0) {
- bpage->stored_checksum = mach_read_from_4(dst_frame + + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4);
- }
+ fil_space_t* space = fil_space_acquire(bpage->space);
- ut_ad(bpage->key_version == 0);
+ fil_space_crypt_t* crypt_data = space->crypt_data;
- if (bpage->offset == 0) {
- /* File header pages are not encrypted/compressed */
- return (TRUE);
+ /* Page is encrypted if encryption information is found from
+ tablespace and page contains used key_version. This is true
+ also for pages first compressed and then encrypted. */
+ if (!crypt_data) {
+ key_version = 0;
}
- /* Store these for corruption check */
- bpage->key_version = key_version;
- bpage->page_encrypted = page_compressed_encrypted;
- bpage->page_compressed = page_compressed;
-
if (page_compressed) {
/* the page we read is unencrypted */
/* Find free slot from temporary memory array */
@@ -6519,6 +6450,13 @@ buf_page_decrypt_after_read(
buf_tmp_buffer_t* slot = NULL;
if (key_version) {
+ /* Verify encryption checksum before we even try to
+ decrypt. */
+ if (!fil_space_verify_crypt_checksum(dst_frame,
+ zip_size, NULL, bpage->offset)) {
+ return (false);
+ }
+
/* Find free slot from temporary memory array */
slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed);
@@ -6526,22 +6464,16 @@ buf_page_decrypt_after_read(
fil_page_type_validate(dst_frame);
#endif
- /* Calculate checksum before decrypt, this will be
- used later to find out if incorrect key was used. */
- if (!page_compressed_encrypted) {
- bpage->calculated_checksum = fil_crypt_calculate_checksum(zip_size, dst_frame);
- }
-
/* decrypt using crypt_buf to dst_frame */
- byte* res = fil_space_decrypt(bpage->space,
+ byte* res = fil_space_decrypt(space,
slot->crypt_buf,
- size,
- dst_frame);
+ dst_frame,
+ &bpage->encrypted);
if (!res) {
- bpage->encrypted = true;
success = false;
}
+
#ifdef UNIV_DEBUG
fil_page_type_validate(dst_frame);
#endif
@@ -6572,7 +6504,6 @@ buf_page_decrypt_after_read(
}
}
- bpage->key_version = key_version;
-
+ fil_space_release(space);
return (success);
}