mirror of
https://github.com/MariaDB/server.git
synced 2026-05-09 16:44:29 +02:00
MDEV-8588: Assertion failure in file ha_innodb.cc line 21140 if at least one encrypted table exists and encryption service is not available
Analysis: Problem was that in fil_read_first_page we do find that
table has encryption information and that encryption service
or used key_id is not available. But, then we just printed
fatal error message that causes above assertion.
Fix: When we open single table tablespace if it has encryption
information (crypt_data) store this crypt data to the table
structure. When we open a table and we find out that tablespace
is not available, check has table a encryption information
and from there is encryption service or used key_id is not available.
If it is, add additional warning for SQL-layer.
This commit is contained in:
parent
e1978234eb
commit
7e916bb86f
44 changed files with 1552 additions and 414 deletions
|
|
@ -1,6 +1,11 @@
|
|||
call mtr.add_suppression("Plugin 'file_key_management' init function returned error");
|
||||
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed.*");
|
||||
call mtr.add_suppression("Plugin 'file_key_management' registration.*failed");
|
||||
call mtr.add_suppression("InnoDB: Block in space_id .* in file test/.* encrypted");
|
||||
call mtr.add_suppression("InnoDB: However key management plugin or used key_id 1 is not found or used encryption algorithm or method does not match.");
|
||||
call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file.");
|
||||
call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem.");
|
||||
call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*");
|
||||
|
||||
# Start server with keys2.txt
|
||||
SET GLOBAL innodb_file_format = `Barracuda`;
|
||||
|
|
@ -33,3 +38,98 @@ Warning 1812 Tablespace is missing for table 'test/t1'
|
|||
Warning 155 Table test/t1 is encrypted but encryption service or used key_id 2 is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t1' doesn't exist in engine
|
||||
DROP TABLE t1;
|
||||
# Start server with keys.txt
|
||||
CREATE TABLE t2 (c VARCHAR(8), id int not null primary key, b int, key(b)) ENGINE=InnoDB ENCRYPTED=YES;
|
||||
INSERT INTO t2 VALUES ('foobar',1,2);
|
||||
|
||||
# Restart server with keys2.txt
|
||||
SELECT * FROM t2;
|
||||
Got one of the listed errors
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 155 Table test/t2 in tablespace 7 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Warning 155 Table test/t2 in tablespace 7 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
SELECT * FROM t2 where id = 1;
|
||||
Got one of the listed errors
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 1812 Tablespace is missing for table 'test/t2'
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
SELECT * FROM t2 where b = 1;
|
||||
Got one of the listed errors
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 1812 Tablespace is missing for table 'test/t2'
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
INSERT INTO t2 VALUES ('tmp',3,3);
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist in engine
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 1812 Tablespace is missing for table 'test/t2'
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
DELETE FROM t2 where b = 3;
|
||||
Got one of the listed errors
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 1812 Tablespace is missing for table 'test/t2'
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
DELETE FROM t2 where id = 3;
|
||||
Got one of the listed errors
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 1812 Tablespace is missing for table 'test/t2'
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
UPDATE t2 set b = b +1;
|
||||
Got one of the listed errors
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 1812 Tablespace is missing for table 'test/t2'
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
OPTIMIZE TABLE t2;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 optimize Warning Tablespace is missing for table 'test/t2'
|
||||
test.t2 optimize Warning Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
test.t2 optimize Error Table 'test.t2' doesn't exist in engine
|
||||
test.t2 optimize status Operation failed
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
ALTER TABLE t2 ADD COLUMN c INT;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist in engine
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 1812 Tablespace is missing for table 'test/t2'
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
ANALYZE TABLE t2;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 analyze Warning Tablespace is missing for table 'test/t2'
|
||||
test.t2 analyze Warning Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
test.t2 analyze Error Table 'test.t2' doesn't exist in engine
|
||||
test.t2 analyze status Operation failed
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
TRUNCATE TABLE t2;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist in engine
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Warning 1812 Tablespace is missing for table 'test/t2'
|
||||
Warning 155 Table test/t2 is encrypted but encryption service or used key_id is not available. Can't continue reading table.
|
||||
Error 1932 Table 'test.t2' doesn't exist in engine
|
||||
DROP TABLE t2;
|
||||
ERROR HY000: Table 't2' is read only
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 1036 Table 't2' is read only
|
||||
|
||||
# Restart server with keys.txt
|
||||
DROP TABLE t2;
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
|
|
|
|||
|
|
@ -2,10 +2,24 @@
|
|||
-- source include/have_file_key_management_plugin.inc
|
||||
# embedded does not support restart
|
||||
-- source include/not_embedded.inc
|
||||
-- source include/not_valgrind.inc
|
||||
# Avoid CrashReporter popup on Mac
|
||||
-- source include/not_crashrep.inc
|
||||
-- source include/not_windows.inc
|
||||
|
||||
#
|
||||
# MDEV-8588: Assertion failure in file ha_innodb.cc line 21140 if at least one encrypted
|
||||
# table exists and encryption service is not available.
|
||||
#
|
||||
|
||||
call mtr.add_suppression("Plugin 'file_key_management' init function returned error");
|
||||
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed.*");
|
||||
call mtr.add_suppression("Plugin 'file_key_management' registration.*failed");
|
||||
call mtr.add_suppression("InnoDB: Block in space_id .* in file test/.* encrypted");
|
||||
call mtr.add_suppression("InnoDB: However key management plugin or used key_id 1 is not found or used encryption algorithm or method does not match.");
|
||||
call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file.");
|
||||
call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem.");
|
||||
call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*");
|
||||
|
||||
--echo
|
||||
--echo # Start server with keys2.txt
|
||||
|
|
@ -43,4 +57,64 @@ SHOW WARNINGS;
|
|||
|
||||
-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keysbad3.txt
|
||||
-- source include/restart_mysqld.inc
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# MDEV-8591: Database page corruption on disk or a failed space, Assertion failure in file buf0buf.cc
|
||||
# line 2856 on querying a table using wrong default encryption key
|
||||
#
|
||||
|
||||
--echo # Start server with keys.txt
|
||||
-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys.txt
|
||||
-- source include/restart_mysqld.inc
|
||||
|
||||
CREATE TABLE t2 (c VARCHAR(8), id int not null primary key, b int, key(b)) ENGINE=InnoDB ENCRYPTED=YES;
|
||||
INSERT INTO t2 VALUES ('foobar',1,2);
|
||||
|
||||
--echo
|
||||
--echo # Restart server with keys2.txt
|
||||
-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt
|
||||
-- source include/restart_mysqld.inc
|
||||
|
||||
--error 1932,1712
|
||||
SELECT * FROM t2;
|
||||
SHOW WARNINGS;
|
||||
--error 1932,1712
|
||||
SELECT * FROM t2 where id = 1;
|
||||
SHOW WARNINGS;
|
||||
--error 1932,1712
|
||||
SELECT * FROM t2 where b = 1;
|
||||
SHOW WARNINGS;
|
||||
--error 1932
|
||||
INSERT INTO t2 VALUES ('tmp',3,3);
|
||||
SHOW WARNINGS;
|
||||
--error 1932,1712
|
||||
DELETE FROM t2 where b = 3;
|
||||
SHOW WARNINGS;
|
||||
--error 1932,1712
|
||||
DELETE FROM t2 where id = 3;
|
||||
SHOW WARNINGS;
|
||||
--error 1932,1712
|
||||
UPDATE t2 set b = b +1;
|
||||
SHOW WARNINGS;
|
||||
OPTIMIZE TABLE t2;
|
||||
SHOW WARNINGS;
|
||||
--error 1932
|
||||
ALTER TABLE t2 ADD COLUMN c INT;
|
||||
SHOW WARNINGS;
|
||||
ANALYZE TABLE t2;
|
||||
SHOW WARNINGS;
|
||||
--error 1932
|
||||
TRUNCATE TABLE t2;
|
||||
SHOW WARNINGS;
|
||||
--error 1036
|
||||
DROP TABLE t2;
|
||||
SHOW WARNINGS;
|
||||
|
||||
--echo
|
||||
--echo # Restart server with keys.txt
|
||||
-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys.txt
|
||||
-- source include/restart_mysqld.inc
|
||||
|
||||
DROP TABLE t2;
|
||||
SHOW WARNINGS;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
Copyright (c) 2014, 2015, MariaDB Corporation
|
||||
|
||||
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
|
||||
|
|
@ -734,6 +735,20 @@ btr_root_block_get(
|
|||
root_page_no = dict_index_get_page(index);
|
||||
|
||||
block = btr_block_get(space, zip_size, root_page_no, mode, index, mtr);
|
||||
|
||||
if (!block) {
|
||||
index->table->is_encrypted = TRUE;
|
||||
index->table->corrupted = FALSE;
|
||||
|
||||
ib_push_warning(index->table->thd, DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s in tablespace %lu is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name, space);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
btr_assert_not_corrupted(block, index);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
if (!dict_index_is_ibuf(index)) {
|
||||
|
|
@ -759,8 +774,10 @@ btr_root_get(
|
|||
const dict_index_t* index, /*!< in: index tree */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
return(buf_block_get_frame(btr_root_block_get(index, RW_X_LATCH,
|
||||
mtr)));
|
||||
buf_block_t* root = btr_root_block_get(index, RW_X_LATCH,
|
||||
mtr);
|
||||
|
||||
return(root ? buf_block_get_frame(root) : NULL);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
|
|
@ -775,7 +792,7 @@ btr_height_get(
|
|||
dict_index_t* index, /*!< in: index tree */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ulint height;
|
||||
ulint height=0;
|
||||
buf_block_t* root_block;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
|
||||
|
|
@ -786,13 +803,15 @@ btr_height_get(
|
|||
/* S latches the page */
|
||||
root_block = btr_root_block_get(index, RW_S_LATCH, mtr);
|
||||
|
||||
height = btr_page_get_level(buf_block_get_frame(root_block), mtr);
|
||||
if (root_block) {
|
||||
height = btr_page_get_level(buf_block_get_frame(root_block), mtr);
|
||||
|
||||
/* Release the S latch on the root page. */
|
||||
mtr_memo_release(mtr, root_block, MTR_MEMO_PAGE_S_FIX);
|
||||
/* Release the S latch on the root page. */
|
||||
mtr_memo_release(mtr, root_block, MTR_MEMO_PAGE_S_FIX);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
sync_thread_reset_level(&root_block->lock);
|
||||
sync_thread_reset_level(&root_block->lock);
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
}
|
||||
|
||||
return(height);
|
||||
}
|
||||
|
|
@ -1240,7 +1259,7 @@ btr_get_size_and_reserved(
|
|||
{
|
||||
fseg_header_t* seg_header;
|
||||
page_t* root;
|
||||
ulint n;
|
||||
ulint n=ULINT_UNDEFINED;
|
||||
ulint dummy;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
|
||||
|
|
@ -1254,17 +1273,21 @@ btr_get_size_and_reserved(
|
|||
}
|
||||
|
||||
root = btr_root_get(index, mtr);
|
||||
*used = 0;
|
||||
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
|
||||
if (root) {
|
||||
|
||||
n = fseg_n_reserved_pages(seg_header, used, mtr);
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
|
||||
|
||||
if (flag == BTR_TOTAL_SIZE) {
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
|
||||
n = fseg_n_reserved_pages(seg_header, used, mtr);
|
||||
|
||||
n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
|
||||
*used += dummy;
|
||||
if (flag == BTR_TOTAL_SIZE) {
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
|
||||
|
||||
n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
|
||||
*used += dummy;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return(n);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
Google, Inc. Those modifications are gratefully acknowledged and are described
|
||||
|
|
@ -347,7 +348,7 @@ search tuple should be performed in the B-tree. InnoDB does an insert
|
|||
immediately after the cursor. Thus, the cursor may end up on a user record,
|
||||
or on a page infimum record. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dberr_t
|
||||
btr_cur_search_to_nth_level(
|
||||
/*========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
|
|
@ -397,6 +398,7 @@ btr_cur_search_to_nth_level(
|
|||
page_cur_t* page_cursor;
|
||||
btr_op_t btr_op;
|
||||
ulint root_height = 0; /* remove warning */
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
#ifdef BTR_CUR_ADAPT
|
||||
btr_search_t* info;
|
||||
|
|
@ -513,7 +515,7 @@ btr_cur_search_to_nth_level(
|
|||
|| mode != PAGE_CUR_LE);
|
||||
btr_cur_n_sea++;
|
||||
|
||||
return;
|
||||
return err;
|
||||
}
|
||||
# endif /* BTR_CUR_HASH_ADAPT */
|
||||
#endif /* BTR_CUR_ADAPT */
|
||||
|
|
@ -609,7 +611,21 @@ search_loop:
|
|||
retry_page_get:
|
||||
block = buf_page_get_gen(
|
||||
space, zip_size, page_no, rw_latch, guess, buf_mode,
|
||||
file, line, mtr);
|
||||
file, line, mtr, &err);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning((void *)NULL,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (block == NULL) {
|
||||
/* This must be a search to perform an insert/delete
|
||||
|
|
@ -822,12 +838,14 @@ func_exit:
|
|||
|
||||
rw_lock_s_lock(&btr_search_latch);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a cursor at either end of an index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dberr_t
|
||||
btr_cur_open_at_index_side_func(
|
||||
/*============================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
|
|
@ -853,6 +871,8 @@ btr_cur_open_at_index_side_func(
|
|||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets = offsets_;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
estimate = latch_mode & BTR_ESTIMATE;
|
||||
|
|
@ -890,11 +910,26 @@ btr_cur_open_at_index_side_func(
|
|||
height = ULINT_UNDEFINED;
|
||||
|
||||
for (;;) {
|
||||
buf_block_t* block;
|
||||
page_t* page;
|
||||
buf_block_t* block=NULL;
|
||||
page_t* page=NULL;
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no,
|
||||
RW_NO_LATCH, NULL, BUF_GET,
|
||||
file, line, mtr);
|
||||
file, line, mtr, &err);
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning((void *)NULL,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX);
|
||||
ut_ad(index->id == btr_page_get_index_id(page));
|
||||
|
|
@ -979,9 +1014,12 @@ btr_cur_open_at_index_side_func(
|
|||
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
@ -1029,10 +1067,25 @@ btr_cur_open_at_rnd_pos_func(
|
|||
for (;;) {
|
||||
buf_block_t* block;
|
||||
page_t* page;
|
||||
dberr_t err=DB_SUCCESS;
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no,
|
||||
RW_NO_LATCH, NULL, BUF_GET,
|
||||
file, line, mtr);
|
||||
file, line, mtr, &err);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning((void *)NULL,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX);
|
||||
ut_ad(index->id == btr_page_get_index_id(page));
|
||||
|
|
@ -1066,6 +1119,7 @@ btr_cur_open_at_rnd_pos_func(
|
|||
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
|
@ -3562,6 +3616,7 @@ btr_estimate_n_rows_in_range_on_level(
|
|||
mtr_t mtr;
|
||||
page_t* page;
|
||||
buf_block_t* block;
|
||||
dberr_t err=DB_SUCCESS;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
|
|
@ -3572,7 +3627,23 @@ btr_estimate_n_rows_in_range_on_level(
|
|||
silence a debug assertion about this. */
|
||||
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH,
|
||||
NULL, BUF_GET_POSSIBLY_FREED,
|
||||
__FILE__, __LINE__, &mtr);
|
||||
__FILE__, __LINE__, &mtr, &err);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning((void *)NULL,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
|
||||
mtr_commit(&mtr);
|
||||
goto inexact;
|
||||
}
|
||||
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#include "srv0mon.h"
|
||||
#include "buf0checksum.h"
|
||||
#include "fil0pagecompress.h"
|
||||
#include "ha_prototypes.h"
|
||||
#include "ut0byte.h"
|
||||
#include <new>
|
||||
|
||||
|
|
@ -312,6 +313,18 @@ on the io_type */
|
|||
? (counter##_READ) \
|
||||
: (counter##_WRITTEN))
|
||||
|
||||
/********************************************************************//**
|
||||
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 */
|
||||
|
||||
/********************************************************************//**
|
||||
Gets the smallest oldest_modification lsn for any page in the pool. Returns
|
||||
zero if all modified pages have been flushed to disk.
|
||||
|
|
@ -1052,6 +1065,9 @@ buf_block_init(
|
|||
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.real_size = 0;
|
||||
block->page.write_size = 0;
|
||||
block->modify_clock = 0;
|
||||
|
|
@ -2243,7 +2259,7 @@ lookup:
|
|||
/* Page not in buf_pool: needs to be read from file */
|
||||
|
||||
ut_ad(!hash_lock);
|
||||
buf_read_page(space, zip_size, offset);
|
||||
buf_read_page(space, zip_size, offset, NULL);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
ut_a(++buf_dbg_counter % 5771 || buf_validate());
|
||||
|
|
@ -2718,7 +2734,8 @@ buf_page_get_gen(
|
|||
BUF_GET_IF_IN_POOL_OR_WATCH */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mini-transaction */
|
||||
mtr_t* mtr, /*!< in: mini-transaction */
|
||||
dberr_t* err) /*!< out: error code */
|
||||
{
|
||||
buf_block_t* block;
|
||||
ulint fold;
|
||||
|
|
@ -2735,6 +2752,11 @@ buf_page_get_gen(
|
|||
ut_ad((rw_latch == RW_S_LATCH)
|
||||
|| (rw_latch == RW_X_LATCH)
|
||||
|| (rw_latch == RW_NO_LATCH));
|
||||
|
||||
if (err) {
|
||||
*err = DB_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
switch (mode) {
|
||||
case BUF_GET_NO_LATCH:
|
||||
|
|
@ -2795,6 +2817,8 @@ loop:
|
|||
}
|
||||
|
||||
if (block == NULL) {
|
||||
buf_page_t* bpage=NULL;
|
||||
|
||||
/* Page not in buf_pool: needs to be read from file */
|
||||
|
||||
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
|
||||
|
|
@ -2827,36 +2851,77 @@ loop:
|
|||
return(NULL);
|
||||
}
|
||||
|
||||
if (buf_read_page(space, zip_size, offset)) {
|
||||
if (buf_read_page(space, zip_size, offset, &bpage)) {
|
||||
buf_read_ahead_random(space, zip_size, offset,
|
||||
ibuf_inside(mtr));
|
||||
|
||||
retries = 0;
|
||||
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
|
||||
++retries;
|
||||
|
||||
bool corrupted = true;
|
||||
|
||||
if (bpage) {
|
||||
corrupted = buf_page_check_corrupt(bpage);
|
||||
}
|
||||
|
||||
/* Do not try again for encrypted pages */
|
||||
if (!corrupted) {
|
||||
ib_mutex_t* pmutex = buf_page_get_mutex(bpage);
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(pmutex);
|
||||
buf_page_set_io_fix(bpage, BUF_IO_NONE);
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
mutex_exit(pmutex);
|
||||
|
||||
if (err) {
|
||||
*err = DB_ENCRYPTED_DECRYPT_FAILED;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"innodb_page_corruption_retries",
|
||||
retries = BUF_PAGE_READ_MAX_RETRIES;
|
||||
);
|
||||
} else {
|
||||
bool corrupted = true;
|
||||
|
||||
fprintf(stderr, "InnoDB: Error: Unable"
|
||||
" to read tablespace %lu page no"
|
||||
" %lu into the buffer pool after"
|
||||
" %lu attempts\n"
|
||||
"InnoDB: The most probable cause"
|
||||
" of this error may be that the"
|
||||
" table has been corrupted.\n"
|
||||
"InnoDB: You can try to fix this"
|
||||
" problem by using"
|
||||
" innodb_force_recovery.\n"
|
||||
"InnoDB: Please see reference manual"
|
||||
" for more details.\n"
|
||||
"InnoDB: Aborting...\n",
|
||||
space, offset,
|
||||
BUF_PAGE_READ_MAX_RETRIES);
|
||||
if (bpage) {
|
||||
corrupted = buf_page_check_corrupt(bpage);
|
||||
}
|
||||
|
||||
ut_error;
|
||||
if (corrupted) {
|
||||
fprintf(stderr, "InnoDB: Error: Unable"
|
||||
" to read tablespace %lu page no"
|
||||
" %lu into the buffer pool after"
|
||||
" %lu attempts\n"
|
||||
"InnoDB: The most probable cause"
|
||||
" of this error may be that the"
|
||||
" table has been corrupted.\n"
|
||||
"InnoDB: You can try to fix this"
|
||||
" problem by using"
|
||||
" innodb_force_recovery.\n"
|
||||
"InnoDB: Please see reference manual"
|
||||
" for more details.\n"
|
||||
"InnoDB: Aborting...\n",
|
||||
space, offset,
|
||||
BUF_PAGE_READ_MAX_RETRIES);
|
||||
|
||||
ut_error;
|
||||
} else {
|
||||
ib_mutex_t* pmutex = buf_page_get_mutex(bpage);
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(pmutex);
|
||||
buf_page_set_io_fix(bpage, BUF_IO_NONE);
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
mutex_exit(pmutex);
|
||||
|
||||
if (err) {
|
||||
*err = DB_ENCRYPTED_DECRYPT_FAILED;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
|
|
@ -3591,8 +3656,11 @@ buf_page_init_low(
|
|||
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->real_size = 0;
|
||||
bpage->slot = NULL;
|
||||
|
||||
|
|
@ -4245,34 +4313,40 @@ buf_mark_space_corrupt(
|
|||
ulint space = bpage->space;
|
||||
ibool ret = TRUE;
|
||||
|
||||
/* First unfix and release lock on the bpage */
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(buf_page_get_mutex(bpage));
|
||||
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
|
||||
ut_ad(bpage->buf_fix_count == 0);
|
||||
if (!bpage->encrypted) {
|
||||
/* First unfix and release lock on the bpage */
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(buf_page_get_mutex(bpage));
|
||||
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
|
||||
ut_ad(bpage->buf_fix_count == 0);
|
||||
|
||||
/* Set BUF_IO_NONE before we remove the block from LRU list */
|
||||
buf_page_set_io_fix(bpage, BUF_IO_NONE);
|
||||
/* Set BUF_IO_NONE before we remove the block from LRU list */
|
||||
buf_page_set_io_fix(bpage, BUF_IO_NONE);
|
||||
|
||||
if (uncompressed) {
|
||||
rw_lock_x_unlock_gen(
|
||||
&((buf_block_t*) bpage)->lock,
|
||||
BUF_IO_READ);
|
||||
if (uncompressed) {
|
||||
rw_lock_x_unlock_gen(
|
||||
&((buf_block_t*) bpage)->lock,
|
||||
BUF_IO_READ);
|
||||
}
|
||||
|
||||
mutex_exit(buf_page_get_mutex(bpage));
|
||||
}
|
||||
|
||||
mutex_exit(buf_page_get_mutex(bpage));
|
||||
|
||||
/* Find the table with specified space id, and mark it corrupted */
|
||||
if (dict_set_corrupted_by_space(space)) {
|
||||
buf_LRU_free_one_page(bpage);
|
||||
if (!bpage->encrypted) {
|
||||
buf_LRU_free_one_page(bpage);
|
||||
}
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
ut_ad(buf_pool->n_pend_reads > 0);
|
||||
buf_pool->n_pend_reads--;
|
||||
if (!bpage->encrypted) {
|
||||
ut_ad(buf_pool->n_pend_reads > 0);
|
||||
buf_pool->n_pend_reads--;
|
||||
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
|
@ -4283,42 +4357,77 @@ corrupted page. Note that we can't be 100% sure if page is corrupted
|
|||
or decrypt/decompress just failed.
|
||||
*/
|
||||
static
|
||||
void
|
||||
ibool
|
||||
buf_page_check_corrupt(
|
||||
/*===================*/
|
||||
const buf_page_t* bpage) /*!< in/out: buffer page read from disk */
|
||||
buf_page_t* bpage) /*!< in/out: buffer page read from disk */
|
||||
{
|
||||
ulint zip_size = buf_page_get_zip_size(bpage);
|
||||
byte* dst_frame = (zip_size) ? bpage->zip.data :
|
||||
((buf_block_t*) bpage)->frame;
|
||||
unsigned key_version = bpage->key_version;
|
||||
bool page_compressed = bpage->page_encrypted;
|
||||
ulint stored_checksum = bpage->stored_checksum;
|
||||
ulint calculated_checksum = bpage->stored_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;
|
||||
|
||||
if (key_version != 0 || page_compressed_encrypted) {
|
||||
bpage->encrypted = true;
|
||||
}
|
||||
|
||||
if (key_version != 0 ||
|
||||
(crypt_data && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED) ||
|
||||
page_compressed || page_compressed_encrypted) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Maybe corruption: Block space_id %lu in file %s maybe corrupted.",
|
||||
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");
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Reason could be that key_version %u 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);
|
||||
|
||||
/* 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);
|
||||
|
||||
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 %u 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 %u is not found or"
|
||||
" used encryption algorithm or method does not match.",
|
||||
key_version);
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Marking tablespace as missing. You may drop this table or"
|
||||
" install correct key management plugin and key file.");
|
||||
}
|
||||
}
|
||||
|
||||
return corrupted;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
|
|
@ -4437,44 +4546,46 @@ buf_page_io_complete(
|
|||
goto page_not_corrupt;
|
||||
;);
|
||||
corrupt:
|
||||
fil_system_enter();
|
||||
space = fil_space_get_by_id(bpage->space);
|
||||
fil_system_exit();
|
||||
bool corrupted = buf_page_check_corrupt(bpage);
|
||||
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Database page corruption on disk"
|
||||
" or a failed");
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Space %lu file %s read of page %lu.",
|
||||
(ulint)bpage->space,
|
||||
space ? space->name : "NULL",
|
||||
(ulong) bpage->offset);
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"You may have to recover"
|
||||
" from a backup.");
|
||||
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 %lu file %s read of page %lu.",
|
||||
(ulint)bpage->space,
|
||||
space ? space->name : "NULL",
|
||||
(ulong) bpage->offset);
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"You may have to recover"
|
||||
" from a backup.");
|
||||
|
||||
buf_page_check_corrupt(bpage);
|
||||
|
||||
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_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
|
||||
/* If page space id is larger than TRX_SYS_SPACE
|
||||
|
|
@ -4484,12 +4595,30 @@ corrupt:
|
|||
&& buf_mark_space_corrupt(bpage)) {
|
||||
return(false);
|
||||
} else {
|
||||
buf_page_check_corrupt(bpage);
|
||||
corrupted = buf_page_check_corrupt(bpage);
|
||||
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Ending processing because of a corrupt database page.");
|
||||
if (corrupted) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Ending processing because of a corrupt database page.");
|
||||
|
||||
ut_error;
|
||||
ut_error;
|
||||
}
|
||||
|
||||
ib_push_warning((void *)NULL, DB_ENCRYPTED_DECRYPT_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->key_version);
|
||||
|
||||
if (bpage->space > TRX_SYS_SPACE) {
|
||||
if (corrupted) {
|
||||
buf_mark_space_corrupt(bpage);
|
||||
}
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4630,11 +4759,13 @@ buf_all_freed_instance(
|
|||
const buf_block_t* block = buf_chunk_not_freed(chunk);
|
||||
|
||||
if (UNIV_LIKELY_NULL(block)) {
|
||||
fprintf(stderr,
|
||||
"Page %lu %lu still fixed or dirty\n",
|
||||
(ulong) block->page.space,
|
||||
(ulong) block->page.offset);
|
||||
ut_error;
|
||||
if (block->page.key_version == 0) {
|
||||
fprintf(stderr,
|
||||
"Page %lu %lu still fixed or dirty\n",
|
||||
(ulong) block->page.space,
|
||||
(ulong) block->page.offset);
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5950,6 +6081,11 @@ 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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
ut_ad(bpage->key_version == 0);
|
||||
|
||||
if (bpage->offset == 0) {
|
||||
|
|
@ -5994,6 +6130,13 @@ buf_page_decrypt_after_read(
|
|||
#ifdef UNIV_DEBUG
|
||||
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 */
|
||||
fil_space_decrypt(bpage->space,
|
||||
slot->crypt_buf,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015. MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -105,21 +106,22 @@ ulint
|
|||
buf_read_page_low(
|
||||
/*==============*/
|
||||
dberr_t* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
|
||||
trying to read from a non-existent tablespace, or a
|
||||
tablespace which is just now being dropped */
|
||||
bool sync, /*!< in: true if synchronous aio is desired */
|
||||
ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
|
||||
ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
|
||||
at read-ahead functions) */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size, or 0 */
|
||||
ibool unzip, /*!< in: TRUE=request uncompressed page */
|
||||
ib_int64_t tablespace_version, /*!< in: if the space memory object has
|
||||
this timestamp different from what we are giving here,
|
||||
treat the tablespace as dropped; this is a timestamp we
|
||||
use to stop dangling page reads from a tablespace
|
||||
which we have DISCARDed + IMPORTed back */
|
||||
ulint offset) /*!< in: page number */
|
||||
trying to read from a non-existent tablespace, or a
|
||||
tablespace which is just now being dropped */
|
||||
bool sync, /*!< in: true if synchronous aio is desired */
|
||||
ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
|
||||
ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
|
||||
at read-ahead functions) */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size, or 0 */
|
||||
ibool unzip, /*!< in: TRUE=request uncompressed page */
|
||||
ib_int64_t tablespace_version, /*!< in: if the space memory object has
|
||||
this timestamp different from what we are giving here,
|
||||
treat the tablespace as dropped; this is a timestamp we
|
||||
use to stop dangling page reads from a tablespace
|
||||
which we have DISCARDed + IMPORTed back */
|
||||
ulint offset, /*!< in: page number */
|
||||
buf_page_t** rbpage) /*!< out: page */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
ulint wake_later;
|
||||
|
|
@ -214,10 +216,17 @@ buf_read_page_low(
|
|||
/* The i/o is already completed when we arrive from
|
||||
fil_read */
|
||||
if (!buf_page_io_complete(bpage)) {
|
||||
if (rbpage) {
|
||||
*rbpage = bpage;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (rbpage) {
|
||||
*rbpage = bpage;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +357,7 @@ read_ahead:
|
|||
&err, false,
|
||||
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
|
||||
space, zip_size, FALSE,
|
||||
tablespace_version, i);
|
||||
tablespace_version, i, NULL);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
|
@ -398,7 +407,8 @@ buf_read_page(
|
|||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset) /*!< in: page number */
|
||||
ulint offset, /*!< in: page number */
|
||||
buf_page_t** bpage) /*!< out: page */
|
||||
{
|
||||
ib_int64_t tablespace_version;
|
||||
ulint count;
|
||||
|
|
@ -411,7 +421,7 @@ buf_read_page(
|
|||
|
||||
count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space,
|
||||
zip_size, FALSE,
|
||||
tablespace_version, offset);
|
||||
tablespace_version, offset, bpage);
|
||||
srv_stats.buf_pool_reads.add(count);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
|
@ -459,7 +469,7 @@ buf_read_page_async(
|
|||
| OS_AIO_SIMULATED_WAKE_LATER
|
||||
| BUF_READ_IGNORE_NONEXISTENT_PAGES,
|
||||
space, zip_size, FALSE,
|
||||
tablespace_version, offset);
|
||||
tablespace_version, offset, NULL);
|
||||
srv_stats.buf_pool_reads.add(count);
|
||||
|
||||
/* We do not increment number of I/O operations used for LRU policy
|
||||
|
|
@ -718,7 +728,7 @@ buf_read_ahead_linear(
|
|||
count += buf_read_page_low(
|
||||
&err, false,
|
||||
ibuf_mode,
|
||||
space, zip_size, FALSE, tablespace_version, i);
|
||||
space, zip_size, FALSE, tablespace_version, i, NULL);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
|
@ -808,7 +818,7 @@ buf_read_ibuf_merge_pages(
|
|||
buf_read_page_low(&err, sync && (i + 1 == n_stored),
|
||||
BUF_READ_ANY_PAGE, space_ids[i],
|
||||
zip_size, TRUE, space_versions[i],
|
||||
page_nos[i]);
|
||||
page_nos[i], NULL);
|
||||
|
||||
if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
|
||||
tablespace_deleted:
|
||||
|
|
@ -903,12 +913,12 @@ buf_read_recv_pages(
|
|||
if ((i + 1 == n_stored) && sync) {
|
||||
buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space,
|
||||
zip_size, TRUE, tablespace_version,
|
||||
page_nos[i]);
|
||||
page_nos[i], NULL);
|
||||
} else {
|
||||
buf_read_page_low(&err, false, BUF_READ_ANY_PAGE
|
||||
| OS_AIO_SIMULATED_WAKE_LATER,
|
||||
space, zip_size, TRUE,
|
||||
tablespace_version, page_nos[i]);
|
||||
tablespace_version, page_nos[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -650,31 +650,8 @@ fil_space_encrypt(
|
|||
|
||||
/* handle post encryption checksum */
|
||||
ib_uint32_t checksum = 0;
|
||||
srv_checksum_algorithm_t algorithm =
|
||||
static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
|
||||
|
||||
if (zip_size == 0) {
|
||||
switch (algorithm) {
|
||||
case SRV_CHECKSUM_ALGORITHM_CRC32:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
|
||||
checksum = buf_calc_page_crc32(dst_frame);
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
|
||||
checksum = (ib_uint32_t) buf_calc_page_new_checksum(
|
||||
dst_frame);
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_NONE:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
||||
checksum = BUF_NO_CHECKSUM_MAGIC;
|
||||
break;
|
||||
/* no default so the compiler will emit a warning
|
||||
* if new enum is added and not handled here */
|
||||
}
|
||||
} else {
|
||||
checksum = page_zip_calc_checksum(dst_frame, zip_size,
|
||||
algorithm);
|
||||
}
|
||||
checksum = fil_crypt_calculate_checksum(zip_size, dst_frame);
|
||||
|
||||
// store the post-encryption checksum after the key-version
|
||||
mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, checksum);
|
||||
|
|
@ -818,6 +795,47 @@ fil_space_decrypt(
|
|||
return src_frame;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Calculate post encryption checksum
|
||||
@return page checksum or BUF_NO_CHECKSUM_MAGIC
|
||||
not needed. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fil_crypt_calculate_checksum(
|
||||
/*=========================*/
|
||||
ulint zip_size, /*!< in: zip_size or 0 */
|
||||
byte* dst_frame) /*!< in: page where to calculate */
|
||||
{
|
||||
ib_uint32_t checksum = 0;
|
||||
srv_checksum_algorithm_t algorithm =
|
||||
static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
|
||||
|
||||
if (zip_size == 0) {
|
||||
switch (algorithm) {
|
||||
case SRV_CHECKSUM_ALGORITHM_CRC32:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
|
||||
checksum = buf_calc_page_crc32(dst_frame);
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
|
||||
checksum = (ib_uint32_t) buf_calc_page_new_checksum(
|
||||
dst_frame);
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_NONE:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
||||
checksum = BUF_NO_CHECKSUM_MAGIC;
|
||||
break;
|
||||
/* no default so the compiler will emit a warning
|
||||
* if new enum is added and not handled here */
|
||||
}
|
||||
} else {
|
||||
checksum = page_zip_calc_checksum(dst_frame, zip_size,
|
||||
algorithm);
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Verify checksum for a page (iff it's encrypted)
|
||||
NOTE: currently this function can only be run in single threaded mode
|
||||
|
|
|
|||
|
|
@ -1747,6 +1747,7 @@ convert_error_code_to_mysql(
|
|||
|
||||
case DB_TABLESPACE_DELETED:
|
||||
case DB_TABLE_NOT_FOUND:
|
||||
case DB_ENCRYPTED_DECRYPT_FAILED:
|
||||
return(HA_ERR_NO_SUCH_TABLE);
|
||||
|
||||
case DB_TABLESPACE_NOT_FOUND:
|
||||
|
|
@ -5592,7 +5593,14 @@ table_opened:
|
|||
|
||||
innobase_copy_frm_flags_from_table_share(ib_table, table->s);
|
||||
|
||||
dict_stats_init(ib_table);
|
||||
ib_table->thd = (void*)thd;
|
||||
|
||||
/* No point to init any statistics if tablespace is still encrypted. */
|
||||
if (!ib_table->is_encrypted) {
|
||||
dict_stats_init(ib_table);
|
||||
} else {
|
||||
ib_table->stat_initialized = 1;
|
||||
}
|
||||
|
||||
MONITOR_INC(MONITOR_TABLE_OPEN);
|
||||
|
||||
|
|
@ -5621,6 +5629,11 @@ table_opened:
|
|||
file, best to play it safe. */
|
||||
|
||||
no_tablespace = true;
|
||||
} else if (ib_table->is_encrypted) {
|
||||
/* This means that tablespace was found but we could not
|
||||
decrypt encrypted page. */
|
||||
no_tablespace = true;
|
||||
ib_table->ibd_file_missing = true;
|
||||
} else {
|
||||
no_tablespace = false;
|
||||
}
|
||||
|
|
@ -5632,9 +5645,9 @@ table_opened:
|
|||
/* If table has no talespace but it has crypt data, check
|
||||
is tablespace made unaccessible because encryption service
|
||||
or used key_id is not available. */
|
||||
if (ib_table && ib_table->crypt_data) {
|
||||
if (ib_table) {
|
||||
fil_space_crypt_t* crypt_data = ib_table->crypt_data;
|
||||
if ((crypt_data->encryption == FIL_SPACE_ENCRYPTION_ON) ||
|
||||
if ((crypt_data && crypt_data->encryption == FIL_SPACE_ENCRYPTION_ON) ||
|
||||
(srv_encrypt_tables &&
|
||||
crypt_data && crypt_data->encryption == FIL_SPACE_ENCRYPTION_DEFAULT)) {
|
||||
|
||||
|
|
@ -5646,6 +5659,13 @@ table_opened:
|
|||
" Can't continue reading table.",
|
||||
ib_table->name, crypt_data->key_id);
|
||||
}
|
||||
} else if (ib_table->is_encrypted) {
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
HA_ERR_NO_SUCH_TABLE,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
ib_table->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -20212,3 +20232,59 @@ static void innodb_remember_check_sysvar_funcs()
|
|||
ut_ad((MYSQL_SYSVAR_NAME(checksum_algorithm).flags & 0x1FF) == PLUGIN_VAR_ENUM);
|
||||
check_sysvar_enum = MYSQL_SYSVAR_NAME(checksum_algorithm).check;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Helper function to push warnings from InnoDB internals to SQL-layer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_push_warning(
|
||||
trx_t* trx, /*!< in: trx */
|
||||
ulint error, /*!< in: error code to push as warning */
|
||||
const char *format,/*!< in: warning message */
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
THD *thd = (THD *)trx->mysql_thd;
|
||||
char *buf;
|
||||
#define MAX_BUF_SIZE 4*1024
|
||||
|
||||
va_start(args, format);
|
||||
buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
|
||||
vsprintf(buf,format, args);
|
||||
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
convert_error_code_to_mysql((dberr_t)error, 0, thd),
|
||||
buf);
|
||||
my_free(buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Helper function to push warnings from InnoDB internals to SQL-layer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_push_warning(
|
||||
void* ithd, /*!< in: thd */
|
||||
ulint error, /*!< in: error code to push as warning */
|
||||
const char *format,/*!< in: warning message */
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
THD *thd = (THD *)ithd;
|
||||
char *buf;
|
||||
#define MAX_BUF_SIZE 4*1024
|
||||
|
||||
if (ithd == NULL) {
|
||||
thd = current_thd;
|
||||
}
|
||||
|
||||
va_start(args, format);
|
||||
buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
|
||||
vsprintf(buf,format, args);
|
||||
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
convert_error_code_to_mysql((dberr_t)error, 0, thd),
|
||||
buf);
|
||||
my_free(buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -57,13 +58,15 @@ btr_block_get_func(
|
|||
buf_block_t* block;
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no, mode,
|
||||
NULL, BUF_GET, file, line, mtr);
|
||||
NULL, BUF_GET, file, line, mtr);
|
||||
|
||||
if (mode != RW_NO_LATCH) {
|
||||
if (block) {
|
||||
if (mode != RW_NO_LATCH) {
|
||||
|
||||
buf_block_dbg_add_level(
|
||||
block, index != NULL && dict_index_is_ibuf(index)
|
||||
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
|
||||
buf_block_dbg_add_level(
|
||||
block, index != NULL && dict_index_is_ibuf(index)
|
||||
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
|
||||
}
|
||||
}
|
||||
|
||||
return(block);
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ Note that if mode is PAGE_CUR_LE, which is used in inserts, then
|
|||
cursor->up_match and cursor->low_match both will have sensible values.
|
||||
If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dberr_t
|
||||
btr_cur_search_to_nth_level(
|
||||
/*========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
|
|
@ -173,7 +173,7 @@ btr_cur_search_to_nth_level(
|
|||
/*****************************************************************//**
|
||||
Opens a cursor at either end of an index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dberr_t
|
||||
btr_cur_open_at_index_side_func(
|
||||
/*============================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ btr_pcur_open_low(
|
|||
Opens an persistent cursor to an index tree without initializing the
|
||||
cursor. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dberr_t
|
||||
btr_pcur_open_with_no_init_func(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
|
|
@ -143,7 +143,7 @@ btr_pcur_open_with_no_init_func(
|
|||
/*****************************************************************//**
|
||||
Opens a persistent cursor at either end of an index. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dberr_t
|
||||
btr_pcur_open_at_index_side(
|
||||
/*========================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ btr_pcur_open_low(
|
|||
Opens an persistent cursor to an index tree without initializing the
|
||||
cursor. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dberr_t
|
||||
btr_pcur_open_with_no_init_func(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
|
|
@ -472,6 +472,7 @@ btr_pcur_open_with_no_init_func(
|
|||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
btr_cur_t* btr_cursor;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
cursor->latch_mode = latch_mode;
|
||||
cursor->search_mode = mode;
|
||||
|
|
@ -480,20 +481,21 @@ btr_pcur_open_with_no_init_func(
|
|||
|
||||
btr_cursor = btr_pcur_get_btr_cur(cursor);
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
|
||||
btr_cursor, has_search_latch,
|
||||
file, line, mtr);
|
||||
err = btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
|
||||
btr_cursor, has_search_latch,
|
||||
file, line, mtr);
|
||||
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
cursor->trx_if_known = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a persistent cursor at either end of an index. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dberr_t
|
||||
btr_pcur_open_at_index_side(
|
||||
/*========================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
|
|
@ -506,6 +508,8 @@ btr_pcur_open_at_index_side(
|
|||
(0=leaf) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
|
||||
pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L;
|
||||
|
|
@ -514,13 +518,15 @@ btr_pcur_open_at_index_side(
|
|||
btr_pcur_init(pcur);
|
||||
}
|
||||
|
||||
btr_cur_open_at_index_side(from_left, index, latch_mode,
|
||||
btr_pcur_get_btr_cur(pcur), level, mtr);
|
||||
err = btr_cur_open_at_index_side(from_left, index, latch_mode,
|
||||
btr_pcur_get_btr_cur(pcur), level, mtr);
|
||||
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
pcur->trx_if_known = NULL;
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
|
||||
Copyright (c) 2013, 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -430,7 +430,8 @@ buf_page_get_gen(
|
|||
BUF_GET_IF_IN_POOL_OR_WATCH */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mini-transaction */
|
||||
mtr_t* mtr, /*!< in: mini-transaction */
|
||||
dberr_t* err = NULL); /*!< out: error code */
|
||||
/********************************************************************//**
|
||||
Initializes a page to the buffer buf_pool. The page is usually not read
|
||||
from a file even if it cannot be found in the buffer buf_pool. This is one
|
||||
|
|
@ -1582,9 +1583,14 @@ struct buf_page_t{
|
|||
operation needed. */
|
||||
|
||||
unsigned key_version; /*!< key version for this block */
|
||||
bool page_encrypted; /*!< page is encrypted */
|
||||
bool page_encrypted; /*!< page is page encrypted */
|
||||
bool page_compressed;/*!< page is page compressed */
|
||||
|
||||
ulint stored_checksum;/*!< stored page checksum if page
|
||||
encrypted */
|
||||
bool encrypted; /*!< page is still encrypted */
|
||||
ulint calculated_checksum;
|
||||
/*!< calculated checksum if page
|
||||
encrypted */
|
||||
ulint real_size; /*!< Real size of the page
|
||||
Normal pages == UNIV_PAGE_SIZE
|
||||
page compressed pages, payload
|
||||
|
|
|
|||
|
|
@ -663,13 +663,18 @@ buf_block_get_frame(
|
|||
/*================*/
|
||||
const buf_block_t* block) /*!< in: pointer to the control block */
|
||||
{
|
||||
ut_ad(block);
|
||||
if (!block) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (buf_block_get_state(block)) {
|
||||
case BUF_BLOCK_POOL_WATCH:
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
case BUF_BLOCK_ZIP_DIRTY:
|
||||
case BUF_BLOCK_NOT_USED:
|
||||
if (block->page.encrypted) {
|
||||
goto ok;
|
||||
}
|
||||
ut_error;
|
||||
break;
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -41,7 +42,8 @@ buf_read_page(
|
|||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset);/*!< in: page number */
|
||||
ulint offset, /*!< in: page number */
|
||||
buf_page_t** bpage);/*!< out: page */
|
||||
/********************************************************************//**
|
||||
High-level function which reads a page asynchronously from a file to the
|
||||
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -132,6 +133,11 @@ enum dberr_t {
|
|||
/*< Too many words in a phrase */
|
||||
DB_TOO_BIG_FOR_REDO, /* Record length greater than 10%
|
||||
of redo log */
|
||||
DB_ENCRYPTED_DECRYPT_FAILED, /* Tablespace encrypted and
|
||||
decrypt operaton failed because
|
||||
of missing key management plugin,
|
||||
or missing or incorrect key or
|
||||
incorret AES method or algorithm. */
|
||||
/* The following are partial failure codes */
|
||||
DB_FAIL = 1000,
|
||||
DB_OVERFLOW,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
|
||||
Copyright (c) 2013, 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -1017,6 +1017,7 @@ struct dict_table_t{
|
|||
table_id_t id; /*!< id of the table */
|
||||
mem_heap_t* heap; /*!< memory heap */
|
||||
char* name; /*!< table name */
|
||||
void* thd; /*!< thd */
|
||||
fil_space_crypt_t *crypt_data; /*!< crypt data if present */
|
||||
const char* dir_path_of_temp_table;/*!< NULL or the directory path
|
||||
where a TEMPORARY table that was explicitly
|
||||
|
|
@ -1330,6 +1331,7 @@ struct dict_table_t{
|
|||
locks; /*!< list of locks on the table; protected
|
||||
by lock_sys->mutex */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
ibool is_encrypted;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint magic_n;/*!< magic number */
|
||||
|
|
|
|||
|
|
@ -382,6 +382,17 @@ fil_crypt_set_encrypt_tables(
|
|||
uint val); /*!< in: New srv_encrypt_tables setting */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
Calculate post encryption checksum
|
||||
@return page checksum or BUF_NO_CHECKSUM_MAGIC
|
||||
not needed. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fil_crypt_calculate_checksum(
|
||||
/*=========================*/
|
||||
ulint zip_size, /*!< in: zip_size or 0 */
|
||||
byte* dst_frame); /*!< in: page where to calculate */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fil0crypt.ic"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -634,5 +634,13 @@ ib_push_warning(
|
|||
ulint error, /*!< in: error code to push as warning */
|
||||
const char *format,/*!< in: warning message */
|
||||
...);
|
||||
|
||||
/********************************************************************//**
|
||||
Helper function to push warnings from InnoDB internals to SQL-layer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_push_warning(
|
||||
void* ithd, /*!< in: thd */
|
||||
ulint error, /*!< in: error code to push as warning */
|
||||
const char *format,/*!< in: warning message */
|
||||
...);
|
||||
#endif /* HA_INNODB_PROTOTYPES_H */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -39,7 +40,10 @@ page_cur_get_page(
|
|||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(page_align(cur->rec));
|
||||
}
|
||||
|
|
@ -54,7 +58,11 @@ page_cur_get_block(
|
|||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(cur->block);
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +88,10 @@ page_cur_get_rec(
|
|||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(cur->rec);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2338,7 +2338,7 @@ row_ins_clust_index_entry_low(
|
|||
{
|
||||
btr_cur_t cursor;
|
||||
ulint* offsets = NULL;
|
||||
dberr_t err;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
big_rec_t* big_rec = NULL;
|
||||
mtr_t mtr;
|
||||
mem_heap_t* offsets_heap = NULL;
|
||||
|
|
@ -2361,9 +2361,16 @@ row_ins_clust_index_entry_low(
|
|||
the function will return in both low_match and up_match of the
|
||||
cursor sensible values */
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, mode,
|
||||
err = btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, mode,
|
||||
&cursor, 0, __FILE__, __LINE__, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
index->table->is_encrypted = true;
|
||||
index->table->ibd_file_missing = true;
|
||||
mtr_commit(&mtr);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
{
|
||||
page_t* page = btr_cur_get_page(&cursor);
|
||||
|
|
@ -2669,9 +2676,22 @@ row_ins_sec_index_entry_low(
|
|||
search_mode |= BTR_IGNORE_SEC_UNIQUE;
|
||||
}
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
|
||||
search_mode,
|
||||
&cursor, 0, __FILE__, __LINE__, &mtr);
|
||||
err = btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
|
||||
search_mode,
|
||||
&cursor, 0, __FILE__, __LINE__, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning(trx->mysql_thd,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
|
||||
/* The insert was buffered during the search: we are done */
|
||||
|
|
|
|||
|
|
@ -623,6 +623,8 @@ handle_new_error:
|
|||
case DB_FTS_INVALID_DOCID:
|
||||
case DB_INTERRUPTED:
|
||||
case DB_DICT_CHANGED:
|
||||
case DB_TABLE_NOT_FOUND:
|
||||
case DB_ENCRYPTED_DECRYPT_FAILED:
|
||||
if (savept) {
|
||||
/* Roll back the latest, possibly incomplete insertion
|
||||
or update */
|
||||
|
|
@ -1315,7 +1317,13 @@ row_insert_for_mysql(
|
|||
prebuilt->table->name);
|
||||
|
||||
return(DB_TABLESPACE_NOT_FOUND);
|
||||
|
||||
} else if (prebuilt->table->is_encrypted) {
|
||||
ib_push_warning(trx, DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s in tablespace %lu encrypted."
|
||||
"However key management plugin or used key_id is not found or"
|
||||
" used encryption algorithm or method does not match.",
|
||||
prebuilt->table->name, prebuilt->table->space);
|
||||
return(DB_ENCRYPTED_DECRYPT_FAILED);
|
||||
} else if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to free a corrupt\n"
|
||||
|
|
@ -1710,6 +1718,13 @@ row_update_for_mysql(
|
|||
"InnoDB: how you can resolve the problem.\n",
|
||||
prebuilt->table->name);
|
||||
return(DB_ERROR);
|
||||
} else if (prebuilt->table->is_encrypted) {
|
||||
ib_push_warning(trx, DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s in tablespace %lu encrypted."
|
||||
"However key management plugin or used key_id is not found or"
|
||||
" used encryption algorithm or method does not match.",
|
||||
prebuilt->table->name, prebuilt->table->space);
|
||||
return (DB_TABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
|
||||
|
|
@ -3919,6 +3934,19 @@ row_drop_table_for_mysql(
|
|||
goto funct_exit;
|
||||
}
|
||||
|
||||
/* If table is encrypted and table page encryption failed
|
||||
mark this table read only. */
|
||||
if (table->is_encrypted) {
|
||||
|
||||
if (table->can_be_evicted) {
|
||||
dict_table_move_from_lru_to_non_lru(table);
|
||||
}
|
||||
|
||||
dict_table_close(table, TRUE, FALSE);
|
||||
err = DB_READ_ONLY;
|
||||
goto funct_exit;
|
||||
}
|
||||
|
||||
/* Turn on this drop bit before we could release the dictionary
|
||||
latch */
|
||||
table->to_be_dropped = true;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
Google, Inc. Those modifications are gratefully acknowledged and are described
|
||||
|
|
@ -3717,6 +3718,9 @@ row_search_for_mysql(
|
|||
|
||||
return(DB_TABLESPACE_NOT_FOUND);
|
||||
|
||||
} else if (prebuilt->table->is_encrypted) {
|
||||
|
||||
return(DB_ENCRYPTED_DECRYPT_FAILED);
|
||||
} else if (!prebuilt->index_usable) {
|
||||
|
||||
return(DB_MISSING_HISTORY);
|
||||
|
|
@ -4143,9 +4147,14 @@ wait_table_again:
|
|||
|
||||
} else if (dtuple_get_n_fields(search_tuple) > 0) {
|
||||
|
||||
btr_pcur_open_with_no_init(index, search_tuple, mode,
|
||||
BTR_SEARCH_LEAF,
|
||||
pcur, 0, &mtr);
|
||||
err = btr_pcur_open_with_no_init(index, search_tuple, mode,
|
||||
BTR_SEARCH_LEAF,
|
||||
pcur, 0, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
rec = NULL;
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
|
||||
pcur->trx_if_known = trx;
|
||||
|
||||
|
|
@ -4179,9 +4188,23 @@ wait_table_again:
|
|||
}
|
||||
}
|
||||
} else if (mode == PAGE_CUR_G || mode == PAGE_CUR_L) {
|
||||
btr_pcur_open_at_index_side(
|
||||
err = btr_pcur_open_at_index_side(
|
||||
mode == PAGE_CUR_G, index, BTR_SEARCH_LEAF,
|
||||
pcur, false, 0, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning(trx->mysql_thd,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
prebuilt->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
rec = NULL;
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
}
|
||||
|
||||
rec_loop:
|
||||
|
|
@ -4196,6 +4219,12 @@ rec_loop:
|
|||
/* PHASE 4: Look for matching records in a loop */
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (!rec) {
|
||||
err = DB_ENCRYPTED_DECRYPT_FAILED;
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
|
||||
ut_ad(!!page_rec_is_comp(rec) == comp);
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
/*
|
||||
|
|
@ -5113,7 +5142,9 @@ lock_wait_or_error:
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
if (rec) {
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
}
|
||||
|
||||
lock_table_wait:
|
||||
mtr_commit(&mtr);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
Copyright (c) 2014, 2015, MariaDB Corporation
|
||||
|
||||
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
|
||||
|
|
@ -741,6 +742,19 @@ btr_root_block_get(
|
|||
|
||||
block = btr_block_get(space, zip_size, root_page_no, mode, index, mtr);
|
||||
|
||||
if (!block) {
|
||||
index->table->is_encrypted = TRUE;
|
||||
index->table->corrupted = FALSE;
|
||||
|
||||
ib_push_warning(index->table->thd, DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s in tablespace %lu is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name, space);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(0););
|
||||
|
||||
btr_assert_not_corrupted(block, index);
|
||||
|
|
@ -779,8 +793,10 @@ btr_root_get(
|
|||
const dict_index_t* index, /*!< in: index tree */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
return(buf_block_get_frame(btr_root_block_get(index, RW_X_LATCH,
|
||||
mtr)));
|
||||
buf_block_t* root = btr_root_block_get(index, RW_X_LATCH,
|
||||
mtr);
|
||||
|
||||
return(root ? buf_block_get_frame(root) : NULL);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
|
|
@ -795,7 +811,7 @@ btr_height_get(
|
|||
dict_index_t* index, /*!< in: index tree */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ulint height;
|
||||
ulint height=0;
|
||||
buf_block_t* root_block;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
|
||||
|
|
@ -806,13 +822,16 @@ btr_height_get(
|
|||
/* S latches the page */
|
||||
root_block = btr_root_block_get(index, RW_S_LATCH, mtr);
|
||||
|
||||
height = btr_page_get_level(buf_block_get_frame_fast(root_block), mtr);
|
||||
if (root_block) {
|
||||
|
||||
/* Release the S latch on the root page. */
|
||||
mtr_memo_release(mtr, root_block, MTR_MEMO_PAGE_S_FIX);
|
||||
height = btr_page_get_level(buf_block_get_frame_fast(root_block), mtr);
|
||||
|
||||
/* Release the S latch on the root page. */
|
||||
mtr_memo_release(mtr, root_block, MTR_MEMO_PAGE_S_FIX);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
sync_thread_reset_level(&root_block->lock);
|
||||
sync_thread_reset_level(&root_block->lock);
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
}
|
||||
|
||||
return(height);
|
||||
}
|
||||
|
|
@ -1260,7 +1279,7 @@ btr_get_size_and_reserved(
|
|||
{
|
||||
fseg_header_t* seg_header;
|
||||
page_t* root;
|
||||
ulint n;
|
||||
ulint n=ULINT_UNDEFINED;
|
||||
ulint dummy;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
|
||||
|
|
@ -1274,17 +1293,21 @@ btr_get_size_and_reserved(
|
|||
}
|
||||
|
||||
root = btr_root_get(index, mtr);
|
||||
*used = 0;
|
||||
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
|
||||
if (root) {
|
||||
|
||||
n = fseg_n_reserved_pages(seg_header, used, mtr);
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
|
||||
|
||||
if (flag == BTR_TOTAL_SIZE) {
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
|
||||
n = fseg_n_reserved_pages(seg_header, used, mtr);
|
||||
|
||||
n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
|
||||
*used += dummy;
|
||||
if (flag == BTR_TOTAL_SIZE) {
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
|
||||
|
||||
n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
|
||||
*used += dummy;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return(n);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
Google, Inc. Those modifications are gratefully acknowledged and are described
|
||||
|
|
@ -386,7 +387,7 @@ search tuple should be performed in the B-tree. InnoDB does an insert
|
|||
immediately after the cursor. Thus, the cursor may end up on a user record,
|
||||
or on a page infimum record. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dberr_t
|
||||
btr_cur_search_to_nth_level(
|
||||
/*========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
|
|
@ -436,6 +437,7 @@ btr_cur_search_to_nth_level(
|
|||
page_cur_t* page_cursor;
|
||||
btr_op_t btr_op;
|
||||
ulint root_height = 0; /* remove warning */
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
#ifdef BTR_CUR_ADAPT
|
||||
btr_search_t* info;
|
||||
|
|
@ -553,7 +555,7 @@ btr_cur_search_to_nth_level(
|
|||
|| mode != PAGE_CUR_LE);
|
||||
btr_cur_n_sea++;
|
||||
|
||||
return;
|
||||
return err;
|
||||
}
|
||||
# endif /* BTR_CUR_HASH_ADAPT */
|
||||
#endif /* BTR_CUR_ADAPT */
|
||||
|
|
@ -649,7 +651,21 @@ search_loop:
|
|||
retry_page_get:
|
||||
block = buf_page_get_gen(
|
||||
space, zip_size, page_no, rw_latch, guess, buf_mode,
|
||||
file, line, mtr);
|
||||
file, line, mtr, &err);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning((void *)NULL,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (block == NULL) {
|
||||
SRV_CORRUPT_TABLE_CHECK(buf_mode == BUF_GET_IF_IN_POOL ||
|
||||
|
|
@ -889,12 +905,14 @@ func_exit:
|
|||
|
||||
rw_lock_s_lock(btr_search_get_latch(cursor->index));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a cursor at either end of an index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dberr_t
|
||||
btr_cur_open_at_index_side_func(
|
||||
/*============================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
|
|
@ -920,6 +938,8 @@ btr_cur_open_at_index_side_func(
|
|||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets = offsets_;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
estimate = latch_mode & BTR_ESTIMATE;
|
||||
|
|
@ -957,11 +977,26 @@ btr_cur_open_at_index_side_func(
|
|||
height = ULINT_UNDEFINED;
|
||||
|
||||
for (;;) {
|
||||
buf_block_t* block;
|
||||
page_t* page;
|
||||
buf_block_t* block=NULL;
|
||||
page_t* page=NULL;
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no,
|
||||
RW_NO_LATCH, NULL, BUF_GET,
|
||||
file, line, mtr);
|
||||
file, line, mtr, &err);
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning((void *)NULL,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
SRV_CORRUPT_TABLE_CHECK(page,
|
||||
|
|
@ -1066,6 +1101,8 @@ exit_loop:
|
|||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
@ -1113,10 +1150,25 @@ btr_cur_open_at_rnd_pos_func(
|
|||
for (;;) {
|
||||
buf_block_t* block;
|
||||
page_t* page;
|
||||
dberr_t err=DB_SUCCESS;
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no,
|
||||
RW_NO_LATCH, NULL, BUF_GET,
|
||||
file, line, mtr);
|
||||
file, line, mtr, &err);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning((void *)NULL,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
SRV_CORRUPT_TABLE_CHECK(page,
|
||||
|
|
@ -3749,6 +3801,7 @@ btr_estimate_n_rows_in_range_on_level(
|
|||
mtr_t mtr;
|
||||
page_t* page;
|
||||
buf_block_t* block;
|
||||
dberr_t err=DB_SUCCESS;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
|
|
@ -3759,7 +3812,23 @@ btr_estimate_n_rows_in_range_on_level(
|
|||
silence a debug assertion about this. */
|
||||
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH,
|
||||
NULL, BUF_GET_POSSIBLY_FREED,
|
||||
__FILE__, __LINE__, &mtr);
|
||||
__FILE__, __LINE__, &mtr, &err);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning((void *)NULL,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
|
||||
mtr_commit(&mtr);
|
||||
goto inexact;
|
||||
}
|
||||
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
|
|
|
|||
|
|
@ -59,11 +59,24 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#include "srv0start.h"
|
||||
#include "ut0byte.h"
|
||||
#include "fil0pagecompress.h"
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
|
||||
/* 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)
|
||||
|
|
@ -1128,6 +1141,9 @@ buf_block_init(
|
|||
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.real_size = 0;
|
||||
block->page.write_size = 0;
|
||||
block->modify_clock = 0;
|
||||
|
|
@ -2234,7 +2250,7 @@ lookup:
|
|||
/* Page not in buf_pool: needs to be read from file */
|
||||
|
||||
ut_ad(!hash_lock);
|
||||
buf_read_page(space, zip_size, offset, trx);
|
||||
buf_read_page(space, zip_size, offset, trx, NULL);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
ut_a(++buf_dbg_counter % 5771 || buf_validate());
|
||||
|
|
@ -2753,7 +2769,8 @@ buf_page_get_gen(
|
|||
BUF_GET_IF_IN_POOL_OR_WATCH */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mini-transaction */
|
||||
mtr_t* mtr, /*!< in: mini-transaction */
|
||||
dberr_t* err) /*!< out: error code */
|
||||
{
|
||||
buf_block_t* block;
|
||||
ulint fold;
|
||||
|
|
@ -2771,6 +2788,11 @@ buf_page_get_gen(
|
|||
ut_ad((rw_latch == RW_S_LATCH)
|
||||
|| (rw_latch == RW_X_LATCH)
|
||||
|| (rw_latch == RW_NO_LATCH));
|
||||
|
||||
if (err) {
|
||||
*err = DB_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
switch (mode) {
|
||||
case BUF_GET_NO_LATCH:
|
||||
|
|
@ -2834,6 +2856,8 @@ loop:
|
|||
}
|
||||
|
||||
if (block == NULL) {
|
||||
buf_page_t* bpage=NULL;
|
||||
|
||||
/* Page not in buf_pool: needs to be read from file */
|
||||
|
||||
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
|
||||
|
|
@ -2868,36 +2892,77 @@ loop:
|
|||
return(NULL);
|
||||
}
|
||||
|
||||
if (buf_read_page(space, zip_size, offset, trx)) {
|
||||
if (buf_read_page(space, zip_size, offset, trx, &bpage)) {
|
||||
buf_read_ahead_random(space, zip_size, offset,
|
||||
ibuf_inside(mtr), trx);
|
||||
|
||||
retries = 0;
|
||||
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
|
||||
++retries;
|
||||
|
||||
bool corrupted = true;
|
||||
|
||||
if (bpage) {
|
||||
corrupted = buf_page_check_corrupt(bpage);
|
||||
}
|
||||
|
||||
/* Do not try again for encrypted pages */
|
||||
if (!corrupted) {
|
||||
ib_mutex_t* pmutex = buf_page_get_mutex(bpage);
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
mutex_enter(pmutex);
|
||||
buf_page_set_io_fix(bpage, BUF_IO_NONE);
|
||||
buf_LRU_free_page(bpage, zip_size ? true : false);
|
||||
mutex_exit(pmutex);
|
||||
|
||||
if (err) {
|
||||
*err = DB_ENCRYPTED_DECRYPT_FAILED;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"innodb_page_corruption_retries",
|
||||
retries = BUF_PAGE_READ_MAX_RETRIES;
|
||||
);
|
||||
} else {
|
||||
bool corrupted = true;
|
||||
|
||||
fprintf(stderr, "InnoDB: Error: Unable"
|
||||
" to read tablespace %lu page no"
|
||||
" %lu into the buffer pool after"
|
||||
" %lu attempts\n"
|
||||
"InnoDB: The most probable cause"
|
||||
" of this error may be that the"
|
||||
" table has been corrupted.\n"
|
||||
"InnoDB: You can try to fix this"
|
||||
" problem by using"
|
||||
" innodb_force_recovery.\n"
|
||||
"InnoDB: Please see reference manual"
|
||||
" for more details.\n"
|
||||
"InnoDB: Aborting...\n",
|
||||
space, offset,
|
||||
BUF_PAGE_READ_MAX_RETRIES);
|
||||
if (bpage) {
|
||||
corrupted = buf_page_check_corrupt(bpage);
|
||||
}
|
||||
|
||||
ut_error;
|
||||
if (corrupted) {
|
||||
fprintf(stderr, "InnoDB: Error: Unable"
|
||||
" to read tablespace %lu page no"
|
||||
" %lu into the buffer pool after"
|
||||
" %lu attempts\n"
|
||||
"InnoDB: The most probable cause"
|
||||
" of this error may be that the"
|
||||
" table has been corrupted.\n"
|
||||
"InnoDB: You can try to fix this"
|
||||
" problem by using"
|
||||
" innodb_force_recovery.\n"
|
||||
"InnoDB: Please see reference manual"
|
||||
" for more details.\n"
|
||||
"InnoDB: Aborting...\n",
|
||||
space, offset,
|
||||
BUF_PAGE_READ_MAX_RETRIES);
|
||||
|
||||
ut_error;
|
||||
} else {
|
||||
ib_mutex_t* pmutex = buf_page_get_mutex(bpage);
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
mutex_enter(pmutex);
|
||||
buf_page_set_io_fix(bpage, BUF_IO_NONE);
|
||||
buf_LRU_free_page(bpage, zip_size ? true : false);
|
||||
mutex_exit(pmutex);
|
||||
|
||||
if (err) {
|
||||
*err = DB_ENCRYPTED_DECRYPT_FAILED;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
|
|
@ -3670,8 +3735,11 @@ buf_page_init_low(
|
|||
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->real_size = 0;
|
||||
|
||||
HASH_INVALIDATE(bpage, hash);
|
||||
|
|
@ -4341,33 +4409,41 @@ buf_mark_space_corrupt(
|
|||
|
||||
/* First unfix and release lock on the bpage */
|
||||
ut_ad(!mutex_own(&buf_pool->LRU_list_mutex));
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
rw_lock_x_lock(hash_lock);
|
||||
mutex_enter(buf_page_get_mutex(bpage));
|
||||
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
|
||||
ut_ad(bpage->buf_fix_count == 0);
|
||||
|
||||
/* Set BUF_IO_NONE before we remove the block from LRU list */
|
||||
buf_page_set_io_fix(bpage, BUF_IO_NONE);
|
||||
if (!bpage->encrypted) {
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
rw_lock_x_lock(hash_lock);
|
||||
mutex_enter(buf_page_get_mutex(bpage));
|
||||
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
|
||||
ut_ad(bpage->buf_fix_count == 0);
|
||||
|
||||
if (uncompressed) {
|
||||
rw_lock_x_unlock_gen(
|
||||
&((buf_block_t*) bpage)->lock,
|
||||
BUF_IO_READ);
|
||||
/* Set BUF_IO_NONE before we remove the block from LRU list */
|
||||
buf_page_set_io_fix(bpage, BUF_IO_NONE);
|
||||
|
||||
if (uncompressed) {
|
||||
rw_lock_x_unlock_gen(
|
||||
&((buf_block_t*) bpage)->lock,
|
||||
BUF_IO_READ);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the table with specified space id, and mark it corrupted */
|
||||
if (dict_set_corrupted_by_space(space)) {
|
||||
buf_LRU_free_one_page(bpage);
|
||||
if (!bpage->encrypted) {
|
||||
buf_LRU_free_one_page(bpage);
|
||||
}
|
||||
} else {
|
||||
mutex_exit(buf_page_get_mutex(bpage));
|
||||
if (!bpage->encrypted) {
|
||||
mutex_exit(buf_page_get_mutex(bpage));
|
||||
}
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
|
||||
ut_ad(buf_pool->n_pend_reads > 0);
|
||||
os_atomic_decrement_ulint(&buf_pool->n_pend_reads, 1);
|
||||
if(!bpage->encrypted) {
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
ut_ad(buf_pool->n_pend_reads > 0);
|
||||
os_atomic_decrement_ulint(&buf_pool->n_pend_reads, 1);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
|
@ -4378,42 +4454,77 @@ corrupted page. Note that we can't be 100% sure if page is corrupted
|
|||
or decrypt/decompress just failed.
|
||||
*/
|
||||
static
|
||||
void
|
||||
ibool
|
||||
buf_page_check_corrupt(
|
||||
/*===================*/
|
||||
const buf_page_t* bpage) /*!< in/out: buffer page read from disk */
|
||||
buf_page_t* bpage) /*!< in/out: buffer page read from disk */
|
||||
{
|
||||
ulint zip_size = buf_page_get_zip_size(bpage);
|
||||
byte* dst_frame = (zip_size) ? bpage->zip.data :
|
||||
((buf_block_t*) bpage)->frame;
|
||||
unsigned key_version = bpage->key_version;
|
||||
bool page_compressed = bpage->page_encrypted;
|
||||
ulint stored_checksum = bpage->stored_checksum;
|
||||
ulint calculated_checksum = bpage->stored_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;
|
||||
|
||||
if (key_version != 0 || page_compressed_encrypted) {
|
||||
bpage->encrypted = true;
|
||||
}
|
||||
|
||||
if (key_version != 0 ||
|
||||
(crypt_data && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED) ||
|
||||
page_compressed || page_compressed_encrypted) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Maybe corruption: Block space_id %lu in file %s maybe corrupted.",
|
||||
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");
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Reason could be that key_version %u 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);
|
||||
|
||||
/* 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);
|
||||
|
||||
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 %u 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 %u is not found or"
|
||||
" used encryption algorithm or method does not match.",
|
||||
key_version);
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Marking tablespace as missing. You may drop this table or"
|
||||
" install correct key management plugin and key file.");
|
||||
}
|
||||
}
|
||||
|
||||
return corrupted;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
|
|
@ -4534,42 +4645,46 @@ buf_page_io_complete(
|
|||
;);
|
||||
corrupt:
|
||||
|
||||
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 %lu file %s read of page %lu.",
|
||||
(ulint)bpage->space,
|
||||
space ? space->name : "NULL",
|
||||
(ulong) bpage->offset);
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"You may have to recover"
|
||||
" from a backup.");
|
||||
bool corrupted = buf_page_check_corrupt(bpage);
|
||||
|
||||
buf_page_check_corrupt(bpage);
|
||||
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 %lu file %s read of page %lu.",
|
||||
(ulint)bpage->space,
|
||||
space ? space->name : "NULL",
|
||||
(ulong) 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);
|
||||
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.");
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
if (srv_pass_corrupt_table && bpage->space != 0
|
||||
&& bpage->space < SRV_LOG_SPACE_FIRST_ID) {
|
||||
|
|
@ -4597,12 +4712,30 @@ corrupt:
|
|||
&& buf_mark_space_corrupt(bpage)) {
|
||||
return(false);
|
||||
} else {
|
||||
buf_page_check_corrupt(bpage);
|
||||
corrupted = buf_page_check_corrupt(bpage);
|
||||
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Ending processing because of a corrupt database page.");
|
||||
if (corrupted) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Ending processing because of a corrupt database page.");
|
||||
|
||||
ut_error;
|
||||
ut_error;
|
||||
}
|
||||
|
||||
ib_push_warning(innobase_get_trx(), DB_ENCRYPTED_DECRYPT_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->key_version);
|
||||
|
||||
if (bpage->space > TRX_SYS_SPACE) {
|
||||
if (corrupted) {
|
||||
buf_mark_space_corrupt(bpage);
|
||||
}
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4780,11 +4913,13 @@ buf_all_freed_instance(
|
|||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
|
||||
if (UNIV_LIKELY_NULL(block)) {
|
||||
fprintf(stderr,
|
||||
"Page %lu %lu still fixed or dirty\n",
|
||||
(ulong) block->page.space,
|
||||
(ulong) block->page.offset);
|
||||
ut_error;
|
||||
if (block->page.key_version == 0) {
|
||||
fprintf(stderr,
|
||||
"Page %lu %lu still fixed or dirty\n",
|
||||
(ulong) block->page.space,
|
||||
(ulong) block->page.offset);
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6124,6 +6259,11 @@ 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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
ut_ad(bpage->key_version == 0);
|
||||
|
||||
if (bpage->offset == 0) {
|
||||
|
|
@ -6168,6 +6308,13 @@ buf_page_decrypt_after_read(
|
|||
#ifdef UNIV_DEBUG
|
||||
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 */
|
||||
fil_space_decrypt(bpage->space,
|
||||
slot->crypt_buf,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
|
||||
Copyright (c) 2013, 2014, 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
|
||||
|
|
@ -124,7 +124,8 @@ buf_read_page_low(
|
|||
use to stop dangling page reads from a tablespace
|
||||
which we have DISCARDed + IMPORTed back */
|
||||
ulint offset, /*!< in: page number */
|
||||
trx_t* trx)
|
||||
trx_t* trx, /*!< in: trx */
|
||||
buf_page_t** rbpage) /*!< out: page */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
ulint wake_later;
|
||||
|
|
@ -259,10 +260,17 @@ not_to_recover:
|
|||
/* The i/o is already completed when we arrive from
|
||||
fil_read */
|
||||
if (!buf_page_io_complete(bpage)) {
|
||||
if (rbpage) {
|
||||
*rbpage = bpage;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (rbpage) {
|
||||
*rbpage = bpage;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
|
@ -398,7 +406,7 @@ read_ahead:
|
|||
&err, false,
|
||||
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
|
||||
space, zip_size, FALSE,
|
||||
tablespace_version, i, trx);
|
||||
tablespace_version, i, trx, NULL);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
|
@ -446,10 +454,11 @@ UNIV_INTERN
|
|||
ibool
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset, /*!< in: page number */
|
||||
trx_t* trx)
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset, /*!< in: page number */
|
||||
trx_t* trx, /*!< in: trx */
|
||||
buf_page_t** bpage) /*!< out: page */
|
||||
{
|
||||
ib_int64_t tablespace_version;
|
||||
ulint count;
|
||||
|
|
@ -462,7 +471,7 @@ buf_read_page(
|
|||
|
||||
count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space,
|
||||
zip_size, FALSE,
|
||||
tablespace_version, offset, trx);
|
||||
tablespace_version, offset, trx, bpage);
|
||||
srv_stats.buf_pool_reads.add(count);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
|
@ -510,7 +519,7 @@ buf_read_page_async(
|
|||
| OS_AIO_SIMULATED_WAKE_LATER
|
||||
| BUF_READ_IGNORE_NONEXISTENT_PAGES,
|
||||
space, zip_size, FALSE,
|
||||
tablespace_version, offset, NULL);
|
||||
tablespace_version, offset, NULL,NULL);
|
||||
srv_stats.buf_pool_reads.add(count);
|
||||
|
||||
/* We do not increment number of I/O operations used for LRU policy
|
||||
|
|
@ -778,7 +787,7 @@ buf_read_ahead_linear(
|
|||
count += buf_read_page_low(
|
||||
&err, false,
|
||||
ibuf_mode,
|
||||
space, zip_size, FALSE, tablespace_version, i, trx);
|
||||
space, zip_size, FALSE, tablespace_version, i, trx, NULL);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
|
@ -868,7 +877,7 @@ buf_read_ibuf_merge_pages(
|
|||
buf_read_page_low(&err, sync && (i + 1 == n_stored),
|
||||
BUF_READ_ANY_PAGE, space_ids[i],
|
||||
zip_size, TRUE, space_versions[i],
|
||||
page_nos[i], NULL);
|
||||
page_nos[i], NULL, NULL);
|
||||
|
||||
if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
|
||||
tablespace_deleted:
|
||||
|
|
@ -1008,12 +1017,12 @@ not_to_recover:
|
|||
if ((i + 1 == n_stored) && sync) {
|
||||
buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space,
|
||||
zip_size, TRUE, tablespace_version,
|
||||
page_nos[i], NULL);
|
||||
page_nos[i], NULL, NULL);
|
||||
} else {
|
||||
buf_read_page_low(&err, false, BUF_READ_ANY_PAGE
|
||||
| OS_AIO_SIMULATED_WAKE_LATER,
|
||||
space, zip_size, TRUE,
|
||||
tablespace_version, page_nos[i], NULL);
|
||||
tablespace_version, page_nos[i], NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -650,31 +650,8 @@ fil_space_encrypt(
|
|||
|
||||
/* handle post encryption checksum */
|
||||
ib_uint32_t checksum = 0;
|
||||
srv_checksum_algorithm_t algorithm =
|
||||
static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
|
||||
|
||||
if (zip_size == 0) {
|
||||
switch (algorithm) {
|
||||
case SRV_CHECKSUM_ALGORITHM_CRC32:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
|
||||
checksum = buf_calc_page_crc32(dst_frame);
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
|
||||
checksum = (ib_uint32_t) buf_calc_page_new_checksum(
|
||||
dst_frame);
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_NONE:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
||||
checksum = BUF_NO_CHECKSUM_MAGIC;
|
||||
break;
|
||||
/* no default so the compiler will emit a warning
|
||||
* if new enum is added and not handled here */
|
||||
}
|
||||
} else {
|
||||
checksum = page_zip_calc_checksum(dst_frame, zip_size,
|
||||
algorithm);
|
||||
}
|
||||
checksum = fil_crypt_calculate_checksum(zip_size, dst_frame);
|
||||
|
||||
// store the post-encryption checksum after the key-version
|
||||
mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, checksum);
|
||||
|
|
@ -818,6 +795,47 @@ fil_space_decrypt(
|
|||
return src_frame;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Calculate post encryption checksum
|
||||
@return page checksum or BUF_NO_CHECKSUM_MAGIC
|
||||
not needed. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fil_crypt_calculate_checksum(
|
||||
/*=========================*/
|
||||
ulint zip_size, /*!< in: zip_size or 0 */
|
||||
byte* dst_frame) /*!< in: page where to calculate */
|
||||
{
|
||||
ib_uint32_t checksum = 0;
|
||||
srv_checksum_algorithm_t algorithm =
|
||||
static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
|
||||
|
||||
if (zip_size == 0) {
|
||||
switch (algorithm) {
|
||||
case SRV_CHECKSUM_ALGORITHM_CRC32:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
|
||||
checksum = buf_calc_page_crc32(dst_frame);
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
|
||||
checksum = (ib_uint32_t) buf_calc_page_new_checksum(
|
||||
dst_frame);
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_NONE:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
||||
checksum = BUF_NO_CHECKSUM_MAGIC;
|
||||
break;
|
||||
/* no default so the compiler will emit a warning
|
||||
* if new enum is added and not handled here */
|
||||
}
|
||||
} else {
|
||||
checksum = page_zip_calc_checksum(dst_frame, zip_size,
|
||||
algorithm);
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Verify checksum for a page (iff it's encrypted)
|
||||
NOTE: currently this function can only be run in single threaded mode
|
||||
|
|
|
|||
|
|
@ -2006,6 +2006,7 @@ convert_error_code_to_mysql(
|
|||
|
||||
case DB_TABLESPACE_DELETED:
|
||||
case DB_TABLE_NOT_FOUND:
|
||||
case DB_ENCRYPTED_DECRYPT_FAILED:
|
||||
return(HA_ERR_NO_SUCH_TABLE);
|
||||
|
||||
case DB_TABLESPACE_NOT_FOUND:
|
||||
|
|
@ -6043,7 +6044,14 @@ table_opened:
|
|||
|
||||
innobase_copy_frm_flags_from_table_share(ib_table, table->s);
|
||||
|
||||
dict_stats_init(ib_table);
|
||||
ib_table->thd = (void*)thd;
|
||||
|
||||
/* No point to init any statistics if tablespace is still encrypted. */
|
||||
if (!ib_table->is_encrypted) {
|
||||
dict_stats_init(ib_table);
|
||||
} else {
|
||||
ib_table->stat_initialized = 1;
|
||||
}
|
||||
|
||||
MONITOR_INC(MONITOR_TABLE_OPEN);
|
||||
|
||||
|
|
@ -6072,6 +6080,11 @@ table_opened:
|
|||
file, best to play it safe. */
|
||||
|
||||
no_tablespace = true;
|
||||
} else if (ib_table->is_encrypted) {
|
||||
/* This means that tablespace was found but we could not
|
||||
decrypt encrypted page. */
|
||||
no_tablespace = true;
|
||||
ib_table->ibd_file_missing = true;
|
||||
} else {
|
||||
no_tablespace = false;
|
||||
}
|
||||
|
|
@ -6083,9 +6096,9 @@ table_opened:
|
|||
/* If table has no talespace but it has crypt data, check
|
||||
is tablespace made unaccessible because encryption service
|
||||
or used key_id is not available. */
|
||||
if (ib_table && ib_table->crypt_data) {
|
||||
if (ib_table) {
|
||||
fil_space_crypt_t* crypt_data = ib_table->crypt_data;
|
||||
if ((crypt_data->encryption == FIL_SPACE_ENCRYPTION_ON) ||
|
||||
if ((crypt_data && crypt_data->encryption == FIL_SPACE_ENCRYPTION_ON) ||
|
||||
(srv_encrypt_tables &&
|
||||
crypt_data && crypt_data->encryption == FIL_SPACE_ENCRYPTION_DEFAULT)) {
|
||||
|
||||
|
|
@ -6097,6 +6110,13 @@ table_opened:
|
|||
" Can't continue reading table.",
|
||||
ib_table->name, crypt_data->key_id);
|
||||
}
|
||||
} else if (ib_table->is_encrypted) {
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
HA_ERR_NO_SUCH_TABLE,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
ib_table->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -21402,3 +21422,59 @@ static void innodb_remember_check_sysvar_funcs()
|
|||
ut_ad((MYSQL_SYSVAR_NAME(checksum_algorithm).flags & 0x1FF) == PLUGIN_VAR_ENUM);
|
||||
check_sysvar_enum = MYSQL_SYSVAR_NAME(checksum_algorithm).check;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Helper function to push warnings from InnoDB internals to SQL-layer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_push_warning(
|
||||
trx_t* trx, /*!< in: trx */
|
||||
ulint error, /*!< in: error code to push as warning */
|
||||
const char *format,/*!< in: warning message */
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
THD *thd = (THD *)trx->mysql_thd;
|
||||
char *buf;
|
||||
#define MAX_BUF_SIZE 4*1024
|
||||
|
||||
va_start(args, format);
|
||||
buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
|
||||
vsprintf(buf,format, args);
|
||||
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
convert_error_code_to_mysql((dberr_t)error, 0, thd),
|
||||
buf);
|
||||
my_free(buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Helper function to push warnings from InnoDB internals to SQL-layer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_push_warning(
|
||||
void* ithd, /*!< in: thd */
|
||||
ulint error, /*!< in: error code to push as warning */
|
||||
const char *format,/*!< in: warning message */
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
THD *thd = (THD *)ithd;
|
||||
char *buf;
|
||||
#define MAX_BUF_SIZE 4*1024
|
||||
|
||||
if (ithd == NULL) {
|
||||
thd = current_thd;
|
||||
}
|
||||
|
||||
va_start(args, format);
|
||||
buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
|
||||
vsprintf(buf,format, args);
|
||||
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
convert_error_code_to_mysql((dberr_t)error, 0, thd),
|
||||
buf);
|
||||
my_free(buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -57,13 +58,15 @@ btr_block_get_func(
|
|||
buf_block_t* block;
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no, mode,
|
||||
NULL, BUF_GET, file, line, mtr);
|
||||
NULL, BUF_GET, file, line, mtr);
|
||||
|
||||
if (mode != RW_NO_LATCH) {
|
||||
if (block) {
|
||||
if (mode != RW_NO_LATCH) {
|
||||
|
||||
buf_block_dbg_add_level(
|
||||
block, index != NULL && dict_index_is_ibuf(index)
|
||||
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
|
||||
buf_block_dbg_add_level(
|
||||
block, index != NULL && dict_index_is_ibuf(index)
|
||||
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
|
||||
}
|
||||
}
|
||||
|
||||
return(block);
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ Note that if mode is PAGE_CUR_LE, which is used in inserts, then
|
|||
cursor->up_match and cursor->low_match both will have sensible values.
|
||||
If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dberr_t
|
||||
btr_cur_search_to_nth_level(
|
||||
/*========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
|
|
@ -173,7 +173,7 @@ btr_cur_search_to_nth_level(
|
|||
/*****************************************************************//**
|
||||
Opens a cursor at either end of an index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dberr_t
|
||||
btr_cur_open_at_index_side_func(
|
||||
/*============================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ btr_pcur_open_low(
|
|||
Opens an persistent cursor to an index tree without initializing the
|
||||
cursor. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dberr_t
|
||||
btr_pcur_open_with_no_init_func(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
|
|
@ -143,7 +143,7 @@ btr_pcur_open_with_no_init_func(
|
|||
/*****************************************************************//**
|
||||
Opens a persistent cursor at either end of an index. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dberr_t
|
||||
btr_pcur_open_at_index_side(
|
||||
/*========================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ btr_pcur_open_low(
|
|||
Opens an persistent cursor to an index tree without initializing the
|
||||
cursor. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dberr_t
|
||||
btr_pcur_open_with_no_init_func(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
|
|
@ -472,6 +472,7 @@ btr_pcur_open_with_no_init_func(
|
|||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
btr_cur_t* btr_cursor;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
cursor->latch_mode = latch_mode;
|
||||
cursor->search_mode = mode;
|
||||
|
|
@ -480,20 +481,21 @@ btr_pcur_open_with_no_init_func(
|
|||
|
||||
btr_cursor = btr_pcur_get_btr_cur(cursor);
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
|
||||
btr_cursor, has_search_latch,
|
||||
file, line, mtr);
|
||||
err = btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
|
||||
btr_cursor, has_search_latch,
|
||||
file, line, mtr);
|
||||
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
cursor->trx_if_known = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a persistent cursor at either end of an index. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dberr_t
|
||||
btr_pcur_open_at_index_side(
|
||||
/*========================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
|
|
@ -506,6 +508,8 @@ btr_pcur_open_at_index_side(
|
|||
(0=leaf) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
|
||||
pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L;
|
||||
|
|
@ -514,13 +518,15 @@ btr_pcur_open_at_index_side(
|
|||
btr_pcur_init(pcur);
|
||||
}
|
||||
|
||||
btr_cur_open_at_index_side(from_left, index, latch_mode,
|
||||
btr_pcur_get_btr_cur(pcur), level, mtr);
|
||||
err = btr_cur_open_at_index_side(from_left, index, latch_mode,
|
||||
btr_pcur_get_btr_cur(pcur), level, mtr);
|
||||
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
pcur->trx_if_known = NULL;
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
|
||||
Copyright (c) 2013, 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -428,7 +428,8 @@ buf_page_get_gen(
|
|||
BUF_GET_IF_IN_POOL_OR_WATCH */
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr); /*!< in: mini-transaction */
|
||||
mtr_t* mtr, /*!< in: mini-transaction */
|
||||
dberr_t* err = NULL); /*!< out: error code */
|
||||
/********************************************************************//**
|
||||
Initializes a page to the buffer buf_pool. The page is usually not read
|
||||
from a file even if it cannot be found in the buffer buf_pool. This is one
|
||||
|
|
@ -1611,8 +1612,14 @@ struct buf_page_t{
|
|||
operation needed. */
|
||||
|
||||
unsigned key_version; /*!< key version for this block */
|
||||
bool page_encrypted; /*!< page is encrypted */
|
||||
bool page_encrypted; /*!< page is page encrypted */
|
||||
bool page_compressed;/*!< page is page compressed */
|
||||
ulint stored_checksum;/*!< stored page checksum if page
|
||||
encrypted */
|
||||
bool encrypted; /*!< page is still encrypted */
|
||||
ulint calculated_checksum;
|
||||
/*!< calculated checksum if page
|
||||
encrypted */
|
||||
|
||||
ulint real_size; /*!< Real size of the page
|
||||
Normal pages == UNIV_PAGE_SIZE
|
||||
|
|
|
|||
|
|
@ -689,6 +689,10 @@ buf_block_get_frame(
|
|||
/*================*/
|
||||
const buf_block_t* block) /*!< in: pointer to the control block */
|
||||
{
|
||||
if (!block) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(0););
|
||||
|
||||
switch (buf_block_get_state(block)) {
|
||||
|
|
@ -696,6 +700,9 @@ buf_block_get_frame(
|
|||
case BUF_BLOCK_ZIP_PAGE:
|
||||
case BUF_BLOCK_ZIP_DIRTY:
|
||||
case BUF_BLOCK_NOT_USED:
|
||||
if (block->page.encrypted) {
|
||||
goto ok;
|
||||
}
|
||||
ut_error;
|
||||
break;
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -39,10 +40,12 @@ UNIV_INTERN
|
|||
ibool
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset, /*!< in: page number */
|
||||
trx_t* trx);
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset, /*!< in: page number */
|
||||
trx_t* trx, /*!< in: trx */
|
||||
buf_page_t** bpage /*!< out: page */
|
||||
);
|
||||
/********************************************************************//**
|
||||
High-level function which reads a page asynchronously from a file to the
|
||||
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -132,6 +133,11 @@ enum dberr_t {
|
|||
/*< Too many words in a phrase */
|
||||
DB_TOO_BIG_FOR_REDO, /* Record length greater than 10%
|
||||
of redo log */
|
||||
DB_ENCRYPTED_DECRYPT_FAILED, /* Tablespace encrypted and
|
||||
decrypt operaton failed because
|
||||
of missing key management plugin,
|
||||
or missing or incorrect key or
|
||||
incorret AES method or algorithm. */
|
||||
/* The following are partial failure codes */
|
||||
DB_FAIL = 1000,
|
||||
DB_OVERFLOW,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
|
||||
Copyright (c) 2013, 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -1033,6 +1033,7 @@ struct dict_table_t{
|
|||
table_id_t id; /*!< id of the table */
|
||||
mem_heap_t* heap; /*!< memory heap */
|
||||
char* name; /*!< table name */
|
||||
void* thd; /*!< thd */
|
||||
fil_space_crypt_t *crypt_data; /*!< crypt data if present */
|
||||
const char* dir_path_of_temp_table;/*!< NULL or the directory path
|
||||
where a TEMPORARY table that was explicitly
|
||||
|
|
@ -1346,6 +1347,7 @@ struct dict_table_t{
|
|||
locks; /*!< list of locks on the table; protected
|
||||
by lock_sys->mutex */
|
||||
ibool is_corrupt;
|
||||
ibool is_encrypted;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
|
|
|
|||
|
|
@ -381,6 +381,17 @@ fil_crypt_set_encrypt_tables(
|
|||
/*=========================*/
|
||||
uint val); /*!< in: New srv_encrypt_tables setting */
|
||||
|
||||
/******************************************************************
|
||||
Calculate post encryption checksum
|
||||
@return page checksum or BUF_NO_CHECKSUM_MAGIC
|
||||
not needed. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fil_crypt_calculate_checksum(
|
||||
/*=========================*/
|
||||
ulint zip_size, /*!< in: zip_size or 0 */
|
||||
byte* dst_frame); /*!< in: page where to calculate */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fil0crypt.ic"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -636,5 +636,13 @@ ib_push_warning(
|
|||
ulint error, /*!< in: error code to push as warning */
|
||||
const char *format,/*!< in: warning message */
|
||||
...);
|
||||
|
||||
/********************************************************************//**
|
||||
Helper function to push warnings from InnoDB internals to SQL-layer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ib_push_warning(
|
||||
void* ithd, /*!< in: thd */
|
||||
ulint error, /*!< in: error code to push as warning */
|
||||
const char *format,/*!< in: warning message */
|
||||
...);
|
||||
#endif /* HA_INNODB_PROTOTYPES_H */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
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
|
||||
|
|
@ -39,7 +40,10 @@ page_cur_get_page(
|
|||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(page_align(cur->rec));
|
||||
}
|
||||
|
|
@ -54,7 +58,11 @@ page_cur_get_block(
|
|||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(cur->block);
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +88,10 @@ page_cur_get_rec(
|
|||
page_cur_t* cur) /*!< in: page cursor */
|
||||
{
|
||||
ut_ad(cur);
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
|
||||
if (cur->rec) {
|
||||
ut_ad(page_align(cur->rec) == cur->block->frame);
|
||||
}
|
||||
|
||||
return(cur->rec);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2350,7 +2350,7 @@ row_ins_clust_index_entry_low(
|
|||
{
|
||||
btr_cur_t cursor;
|
||||
ulint* offsets = NULL;
|
||||
dberr_t err;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
big_rec_t* big_rec = NULL;
|
||||
mtr_t mtr;
|
||||
mem_heap_t* offsets_heap = NULL;
|
||||
|
|
@ -2380,9 +2380,16 @@ row_ins_clust_index_entry_low(
|
|||
the function will return in both low_match and up_match of the
|
||||
cursor sensible values */
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, mode,
|
||||
err = btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, mode,
|
||||
&cursor, 0, __FILE__, __LINE__, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
index->table->is_encrypted = true;
|
||||
index->table->ibd_file_missing = true;
|
||||
mtr_commit(&mtr);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
{
|
||||
page_t* page = btr_cur_get_page(&cursor);
|
||||
|
|
@ -2696,9 +2703,22 @@ row_ins_sec_index_entry_low(
|
|||
search_mode |= BTR_IGNORE_SEC_UNIQUE;
|
||||
}
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
|
||||
search_mode,
|
||||
&cursor, 0, __FILE__, __LINE__, &mtr);
|
||||
err = btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
|
||||
search_mode,
|
||||
&cursor, 0, __FILE__, __LINE__, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning(trx->mysql_thd,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
index->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
|
||||
/* The insert was buffered during the search: we are done */
|
||||
|
|
|
|||
|
|
@ -622,6 +622,8 @@ handle_new_error:
|
|||
case DB_FTS_INVALID_DOCID:
|
||||
case DB_INTERRUPTED:
|
||||
case DB_DICT_CHANGED:
|
||||
case DB_TABLE_NOT_FOUND:
|
||||
case DB_ENCRYPTED_DECRYPT_FAILED:
|
||||
if (savept) {
|
||||
/* Roll back the latest, possibly incomplete insertion
|
||||
or update */
|
||||
|
|
@ -1314,7 +1316,13 @@ row_insert_for_mysql(
|
|||
prebuilt->table->name);
|
||||
|
||||
return(DB_TABLESPACE_NOT_FOUND);
|
||||
|
||||
} else if (prebuilt->table->is_encrypted) {
|
||||
ib_push_warning(trx, DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s in tablespace %lu encrypted."
|
||||
"However key management plugin or used key_id is not found or"
|
||||
" used encryption algorithm or method does not match.",
|
||||
prebuilt->table->name, prebuilt->table->space);
|
||||
return(DB_ENCRYPTED_DECRYPT_FAILED);
|
||||
} else if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to free a corrupt\n"
|
||||
|
|
@ -1713,6 +1721,13 @@ row_update_for_mysql(
|
|||
"InnoDB: how you can resolve the problem.\n",
|
||||
prebuilt->table->name);
|
||||
return(DB_ERROR);
|
||||
} else if (prebuilt->table->is_encrypted) {
|
||||
ib_push_warning(trx, DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s in tablespace %lu encrypted."
|
||||
"However key management plugin or used key_id is not found or"
|
||||
" used encryption algorithm or method does not match.",
|
||||
prebuilt->table->name, prebuilt->table->space);
|
||||
return (DB_TABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
|
||||
|
|
@ -3932,6 +3947,19 @@ row_drop_table_for_mysql(
|
|||
goto funct_exit;
|
||||
}
|
||||
|
||||
/* If table is encrypted and table page encryption failed
|
||||
mark this table read only. */
|
||||
if (table->is_encrypted) {
|
||||
|
||||
if (table->can_be_evicted) {
|
||||
dict_table_move_from_lru_to_non_lru(table);
|
||||
}
|
||||
|
||||
dict_table_close(table, TRUE, FALSE);
|
||||
err = DB_READ_ONLY;
|
||||
goto funct_exit;
|
||||
}
|
||||
|
||||
/* Turn on this drop bit before we could release the dictionary
|
||||
latch */
|
||||
table->to_be_dropped = true;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
Copyright (c) 2015, MariaDB Corporation.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
Google, Inc. Those modifications are gratefully acknowledged and are described
|
||||
|
|
@ -3726,6 +3727,9 @@ row_search_for_mysql(
|
|||
|
||||
return(DB_TABLESPACE_NOT_FOUND);
|
||||
|
||||
} else if (prebuilt->table->is_encrypted) {
|
||||
|
||||
return(DB_ENCRYPTED_DECRYPT_FAILED);
|
||||
} else if (!prebuilt->index_usable) {
|
||||
|
||||
return(DB_MISSING_HISTORY);
|
||||
|
|
@ -4137,9 +4141,14 @@ wait_table_again:
|
|||
|
||||
} else if (dtuple_get_n_fields(search_tuple) > 0) {
|
||||
|
||||
btr_pcur_open_with_no_init(index, search_tuple, mode,
|
||||
BTR_SEARCH_LEAF,
|
||||
pcur, 0, &mtr);
|
||||
err = btr_pcur_open_with_no_init(index, search_tuple, mode,
|
||||
BTR_SEARCH_LEAF,
|
||||
pcur, 0, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
rec = NULL;
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
|
||||
pcur->trx_if_known = trx;
|
||||
|
||||
|
|
@ -4173,9 +4182,23 @@ wait_table_again:
|
|||
}
|
||||
}
|
||||
} else if (mode == PAGE_CUR_G || mode == PAGE_CUR_L) {
|
||||
btr_pcur_open_at_index_side(
|
||||
err = btr_pcur_open_at_index_side(
|
||||
mode == PAGE_CUR_G, index, BTR_SEARCH_LEAF,
|
||||
pcur, false, 0, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_ENCRYPTED_DECRYPT_FAILED) {
|
||||
ib_push_warning(trx->mysql_thd,
|
||||
DB_ENCRYPTED_DECRYPT_FAILED,
|
||||
"Table %s is encrypted but encryption service or"
|
||||
" used key_id is not available. "
|
||||
" Can't continue reading table.",
|
||||
prebuilt->table->name);
|
||||
index->table->is_encrypted = true;
|
||||
}
|
||||
rec = NULL;
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
}
|
||||
|
||||
rec_loop:
|
||||
|
|
@ -4191,6 +4214,11 @@ rec_loop:
|
|||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (!rec) {
|
||||
err = DB_ENCRYPTED_DECRYPT_FAILED;
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
|
||||
SRV_CORRUPT_TABLE_CHECK(rec,
|
||||
{
|
||||
err = DB_CORRUPTION;
|
||||
|
|
@ -5132,7 +5160,9 @@ lock_wait_or_error:
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
if (rec) {
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
}
|
||||
|
||||
lock_table_wait:
|
||||
mtr_commit(&mtr);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue