From c358e216d989a57f4188e766799fc83a4675c5d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 10 Jul 2023 11:14:54 +0300 Subject: [PATCH] MDEV-31642: Upgrade may crash if innodb_log_file_buffering=OFF recv_log_recover_10_5(): Make reads aligned by 4096 bytes, to avoid any trouble in case the file was opened in O_DIRECT mode and the physical block size is larger than 512 bytes. Because innodb_log_file_size used to be defined in whole megabytes, reading multiples of 4096 bytes instead of 512 should not be an issue. --- mysql-test/suite/innodb/t/log_corruption.test | 6 +++--- storage/innobase/log/log0recv.cc | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/innodb/t/log_corruption.test b/mysql-test/suite/innodb/t/log_corruption.test index 6f7080f5b50..b4466c5efde 100644 --- a/mysql-test/suite/innodb/t/log_corruption.test +++ b/mysql-test/suite/innodb/t/log_corruption.test @@ -591,11 +591,11 @@ print OUT pack("x[470]N", 0x677700cf); # invalid (all-zero) checkpoint page 1 and an empty log page print OUT chr(0) x 1024; # valid checkpoint block 2 -print OUT pack("x[12]NNNx[264]", 0x12860c, 0, 0x80c); +print OUT pack("x[12]NNNx[264]", 0x12860c, 0, 0x120c); # pointer to the FILE_CHECKPOINT record, and checkpoint page checksum -print OUT pack("H*x[204]NNN", "590DBAACFE922582", 0x128612, 0, 0x101741b); +print OUT pack("H*x[204]NNN", "590DBAACFE922582", 0x128612, 0, 0x3b4ce62d); # log page -print OUT pack("NnnNx[496]N", 0x80000944, 12, 12, 1, 0x46c8a2a2); +print OUT pack("x[2560]NnnNx[496]N", 0x80000944, 12, 12, 1, 0x46c8a2a2); close OUT or die; EOF diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 042e7981d73..8aba2981092 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1639,7 +1639,10 @@ static dberr_t recv_log_recover_10_5(lsn_t lsn_offset) if (lsn_offset < (log_sys.is_pmem() ? log_sys.file_size : 4096)) memcpy_aligned<512>(buf, &log_sys.buf[lsn_offset & ~511], 512); else - recv_sys.read(lsn_offset & ~lsn_t{511}, {buf, 512}); + { + recv_sys.read(lsn_offset & ~lsn_t{4095}, {buf, 4096}); + buf+= lsn_offset & 0xe00; + } if (!recv_check_log_block(buf)) { @@ -1757,7 +1760,7 @@ dberr_t recv_sys_t::find_checkpoint() if (dberr_t err= recv_log_recover_pre_10_2()) return err; upgrade: - memset_aligned<512>(const_cast(field_ref_zero), 0, 512); + memset_aligned<4096>(const_cast(field_ref_zero), 0, 4096); /* Mark the redo log for upgrading. */ log_sys.last_checkpoint_lsn= log_sys.next_checkpoint_lsn; log_sys.set_recovered_lsn(log_sys.next_checkpoint_lsn);