summaryrefslogtreecommitdiff
path: root/storage/innobase/buf/buf0flu.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/buf/buf0flu.cc')
-rw-r--r--storage/innobase/buf/buf0flu.cc190
1 files changed, 122 insertions, 68 deletions
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index d74b41b0e8e..c2a9cbcfa16 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -870,8 +870,9 @@ static void buf_tmp_reserve_compression_buf(buf_tmp_buffer_t* slot)
static byte* buf_tmp_page_encrypt(ulint offset, const byte* s, byte* d)
{
/* Calculate the start offset in a page */
- uint srclen= srv_page_size - (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION +
- FIL_PAGE_FCRC32_CHECKSUM);
+ uint srclen= static_cast<uint>(srv_page_size) -
+ (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION +
+ FIL_PAGE_FCRC32_CHECKSUM);
const byte* src= s + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
byte* dst= d + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
@@ -897,6 +898,10 @@ a page is written to disk.
(may be src_frame or an encrypted/compressed copy of it) */
static byte* buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s)
{
+ if (bpage->status == buf_page_t::FREED) {
+ return s;
+ }
+
ut_ad(space->id == bpage->id.space());
bpage->real_size = srv_page_size;
@@ -1022,6 +1027,57 @@ not_compressed:
return d;
}
+/** The following function deals with freed page during flushing.
+ i) Writing zeros to the file asynchronously if scrubbing is enabled
+ ii) Punch the hole to the file synchoronously if page_compressed is
+ enabled for the tablespace
+This function also resets the IO_FIX to IO_NONE and making the
+page status as NORMAL. It initiates the write to the file only after
+releasing the page from flush list and its associated mutex.
+@param[in,out] bpage freed buffer page
+@param[in] space tablespace object of the freed page */
+static void buf_flush_freed_page(buf_page_t *bpage, fil_space_t *space)
+{
+ ut_ad(buf_page_in_file(bpage));
+ const bool uncompressed= buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE;
+ BPageMutex *block_mutex= uncompressed
+ ? &reinterpret_cast<buf_block_t*>(bpage)->mutex
+ : &buf_pool->zip_mutex;
+
+ mutex_enter(&buf_pool->mutex);
+ mutex_enter(block_mutex);
+
+ buf_page_set_io_fix(bpage, BUF_IO_NONE);
+ bpage->status= buf_page_t::NORMAL;
+ buf_flush_write_complete(bpage, false);
+
+ if (uncompressed)
+ rw_lock_sx_unlock_gen(&reinterpret_cast<buf_block_t*>(bpage)->lock,
+ BUF_IO_WRITE);
+
+ buf_pool->stat.n_pages_written++;
+ mutex_exit(&buf_pool->mutex);
+ const page_id_t page_id(bpage->id);
+ const auto zip_size= bpage->zip_size();
+ mutex_exit(block_mutex);
+
+ const bool punch_hole=
+#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32)
+ space->is_compressed() ||
+#endif
+ false;
+
+ ut_ad(space->id == page_id.space());
+ ut_ad(space->zip_size() == zip_size);
+
+ if (punch_hole || srv_immediate_scrub_data_uncompressed)
+ fil_io(IORequestWrite, punch_hole, page_id, zip_size, 0,
+ zip_size ? zip_size : srv_page_size,
+ const_cast<byte*>(field_ref_zero), nullptr, false, punch_hole);
+
+ space->release_for_io();
+}
+
/********************************************************************//**
Does an asynchronous write of a buffer page. NOTE: when the
doublewrite buffer is used, we must call
@@ -1084,6 +1140,12 @@ buf_flush_write_block_low(
frame = ((buf_block_t*) bpage)->frame;
}
+ /* Skip the encryption and compression for the
+ freed page */
+ if (bpage->status == buf_page_t::FREED) {
+ break;
+ }
+
byte* page = reinterpret_cast<const buf_block_t*>(bpage)->frame;
if (full_crc32) {
@@ -1111,8 +1173,13 @@ buf_flush_write_block_low(
ut_ad(space->atomic_write_supported);
}
- const bool use_doublewrite = !bpage->init_on_flush
- && space->use_doublewrite();
+ if (bpage->status == buf_page_t::FREED) {
+ buf_flush_freed_page(bpage, space);
+ return;
+ }
+
+ const bool use_doublewrite = bpage->status != buf_page_t::INIT_ON_FLUSH
+ && space->use_doublewrite();
if (!use_doublewrite) {
ulint type = IORequest::WRITE;
@@ -1191,17 +1258,14 @@ bool buf_flush_page(buf_page_t* bpage, buf_flush_t flush_type, bool sync)
ut_ad(buf_flush_ready_for_flush(bpage, flush_type));
- bool is_uncompressed;
-
- is_uncompressed = (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
+ bool is_uncompressed = (buf_page_get_state(bpage)
+ == BUF_BLOCK_FILE_PAGE);
ut_ad(is_uncompressed == (block_mutex != &buf_pool->zip_mutex));
- ibool flush;
rw_lock_t* rw_lock;
bool no_fix_count = bpage->buf_fix_count == 0;
if (!is_uncompressed) {
- flush = TRUE;
rw_lock = NULL;
} else if (!(no_fix_count || flush_type == BUF_FLUSH_LIST)
|| (!no_fix_count
@@ -1211,61 +1275,55 @@ bool buf_flush_page(buf_page_t* bpage, buf_flush_t flush_type, bool sync)
/* For table residing in temporary tablespace sync is done
using IO_FIX and so before scheduling for flush ensure that
page is not fixed. */
- flush = FALSE;
+ return false;
} else {
rw_lock = &reinterpret_cast<buf_block_t*>(bpage)->lock;
- if (flush_type != BUF_FLUSH_LIST) {
- flush = rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE);
- } else {
- /* Will SX lock later */
- flush = TRUE;
+ if (flush_type != BUF_FLUSH_LIST
+ && !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) {
+ return false;
}
}
- if (flush) {
-
- /* We are committed to flushing by the time we get here */
+ /* We are committed to flushing by the time we get here */
- buf_page_set_io_fix(bpage, BUF_IO_WRITE);
+ buf_page_set_io_fix(bpage, BUF_IO_WRITE);
- buf_page_set_flush_type(bpage, flush_type);
+ buf_page_set_flush_type(bpage, flush_type);
- if (buf_pool->n_flush[flush_type] == 0) {
- os_event_reset(buf_pool->no_flush[flush_type]);
- }
-
- ++buf_pool->n_flush[flush_type];
- ut_ad(buf_pool->n_flush[flush_type] != 0);
+ if (buf_pool->n_flush[flush_type] == 0) {
+ os_event_reset(buf_pool->no_flush[flush_type]);
+ }
- mutex_exit(block_mutex);
+ ++buf_pool->n_flush[flush_type];
+ ut_ad(buf_pool->n_flush[flush_type] != 0);
- mutex_exit(&buf_pool->mutex);
+ mutex_exit(block_mutex);
- if (flush_type == BUF_FLUSH_LIST
- && is_uncompressed
- && !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) {
+ mutex_exit(&buf_pool->mutex);
- if (!fsp_is_system_temporary(bpage->id.space())) {
- /* avoiding deadlock possibility involves
- doublewrite buffer, should flush it, because
- it might hold the another block->lock. */
- buf_dblwr_flush_buffered_writes();
- } else {
- buf_dblwr_sync_datafiles();
- }
+ if (flush_type == BUF_FLUSH_LIST
+ && is_uncompressed
+ && !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) {
- rw_lock_sx_lock_gen(rw_lock, BUF_IO_WRITE);
+ if (!fsp_is_system_temporary(bpage->id.space())) {
+ /* avoiding deadlock possibility involves
+ doublewrite buffer, should flush it, because
+ it might hold the another block->lock. */
+ buf_dblwr_flush_buffered_writes();
+ } else {
+ buf_dblwr_sync_datafiles();
}
- /* Even though bpage is not protected by any mutex at this
- point, it is safe to access bpage, because it is io_fixed and
- oldest_modification != 0. Thus, it cannot be relocated in the
- buffer pool or removed from flush_list or LRU_list. */
-
- buf_flush_write_block_low(bpage, flush_type, sync);
+ rw_lock_sx_lock_gen(rw_lock, BUF_IO_WRITE);
}
- return(flush);
+ /* Even though bpage is not protected by any mutex at this
+ point, it is safe to access bpage, because it is io_fixed and
+ oldest_modification != 0. Thus, it cannot be relocated in the
+ buffer pool or removed from flush_list or LRU_list. */
+
+ buf_flush_write_block_low(bpage, flush_type, sync);
+ return true;
}
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
@@ -2183,9 +2241,9 @@ af_get_pct_for_dirty()
/* 1 + is there to avoid division by zero (in case the buffer
pool (including the flush_list) was emptied while we are
looking at it) */
- double dirty_pct = double(100 * dirty)
- / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
- + UT_LIST_GET_LEN(buf_pool->free));
+ double dirty_pct = 100 * static_cast<double>(dirty)
+ / static_cast<double>(1 + UT_LIST_GET_LEN(buf_pool->LRU)
+ + UT_LIST_GET_LEN(buf_pool->free));
ut_a(srv_max_dirty_pages_pct_lwm
<= srv_max_buf_pool_modified_pct);
@@ -2219,8 +2277,9 @@ af_get_pct_for_lsn(
{
lsn_t max_async_age;
lsn_t lsn_age_factor;
- lsn_t af_lwm = (lsn_t) ((srv_adaptive_flushing_lwm
- * log_get_capacity()) / 100);
+ lsn_t af_lwm = static_cast<lsn_t>(
+ srv_adaptive_flushing_lwm
+ * static_cast<double>(log_get_capacity()) / 100);
if (age < af_lwm) {
/* No adaptive flushing. */
@@ -2242,10 +2301,11 @@ af_get_pct_for_lsn(
lsn_age_factor = (age * 100) / max_async_age;
ut_ad(srv_max_io_capacity >= srv_io_capacity);
- return(static_cast<ulint>(
- ((srv_max_io_capacity / srv_io_capacity)
- * (lsn_age_factor * sqrt((double)lsn_age_factor)))
- / 7.5));
+ return static_cast<ulint>(
+ (static_cast<double>(srv_max_io_capacity / srv_io_capacity
+ * lsn_age_factor)
+ * sqrt(static_cast<double>(lsn_age_factor))
+ / 7.5));
}
/*********************************************************************//**
@@ -2273,14 +2333,7 @@ page_cleaner_flush_pages_recommendation(ulint last_pages_in)
ulint pct_for_lsn = 0;
ulint pct_total = 0;
- cur_lsn = log_get_lsn_nowait();
-
- /* log_get_lsn_nowait tries to get log_sys.mutex with
- mutex_enter_nowait, if this does not succeed function
- returns 0, do not use that value to update stats. */
- if (cur_lsn == 0) {
- return(0);
- }
+ cur_lsn = log_sys.get_lsn();
if (prev_lsn == 0) {
/* First time around. */
@@ -2301,7 +2354,7 @@ page_cleaner_flush_pages_recommendation(ulint last_pages_in)
/* We update our variables every srv_flushing_avg_loops
iterations to smooth out transition in workload. */
if (++n_iterations >= srv_flushing_avg_loops
- || time_elapsed >= srv_flushing_avg_loops) {
+ || time_elapsed >= static_cast<double>(srv_flushing_avg_loops)) {
if (time_elapsed < 1) {
time_elapsed = 1;
@@ -2310,7 +2363,7 @@ page_cleaner_flush_pages_recommendation(ulint last_pages_in)
avg_page_rate = static_cast<ulint>(
((static_cast<double>(sum_pages)
/ time_elapsed)
- + avg_page_rate) / 2);
+ + static_cast<double>(avg_page_rate)) / 2);
/* How much LSN we have generated since last call. */
lsn_rate = static_cast<lsn_t>(
@@ -2431,7 +2484,8 @@ page_cleaner_flush_pages_recommendation(ulint last_pages_in)
pages_for_lsn = std::min<ulint>(
pages_for_lsn, srv_max_io_capacity * 2);
- n_pages = (PCT_IO(pct_total) + avg_page_rate + pages_for_lsn) / 3;
+ n_pages = (ulint(double(srv_io_capacity) * double(pct_total) / 100.0)
+ + avg_page_rate + pages_for_lsn) / 3;
if (n_pages > srv_max_io_capacity) {
n_pages = srv_max_io_capacity;
@@ -2939,7 +2993,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*)
} else if (ret_sleep == OS_SYNC_TIME_EXCEEDED) {
/* no activity, slept enough */
- buf_flush_lists(PCT_IO(100), LSN_MAX, &n_flushed);
+ buf_flush_lists(srv_io_capacity, LSN_MAX, &n_flushed);
n_flushed_last += n_flushed;