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 /extra/mariabackup | |
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 'extra/mariabackup')
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 27 |
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; } |