mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-8143: InnoDB: Database page corruption on disk or a failed file read
Analysis: Problem was that we did create crypt data for encrypted table but this new crypt data was not written to page 0. Instead a default crypt data was written to page 0 at table creation. Fixed by explicitly writing new crypt data to page 0 after successfull table creation.
This commit is contained in:
@@ -217,11 +217,11 @@ select count(*) from innodb_redundant t1, innodb_normal t2 where
|
|||||||
t1.c1 = t2.c1 and t1.b = t2.b;
|
t1.c1 = t2.c1 and t1.b = t2.b;
|
||||||
count(*)
|
count(*)
|
||||||
2000
|
2000
|
||||||
SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_encrypted';
|
SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_encrypted';
|
||||||
variable_value = 0
|
variable_value >= 0
|
||||||
1
|
1
|
||||||
SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_decrypted';
|
SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_decrypted';
|
||||||
variable_value = 0
|
variable_value >= 0
|
||||||
1
|
1
|
||||||
drop procedure innodb_insert_proc;
|
drop procedure innodb_insert_proc;
|
||||||
drop table innodb_normal;
|
drop table innodb_normal;
|
||||||
@@ -229,3 +229,11 @@ drop table innodb_compact;
|
|||||||
drop table innodb_compressed;
|
drop table innodb_compressed;
|
||||||
drop table innodb_dynamic;
|
drop table innodb_dynamic;
|
||||||
drop table innodb_redundant;
|
drop table innodb_redundant;
|
||||||
|
CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=InnoDB ENCRYPTION_KEY_ID=2 ENCRYPTED=YES;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
# Restarting server...
|
||||||
|
SELECT * FROM t1;
|
||||||
|
pk
|
||||||
|
1
|
||||||
|
2
|
||||||
|
DROP TABLE t1;
|
||||||
|
@@ -1 +1,3 @@
|
|||||||
--innodb-encrypt-log
|
--innodb-encrypt-log=ON
|
||||||
|
--innodb-encrypt-tables=ON
|
||||||
|
|
||||||
|
@@ -133,9 +133,8 @@ t1.c1 = t2.c1 and t1.b = t2.b;
|
|||||||
select count(*) from innodb_redundant t1, innodb_normal t2 where
|
select count(*) from innodb_redundant t1, innodb_normal t2 where
|
||||||
t1.c1 = t2.c1 and t1.b = t2.b;
|
t1.c1 = t2.c1 and t1.b = t2.b;
|
||||||
|
|
||||||
# After alter+restart these should be 0
|
SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_encrypted';
|
||||||
SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_encrypted';
|
SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_decrypted';
|
||||||
SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_decrypted';
|
|
||||||
|
|
||||||
drop procedure innodb_insert_proc;
|
drop procedure innodb_insert_proc;
|
||||||
drop table innodb_normal;
|
drop table innodb_normal;
|
||||||
@@ -144,6 +143,19 @@ drop table innodb_compressed;
|
|||||||
drop table innodb_dynamic;
|
drop table innodb_dynamic;
|
||||||
drop table innodb_redundant;
|
drop table innodb_redundant;
|
||||||
|
|
||||||
|
#
|
||||||
|
# MDEV-8143: InnoDB: Database page corruption on disk or a failed file read
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=InnoDB ENCRYPTION_KEY_ID=2 ENCRYPTED=YES;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
|
||||||
|
--echo # Restarting server...
|
||||||
|
--source include/restart_mysqld.inc
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
# reset system
|
# reset system
|
||||||
--disable_query_log
|
--disable_query_log
|
||||||
EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig;
|
EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig;
|
||||||
|
@@ -5701,6 +5701,10 @@ buf_page_encrypt_before_write(
|
|||||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
|
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
|
||||||
bpage->real_size = UNIV_PAGE_SIZE;
|
bpage->real_size = UNIV_PAGE_SIZE;
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(src_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (crypt_data != NULL && crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) {
|
if (crypt_data != NULL && crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) {
|
||||||
/* Encryption is disabled */
|
/* Encryption is disabled */
|
||||||
return const_cast<byte*>(src_frame);
|
return const_cast<byte*>(src_frame);
|
||||||
@@ -5754,6 +5758,11 @@ buf_page_encrypt_before_write(
|
|||||||
ut_ad(key_version == 0 || key_version >= bpage->key_version);
|
ut_ad(key_version == 0 || key_version >= bpage->key_version);
|
||||||
bpage->key_version = key_version;
|
bpage->key_version = key_version;
|
||||||
bpage->real_size = page_size;
|
bpage->real_size = page_size;
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* First we compress the page content */
|
/* First we compress the page content */
|
||||||
ulint out_len = 0;
|
ulint out_len = 0;
|
||||||
@@ -5775,6 +5784,10 @@ buf_page_encrypt_before_write(
|
|||||||
|
|
||||||
bpage->real_size = out_len;
|
bpage->real_size = out_len;
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(tmp);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* And then we encrypt the page content */
|
/* And then we encrypt the page content */
|
||||||
fil_space_encrypt(bpage->space,
|
fil_space_encrypt(bpage->space,
|
||||||
bpage->offset,
|
bpage->offset,
|
||||||
@@ -5784,6 +5797,10 @@ buf_page_encrypt_before_write(
|
|||||||
dst_frame);
|
dst_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
// return dst_frame which will be written
|
// return dst_frame which will be written
|
||||||
return dst_frame;
|
return dst_frame;
|
||||||
}
|
}
|
||||||
@@ -5822,6 +5839,10 @@ buf_page_decrypt_after_read(
|
|||||||
/* Find free slot from temporary memory array */
|
/* Find free slot from temporary memory array */
|
||||||
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed);
|
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
fil_decompress_page(slot->comp_buf,
|
fil_decompress_page(slot->comp_buf,
|
||||||
dst_frame,
|
dst_frame,
|
||||||
size,
|
size,
|
||||||
@@ -5830,6 +5851,10 @@ buf_page_decrypt_after_read(
|
|||||||
/* Mark this slot as free */
|
/* Mark this slot as free */
|
||||||
slot->reserved = false;
|
slot->reserved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* the page we read is encrypted */
|
/* the page we read is encrypted */
|
||||||
/* Find free slot from temporary memory array */
|
/* Find free slot from temporary memory array */
|
||||||
@@ -5837,12 +5862,22 @@ buf_page_decrypt_after_read(
|
|||||||
|
|
||||||
memcpy(slot->crypt_buf, dst_frame, size);
|
memcpy(slot->crypt_buf, dst_frame, size);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
fil_page_type_validate(slot->crypt_buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* decrypt from crypt_buf to dst_frame */
|
/* decrypt from crypt_buf to dst_frame */
|
||||||
fil_space_decrypt(bpage->space,
|
fil_space_decrypt(bpage->space,
|
||||||
slot->crypt_buf,
|
slot->crypt_buf,
|
||||||
size,
|
size,
|
||||||
dst_frame);
|
dst_frame);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
fil_page_type_validate(slot->crypt_buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* decompress from dst_frame to comp_buf and then copy to
|
/* decompress from dst_frame to comp_buf and then copy to
|
||||||
buffer pool */
|
buffer pool */
|
||||||
if (page_compressed) {
|
if (page_compressed) {
|
||||||
@@ -5852,6 +5887,10 @@ buf_page_decrypt_after_read(
|
|||||||
&bpage->write_size);
|
&bpage->write_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Mark this slot as free */
|
/* Mark this slot as free */
|
||||||
slot->reserved = false;
|
slot->reserved = false;
|
||||||
}
|
}
|
||||||
|
@@ -272,8 +272,10 @@ Create a fil_space_crypt_t object
|
|||||||
@return crypt object */
|
@return crypt object */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
fil_space_crypt_t*
|
fil_space_crypt_t*
|
||||||
fil_space_create_crypt_data(uint key_id)
|
fil_space_create_crypt_data(
|
||||||
/*=========================*/
|
/*========================*/
|
||||||
|
fil_encryption_t encrypt_mode, /*!< in: encryption mode */
|
||||||
|
uint key_id) /*!< in: encryption key id */
|
||||||
{
|
{
|
||||||
const uint iv_length = CRYPT_SCHEME_1_IV_LEN;
|
const uint iv_length = CRYPT_SCHEME_1_IV_LEN;
|
||||||
const uint sz = sizeof(fil_space_crypt_t) + iv_length;
|
const uint sz = sizeof(fil_space_crypt_t) + iv_length;
|
||||||
@@ -282,7 +284,8 @@ fil_space_create_crypt_data(uint key_id)
|
|||||||
|
|
||||||
memset(crypt_data, 0, sz);
|
memset(crypt_data, 0, sz);
|
||||||
|
|
||||||
if (!srv_encrypt_tables) {
|
if (encrypt_mode == FIL_SPACE_ENCRYPTION_OFF ||
|
||||||
|
(!srv_encrypt_tables && encrypt_mode == FIL_SPACE_ENCRYPTION_DEFAULT)) {
|
||||||
crypt_data->type = CRYPT_SCHEME_UNENCRYPTED;
|
crypt_data->type = CRYPT_SCHEME_UNENCRYPTED;
|
||||||
crypt_data->min_key_version = 0;
|
crypt_data->min_key_version = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -515,10 +518,15 @@ fil_space_write_crypt_data(
|
|||||||
{
|
{
|
||||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||||
|
|
||||||
/* If no crypt data is stored on memory cache for this space
|
/* If no crypt data is stored on memory cache for this space,
|
||||||
or space is not encrypted and encryption is not enabled, then
|
then do not continue writing crypt data to page 0. */
|
||||||
do not continue writing crypt data to page 0. */
|
if (crypt_data == NULL) {
|
||||||
if (crypt_data == NULL || !srv_encrypt_tables) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If tablespace encryption is disabled and encryption mode is
|
||||||
|
DEFAULT, then do not continue writing crypt data to page 0. */
|
||||||
|
if (!srv_encrypt_tables && crypt_data->encryption == FIL_SPACE_ENCRYPTION_DEFAULT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -577,7 +585,7 @@ fil_parse_write_crypt_data(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(key_id);
|
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(encryption, key_id);
|
||||||
crypt_data->page0_offset = offset;
|
crypt_data->page0_offset = offset;
|
||||||
crypt_data->min_key_version = min_key_version;
|
crypt_data->min_key_version = min_key_version;
|
||||||
crypt_data->encryption = encryption;
|
crypt_data->encryption = encryption;
|
||||||
@@ -1112,7 +1120,7 @@ fil_crypt_start_encrypting_space(
|
|||||||
* crypt data in page 0 */
|
* crypt data in page 0 */
|
||||||
|
|
||||||
/* 1 - create crypt data */
|
/* 1 - create crypt data */
|
||||||
crypt_data = fil_space_create_crypt_data(FIL_DEFAULT_ENCRYPTION_KEY);
|
crypt_data = fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
|
||||||
if (crypt_data == NULL) {
|
if (crypt_data == NULL) {
|
||||||
mutex_exit(&fil_crypt_threads_mutex);
|
mutex_exit(&fil_crypt_threads_mutex);
|
||||||
return pending_op;
|
return pending_op;
|
||||||
|
@@ -3474,7 +3474,7 @@ fil_create_new_single_table_tablespace(
|
|||||||
}
|
}
|
||||||
|
|
||||||
success = fil_space_create(tablename, space_id, flags, FIL_TABLESPACE,
|
success = fil_space_create(tablename, space_id, flags, FIL_TABLESPACE,
|
||||||
fil_space_create_crypt_data(FIL_DEFAULT_ENCRYPTION_KEY));
|
fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY));
|
||||||
|
|
||||||
if (!success || !fil_node_create(path, size, space_id, FALSE)) {
|
if (!success || !fil_node_create(path, size, space_id, FALSE)) {
|
||||||
err = DB_ERROR;
|
err = DB_ERROR;
|
||||||
|
@@ -11718,12 +11718,12 @@ ha_innobase::create(
|
|||||||
/* If user has requested that table should be encrypted or table
|
/* If user has requested that table should be encrypted or table
|
||||||
should remain as unencrypted store crypt data */
|
should remain as unencrypted store crypt data */
|
||||||
if (encrypt != FIL_SPACE_ENCRYPTION_DEFAULT) {
|
if (encrypt != FIL_SPACE_ENCRYPTION_DEFAULT) {
|
||||||
ulint maxsize;
|
ulint maxsize=0;
|
||||||
ulint zip_size = fil_space_get_zip_size(innobase_table->space);
|
ulint zip_size = fil_space_get_zip_size(innobase_table->space);
|
||||||
fil_space_crypt_t* old_crypt_data = fil_space_get_crypt_data(innobase_table->space);
|
fil_space_crypt_t* old_crypt_data = fil_space_get_crypt_data(innobase_table->space);
|
||||||
fil_space_crypt_t* crypt_data;
|
fil_space_crypt_t* crypt_data;
|
||||||
|
|
||||||
crypt_data = fil_space_create_crypt_data(key_id);
|
crypt_data = fil_space_create_crypt_data(encrypt, key_id);
|
||||||
crypt_data->page0_offset = fsp_header_get_crypt_offset(zip_size, &maxsize);
|
crypt_data->page0_offset = fsp_header_get_crypt_offset(zip_size, &maxsize);
|
||||||
crypt_data->encryption = encrypt;
|
crypt_data->encryption = encrypt;
|
||||||
|
|
||||||
@@ -11733,7 +11733,29 @@ ha_innobase::create(
|
|||||||
crypt_data->iv_length = old_crypt_data->iv_length;
|
crypt_data->iv_length = old_crypt_data->iv_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mtr_t mtr;
|
||||||
|
mtr_start(&mtr);
|
||||||
|
/* Get page 0*/
|
||||||
|
ulint offset = 0;
|
||||||
|
buf_block_t* block = buf_page_get_gen(innobase_table->space,
|
||||||
|
zip_size,
|
||||||
|
offset,
|
||||||
|
RW_X_LATCH,
|
||||||
|
NULL,
|
||||||
|
BUF_GET,
|
||||||
|
__FILE__, __LINE__,
|
||||||
|
&mtr);
|
||||||
|
|
||||||
|
/* Set up new crypt data */
|
||||||
fil_space_set_crypt_data(innobase_table->space, crypt_data);
|
fil_space_set_crypt_data(innobase_table->space, crypt_data);
|
||||||
|
|
||||||
|
/* Compute location to store crypt data */
|
||||||
|
byte* frame = buf_block_get_frame(block);
|
||||||
|
|
||||||
|
/* Write crypt data to page 0 */
|
||||||
|
fil_space_write_crypt_data(innobase_table->space, frame, crypt_data->page0_offset, maxsize, &mtr);
|
||||||
|
|
||||||
|
mtr_commit(&mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
innobase_copy_frm_flags_from_create_info(innobase_table, create_info);
|
innobase_copy_frm_flags_from_create_info(innobase_table, create_info);
|
||||||
|
@@ -118,7 +118,10 @@ fil_space_crypt_cleanup();
|
|||||||
Create crypt data, i.e data that is used for a single tablespace */
|
Create crypt data, i.e data that is used for a single tablespace */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
fil_space_crypt_t *
|
fil_space_crypt_t *
|
||||||
fil_space_create_crypt_data(uint key_id);
|
fil_space_create_crypt_data(
|
||||||
|
/*========================*/
|
||||||
|
fil_encryption_t encrypt_mode, /*!< in: encryption mode */
|
||||||
|
uint key_id); /*!< in: encryption key id */
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Destroy crypt data */
|
Destroy crypt data */
|
||||||
|
@@ -105,4 +105,70 @@ fil_node_get_block_size(
|
|||||||
return (node->file_block_size);
|
return (node->file_block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
/****************************************************************//**
|
||||||
|
Validate page type.
|
||||||
|
@return true if valid, false if not */
|
||||||
|
UNIV_INLINE
|
||||||
|
bool
|
||||||
|
fil_page_type_validate(
|
||||||
|
const byte* page) /*!< in: page */
|
||||||
|
{
|
||||||
|
ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE);
|
||||||
|
#ifdef UNIV_ENCRYPTION_EXTRA_DEBUG
|
||||||
|
uint key_version = mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
|
||||||
|
bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED);
|
||||||
|
ulint space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
|
||||||
|
ulint offset = mach_read_from_4(page + FIL_PAGE_OFFSET);
|
||||||
|
ib_uint64_t lsn = mach_read_from_8(page + FIL_PAGE_LSN);
|
||||||
|
ulint compressed_len = mach_read_from_2(page + FIL_PAGE_DATA);
|
||||||
|
fil_system_enter();
|
||||||
|
fil_space_t* rspace = fil_space_get_by_id(space);
|
||||||
|
fil_system_exit();
|
||||||
|
|
||||||
|
/* Dump out the page info */
|
||||||
|
fprintf(stderr, "InnoDB: Space %lu offset %lu name %s page_type %lu page_type_name %s\n"
|
||||||
|
"InnoDB: key_version %u page_compressed %d lsn %lu compressed_len %lu\n",
|
||||||
|
space, offset, rspace->name, page_type, fil_get_page_type_name(page_type),
|
||||||
|
key_version, page_compressed, lsn, compressed_len);
|
||||||
|
fflush(stderr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Validate page type */
|
||||||
|
if (!((page_type == FIL_PAGE_PAGE_COMPRESSED ||
|
||||||
|
page_type == FIL_PAGE_INDEX ||
|
||||||
|
page_type == FIL_PAGE_UNDO_LOG ||
|
||||||
|
page_type == FIL_PAGE_INODE ||
|
||||||
|
page_type == FIL_PAGE_IBUF_FREE_LIST ||
|
||||||
|
page_type == FIL_PAGE_TYPE_ALLOCATED ||
|
||||||
|
page_type == FIL_PAGE_IBUF_BITMAP ||
|
||||||
|
page_type == FIL_PAGE_TYPE_SYS ||
|
||||||
|
page_type == FIL_PAGE_TYPE_TRX_SYS ||
|
||||||
|
page_type == FIL_PAGE_TYPE_FSP_HDR ||
|
||||||
|
page_type == FIL_PAGE_TYPE_XDES ||
|
||||||
|
page_type == FIL_PAGE_TYPE_BLOB ||
|
||||||
|
page_type == FIL_PAGE_TYPE_ZBLOB ||
|
||||||
|
page_type == FIL_PAGE_TYPE_COMPRESSED))) {
|
||||||
|
|
||||||
|
ut_ad(page_type == FIL_PAGE_PAGE_COMPRESSED ||
|
||||||
|
page_type == FIL_PAGE_INDEX ||
|
||||||
|
page_type == FIL_PAGE_UNDO_LOG ||
|
||||||
|
page_type == FIL_PAGE_INODE ||
|
||||||
|
page_type == FIL_PAGE_IBUF_FREE_LIST ||
|
||||||
|
page_type == FIL_PAGE_TYPE_ALLOCATED ||
|
||||||
|
page_type == FIL_PAGE_IBUF_BITMAP ||
|
||||||
|
page_type == FIL_PAGE_TYPE_SYS ||
|
||||||
|
page_type == FIL_PAGE_TYPE_TRX_SYS ||
|
||||||
|
page_type == FIL_PAGE_TYPE_FSP_HDR ||
|
||||||
|
page_type == FIL_PAGE_TYPE_XDES ||
|
||||||
|
page_type == FIL_PAGE_TYPE_BLOB ||
|
||||||
|
page_type == FIL_PAGE_TYPE_ZBLOB ||
|
||||||
|
page_type == FIL_PAGE_TYPE_COMPRESSED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
#endif /* fil0fil_ic */
|
#endif /* fil0fil_ic */
|
||||||
|
@@ -1120,7 +1120,7 @@ check_first_page:
|
|||||||
|
|
||||||
*sum_of_new_sizes += srv_data_file_sizes[i];
|
*sum_of_new_sizes += srv_data_file_sizes[i];
|
||||||
|
|
||||||
crypt_data = fil_space_create_crypt_data(FIL_DEFAULT_ENCRYPTION_KEY);
|
crypt_data = fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = os_file_close(files[i]);
|
ret = os_file_close(files[i]);
|
||||||
|
@@ -5859,6 +5859,10 @@ buf_page_encrypt_before_write(
|
|||||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
|
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id);
|
||||||
bpage->real_size = UNIV_PAGE_SIZE;
|
bpage->real_size = UNIV_PAGE_SIZE;
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(src_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (crypt_data != NULL && crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) {
|
if (crypt_data != NULL && crypt_data->encryption == FIL_SPACE_ENCRYPTION_OFF) {
|
||||||
/* Encryption is disabled */
|
/* Encryption is disabled */
|
||||||
return const_cast<byte*>(src_frame);
|
return const_cast<byte*>(src_frame);
|
||||||
@@ -5912,6 +5916,11 @@ buf_page_encrypt_before_write(
|
|||||||
ut_ad(key_version == 0 || key_version >= bpage->key_version);
|
ut_ad(key_version == 0 || key_version >= bpage->key_version);
|
||||||
bpage->key_version = key_version;
|
bpage->key_version = key_version;
|
||||||
bpage->real_size = page_size;
|
bpage->real_size = page_size;
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* First we compress the page content */
|
/* First we compress the page content */
|
||||||
ulint out_len = 0;
|
ulint out_len = 0;
|
||||||
@@ -5933,6 +5942,10 @@ buf_page_encrypt_before_write(
|
|||||||
|
|
||||||
bpage->real_size = out_len;
|
bpage->real_size = out_len;
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(tmp);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* And then we encrypt the page content */
|
/* And then we encrypt the page content */
|
||||||
fil_space_encrypt(bpage->space,
|
fil_space_encrypt(bpage->space,
|
||||||
bpage->offset,
|
bpage->offset,
|
||||||
@@ -5942,6 +5955,10 @@ buf_page_encrypt_before_write(
|
|||||||
dst_frame);
|
dst_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
// return dst_frame which will be written
|
// return dst_frame which will be written
|
||||||
return dst_frame;
|
return dst_frame;
|
||||||
}
|
}
|
||||||
@@ -5977,6 +5994,10 @@ buf_page_decrypt_after_read(
|
|||||||
/* Find free slot from temporary memory array */
|
/* Find free slot from temporary memory array */
|
||||||
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed);
|
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
fil_decompress_page(slot->comp_buf,
|
fil_decompress_page(slot->comp_buf,
|
||||||
dst_frame,
|
dst_frame,
|
||||||
size,
|
size,
|
||||||
@@ -5985,22 +6006,40 @@ buf_page_decrypt_after_read(
|
|||||||
/* Mark this slot as free */
|
/* Mark this slot as free */
|
||||||
slot->reserved = false;
|
slot->reserved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* Find free slot from temporary memory array */
|
/* Find free slot from temporary memory array */
|
||||||
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed);
|
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed);
|
||||||
memcpy(slot->crypt_buf, dst_frame, size);
|
memcpy(slot->crypt_buf, dst_frame, size);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
fil_page_type_validate(slot->crypt_buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* decrypt from crypt_buf to dst_frame */
|
/* decrypt from crypt_buf to dst_frame */
|
||||||
fil_space_decrypt(bpage->space,
|
fil_space_decrypt(bpage->space,
|
||||||
slot->crypt_buf,
|
slot->crypt_buf,
|
||||||
size,
|
size,
|
||||||
dst_frame);
|
dst_frame);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
fil_page_type_validate(slot->crypt_buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (page_compressed) {
|
if (page_compressed) {
|
||||||
fil_decompress_page(slot->comp_buf,
|
fil_decompress_page(slot->comp_buf,
|
||||||
dst_frame,
|
dst_frame,
|
||||||
size,
|
size,
|
||||||
&bpage->write_size);
|
&bpage->write_size);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
fil_page_type_validate(dst_frame);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark this slot as free */
|
/* Mark this slot as free */
|
||||||
|
@@ -272,8 +272,10 @@ Create a fil_space_crypt_t object
|
|||||||
@return crypt object */
|
@return crypt object */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
fil_space_crypt_t*
|
fil_space_crypt_t*
|
||||||
fil_space_create_crypt_data(uint key_id)
|
fil_space_create_crypt_data(
|
||||||
/*=========================*/
|
/*========================*/
|
||||||
|
fil_encryption_t encrypt_mode, /*!< in: encryption mode */
|
||||||
|
uint key_id) /*!< in: encryption key id */
|
||||||
{
|
{
|
||||||
const uint iv_length = CRYPT_SCHEME_1_IV_LEN;
|
const uint iv_length = CRYPT_SCHEME_1_IV_LEN;
|
||||||
const uint sz = sizeof(fil_space_crypt_t) + iv_length;
|
const uint sz = sizeof(fil_space_crypt_t) + iv_length;
|
||||||
@@ -282,7 +284,8 @@ fil_space_create_crypt_data(uint key_id)
|
|||||||
|
|
||||||
memset(crypt_data, 0, sz);
|
memset(crypt_data, 0, sz);
|
||||||
|
|
||||||
if (!srv_encrypt_tables) {
|
if (encrypt_mode == FIL_SPACE_ENCRYPTION_OFF ||
|
||||||
|
(!srv_encrypt_tables && encrypt_mode == FIL_SPACE_ENCRYPTION_DEFAULT)) {
|
||||||
crypt_data->type = CRYPT_SCHEME_UNENCRYPTED;
|
crypt_data->type = CRYPT_SCHEME_UNENCRYPTED;
|
||||||
crypt_data->min_key_version = 0;
|
crypt_data->min_key_version = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -515,10 +518,15 @@ fil_space_write_crypt_data(
|
|||||||
{
|
{
|
||||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||||
|
|
||||||
/* If no crypt data is stored on memory cache for this space
|
/* If no crypt data is stored on memory cache for this space,
|
||||||
or space is not encrypted and encryption is not enabled, then
|
then do not continue writing crypt data to page 0. */
|
||||||
do not continue writing crypt data to page 0. */
|
if (crypt_data == NULL) {
|
||||||
if (crypt_data == NULL || !srv_encrypt_tables) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If tablespace encryption is disabled and encryption mode is
|
||||||
|
DEFAULT, then do not continue writing crypt data to page 0. */
|
||||||
|
if (!srv_encrypt_tables && crypt_data->encryption == FIL_SPACE_ENCRYPTION_DEFAULT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -577,7 +585,7 @@ fil_parse_write_crypt_data(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(key_id);
|
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(encryption, key_id);
|
||||||
crypt_data->page0_offset = offset;
|
crypt_data->page0_offset = offset;
|
||||||
crypt_data->min_key_version = min_key_version;
|
crypt_data->min_key_version = min_key_version;
|
||||||
crypt_data->encryption = encryption;
|
crypt_data->encryption = encryption;
|
||||||
@@ -1112,7 +1120,7 @@ fil_crypt_start_encrypting_space(
|
|||||||
* crypt data in page 0 */
|
* crypt data in page 0 */
|
||||||
|
|
||||||
/* 1 - create crypt data */
|
/* 1 - create crypt data */
|
||||||
crypt_data = fil_space_create_crypt_data(FIL_DEFAULT_ENCRYPTION_KEY);
|
crypt_data = fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
|
||||||
if (crypt_data == NULL) {
|
if (crypt_data == NULL) {
|
||||||
mutex_exit(&fil_crypt_threads_mutex);
|
mutex_exit(&fil_crypt_threads_mutex);
|
||||||
return pending_op;
|
return pending_op;
|
||||||
|
@@ -3508,7 +3508,7 @@ fil_create_new_single_table_tablespace(
|
|||||||
}
|
}
|
||||||
|
|
||||||
success = fil_space_create(tablename, space_id, flags, FIL_TABLESPACE,
|
success = fil_space_create(tablename, space_id, flags, FIL_TABLESPACE,
|
||||||
fil_space_create_crypt_data(FIL_DEFAULT_ENCRYPTION_KEY));
|
fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY));
|
||||||
|
|
||||||
if (!success || !fil_node_create(path, size, space_id, FALSE)) {
|
if (!success || !fil_node_create(path, size, space_id, FALSE)) {
|
||||||
err = DB_ERROR;
|
err = DB_ERROR;
|
||||||
|
@@ -12231,12 +12231,12 @@ ha_innobase::create(
|
|||||||
/* If user has requested that table should be encrypted or table
|
/* If user has requested that table should be encrypted or table
|
||||||
should remain as unencrypted store crypt data */
|
should remain as unencrypted store crypt data */
|
||||||
if (encrypt != FIL_SPACE_ENCRYPTION_DEFAULT) {
|
if (encrypt != FIL_SPACE_ENCRYPTION_DEFAULT) {
|
||||||
ulint maxsize;
|
ulint maxsize=0;
|
||||||
ulint zip_size = fil_space_get_zip_size(innobase_table->space);
|
ulint zip_size = fil_space_get_zip_size(innobase_table->space);
|
||||||
fil_space_crypt_t* old_crypt_data = fil_space_get_crypt_data(innobase_table->space);
|
fil_space_crypt_t* old_crypt_data = fil_space_get_crypt_data(innobase_table->space);
|
||||||
fil_space_crypt_t* crypt_data;
|
fil_space_crypt_t* crypt_data;
|
||||||
|
|
||||||
crypt_data = fil_space_create_crypt_data(key_id);
|
crypt_data = fil_space_create_crypt_data(encrypt, key_id);
|
||||||
crypt_data->page0_offset = fsp_header_get_crypt_offset(zip_size, &maxsize);
|
crypt_data->page0_offset = fsp_header_get_crypt_offset(zip_size, &maxsize);
|
||||||
crypt_data->encryption = encrypt;
|
crypt_data->encryption = encrypt;
|
||||||
|
|
||||||
@@ -12246,7 +12246,29 @@ ha_innobase::create(
|
|||||||
crypt_data->iv_length = old_crypt_data->iv_length;
|
crypt_data->iv_length = old_crypt_data->iv_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mtr_t mtr;
|
||||||
|
mtr_start(&mtr);
|
||||||
|
/* Get page 0*/
|
||||||
|
ulint offset = 0;
|
||||||
|
buf_block_t* block = buf_page_get_gen(innobase_table->space,
|
||||||
|
zip_size,
|
||||||
|
offset,
|
||||||
|
RW_X_LATCH,
|
||||||
|
NULL,
|
||||||
|
BUF_GET,
|
||||||
|
__FILE__, __LINE__,
|
||||||
|
&mtr);
|
||||||
|
|
||||||
|
/* Set up new crypt data */
|
||||||
fil_space_set_crypt_data(innobase_table->space, crypt_data);
|
fil_space_set_crypt_data(innobase_table->space, crypt_data);
|
||||||
|
|
||||||
|
/* Compute location to store crypt data */
|
||||||
|
byte* frame = buf_block_get_frame(block);
|
||||||
|
|
||||||
|
/* Write crypt data to page 0 */
|
||||||
|
fil_space_write_crypt_data(innobase_table->space, frame, crypt_data->page0_offset, maxsize, &mtr);
|
||||||
|
|
||||||
|
mtr_commit(&mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
innobase_copy_frm_flags_from_create_info(innobase_table, create_info);
|
innobase_copy_frm_flags_from_create_info(innobase_table, create_info);
|
||||||
|
@@ -118,7 +118,10 @@ fil_space_crypt_cleanup();
|
|||||||
Create crypt data, i.e data that is used for a single tablespace */
|
Create crypt data, i.e data that is used for a single tablespace */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
fil_space_crypt_t *
|
fil_space_crypt_t *
|
||||||
fil_space_create_crypt_data(uint key_id);
|
fil_space_create_crypt_data(
|
||||||
|
/*========================*/
|
||||||
|
fil_encryption_t encrypt_mode, /*!< in: encryption mode */
|
||||||
|
uint key_id); /*!< in: encryption key id */
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Destroy crypt data */
|
Destroy crypt data */
|
||||||
|
@@ -105,4 +105,71 @@ fil_node_get_block_size(
|
|||||||
return (node->file_block_size);
|
return (node->file_block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
/****************************************************************//**
|
||||||
|
Validate page type.
|
||||||
|
@return true if valid, false if not */
|
||||||
|
UNIV_INLINE
|
||||||
|
bool
|
||||||
|
fil_page_type_validate(
|
||||||
|
const byte* page) /*!< in: page */
|
||||||
|
{
|
||||||
|
ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE);
|
||||||
|
#ifdef UNIV_ENCRYPTION_EXTRA_DEBUG
|
||||||
|
uint key_version = mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
|
||||||
|
bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED);
|
||||||
|
ulint space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
|
||||||
|
ulint offset = mach_read_from_4(page + FIL_PAGE_OFFSET);
|
||||||
|
ib_uint64_t lsn = mach_read_from_8(page + FIL_PAGE_LSN);
|
||||||
|
ulint compressed_len = mach_read_from_2(page + FIL_PAGE_DATA);
|
||||||
|
fil_system_enter();
|
||||||
|
fil_space_t* rspace = fil_space_get_by_id(space);
|
||||||
|
fil_system_exit();
|
||||||
|
|
||||||
|
|
||||||
|
/* Dump out the page info */
|
||||||
|
fprintf(stderr, "InnoDB: Space %lu offset %lu name %s page_type %lu page_type_name %s\n"
|
||||||
|
"InnoDB: key_version %u page_compressed %d lsn %lu compressed_len %lu\n",
|
||||||
|
space, offset, rspace->name, page_type, fil_get_page_type_name(page_type),
|
||||||
|
key_version, page_compressed, lsn, compressed_len);
|
||||||
|
fflush(stderr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Validate page type */
|
||||||
|
if (!((page_type == FIL_PAGE_PAGE_COMPRESSED ||
|
||||||
|
page_type == FIL_PAGE_INDEX ||
|
||||||
|
page_type == FIL_PAGE_UNDO_LOG ||
|
||||||
|
page_type == FIL_PAGE_INODE ||
|
||||||
|
page_type == FIL_PAGE_IBUF_FREE_LIST ||
|
||||||
|
page_type == FIL_PAGE_TYPE_ALLOCATED ||
|
||||||
|
page_type == FIL_PAGE_IBUF_BITMAP ||
|
||||||
|
page_type == FIL_PAGE_TYPE_SYS ||
|
||||||
|
page_type == FIL_PAGE_TYPE_TRX_SYS ||
|
||||||
|
page_type == FIL_PAGE_TYPE_FSP_HDR ||
|
||||||
|
page_type == FIL_PAGE_TYPE_XDES ||
|
||||||
|
page_type == FIL_PAGE_TYPE_BLOB ||
|
||||||
|
page_type == FIL_PAGE_TYPE_ZBLOB ||
|
||||||
|
page_type == FIL_PAGE_TYPE_COMPRESSED))) {
|
||||||
|
|
||||||
|
ut_ad(page_type == FIL_PAGE_PAGE_COMPRESSED ||
|
||||||
|
page_type == FIL_PAGE_INDEX ||
|
||||||
|
page_type == FIL_PAGE_UNDO_LOG ||
|
||||||
|
page_type == FIL_PAGE_INODE ||
|
||||||
|
page_type == FIL_PAGE_IBUF_FREE_LIST ||
|
||||||
|
page_type == FIL_PAGE_TYPE_ALLOCATED ||
|
||||||
|
page_type == FIL_PAGE_IBUF_BITMAP ||
|
||||||
|
page_type == FIL_PAGE_TYPE_SYS ||
|
||||||
|
page_type == FIL_PAGE_TYPE_TRX_SYS ||
|
||||||
|
page_type == FIL_PAGE_TYPE_FSP_HDR ||
|
||||||
|
page_type == FIL_PAGE_TYPE_XDES ||
|
||||||
|
page_type == FIL_PAGE_TYPE_BLOB ||
|
||||||
|
page_type == FIL_PAGE_TYPE_ZBLOB ||
|
||||||
|
page_type == FIL_PAGE_TYPE_COMPRESSED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
#endif /* fil0fil_ic */
|
#endif /* fil0fil_ic */
|
||||||
|
@@ -1154,7 +1154,7 @@ check_first_page:
|
|||||||
|
|
||||||
*sum_of_new_sizes += srv_data_file_sizes[i];
|
*sum_of_new_sizes += srv_data_file_sizes[i];
|
||||||
|
|
||||||
crypt_data = fil_space_create_crypt_data(FIL_DEFAULT_ENCRYPTION_KEY);
|
crypt_data = fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = os_file_close(files[i]);
|
ret = os_file_close(files[i]);
|
||||||
|
Reference in New Issue
Block a user