1
0
mirror of https://github.com/MariaDB/server.git synced 2025-06-15 00:02:46 +03:00

MDEV-8164: Server crashes in pfs_mutex_enter_func after fil_crypt_is_closing or alike

Analysis: Problem was that tablespaces not encrypted might not have
crypt_data stored on disk.

Fixed by always creating crypt_data to memory cache of the tablespace.

MDEV-8138: strange results from encrypt-and-grep test

Analysis: crypt_data->type is not updated correctly on memory
cache. This caused problem with state tranfer on
encrypted => unencrypted => encrypted.

Fixed by updating memory cache of crypt_data->type correctly based on
current srv_encrypt_tables value to either CRYPT_SCHEME_1 or
CRYPT_SCHEME_UNENCRYPTED.
This commit is contained in:
Jan Lindström
2015-05-17 14:14:16 +03:00
parent 476dfb1603
commit 20c23048c1
17 changed files with 993 additions and 249 deletions

View File

@ -0,0 +1,14 @@
##############################################################################
#
# List the test cases that are to be disabled temporarily.
#
# Separate the test case name and the comment with ':'.
#
# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment>
#
# Do not use any TAB characters for whitespace.
#
##############################################################################
innodb_scrub : MDEV-8139
innodb_scrub_compressed : MDEV-8139

View File

@ -0,0 +1,42 @@
SET GLOBAL innodb_file_per_table = ON;
create table t1 (a varchar(255)) engine=innodb encrypted=yes;
create table t2 (a varchar(255)) engine=innodb;
create table t3 (a varchar(255)) engine=innodb encrypted=no;
insert t1 values (repeat('foobar', 42));
insert t2 values (repeat('temp', 42));
insert t3 values (repeat('dummy', 42));
# Wait max 10 min for key encryption threads to encrypt all spaces
# t1 yes on expecting NOT FOUND
NOT FOUND /foobar/ in t1.ibd
# t2 ... on expecting NOT FOUND
NOT FOUND /temp/ in t2.ibd
# t3 no on expecting FOUND
FOUND /dummy/ in t3.ibd
# ibdata1 expecting NOT FOUND
NOT FOUND /foobar/ in ibdata1
# Now turn off encryption and wait for threads to decrypt everything
SET GLOBAL innodb_encryption_threads = 4;
SET GLOBAL innodb_encrypt_tables = off;
# Wait max 10 min for key encryption threads to decrypt all spaces
# t1 yes on expecting NOT FOUND
NOT FOUND /foobar/ in t1.ibd
# t2 ... on expecting FOUND
FOUND /temp/ in t2.ibd
# t3 no on expecting FOUND
FOUND /dummy/ in t3.ibd
# ibdata1 expecting NOT FOUND
NOT FOUND /foobar/ in ibdata1
# Now turn on encryption and wait for threads to encrypt all spaces
SET GLOBAL innodb_encryption_threads = 4;
SET GLOBAL innodb_encrypt_tables = on;
# Wait max 10 min for key encryption threads to encrypt all spaces
# t1 yes on expecting NOT FOUND
NOT FOUND /foobar/ in t1.ibd
# t2 ... on expecting NOT FOUND
NOT FOUND /temp/ in t2.ibd
# t3 no on expecting FOUND
FOUND /dummy/ in t3.ibd
# ibdata1 expecting NOT FOUND
NOT FOUND /foobar/ in ibdata1
# TODO: add shutdown + grep tests
drop table t1, t2, t3;

View File

@ -0,0 +1,325 @@
SET default_storage_engine = InnoDB;
CREATE TABLE t1 (pk INT PRIMARY KEY, c VARCHAR(256));
CREATE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
drop table t1,t2;
SET GLOBAL innodb_encryption_threads = 0;

View File

@ -0,0 +1,8 @@
--innodb-encrypt-tables=ON
--innodb-encrypt-log=ON
--innodb-encryption-rotate-key-age=15
--innodb-encryption-threads=4
--innodb-tablespaces-encryption
--innodb-max-dirty-pages-pct=0.001

View File

@ -0,0 +1,104 @@
-- source include/have_innodb.inc
-- source include/have_example_key_management_plugin.inc
# embedded does not support restart
-- source include/not_embedded.inc
#
# MDEV-8138: strange results from encrypt-and-grep test
#
--let $MYSQLD_DATADIR=`select @@datadir`
--let ib1_IBD = $MYSQLD_DATADIR/ibdata1
--let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd
--let t2_IBD = $MYSQLD_DATADIR/test/t2.ibd
--let t3_IBD = $MYSQLD_DATADIR/test/t3.ibd
--let SEARCH_RANGE = 10000000
--let SEARCH_PATTERN=foobar
SET GLOBAL innodb_file_per_table = ON;
create table t1 (a varchar(255)) engine=innodb encrypted=yes;
create table t2 (a varchar(255)) engine=innodb;
create table t3 (a varchar(255)) engine=innodb encrypted=no;
insert t1 values (repeat('foobar', 42));
insert t2 values (repeat('temp', 42));
insert t3 values (repeat('dummy', 42));
--echo # Wait max 10 min for key encryption threads to encrypt all spaces
--let $wait_timeout= 600
--let $wait_condition=SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0
--source include/wait_condition.inc
--let SEARCH_PATTERN=foobar
--echo # t1 yes on expecting NOT FOUND
-- let SEARCH_FILE=$t1_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=temp
--echo # t2 ... on expecting NOT FOUND
-- let SEARCH_FILE=$t2_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=dummy
--echo # t3 no on expecting FOUND
-- let SEARCH_FILE=$t3_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=foobar
--echo # ibdata1 expecting NOT FOUND
-- let SEARCH_FILE=$ib1_IBD
-- source include/search_pattern_in_file.inc
--echo # Now turn off encryption and wait for threads to decrypt everything
SET GLOBAL innodb_encryption_threads = 4;
SET GLOBAL innodb_encrypt_tables = off;
--echo # Wait max 10 min for key encryption threads to decrypt all spaces
--let $wait_timeout= 600
--let $wait_condition=SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
--source include/wait_condition.inc
--let SEARCH_PATTERN=foobar
--echo # t1 yes on expecting NOT FOUND
-- let SEARCH_FILE=$t1_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=temp
--echo # t2 ... on expecting FOUND
-- let SEARCH_FILE=$t2_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=dummy
--echo # t3 no on expecting FOUND
-- let SEARCH_FILE=$t3_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=foobar
--echo # ibdata1 expecting NOT FOUND
-- let SEARCH_FILE=$ib1_IBD
-- source include/search_pattern_in_file.inc
--echo # Now turn on encryption and wait for threads to encrypt all spaces
SET GLOBAL innodb_encryption_threads = 4;
SET GLOBAL innodb_encrypt_tables = on;
--echo # Wait max 10 min for key encryption threads to encrypt all spaces
--let $wait_timeout= 600
--let $wait_condition=SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
--source include/wait_condition.inc
--let SEARCH_PATTERN=foobar
--echo # t1 yes on expecting NOT FOUND
-- let SEARCH_FILE=$t1_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=temp
--echo # t2 ... on expecting NOT FOUND
-- let SEARCH_FILE=$t2_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=dummy
--echo # t3 no on expecting FOUND
-- let SEARCH_FILE=$t3_IBD
-- source include/search_pattern_in_file.inc
--let SEARCH_PATTERN=foobar
--echo # ibdata1 expecting NOT FOUND
-- let SEARCH_FILE=$ib1_IBD
-- source include/search_pattern_in_file.inc
--echo # TODO: add shutdown + grep tests
drop table t1, t2, t3;

View File

@ -0,0 +1,3 @@
--plugin-load-add=$FILE_KEY_MANAGEMENT_SO
--file-key-management-filekey=FILE:$MTR_SUITE_DIR/t/filekeys-data.key
--file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data.enc

View File

@ -0,0 +1,25 @@
--source include/have_innodb.inc
#
# MDEV-8164: Server crashes in pfs_mutex_enter_func after fil_crypt_is_closing or alike
#
SET default_storage_engine = InnoDB;
CREATE TABLE t1 (pk INT PRIMARY KEY, c VARCHAR(256));
CREATE TABLE t2 AS SELECT * FROM t1;
let $i = 40;
while ($i)
{
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encryption_threads = 1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
SET GLOBAL innodb_encryption_rotation_iops = 100;
SET GLOBAL innodb_encrypt_tables = OFF;
CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM t2;
dec $i;
}
drop table t1,t2;
SET GLOBAL innodb_encryption_threads = 0;

View File

@ -4225,6 +4225,7 @@ buf_page_io_complete(
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
const ibool uncompressed = (buf_page_get_state(bpage)
== BUF_BLOCK_FILE_PAGE);
fil_space_t* space = NULL;
ut_a(buf_page_in_file(bpage));
@ -4323,12 +4324,18 @@ buf_page_io_complete(
goto page_not_corrupt;
;);
corrupt:
fil_system_enter();
space = fil_space_get_by_id(bpage->space);
fil_system_exit();
fprintf(stderr,
"InnoDB: Database page corruption on disk"
" or a failed\n"
"InnoDB: file read of page %lu.\n"
"InnoDB: space %lu file %s read of page %lu.\n"
"InnoDB: You may have to recover"
" from a backup.\n",
bpage->space,
space ? space->name : "NULL",
(ulong) bpage->offset);
buf_page_print(frame, buf_page_get_zip_size(bpage),
BUF_PAGE_PRINT_NO_CRASH);

View File

@ -43,6 +43,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
/** Mutex for keys */
UNIV_INTERN ib_mutex_t fil_crypt_key_mutex;
static bool fil_crypt_threads_inited = false;
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t fil_crypt_key_mutex_key;
#endif
@ -107,6 +109,8 @@ UNIV_INTERN mysql_pfs_key_t fil_crypt_data_mutex_key;
static bool
fil_crypt_needs_rotation(
/*=====================*/
fil_encryption_t encrypt_mode, /*!< in: Encryption
mode */
uint key_version, /*!< in: Key version */
uint latest_key_version, /*!< in: Latest key version */
uint rotate_key_age); /*!< in: When to rotate */
@ -154,13 +158,14 @@ Get the latest(key-version), waking the encrypt thread, if needed */
static inline
uint
fil_crypt_get_latest_key_version(
/*=====================*/
/*=============================*/
fil_space_crypt_t* crypt_data) /*!< in: crypt data */
{
uint rc = encryption_key_get_latest_version(crypt_data->key_id);
if (fil_crypt_needs_rotation(crypt_data->min_key_version,
rc, srv_fil_crypt_rotate_key_age)) {
if (fil_crypt_needs_rotation(crypt_data->encryption,
crypt_data->min_key_version,
rc, srv_fil_crypt_rotate_key_age)) {
os_event_set(fil_crypt_threads_event);
}
@ -169,7 +174,12 @@ fil_crypt_get_latest_key_version(
/******************************************************************
Mutex helper for crypt_data->scheme */
static void crypt_data_scheme_locker(st_encryption_scheme *scheme, int exit)
static
void
crypt_data_scheme_locker(
/*=====================*/
st_encryption_scheme* scheme,
int exit)
{
fil_space_crypt_t* crypt_data =
static_cast<fil_space_crypt_t*>(scheme);
@ -220,7 +230,7 @@ Merge fil_space_crypt_t object */
UNIV_INTERN
void
fil_space_merge_crypt_data(
/*====================*/
/*=======================*/
fil_space_crypt_t* dst,/*!< out: Crypt data */
const fil_space_crypt_t* src)/*!< in: Crypt data */
{
@ -236,6 +246,7 @@ fil_space_merge_crypt_data(
/* no support for changing iv (yet?) */
ut_a(memcmp(src->iv, dst->iv, sizeof(src->iv)) == 0);
dst->encryption = src->encryption;
dst->type = src->type;
dst->min_key_version = src->min_key_version;
dst->keyserver_requests += src->keyserver_requests;
@ -255,8 +266,13 @@ fil_space_read_crypt_data(
ulint offset) /*!< in: offset */
{
if (memcmp(page + offset, EMPTY_PATTERN, MAGIC_SZ) == 0) {
/* crypt is not stored */
return NULL;
/* crypt is not stored but create memory cache for
not system tablespace */
if (space != 0) {
return fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
} else {
return NULL;
}
}
if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) {
@ -272,7 +288,12 @@ fil_space_read_crypt_data(
page[offset + 3],
page[offset + 4],
page[offset + 5]);
return NULL;
/* Create memory cache for not system tablespace */
if (space != 0) {
return fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
} else {
return NULL;
}
}
ulint type = mach_read_from_1(page + offset + MAGIC_SZ + 0);
@ -542,11 +563,12 @@ Check if page shall be encrypted before write
UNIV_INTERN
bool
fil_space_check_encryption_write(
/*==============================*/
ulint space) /*!< in: tablespace id */
/*=============================*/
ulint space) /*!< in: tablespace id */
{
if (!srv_encrypt_tables)
if (!srv_encrypt_tables) {
return false;
}
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
@ -599,6 +621,8 @@ fil_space_encrypt(
return;
}
ut_ad(crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF);
key_version = fil_crypt_get_latest_key_version(crypt_data);
if (key_version == ENCRYPTION_KEY_VERSION_INVALID) {
@ -742,6 +766,8 @@ fil_space_decrypt(
return false; /* page not decrypted */
}
ut_ad(crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF);
/* read space & offset & lsn */
ulint space = mach_read_from_4(
src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
@ -937,12 +963,15 @@ Check if a key needs rotation given a key_state
static bool
fil_crypt_needs_rotation(
/*=====================*/
fil_encryption_t encrypt_mode, /*!< in: Encryption
mode */
uint key_version, /*!< in: Key version */
uint latest_key_version, /*!< in: Latest key version */
uint rotate_key_age) /*!< in: When to rotate */
{
if (key_version == ENCRYPTION_KEY_VERSION_INVALID)
if (key_version == ENCRYPTION_KEY_VERSION_INVALID) {
return false;
}
if (key_version == 0 && latest_key_version != 0) {
/* this is rotation unencrypted => encrypted
@ -951,8 +980,11 @@ fil_crypt_needs_rotation(
}
if (latest_key_version == 0 && key_version != 0) {
/* this is rotation encrypted => unencrypted */
return true;
if (encrypt_mode == FIL_SPACE_ENCRYPTION_DEFAULT) {
/* this is rotation encrypted => unencrypted */
return true;
}
return false;
}
/* this is rotation encrypted => encrypted,
@ -973,11 +1005,15 @@ fil_crypt_is_closing(
/*=================*/
ulint space) /*!< in: FIL space id */
{
bool closing;
bool closing=true;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex);
closing = crypt_data->closing;
mutex_exit(&crypt_data->mutex);
if (crypt_data) {
mutex_enter(&crypt_data->mutex);
closing = crypt_data->closing;
mutex_exit(&crypt_data->mutex);
}
return closing;
}
@ -1189,6 +1225,7 @@ Check if space needs rotation given a key_state
static
bool
fil_crypt_space_needs_rotation(
/*===========================*/
rotate_thread_t* state, /*!< in: Key rotation state */
key_state_t* key_state, /*!< in: Key state */
bool* recheck) /*!< out: needs recheck ? */
@ -1228,11 +1265,6 @@ fil_crypt_space_needs_rotation(
mutex_enter(&crypt_data->mutex);
do {
if (crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) {
/* This space is unencrypted by user request */
break;
}
/* prevent threads from starting to rotate space */
if (crypt_data->rotate_state.starting) {
/* recheck this space later */
@ -1255,6 +1287,7 @@ fil_crypt_space_needs_rotation(
}
bool need_key_rotation = fil_crypt_needs_rotation(
crypt_data->encryption,
crypt_data->min_key_version,
key_state->key_version, key_state->rotate_key_age);
@ -1351,7 +1384,7 @@ used when inside a space */
static
void
fil_crypt_realloc_iops(
/*========================*/
/*===================*/
rotate_thread_t *state) /*!< in: Key rotation status */
{
ut_a(state->allocated_iops > 0);
@ -1444,7 +1477,7 @@ Return allocated iops to global */
static
void
fil_crypt_return_iops(
/*========================*/
/*==================*/
rotate_thread_t *state) /*!< in: Key rotation status */
{
if (state->allocated_iops > 0) {
@ -1526,11 +1559,17 @@ fil_crypt_start_rotate_space(
ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex);
ut_ad(key_state->key_id == crypt_data->key_id);
if (crypt_data->rotate_state.active_threads == 0) {
/* only first thread needs to init */
if (crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) {
crypt_data->type = CRYPT_SCHEME_UNENCRYPTED;
} else {
crypt_data->type = CRYPT_SCHEME_1;
}
crypt_data->rotate_state.next_offset = 1; // skip page 0
/* no need to rotate beyond current max
* if space extends, it will be encrypted with newer version */
@ -1568,28 +1607,33 @@ fil_crypt_find_page_to_rotate(
ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex);
ut_ad(key_state->key_id == crypt_data->key_id);
/* Space might already be dropped */
if (crypt_data) {
mutex_enter(&crypt_data->mutex);
ut_ad(key_state->key_id == crypt_data->key_id);
if (crypt_data->closing == false &&
crypt_data->rotate_state.next_offset <
crypt_data->rotate_state.max_offset) {
if (crypt_data->closing == false &&
crypt_data->rotate_state.next_offset <
crypt_data->rotate_state.max_offset) {
state->offset = crypt_data->rotate_state.next_offset;
ulint remaining = crypt_data->rotate_state.max_offset -
crypt_data->rotate_state.next_offset;
state->offset = crypt_data->rotate_state.next_offset;
ulint remaining = crypt_data->rotate_state.max_offset -
crypt_data->rotate_state.next_offset;
if (batch <= remaining)
state->batch = batch;
else
state->batch = remaining;
if (batch <= remaining) {
state->batch = batch;
} else {
state->batch = remaining;
}
crypt_data->rotate_state.next_offset += batch;
mutex_exit(&crypt_data->mutex);
return true;
}
crypt_data->rotate_state.next_offset += batch;
mutex_exit(&crypt_data->mutex);
return true;
}
mutex_exit(&crypt_data->mutex);
return false;
}
@ -1636,6 +1680,7 @@ Get a page and compute sleep time
static
buf_block_t*
fil_crypt_get_page_throttle_func(
/*=============================*/
rotate_thread_t* state, /*!< in/out: Key rotation state */
ulint space, /*!< in: FIL space id */
uint zip_size, /*!< in: compressed size if
@ -1752,7 +1797,7 @@ Rotate one page */
static
void
fil_crypt_rotate_page(
/*===================*/
/*==================*/
const key_state_t* key_state, /*!< in: Key state */
rotate_thread_t* state) /*!< in: Key rotation state */
{
@ -1791,8 +1836,10 @@ fil_crypt_rotate_page(
if (kv == 0 &&
fil_crypt_is_page_uninitialized(frame, zip_size)) {
;
} else if (fil_crypt_needs_rotation(kv, key_state->key_version,
key_state->rotate_key_age)) {
} else if (fil_crypt_needs_rotation(
crypt_data->encryption,
kv, key_state->key_version,
key_state->rotate_key_age)) {
/* page can be "fresh" i.e never written in case
* kv == 0 or it should have a key version at least
@ -1812,11 +1859,13 @@ fil_crypt_rotate_page(
/* statistics */
state->crypt_stat.pages_modified++;
} else {
ut_a(kv >= crypt_data->min_key_version ||
(kv == 0 && key_state->key_version == 0));
if (crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF) {
ut_a(kv >= crypt_data->min_key_version ||
(kv == 0 && key_state->key_version == 0));
if (kv < state->min_key_version_found) {
state->min_key_version_found = kv;
if (kv < state->min_key_version_found) {
state->min_key_version_found = kv;
}
}
}
@ -1878,6 +1927,7 @@ fil_crypt_rotate_page(
/* if we just detected that scrubbing was turned off
* update global state to reflect this */
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing.is_active = false;
mutex_exit(&crypt_data->mutex);
@ -2006,68 +2056,73 @@ fil_crypt_complete_rotate_space(
{
ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex);
/**
* Update crypt data state with state from thread
*/
if (state->min_key_version_found <
crypt_data->rotate_state.min_key_version_found) {
crypt_data->rotate_state.min_key_version_found =
state->min_key_version_found;
}
/* Space might already be dropped */
if (crypt_data) {
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex);
if (state->end_lsn > crypt_data->rotate_state.end_lsn) {
crypt_data->rotate_state.end_lsn = state->end_lsn;
}
/**
* Update crypt data state with state from thread
*/
if (state->min_key_version_found <
crypt_data->rotate_state.min_key_version_found) {
crypt_data->rotate_state.min_key_version_found =
state->min_key_version_found;
}
ut_a(crypt_data->rotate_state.active_threads > 0);
crypt_data->rotate_state.active_threads--;
bool last = crypt_data->rotate_state.active_threads == 0;
if (state->end_lsn > crypt_data->rotate_state.end_lsn) {
crypt_data->rotate_state.end_lsn = state->end_lsn;
}
/**
* check if space is fully done
* this as when threads shutdown, it could be that we "complete"
* iterating before we have scanned the full space.
*/
bool done = crypt_data->rotate_state.next_offset >=
crypt_data->rotate_state.max_offset;
ut_a(crypt_data->rotate_state.active_threads > 0);
crypt_data->rotate_state.active_threads--;
bool last = crypt_data->rotate_state.active_threads == 0;
/**
* we should flush space if we're last thread AND
* the iteration is done
*/
bool should_flush = last && done;
/**
* check if space is fully done
* this as when threads shutdown, it could be that we "complete"
* iterating before we have scanned the full space.
*/
bool done = crypt_data->rotate_state.next_offset >=
crypt_data->rotate_state.max_offset;
if (should_flush) {
/* we're the last active thread */
crypt_data->rotate_state.flushing = true;
crypt_data->min_key_version =
crypt_data->rotate_state.min_key_version_found;
}
/**
* we should flush space if we're last thread AND
* the iteration is done
*/
bool should_flush = last && done;
/* inform scrubbing */
crypt_data->rotate_state.scrubbing.is_active = false;
mutex_exit(&crypt_data->mutex);
/* all threads must call btr_scrub_complete_space wo/ mutex held */
if (btr_scrub_complete_space(&state->scrub_data) == true) {
if (should_flush) {
/* only last thread updates last_scrub_completed */
/* we're the last active thread */
crypt_data->rotate_state.flushing = true;
crypt_data->min_key_version =
crypt_data->rotate_state.min_key_version_found;
}
/* inform scrubbing */
crypt_data->rotate_state.scrubbing.is_active = false;
mutex_exit(&crypt_data->mutex);
/* all threads must call btr_scrub_complete_space wo/ mutex held */
if (btr_scrub_complete_space(&state->scrub_data) == true) {
if (should_flush) {
/* only last thread updates last_scrub_completed */
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing.
last_scrub_completed = time(0);
mutex_exit(&crypt_data->mutex);
}
}
if (should_flush) {
fil_crypt_flush_space(state, space);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing.
last_scrub_completed = time(0);
crypt_data->rotate_state.flushing = false;
mutex_exit(&crypt_data->mutex);
}
}
if (should_flush) {
fil_crypt_flush_space(state, space);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.flushing = false;
mutex_exit(&crypt_data->mutex);
}
}
/*********************************************************************//**
@ -2194,8 +2249,8 @@ fil_crypt_set_thread_cnt(
os_thread_id_t rotation_thread_id;
os_thread_create(fil_crypt_thread, NULL, &rotation_thread_id);
ib_logf(IB_LOG_LEVEL_INFO,
"Creating #%d thread id %lu total threads %du\n",
i, os_thread_pf(rotation_thread_id), new_cnt);
"Creating #%d thread id %lu total threads %u\n",
i+1, os_thread_pf(rotation_thread_id), new_cnt);
}
} else if (new_cnt < srv_n_fil_crypt_threads) {
srv_n_fil_crypt_threads = new_cnt;
@ -2232,6 +2287,18 @@ fil_crypt_set_rotation_iops(
os_event_set(fil_crypt_threads_event);
}
/*********************************************************************
Adjust encrypt tables */
UNIV_INTERN
void
fil_crypt_set_encrypt_tables(
/*=========================*/
uint val) /*!< in: New srv_encrypt_tables setting */
{
srv_encrypt_tables = val;
os_event_set(fil_crypt_threads_event);
}
/*********************************************************************
Init threads for key rotation */
UNIV_INTERN
@ -2243,6 +2310,7 @@ fil_crypt_threads_init()
fil_crypt_threads_event = os_event_create();
mutex_create(fil_crypt_threads_mutex_key,
&fil_crypt_threads_mutex, SYNC_NO_ORDER_CHECK);
fil_crypt_threads_inited = true;
uint cnt = srv_n_fil_crypt_threads;
srv_n_fil_crypt_threads = 0;
@ -2279,7 +2347,7 @@ fil_space_crypt_mark_space_closing(
/*===============================*/
ulint space) /*!< in: Space id */
{
if (!srv_encrypt_tables) {
if (!fil_crypt_threads_inited) {
return;
}

View File

@ -6857,7 +6857,7 @@ Get crypt data for a tablespace */
UNIV_INTERN
void
fil_space_set_crypt_data(
/*==================*/
/*=====================*/
ulint id, /*!< in: space id */
fil_space_crypt_t* crypt_data) /*!< in: crypt data */
{
@ -6872,19 +6872,26 @@ fil_space_set_crypt_data(
if (space != NULL) {
if (space->crypt_data != NULL) {
/* Here we need to release fil_system mutex to
avoid mutex deadlock assertion. Here we would
taje mutexes in order fil_system, crypt_data and
in fil_crypt_start_encrypting_space we would
take them in order crypt_data, fil_system
at fil_space_get_flags -> fil_space_get_space */
mutex_exit(&fil_system->mutex);
fil_space_merge_crypt_data(space->crypt_data,
crypt_data);
free_crypt_data = crypt_data;
} else {
space->crypt_data = crypt_data;
mutex_exit(&fil_system->mutex);
}
} else {
/* there is a small risk that tablespace has been deleted */
free_crypt_data = crypt_data;
mutex_exit(&fil_system->mutex);
}
mutex_exit(&fil_system->mutex);
if (free_crypt_data != NULL) {
/* there was already crypt data present and the new crypt
* data provided as argument to this function has been merged

View File

@ -17821,6 +17821,7 @@ which control InnoDB "status monitor" output to the error log.
static
void
innodb_status_output_update(
/*========================*/
THD* thd __attribute__((unused)),
struct st_mysql_sys_var* var __attribute__((unused)),
void* var_ptr __attribute__((unused)),
@ -17836,7 +17837,7 @@ Update the system variable innodb_encryption_threads */
static
void
innodb_encryption_threads_update(
/*=========================*/
/*=============================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
@ -17853,7 +17854,7 @@ Update the system variable innodb_encryption_rotate_key_age */
static
void
innodb_encryption_rotate_key_age_update(
/*=========================*/
/*====================================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
@ -17870,7 +17871,7 @@ Update the system variable innodb_encryption_rotation_iops */
static
void
innodb_encryption_rotation_iops_update(
/*=========================*/
/*===================================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
@ -17882,6 +17883,23 @@ innodb_encryption_rotation_iops_update(
fil_crypt_set_rotation_iops(*static_cast<const uint*>(save));
}
/******************************************************************
Update the system variable innodb_encrypt_tables*/
static
void
innodb_encrypt_tables_update(
/*=========================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
void* var_ptr,/*!< out: where the
formal string goes */
const void* save) /*!< in: immediate result
from check function */
{
fil_crypt_set_encrypt_tables(*static_cast<const uint*>(save));
}
static SHOW_VAR innodb_status_variables_export[]= {
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
{NullS, NullS, SHOW_LONG}
@ -19183,7 +19201,9 @@ static MYSQL_SYSVAR_ENUM(encrypt_tables, srv_encrypt_tables,
PLUGIN_VAR_OPCMDARG,
"Enable encryption for tables. "
"Don't forget to enable --innodb-encrypt-log too",
innodb_encrypt_tables_validate, NULL, 0,
NULL,
innodb_encrypt_tables_update,
0,
&srv_encrypt_tables_typelib);
static MYSQL_SYSVAR_UINT(encryption_threads, srv_n_fil_crypt_threads,

View File

@ -128,7 +128,7 @@ Get crypt data for a space*/
UNIV_INTERN
fil_space_crypt_t *
fil_space_get_crypt_data(
/*======================*/
/*=====================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
@ -136,15 +136,16 @@ Set crypt data for a space*/
UNIV_INTERN
void
fil_space_set_crypt_data(
/*======================*/
/*=====================*/
ulint space, /*!< in: tablespace id */
fil_space_crypt_t* crypt_data); /*!< in: crypt data to set */
/*********************************************************************
Merge crypt data */
UNIV_INTERN
void
fil_space_merge_crypt_data(
/*======================*/
/*=======================*/
fil_space_crypt_t* dst_crypt_data, /*!< in: crypt_data */
const fil_space_crypt_t* src_crypt_data); /*!< in: crypt data */
@ -175,7 +176,7 @@ Clear crypt data from page 0 (used for import tablespace) */
UNIV_INTERN
void
fil_space_clear_crypt_data(
/*======================*/
/*=======================*/
byte* page, /*!< in: buffer page */
ulint offset); /*!< in: offset where crypt data is stored */
@ -194,7 +195,7 @@ Check if extra buffer shall be allocated for decrypting after read */
UNIV_INTERN
bool
fil_space_check_encryption_read(
/*==============================*/
/*============================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
@ -202,7 +203,7 @@ Check if page shall be encrypted before write */
UNIV_INTERN
bool
fil_space_check_encryption_write(
/*==============================*/
/*=============================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
@ -210,7 +211,7 @@ Encrypt buffer page */
UNIV_INTERN
void
fil_space_encrypt(
/*===============*/
/*==============*/
ulint space, /*!< in: tablespace id */
ulint offset, /*!< in: page no */
lsn_t lsn, /*!< in: page lsn */
@ -223,7 +224,7 @@ Decrypt buffer page */
UNIV_INTERN
void
fil_space_decrypt(
/*===============*/
/*==============*/
ulint space, /*!< in: tablespace id */
const byte* src_frame,/*!< in: page frame */
ulint page_size, /*!< in: size of data to encrypt */
@ -236,7 +237,7 @@ Decrypt buffer page
UNIV_INTERN
bool
fil_space_decrypt(
/*===============*/
/*==============*/
fil_space_crypt_t* crypt_data, /*!< in: crypt data */
const byte* src_frame,/*!< in: page frame */
ulint page_size, /*!< in: page size */
@ -250,7 +251,7 @@ as it modifies srv_checksum_algorithm (temporarily)
UNIV_INTERN
bool
fil_space_verify_crypt_checksum(
/*===============*/
/*============================*/
const byte* src_frame,/*!< in: page frame */
ulint zip_size); /*!< in: size of data to encrypt */
@ -285,7 +286,7 @@ Set rotate key age */
UNIV_INTERN
void
fil_crypt_set_rotate_key_age(
/*=====================*/
/*=========================*/
uint rotate_age); /*!< in: requested rotate age */
/*********************************************************************
@ -293,7 +294,7 @@ Set rotation threads iops */
UNIV_INTERN
void
fil_crypt_set_rotation_iops(
/*=====================*/
/*========================*/
uint iops); /*!< in: requested iops */
/*********************************************************************
@ -301,7 +302,7 @@ Mark a space as closing */
UNIV_INTERN
void
fil_space_crypt_mark_space_closing(
/*===============*/
/*===============================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
@ -309,7 +310,7 @@ Wait for crypt threads to stop accessing space */
UNIV_INTERN
void
fil_space_crypt_close_tablespace(
/*===============*/
/*=============================*/
ulint space); /*!< in: tablespace id */
/** Struct for retreiving info about encryption */
@ -331,7 +332,7 @@ Get crypt status for a space
UNIV_INTERN
int
fil_space_crypt_get_status(
/*==================*/
/*=======================*/
ulint id, /*!< in: space id */
struct fil_space_crypt_status_t * status); /*!< out: status */
@ -370,10 +371,19 @@ Get scrub status for a space
UNIV_INTERN
int
fil_space_get_scrub_status(
/*==================*/
/*=======================*/
ulint id, /*!< in: space id */
struct fil_space_scrub_status_t * status); /*!< out: status */
/*********************************************************************
Adjust encrypt tables */
UNIV_INTERN
void
fil_crypt_set_encrypt_tables(
/*=========================*/
uint val); /*!< in: New srv_encrypt_tables setting */
#ifndef UNIV_NONINL
#include "fil0crypt.ic"
#endif

View File

@ -4302,6 +4302,7 @@ buf_page_io_complete(
const ibool uncompressed = (buf_page_get_state(bpage)
== BUF_BLOCK_FILE_PAGE);
bool have_LRU_mutex = false;
fil_space_t* space = NULL;
ut_a(buf_page_in_file(bpage));
@ -4403,13 +4404,20 @@ buf_page_io_complete(
goto page_not_corrupt;
;);
corrupt:
fil_system_enter();
space = fil_space_get_by_id(bpage->space);
fil_system_exit();
fprintf(stderr,
"InnoDB: Database page corruption on disk"
" or a failed\n"
"InnoDB: file read of page %lu.\n"
"InnoDB: space %lu file %s read of page %lu.\n"
"InnoDB: You may have to recover"
" from a backup.\n",
bpage->space,
space ? space->name : "NULL",
(ulong) bpage->offset);
buf_page_print(frame, buf_page_get_zip_size(bpage),
BUF_PAGE_PRINT_NO_CRASH);
fprintf(stderr,

View File

@ -43,6 +43,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
/** Mutex for keys */
UNIV_INTERN ib_mutex_t fil_crypt_key_mutex;
static bool fil_crypt_threads_inited = false;
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t fil_crypt_key_mutex_key;
#endif
@ -107,6 +109,8 @@ UNIV_INTERN mysql_pfs_key_t fil_crypt_data_mutex_key;
static bool
fil_crypt_needs_rotation(
/*=====================*/
fil_encryption_t encrypt_mode, /*!< in: Encryption
mode */
uint key_version, /*!< in: Key version */
uint latest_key_version, /*!< in: Latest key version */
uint rotate_key_age); /*!< in: When to rotate */
@ -154,13 +158,14 @@ Get the latest(key-version), waking the encrypt thread, if needed */
static inline
uint
fil_crypt_get_latest_key_version(
/*=====================*/
/*=============================*/
fil_space_crypt_t* crypt_data) /*!< in: crypt data */
{
uint rc = encryption_key_get_latest_version(crypt_data->key_id);
if (fil_crypt_needs_rotation(crypt_data->min_key_version,
rc, srv_fil_crypt_rotate_key_age)) {
if (fil_crypt_needs_rotation(crypt_data->encryption,
crypt_data->min_key_version,
rc, srv_fil_crypt_rotate_key_age)) {
os_event_set(fil_crypt_threads_event);
}
@ -169,7 +174,12 @@ fil_crypt_get_latest_key_version(
/******************************************************************
Mutex helper for crypt_data->scheme */
static void crypt_data_scheme_locker(st_encryption_scheme *scheme, int exit)
static
void
crypt_data_scheme_locker(
/*=====================*/
st_encryption_scheme* scheme,
int exit)
{
fil_space_crypt_t* crypt_data =
static_cast<fil_space_crypt_t*>(scheme);
@ -220,7 +230,7 @@ Merge fil_space_crypt_t object */
UNIV_INTERN
void
fil_space_merge_crypt_data(
/*====================*/
/*=======================*/
fil_space_crypt_t* dst,/*!< out: Crypt data */
const fil_space_crypt_t* src)/*!< in: Crypt data */
{
@ -236,6 +246,7 @@ fil_space_merge_crypt_data(
/* no support for changing iv (yet?) */
ut_a(memcmp(src->iv, dst->iv, sizeof(src->iv)) == 0);
dst->encryption = src->encryption;
dst->type = src->type;
dst->min_key_version = src->min_key_version;
dst->keyserver_requests += src->keyserver_requests;
@ -255,8 +266,13 @@ fil_space_read_crypt_data(
ulint offset) /*!< in: offset */
{
if (memcmp(page + offset, EMPTY_PATTERN, MAGIC_SZ) == 0) {
/* crypt is not stored */
return NULL;
/* crypt is not stored but create memory cache for
not system tablespace */
if (space != 0) {
return fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
} else {
return NULL;
}
}
if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) {
@ -272,7 +288,12 @@ fil_space_read_crypt_data(
page[offset + 3],
page[offset + 4],
page[offset + 5]);
return NULL;
/* Create memory cache for not system tablespace */
if (space != 0) {
return fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
} else {
return NULL;
}
}
ulint type = mach_read_from_1(page + offset + MAGIC_SZ + 0);
@ -542,11 +563,12 @@ Check if page shall be encrypted before write
UNIV_INTERN
bool
fil_space_check_encryption_write(
/*==============================*/
ulint space) /*!< in: tablespace id */
/*=============================*/
ulint space) /*!< in: tablespace id */
{
if (!srv_encrypt_tables)
if (!srv_encrypt_tables) {
return false;
}
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
@ -599,6 +621,8 @@ fil_space_encrypt(
return;
}
ut_ad(crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF);
key_version = fil_crypt_get_latest_key_version(crypt_data);
if (key_version == ENCRYPTION_KEY_VERSION_INVALID) {
@ -742,6 +766,8 @@ fil_space_decrypt(
return false; /* page not decrypted */
}
ut_ad(crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF);
/* read space & offset & lsn */
ulint space = mach_read_from_4(
src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
@ -794,7 +820,7 @@ fil_space_decrypt(
FIL_PAGE_DATA_END);
// clear key-version & crypt-checksum from dst
memset(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
memset(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
}
srv_stats.pages_decrypted.inc();
@ -937,12 +963,15 @@ Check if a key needs rotation given a key_state
static bool
fil_crypt_needs_rotation(
/*=====================*/
fil_encryption_t encrypt_mode, /*!< in: Encryption
mode */
uint key_version, /*!< in: Key version */
uint latest_key_version, /*!< in: Latest key version */
uint rotate_key_age) /*!< in: When to rotate */
{
if (key_version == ENCRYPTION_KEY_VERSION_INVALID)
if (key_version == ENCRYPTION_KEY_VERSION_INVALID) {
return false;
}
if (key_version == 0 && latest_key_version != 0) {
/* this is rotation unencrypted => encrypted
@ -951,8 +980,11 @@ fil_crypt_needs_rotation(
}
if (latest_key_version == 0 && key_version != 0) {
/* this is rotation encrypted => unencrypted */
return true;
if (encrypt_mode == FIL_SPACE_ENCRYPTION_DEFAULT) {
/* this is rotation encrypted => unencrypted */
return true;
}
return false;
}
/* this is rotation encrypted => encrypted,
@ -973,11 +1005,15 @@ fil_crypt_is_closing(
/*=================*/
ulint space) /*!< in: FIL space id */
{
bool closing;
bool closing=true;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex);
closing = crypt_data->closing;
mutex_exit(&crypt_data->mutex);
if (crypt_data) {
mutex_enter(&crypt_data->mutex);
closing = crypt_data->closing;
mutex_exit(&crypt_data->mutex);
}
return closing;
}
@ -1189,6 +1225,7 @@ Check if space needs rotation given a key_state
static
bool
fil_crypt_space_needs_rotation(
/*===========================*/
rotate_thread_t* state, /*!< in: Key rotation state */
key_state_t* key_state, /*!< in: Key state */
bool* recheck) /*!< out: needs recheck ? */
@ -1228,11 +1265,6 @@ fil_crypt_space_needs_rotation(
mutex_enter(&crypt_data->mutex);
do {
if (crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) {
/* This space is unencrypted by user request */
break;
}
/* prevent threads from starting to rotate space */
if (crypt_data->rotate_state.starting) {
/* recheck this space later */
@ -1255,6 +1287,7 @@ fil_crypt_space_needs_rotation(
}
bool need_key_rotation = fil_crypt_needs_rotation(
crypt_data->encryption,
crypt_data->min_key_version,
key_state->key_version, key_state->rotate_key_age);
@ -1351,7 +1384,7 @@ used when inside a space */
static
void
fil_crypt_realloc_iops(
/*========================*/
/*===================*/
rotate_thread_t *state) /*!< in: Key rotation status */
{
ut_a(state->allocated_iops > 0);
@ -1444,7 +1477,7 @@ Return allocated iops to global */
static
void
fil_crypt_return_iops(
/*========================*/
/*==================*/
rotate_thread_t *state) /*!< in: Key rotation status */
{
if (state->allocated_iops > 0) {
@ -1526,11 +1559,17 @@ fil_crypt_start_rotate_space(
ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex);
ut_ad(key_state->key_id == crypt_data->key_id);
if (crypt_data->rotate_state.active_threads == 0) {
/* only first thread needs to init */
if (crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) {
crypt_data->type = CRYPT_SCHEME_UNENCRYPTED;
} else {
crypt_data->type = CRYPT_SCHEME_1;
}
crypt_data->rotate_state.next_offset = 1; // skip page 0
/* no need to rotate beyond current max
* if space extends, it will be encrypted with newer version */
@ -1568,28 +1607,33 @@ fil_crypt_find_page_to_rotate(
ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex);
ut_ad(key_state->key_id == crypt_data->key_id);
/* Space might already be dropped */
if (crypt_data) {
mutex_enter(&crypt_data->mutex);
ut_ad(key_state->key_id == crypt_data->key_id);
if (crypt_data->closing == false &&
crypt_data->rotate_state.next_offset <
crypt_data->rotate_state.max_offset) {
if (crypt_data->closing == false &&
crypt_data->rotate_state.next_offset <
crypt_data->rotate_state.max_offset) {
state->offset = crypt_data->rotate_state.next_offset;
ulint remaining = crypt_data->rotate_state.max_offset -
crypt_data->rotate_state.next_offset;
state->offset = crypt_data->rotate_state.next_offset;
ulint remaining = crypt_data->rotate_state.max_offset -
crypt_data->rotate_state.next_offset;
if (batch <= remaining)
state->batch = batch;
else
state->batch = remaining;
if (batch <= remaining) {
state->batch = batch;
} else {
state->batch = remaining;
}
crypt_data->rotate_state.next_offset += batch;
mutex_exit(&crypt_data->mutex);
return true;
}
crypt_data->rotate_state.next_offset += batch;
mutex_exit(&crypt_data->mutex);
return true;
}
mutex_exit(&crypt_data->mutex);
return false;
}
@ -1636,6 +1680,7 @@ Get a page and compute sleep time
static
buf_block_t*
fil_crypt_get_page_throttle_func(
/*=============================*/
rotate_thread_t* state, /*!< in/out: Key rotation state */
ulint space, /*!< in: FIL space id */
uint zip_size, /*!< in: compressed size if
@ -1752,7 +1797,7 @@ Rotate one page */
static
void
fil_crypt_rotate_page(
/*===================*/
/*==================*/
const key_state_t* key_state, /*!< in: Key state */
rotate_thread_t* state) /*!< in: Key rotation state */
{
@ -1791,8 +1836,10 @@ fil_crypt_rotate_page(
if (kv == 0 &&
fil_crypt_is_page_uninitialized(frame, zip_size)) {
;
} else if (fil_crypt_needs_rotation(kv, key_state->key_version,
key_state->rotate_key_age)) {
} else if (fil_crypt_needs_rotation(
crypt_data->encryption,
kv, key_state->key_version,
key_state->rotate_key_age)) {
/* page can be "fresh" i.e never written in case
* kv == 0 or it should have a key version at least
@ -1812,11 +1859,13 @@ fil_crypt_rotate_page(
/* statistics */
state->crypt_stat.pages_modified++;
} else {
ut_a(kv >= crypt_data->min_key_version ||
(kv == 0 && key_state->key_version == 0));
if (crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF) {
ut_a(kv >= crypt_data->min_key_version ||
(kv == 0 && key_state->key_version == 0));
if (kv < state->min_key_version_found) {
state->min_key_version_found = kv;
if (kv < state->min_key_version_found) {
state->min_key_version_found = kv;
}
}
}
@ -1878,6 +1927,7 @@ fil_crypt_rotate_page(
/* if we just detected that scrubbing was turned off
* update global state to reflect this */
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing.is_active = false;
mutex_exit(&crypt_data->mutex);
@ -2006,68 +2056,73 @@ fil_crypt_complete_rotate_space(
{
ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex);
/**
* Update crypt data state with state from thread
*/
if (state->min_key_version_found <
crypt_data->rotate_state.min_key_version_found) {
crypt_data->rotate_state.min_key_version_found =
state->min_key_version_found;
}
/* Space might already be dropped */
if (crypt_data) {
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex);
if (state->end_lsn > crypt_data->rotate_state.end_lsn) {
crypt_data->rotate_state.end_lsn = state->end_lsn;
}
/**
* Update crypt data state with state from thread
*/
if (state->min_key_version_found <
crypt_data->rotate_state.min_key_version_found) {
crypt_data->rotate_state.min_key_version_found =
state->min_key_version_found;
}
ut_a(crypt_data->rotate_state.active_threads > 0);
crypt_data->rotate_state.active_threads--;
bool last = crypt_data->rotate_state.active_threads == 0;
if (state->end_lsn > crypt_data->rotate_state.end_lsn) {
crypt_data->rotate_state.end_lsn = state->end_lsn;
}
/**
* check if space is fully done
* this as when threads shutdown, it could be that we "complete"
* iterating before we have scanned the full space.
*/
bool done = crypt_data->rotate_state.next_offset >=
crypt_data->rotate_state.max_offset;
ut_a(crypt_data->rotate_state.active_threads > 0);
crypt_data->rotate_state.active_threads--;
bool last = crypt_data->rotate_state.active_threads == 0;
/**
* we should flush space if we're last thread AND
* the iteration is done
*/
bool should_flush = last && done;
/**
* check if space is fully done
* this as when threads shutdown, it could be that we "complete"
* iterating before we have scanned the full space.
*/
bool done = crypt_data->rotate_state.next_offset >=
crypt_data->rotate_state.max_offset;
if (should_flush) {
/* we're the last active thread */
crypt_data->rotate_state.flushing = true;
crypt_data->min_key_version =
crypt_data->rotate_state.min_key_version_found;
}
/**
* we should flush space if we're last thread AND
* the iteration is done
*/
bool should_flush = last && done;
/* inform scrubbing */
crypt_data->rotate_state.scrubbing.is_active = false;
mutex_exit(&crypt_data->mutex);
/* all threads must call btr_scrub_complete_space wo/ mutex held */
if (btr_scrub_complete_space(&state->scrub_data) == true) {
if (should_flush) {
/* only last thread updates last_scrub_completed */
/* we're the last active thread */
crypt_data->rotate_state.flushing = true;
crypt_data->min_key_version =
crypt_data->rotate_state.min_key_version_found;
}
/* inform scrubbing */
crypt_data->rotate_state.scrubbing.is_active = false;
mutex_exit(&crypt_data->mutex);
/* all threads must call btr_scrub_complete_space wo/ mutex held */
if (btr_scrub_complete_space(&state->scrub_data) == true) {
if (should_flush) {
/* only last thread updates last_scrub_completed */
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing.
last_scrub_completed = time(0);
mutex_exit(&crypt_data->mutex);
}
}
if (should_flush) {
fil_crypt_flush_space(state, space);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing.
last_scrub_completed = time(0);
crypt_data->rotate_state.flushing = false;
mutex_exit(&crypt_data->mutex);
}
}
if (should_flush) {
fil_crypt_flush_space(state, space);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.flushing = false;
mutex_exit(&crypt_data->mutex);
}
}
/*********************************************************************//**
@ -2194,8 +2249,8 @@ fil_crypt_set_thread_cnt(
os_thread_id_t rotation_thread_id;
os_thread_create(fil_crypt_thread, NULL, &rotation_thread_id);
ib_logf(IB_LOG_LEVEL_INFO,
"Creating #%d thread id %lu total threads %du\n",
i, os_thread_pf(rotation_thread_id), new_cnt);
"Creating #%d thread id %lu total threads %u\n",
i+1, os_thread_pf(rotation_thread_id), new_cnt);
}
} else if (new_cnt < srv_n_fil_crypt_threads) {
srv_n_fil_crypt_threads = new_cnt;
@ -2232,6 +2287,18 @@ fil_crypt_set_rotation_iops(
os_event_set(fil_crypt_threads_event);
}
/*********************************************************************
Adjust encrypt tables */
UNIV_INTERN
void
fil_crypt_set_encrypt_tables(
/*=========================*/
uint val) /*!< in: New srv_encrypt_tables setting */
{
srv_encrypt_tables = val;
os_event_set(fil_crypt_threads_event);
}
/*********************************************************************
Init threads for key rotation */
UNIV_INTERN
@ -2279,7 +2346,7 @@ fil_space_crypt_mark_space_closing(
/*===============================*/
ulint space) /*!< in: Space id */
{
if (!srv_encrypt_tables) {
if (!fil_crypt_threads_inited) {
return;
}

View File

@ -6999,19 +6999,26 @@ fil_space_set_crypt_data(
if (space != NULL) {
if (space->crypt_data != NULL) {
/* Here we need to release fil_system mutex to
avoid mutex deadlock assertion. Here we would
take mutexes in order fil_system, crypt_data and
in fil_crypt_start_encrypting_space we would
take them in order crypt_data, fil_system
at fil_space_get_flags -> fil_space_get_space */
mutex_exit(&fil_system->mutex);
fil_space_merge_crypt_data(space->crypt_data,
crypt_data);
free_crypt_data = crypt_data;
} else {
space->crypt_data = crypt_data;
mutex_exit(&fil_system->mutex);
}
} else {
/* there is a small risk that tablespace has been deleted */
free_crypt_data = crypt_data;
mutex_exit(&fil_system->mutex);
}
mutex_exit(&fil_system->mutex);
if (free_crypt_data != NULL) {
/* there was already crypt data present and the new crypt
* data provided as argument to this function has been merged

View File

@ -3604,7 +3604,7 @@ innobase_init(
goto error;
}
}
#ifndef HAVE_LZ4
if (innodb_compression_algorithm == PAGE_LZ4_ALGORITHM) {
sql_print_error("InnoDB: innodb_compression_algorithm = %lu unsupported.\n"
@ -18746,6 +18746,7 @@ which control InnoDB "status monitor" output to the error log.
static
void
innodb_status_output_update(
/*========================*/
THD* thd __attribute__((unused)),
struct st_mysql_sys_var* var __attribute__((unused)),
void* var_ptr __attribute__((unused)),
@ -18761,7 +18762,7 @@ Update the system variable innodb_encryption_threads */
static
void
innodb_encryption_threads_update(
/*=========================*/
/*=============================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
@ -18778,7 +18779,7 @@ Update the system variable innodb_encryption_rotate_key_age */
static
void
innodb_encryption_rotate_key_age_update(
/*=========================*/
/*====================================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
@ -18795,7 +18796,7 @@ Update the system variable innodb_encryption_rotation_iops */
static
void
innodb_encryption_rotation_iops_update(
/*=========================*/
/*===================================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
@ -18807,6 +18808,23 @@ innodb_encryption_rotation_iops_update(
fil_crypt_set_rotation_iops(*static_cast<const uint*>(save));
}
/******************************************************************
Update the system variable innodb_encrypt_tables*/
static
void
innodb_encrypt_tables_update(
/*=========================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
void* var_ptr,/*!< out: where the
formal string goes */
const void* save) /*!< in: immediate result
from check function */
{
fil_crypt_set_encrypt_tables(*static_cast<const uint*>(save));
}
static SHOW_VAR innodb_status_variables_export[]= {
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
{NullS, NullS, SHOW_LONG}
@ -20365,7 +20383,9 @@ static MYSQL_SYSVAR_ENUM(encrypt_tables, srv_encrypt_tables,
PLUGIN_VAR_OPCMDARG,
"Enable encryption for tables. "
"Don't forget to enable --innodb-encrypt-log too",
innodb_encrypt_tables_validate, NULL, 0,
NULL,
innodb_encrypt_tables_update,
0,
&srv_encrypt_tables_typelib);
static MYSQL_SYSVAR_UINT(encryption_threads, srv_n_fil_crypt_threads,

View File

@ -128,7 +128,7 @@ Get crypt data for a space*/
UNIV_INTERN
fil_space_crypt_t *
fil_space_get_crypt_data(
/*======================*/
/*=====================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
@ -136,15 +136,16 @@ Set crypt data for a space*/
UNIV_INTERN
void
fil_space_set_crypt_data(
/*======================*/
/*=====================*/
ulint space, /*!< in: tablespace id */
fil_space_crypt_t* crypt_data); /*!< in: crypt data to set */
/*********************************************************************
Merge crypt data */
UNIV_INTERN
void
fil_space_merge_crypt_data(
/*======================*/
/*=======================*/
fil_space_crypt_t* dst_crypt_data, /*!< in: crypt_data */
const fil_space_crypt_t* src_crypt_data); /*!< in: crypt data */
@ -175,7 +176,7 @@ Clear crypt data from page 0 (used for import tablespace) */
UNIV_INTERN
void
fil_space_clear_crypt_data(
/*======================*/
/*=======================*/
byte* page, /*!< in: buffer page */
ulint offset); /*!< in: offset where crypt data is stored */
@ -194,7 +195,7 @@ Check if extra buffer shall be allocated for decrypting after read */
UNIV_INTERN
bool
fil_space_check_encryption_read(
/*==============================*/
/*============================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
@ -202,7 +203,7 @@ Check if page shall be encrypted before write */
UNIV_INTERN
bool
fil_space_check_encryption_write(
/*==============================*/
/*=============================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
@ -210,7 +211,7 @@ Encrypt buffer page */
UNIV_INTERN
void
fil_space_encrypt(
/*===============*/
/*==============*/
ulint space, /*!< in: tablespace id */
ulint offset, /*!< in: page no */
lsn_t lsn, /*!< in: page lsn */
@ -223,7 +224,7 @@ Decrypt buffer page */
UNIV_INTERN
void
fil_space_decrypt(
/*===============*/
/*==============*/
ulint space, /*!< in: tablespace id */
const byte* src_frame,/*!< in: page frame */
ulint page_size, /*!< in: size of data to encrypt */
@ -236,7 +237,7 @@ Decrypt buffer page
UNIV_INTERN
bool
fil_space_decrypt(
/*===============*/
/*==============*/
fil_space_crypt_t* crypt_data, /*!< in: crypt data */
const byte* src_frame,/*!< in: page frame */
ulint page_size, /*!< in: page size */
@ -250,7 +251,7 @@ as it modifies srv_checksum_algorithm (temporarily)
UNIV_INTERN
bool
fil_space_verify_crypt_checksum(
/*===============*/
/*============================*/
const byte* src_frame,/*!< in: page frame */
ulint zip_size); /*!< in: size of data to encrypt */
@ -285,7 +286,7 @@ Set rotate key age */
UNIV_INTERN
void
fil_crypt_set_rotate_key_age(
/*=====================*/
/*=========================*/
uint rotate_age); /*!< in: requested rotate age */
/*********************************************************************
@ -293,7 +294,7 @@ Set rotation threads iops */
UNIV_INTERN
void
fil_crypt_set_rotation_iops(
/*=====================*/
/*========================*/
uint iops); /*!< in: requested iops */
/*********************************************************************
@ -301,7 +302,7 @@ Mark a space as closing */
UNIV_INTERN
void
fil_space_crypt_mark_space_closing(
/*===============*/
/*===============================*/
ulint space); /*!< in: tablespace id */
/*********************************************************************
@ -309,7 +310,7 @@ Wait for crypt threads to stop accessing space */
UNIV_INTERN
void
fil_space_crypt_close_tablespace(
/*===============*/
/*=============================*/
ulint space); /*!< in: tablespace id */
/** Struct for retreiving info about encryption */
@ -331,7 +332,7 @@ Get crypt status for a space
UNIV_INTERN
int
fil_space_crypt_get_status(
/*==================*/
/*=======================*/
ulint id, /*!< in: space id */
struct fil_space_crypt_status_t * status); /*!< out: status */
@ -370,10 +371,18 @@ Get scrub status for a space
UNIV_INTERN
int
fil_space_get_scrub_status(
/*==================*/
/*=======================*/
ulint id, /*!< in: space id */
struct fil_space_scrub_status_t * status); /*!< out: status */
/*********************************************************************
Adjust encrypt tables */
UNIV_INTERN
void
fil_crypt_set_encrypt_tables(
/*=========================*/
uint val); /*!< in: New srv_encrypt_tables setting */
#ifndef UNIV_NONINL
#include "fil0crypt.ic"
#endif