1
0
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:
Jan Lindström
2015-05-13 11:41:22 +03:00
parent be2038e3cb
commit f8cacd03a7
17 changed files with 335 additions and 36 deletions

View File

@@ -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;

View File

@@ -1 +1,3 @@
--innodb-encrypt-log --innodb-encrypt-log=ON
--innodb-encrypt-tables=ON

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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]);

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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]);