summaryrefslogtreecommitdiff
path: root/extra/mariabackup
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-09-11 16:47:23 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2017-09-12 11:32:49 +0300
commit66a09bd6aba0f7b74492d198146bb8d47cdd9dbb (patch)
treee657de3adc503b0f1d2b920b4652e1ceb906e6ae /extra/mariabackup
parent8ee4b414ae071b1c666b97bac1808bc67a260e78 (diff)
downloadmariadb-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 'extra/mariabackup')
-rw-r--r--extra/mariabackup/xtrabackup.cc27
1 files changed, 17 insertions, 10 deletions
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 5d8bc7eaaf3..0027de960c1 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -2359,10 +2359,18 @@ xtrabackup_copy_log(copy_logfile copy, lsn_t start_lsn, lsn_t end_lsn)
scanned_checkpoint = checkpoint;
ulint data_len = log_block_get_data_len(log_block);
- scanned_lsn += data_len;
- if (data_len != OS_FILE_LOG_BLOCK_SIZE) {
- /* The current end of the log was reached. */
+ if (data_len == OS_FILE_LOG_BLOCK_SIZE) {
+ /* We got a full log block. */
+ scanned_lsn += data_len;
+ } else if (data_len
+ >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE
+ || data_len <= LOG_BLOCK_HDR_SIZE) {
+ /* We got a garbage block (abrupt end of the log). */
+ break;
+ } else {
+ /* We got a partial block (abrupt end of the log). */
+ scanned_lsn += data_len;
break;
}
}
@@ -2375,7 +2383,7 @@ xtrabackup_copy_log(copy_logfile copy, lsn_t start_lsn, lsn_t end_lsn)
if (ulint write_size = ulint(end_lsn - start_lsn)) {
if (srv_encrypt_log) {
- log_crypt(log_sys->buf, write_size);
+ log_crypt(log_sys->buf, start_lsn, write_size);
}
if (ds_write(dst_log_file, log_sys->buf, write_size)) {
@@ -3757,10 +3765,10 @@ old_format:
const byte* buf = log_sys->checkpoint_buf;
- checkpoint_lsn_start = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
- checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
-
reread_log_header:
+ checkpoint_lsn_start = log_sys->log.lsn;
+ checkpoint_no_start = log_sys->next_checkpoint_no;
+
err = recv_find_max_checkpoint(&max_cp_field);
if (err != DB_SUCCESS) {
@@ -3774,10 +3782,9 @@ reread_log_header:
ut_ad(!((log_sys->log.format ^ LOG_HEADER_FORMAT_CURRENT)
& ~LOG_HEADER_FORMAT_ENCRYPTED));
- if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) {
+ log_group_header_read(&log_sys->log, max_cp_field);
- checkpoint_lsn_start = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
- checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
+ if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) {
goto reread_log_header;
}