diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-03-11 11:10:09 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-03-11 11:10:09 +0200 |
commit | b95942a2a7b0127e0fc466876974bf48e2c53ed3 (patch) | |
tree | 2ae57e20f504161d1bc9189cd8ba5a349a66c2f0 | |
parent | 99e74478c826bd667ae80192af3c189538750ee0 (diff) | |
download | mariadb-git-b95942a2a7b0127e0fc466876974bf48e2c53ed3.tar.gz |
MDEV-27812: Fix a race condition, and pacify MemorySanitizer
log_t::write_checkpoint(): Avoid a race condition with resize_abort()
by loading log_sys.resize_lsn only while holding the locks.
Also, remove an unnecessary write of all outstanding log before
switching log files.
log_t::write_buf(): Mark the entire block in the resize buffer
as initialized, to allow the test innodb.log_file_size_online to pass
when not using the mmap() based interface.
-rw-r--r-- | storage/innobase/buf/buf0flu.cc | 18 | ||||
-rw-r--r-- | storage/innobase/include/log0log.h | 2 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 11 |
3 files changed, 14 insertions, 17 deletions
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 04822c3cc00..090757ef7ce 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1718,11 +1718,13 @@ inline void log_t::write_checkpoint(lsn_t end_lsn) noexcept mach_write_to_8(my_assume_aligned<8>(c + 8), end_lsn); mach_write_to_4(my_assume_aligned<4>(c + 60), my_crc32c(0, c, 60)); - lsn_t resizing= resize_lsn.load(std::memory_order_relaxed); + lsn_t resizing; #ifdef HAVE_PMEM if (is_pmem()) { + resizing= resize_lsn.load(std::memory_order_relaxed); + if (resizing > 1 && resizing <= next_checkpoint_lsn) { memcpy_aligned<64>(resize_buf + CHECKPOINT_1, c, 64); @@ -1737,6 +1739,7 @@ inline void log_t::write_checkpoint(lsn_t end_lsn) noexcept n_pending_checkpoint_writes++; latch.wr_unlock(); log_write_and_flush_prepare(); + resizing= resize_lsn.load(std::memory_order_relaxed); /* FIXME: issue an asynchronous write */ log.write(offset, {c, get_block_size()}); if (resizing > 1 && resizing <= next_checkpoint_lsn) @@ -1747,16 +1750,11 @@ inline void log_t::write_checkpoint(lsn_t end_lsn) noexcept resize_log.write(0, {buf, 4096}); aligned_free(buf); resize_log.write(CHECKPOINT_1, {c, get_block_size()}); - latch.wr_lock(SRW_LOCK_CALL); - /* FIXME: write and flush outside exclusive latch */ - ut_a(flush(write_buf<false>())); - } - else - { - if (srv_file_flush_method != SRV_O_DSYNC) - ut_a(log.flush()); - latch.wr_lock(SRW_LOCK_CALL); } + + if (srv_file_flush_method != SRV_O_DSYNC) + ut_a(log.flush()); + latch.wr_lock(SRW_LOCK_CALL); n_pending_checkpoint_writes--; resizing= resize_lsn.load(std::memory_order_relaxed); } diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 57ecc8ed3f5..7e20fc12cda 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -486,7 +486,7 @@ public: /** Write buf to ib_logfile0. @tparam release_latch whether to invoke latch.wr_unlock() @return the current log sequence number */ - template<bool release_latch> lsn_t write_buf() noexcept; + template<bool release_latch> inline lsn_t write_buf() noexcept; /** Create the log. */ void create(lsn_t lsn) noexcept; diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index dad5d695964..83b78ebf385 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -733,7 +733,7 @@ ATTRIBUTE_COLD void log_t::resize_write_buf(size_t length) noexcept /** Write buf to ib_logfile0. @tparam release_latch whether to invoke latch.wr_unlock() @return the current log sequence number */ -template<bool release_latch> lsn_t log_t::write_buf() noexcept +template<bool release_latch> inline lsn_t log_t::write_buf() noexcept { #ifndef SUX_LOCK_GENERIC ut_ad(latch.is_write_locked()); @@ -777,16 +777,17 @@ template<bool release_latch> lsn_t log_t::write_buf() noexcept (We want to avoid memset() while holding mutex.) This block will be overwritten later, once records beyond the current LSN are generated. */ +# ifdef HAVE_valgrind MEM_MAKE_DEFINED(buf + length, get_block_size() - new_buf_free); + if (UNIV_LIKELY_NULL(resize_flush_buf)) + MEM_MAKE_DEFINED(resize_buf + length, get_block_size() - new_buf_free); +# endif buf[length]= 0; /* allow recovery to catch EOF faster */ length&= ~block_size_1; memcpy_aligned<16>(flush_buf, buf + length, (new_buf_free + 15) & ~15); if (UNIV_LIKELY_NULL(resize_flush_buf)) - { - MEM_MAKE_DEFINED(resize_buf + length, get_block_size() - new_buf_free); memcpy_aligned<16>(resize_flush_buf, resize_buf + length, (new_buf_free + 15) & ~15); - } length+= get_block_size(); #endif } @@ -813,8 +814,6 @@ template<bool release_latch> lsn_t log_t::write_buf() noexcept return lsn; } -template lsn_t log_t::write_buf<false>() noexcept; - bool log_t::flush(lsn_t lsn) noexcept { ut_ad(lsn >= get_flushed_lsn()); |