summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-03-11 11:10:09 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2022-03-11 11:10:09 +0200
commitb95942a2a7b0127e0fc466876974bf48e2c53ed3 (patch)
tree2ae57e20f504161d1bc9189cd8ba5a349a66c2f0
parent99e74478c826bd667ae80192af3c189538750ee0 (diff)
downloadmariadb-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.cc18
-rw-r--r--storage/innobase/include/log0log.h2
-rw-r--r--storage/innobase/log/log0log.cc11
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());