Skip to content
/ server Public
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion extra/mariabackup/xtrabackup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2698,9 +2698,14 @@ static bool innodb_init()
}

ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT);
mysql_mutex_lock(&recv_sys.mutex);
ut_ad(recv_no_log_write);
buf_flush_sync();
if (recv_sys.recovery_on)
recv_sys.apply(true);
mysql_mutex_unlock(&recv_sys.mutex);
recv_sys.debug_free();

buf_flush_sync_batch(LSN_MAX);
ut_ad(!os_aio_pending_reads());
ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
ut_ad(!buf_pool.get_oldest_modification(0));
Expand Down
47 changes: 9 additions & 38 deletions storage/innobase/buf/buf0buf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3118,7 +3118,7 @@ buf_page_get_low(
return(NULL);
}

buf_flush_sync();
buf_flush_sync_batch(LSN_MAX);

state = block->page.state();

Expand Down Expand Up @@ -4090,15 +4090,15 @@ ATTRIBUTE_COLD void buf_pool_t::clear_hash_index() noexcept
@retval nullptr if all freed */
void buf_pool_t::assert_all_freed() noexcept
{
mysql_mutex_lock(&mutex);
mysql_mutex_assert_owner(&mutex);

for (char *extent= memory,
*end= memory + block_descriptors_in_bytes(n_blocks);
extent < end; extent+= innodb_buffer_pool_extent_size)
for (buf_block_t *block= reinterpret_cast<buf_block_t*>(extent),
*extent_end= block +
pages_in_extent[srv_page_size_shift - UNIV_PAGE_SIZE_SHIFT_MIN];
block < extent_end && reinterpret_cast<char*>(block) < end; block++)
for (char *extent= memory,
*end= memory + block_descriptors_in_bytes(n_blocks);
extent < end; extent+= innodb_buffer_pool_extent_size)
for (buf_block_t *block= reinterpret_cast<buf_block_t*>(extent),
*extent_end= block +
pages_in_extent[srv_page_size_shift - UNIV_PAGE_SIZE_SHIFT_MIN];
block < extent_end && reinterpret_cast<char*>(block) < end; block++)
{
if (!block->page.in_file())
continue;
Expand Down Expand Up @@ -4128,8 +4128,6 @@ void buf_pool_t::assert_all_freed() noexcept
fixed_or_dirty:
ib::fatal() << "Page " << block->page.id() << " still fixed or dirty";
}

mysql_mutex_unlock(&mutex);
}
#endif /* UNIV_DEBUG */

Expand All @@ -4140,33 +4138,6 @@ void buf_refresh_io_stats() noexcept
buf_pool.old_stat = buf_pool.stat;
}

/** Invalidate all pages in the buffer pool.
All pages must be in a replaceable state (not modified or latched). */
void buf_pool_invalidate() noexcept
{
/* It is possible that a write batch that has been posted
earlier is still not complete. For buffer pool invalidation to
proceed we must ensure there is NO write activity happening. */

os_aio_wait_until_no_pending_writes(false);
ut_d(buf_pool.assert_all_freed());
mysql_mutex_lock(&buf_pool.mutex);

while (UT_LIST_GET_LEN(buf_pool.LRU)) {
buf_LRU_scan_and_free_block();
}

ut_ad(UT_LIST_GET_LEN(buf_pool.unzip_LRU) == 0);

buf_pool.freed_page_clock = 0;
buf_pool.LRU_old = NULL;
buf_pool.LRU_old_len = 0;
buf_pool.stat.init();

buf_refresh_io_stats();
mysql_mutex_unlock(&buf_pool.mutex);
}

#ifdef UNIV_DEBUG
/** Validate the buffer pool. */
void buf_pool_t::validate() noexcept
Expand Down
11 changes: 6 additions & 5 deletions storage/innobase/buf/buf0dblwr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,15 @@ bool buf_dblwr_t::create() noexcept
ut_ad(init_mtr.get_savepoint() == 1);
ut_ad(init_mtr.m_memo[0].object == new_block);
ut_ad(init_mtr.m_memo[0].type == MTR_MEMO_PAGE_X_MODIFY);
new_block->page.fix();
init_mtr.m_memo[0].type= MTR_MEMO_PAGE_X_FIX;
init_mtr.rollback_to_savepoint(0, 1);
init_mtr.m_log.erase();
mysql_mutex_lock(&buf_pool.mutex);
new_block->page.unfix();
ut_d(bool freed=) buf_LRU_free_page(&new_block->page, true);
ut_ad(freed);
mysql_mutex_unlock(&buf_pool.mutex);

if (i == size / 2)
ut_a(id.page_no() == size);
Expand All @@ -202,11 +208,6 @@ bool buf_dblwr_t::create() noexcept
TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N);
mtr.commit();

buf_flush_wait_flushed(mtr.commit_lsn());

/* Remove doublewrite pages from LRU */
buf_pool_invalidate();

sql_print_information("InnoDB: Doublewrite buffer created");
goto start_again;
}
Expand Down
48 changes: 2 additions & 46 deletions storage/innobase/buf/buf0flu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2057,8 +2057,7 @@ log file. Use log_make_checkpoint() to flush also the pool.
@retval false if a checkpoint write was already running */
static bool log_checkpoint() noexcept
{
if (recv_recovery_is_on())
recv_sys.apply(true);
ut_ad(!recv_recovery_is_on());

#if defined HAVE_valgrind && !__has_feature(memory_sanitizer)
/* The built-in scheduler in Valgrind may neglect some threads for a
Expand Down Expand Up @@ -2130,9 +2129,6 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn) noexcept
ut_ad(sync_lsn < LSN_MAX);
ut_ad(!srv_read_only_mode);

if (recv_recovery_is_on())
recv_sys.apply(true);

mysql_mutex_lock(&buf_pool.flush_list_mutex);

if (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn)
Expand Down Expand Up @@ -2189,9 +2185,6 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious) noexcept
{
ut_ad(!srv_read_only_mode);

if (recv_recovery_is_on())
recv_sys.apply(true);

DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", return;);

Atomic_relaxed<lsn_t> &limit= furious
Expand Down Expand Up @@ -2861,51 +2854,14 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool() noexcept

/** Synchronously flush dirty blocks during recv_sys_t::apply().
NOTE: The calling thread is not allowed to hold any buffer page latches! */
void buf_flush_sync_batch(lsn_t lsn) noexcept
ATTRIBUTE_COLD void buf_flush_sync_batch(lsn_t lsn) noexcept
{
lsn= std::max(lsn, log_get_lsn());
mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_flush_wait(lsn);
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
}

/** Synchronously flush dirty blocks.
NOTE: The calling thread is not allowed to hold any buffer page latches! */
void buf_flush_sync() noexcept
{
if (recv_recovery_is_on())
{
mysql_mutex_lock(&recv_sys.mutex);
recv_sys.apply(true);
mysql_mutex_unlock(&recv_sys.mutex);
}

thd_wait_begin(nullptr, THD_WAIT_DISKIO);
tpool::tpool_wait_begin();
log_sys.latch.wr_lock(SRW_LOCK_CALL);

for (lsn_t lsn= log_sys.get_lsn();;)
{
log_sys.latch.wr_unlock();
mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_flush_wait(lsn);
/* Wait for the page cleaner to be idle (for log resizing at startup) */
while (buf_flush_sync_lsn)
my_cond_wait(&buf_pool.done_flush_list,
&buf_pool.flush_list_mutex.m_mutex);
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
log_sys.latch.wr_lock(SRW_LOCK_CALL);
lsn_t new_lsn= log_sys.get_lsn();
if (lsn == new_lsn)
break;
lsn= new_lsn;
}

log_sys.latch.wr_unlock();
tpool::tpool_wait_end();
thd_wait_end(nullptr);
}

ATTRIBUTE_COLD void buf_pool_t::print_flush_info() const noexcept
{
/* We do dirty read of UT_LIST count variable. */
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18440,7 +18440,7 @@ buf_flush_list_now_set(THD*, st_mysql_sys_var*, void*, const void* save)
os_aio_wait_until_no_pending_writes(true);
}
else
buf_flush_sync();
buf_flush_sync_batch(LSN_MAX);
mysql_mutex_lock(&LOCK_global_system_variables);
}

Expand Down
4 changes: 0 additions & 4 deletions storage/innobase/include/buf0buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -400,10 +400,6 @@ buf_print_io(
/** Refresh the statistics used to print per-second averages. */
void buf_refresh_io_stats() noexcept;

/** Invalidate all pages in the buffer pool.
All pages must be in a replaceable state (not modified or latched). */
void buf_pool_invalidate() noexcept;

/*========================================================================
--------------------------- LOWER LEVEL ROUTINES -------------------------
=========================================================================*/
Expand Down
6 changes: 1 addition & 5 deletions storage/innobase/include/buf0flu.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,4 @@ void buf_flush_validate() noexcept;

/** Synchronously flush dirty blocks during recv_sys_t::apply().
NOTE: The calling thread is not allowed to hold any buffer page latches! */
void buf_flush_sync_batch(lsn_t lsn) noexcept;

/** Synchronously flush dirty blocks.
NOTE: The calling thread is not allowed to hold any buffer page latches! */
void buf_flush_sync() noexcept;
ATTRIBUTE_COLD void buf_flush_sync_batch(lsn_t lsn) noexcept;
5 changes: 4 additions & 1 deletion storage/innobase/include/log0recv.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,10 @@ struct recv_sys_t

/** whether we are applying redo log records during crash recovery.
This can be cleared when holding mutex, or when pages.empty() and
we are holding exclusive log_sys.latch. */
we are holding exclusive log_sys.latch. When this is set,
buf_flush_page_cleaner() will not invoke log_checkpoint_low(),
buf_pool.flush_list may be unsorted by buf_page_t::oldest_modification(),
and garbage_collect() replaces buf_pool_t::running_out(). */
Atomic_relaxed<bool> recovery_on= false;
/** whether recv_recover_page(), invoked from buf_page_t::read_complete(),
should apply log records*/
Expand Down
2 changes: 2 additions & 0 deletions storage/innobase/log/log0log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1506,7 +1506,9 @@ ATTRIBUTE_COLD void logs_empty_and_mark_files_at_shutdown() noexcept

service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
"Free innodb buffer pool");
ut_d(mysql_mutex_lock(&buf_pool.mutex));
ut_d(buf_pool.assert_all_freed());
ut_d(mysql_mutex_unlock(&buf_pool.mutex));

ut_a(lsn == log_get_lsn()
|| srv_force_recovery == SRV_FORCE_NO_LOG_REDO);
Expand Down
24 changes: 24 additions & 0 deletions storage/innobase/log/log0recv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4091,6 +4091,30 @@ static void log_sort_flush_list() noexcept
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
}

/** Invalidate all pages in the buffer pool.
All pages must be replaceable (not modified, latched, or io-fixed). */
ATTRIBUTE_COLD static void buf_pool_invalidate() noexcept
{
mysql_mutex_lock(&buf_pool.mutex);
ut_ad(!os_aio_pending_reads());
/* os_aio_pending_writes() may hold here if some write_io_callback()
did not release the slot yet. However, buf_flush_sync_batch() waited
for the page write itself to complete, which we will check below. */
ut_d(buf_pool.assert_all_freed());

while (UT_LIST_GET_LEN(buf_pool.LRU))
buf_LRU_scan_and_free_block();

ut_ad(UT_LIST_GET_LEN(buf_pool.unzip_LRU) == 0);

buf_pool.freed_page_clock= 0;
buf_pool.LRU_old= nullptr;
buf_pool.LRU_old_len= 0;
buf_pool.stat.init();
buf_refresh_io_stats();
mysql_mutex_unlock(&buf_pool.mutex);
}

/** Apply buffered log to persistent data pages.
@param last_batch whether it is possible to write more redo log */
void recv_sys_t::apply(bool last_batch)
Expand Down
Loading