diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-09-11 16:47:23 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-09-12 11:32:49 +0300 |
commit | 66a09bd6aba0f7b74492d198146bb8d47cdd9dbb (patch) | |
tree | e657de3adc503b0f1d2b920b4652e1ceb906e6ae /storage/innobase/log/log0crypt.cc | |
parent | 8ee4b414ae071b1c666b97bac1808bc67a260e78 (diff) | |
download | mariadb-git-66a09bd6aba0f7b74492d198146bb8d47cdd9dbb.tar.gz |
MDEV-13318 Crash recovery failure after the server is killed during innodb_encrypt_log startup
This fixes several InnoDB bugs related to innodb_encrypt_log and
two Mariabackup --backup bugs.
log_crypt(): Properly derive the initialization vector from the
start LSN of each block. Add a debug assertion.
log_crypt_init(): Note that the function should only be used when
creating redo log files and that the information is persisted in
the checkpoint pages.
xtrabackup_copy_log(): Validate data_len.
xtrabackup_backup_func(): Always use the chosen checkpoint buffer.
log_group_write_buf(), log_write_up_to(): Only log_crypt() the redo
log payload, not the padding bytes.
innobase_start_or_create_for_mysql(): Do not invoke log_crypt_init()
or initiate a redo log checkpoint.
recv_find_max_checkpoint(): Return the contents of LOG_CHECKPOINT_NO
to xtrabackup_backup_func() in log_sys->next_checkpoint_no.
Diffstat (limited to 'storage/innobase/log/log0crypt.cc')
-rw-r--r-- | storage/innobase/log/log0crypt.cc | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc index 69cfec10fed..c0a10c74073 100644 --- a/storage/innobase/log/log0crypt.cc +++ b/storage/innobase/log/log0crypt.cc @@ -103,11 +103,12 @@ get_crypt_info(ulint checkpoint_no) /** Encrypt or decrypt log blocks. @param[in,out] buf log blocks to encrypt or decrypt +@param[in] lsn log sequence number of the start of the buffer @param[in] size size of the buffer, in bytes @param[in] decrypt whether to decrypt instead of encrypting */ UNIV_INTERN void -log_crypt(byte* buf, ulint size, bool decrypt) +log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt) { ut_ad(size % OS_FILE_LOG_BLOCK_SIZE == 0); ut_a(info.key_version); @@ -117,12 +118,12 @@ log_crypt(byte* buf, ulint size, bool decrypt) compile_time_assert(sizeof(uint32_t) == 4); #define LOG_CRYPT_HDR_SIZE 4 + lsn &= ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1); for (const byte* const end = buf + size; buf != end; - buf += OS_FILE_LOG_BLOCK_SIZE) { + buf += OS_FILE_LOG_BLOCK_SIZE, lsn += OS_FILE_LOG_BLOCK_SIZE) { uint32_t dst[(OS_FILE_LOG_BLOCK_SIZE - LOG_CRYPT_HDR_SIZE) / sizeof(uint32_t)]; - const ulint log_block_no = log_block_get_hdr_no(buf); /* The log block number is not encrypted. */ *aes_ctr_iv = @@ -137,10 +138,10 @@ log_crypt(byte* buf, ulint size, bool decrypt) # error "LOG_BLOCK_HDR_NO has been moved; redo log format affected!" #endif aes_ctr_iv[1] = info.crypt_nonce.word; - mach_write_to_8(reinterpret_cast<byte*>(aes_ctr_iv + 2), - log_block_get_start_lsn( - decrypt ? srv_start_lsn : log_sys->lsn, - log_block_no)); + mach_write_to_8(reinterpret_cast<byte*>(aes_ctr_iv + 2), lsn); + ut_ad(log_block_get_start_lsn(lsn, + log_block_get_hdr_no(buf)) + == lsn); int rc = encryption_crypt( buf + LOG_CRYPT_HDR_SIZE, sizeof dst, @@ -206,7 +207,11 @@ init_crypt_key(crypt_info_t* info, bool upgrade = false) return true; } -/** Initialize the redo log encryption key. +/** Initialize the redo log encryption key and random parameters +when creating a new redo log. +The random parameters will be persisted in the log checkpoint pages. +@see log_crypt_write_checkpoint_buf() +@see log_crypt_read_checkpoint_buf() @return whether the operation succeeded */ UNIV_INTERN bool |