summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2020-03-05 02:03:06 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2020-03-05 02:03:06 +0530
commit7061dc6a8a4c157f6dd183a2b9c2cf94438f369c (patch)
tree950781325b678d2c8d11fcbc469df38bd6ae52dc
parent6396b0e683640ad97f0f9e0c0a5c635bee67c0f1 (diff)
downloadmariadb-git-7061dc6a8a4c157f6dd183a2b9c2cf94438f369c.tar.gz
MDEV-15528 Punch holes when pages are freed
- Flush handler does synchorous punch hole on freed page offset of page_compressed tablespace.
-rw-r--r--storage/innobase/buf/buf0flu.cc59
-rw-r--r--storage/innobase/fil/fil0fil.cc26
-rw-r--r--storage/innobase/include/fil0fil.h4
3 files changed, 68 insertions, 21 deletions
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 07e60eee5d1..11f3fb758d4 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -1026,19 +1026,19 @@ not_compressed:
Does an asynchronous write of a buffer page. NOTE: when the
doublewrite buffer is used, we must call
buf_dblwr_flush_buffered_writes after we have posted a batch of
-writes! */
+writes!
+@param[in] bpage buffer block to write
+@param[in] flush_type type of flush
+@param[in] sync true if sync IO request
+@param[in] space page of the tablespace to be flushed */
static
void
buf_flush_write_block_low(
-/*======================*/
- buf_page_t* bpage, /*!< in: buffer block to write */
- buf_flush_t flush_type, /*!< in: type of flush */
- bool sync) /*!< in: true if sync IO request */
+ buf_page_t* bpage,
+ buf_flush_t flush_type,
+ bool sync,
+ fil_space_t* space)
{
- fil_space_t* space = fil_space_acquire_for_io(bpage->id.space());
- if (!space) {
- return;
- }
ut_ad(space->purpose == FIL_TYPE_TEMPORARY
|| space->purpose == FIL_TYPE_IMPORT
|| space->purpose == FIL_TYPE_TABLESPACE);
@@ -1168,13 +1168,29 @@ buf_flush_write_block_low(
ut_ad(err == DB_SUCCESS);
}
- space->release_for_io();
-
/* Increment the counter of I/O operations used
for selecting LRU policy. */
buf_LRU_stat_inc_io();
}
+/** Punch hole the file for particular page in page compressed tablespace
+@param[in] bpage buffer control block */
+static void buf_flush_do_punch_hole(buf_page_t* bpage)
+{
+ /* Release all the mutex before punch hole the file */
+ buf_flush_remove(bpage);
+
+ BPageMutex* block_mutex = buf_page_get_mutex(bpage);
+ mutex_exit(block_mutex);
+ mutex_exit(&buf_pool->mutex);
+
+ ulint type = IORequest::WRITE;
+ IORequest request(type, bpage);
+ fil_io(request, true, bpage->id, bpage->zip_size(), 0,
+ bpage->physical_size(), NULL, bpage,
+ false, /* Punch hole */true);
+}
+
/** Write a flushable page asynchronously from the buffer pool to a file.
NOTE: 1. in simulated aio we must call os_aio_simulated_wake_handler_threads
after we have posted a batch of writes! 2. buf_page_get_mutex(bpage) must be
@@ -1198,18 +1214,34 @@ bool buf_flush_page(buf_page_t* bpage, buf_flush_t flush_type, bool sync)
ut_ad(mutex_own(block_mutex));
ut_ad(buf_flush_ready_for_flush(bpage, flush_type));
+ fil_space_t* space = fil_space_acquire_for_io(bpage->id.space());
/* Ignore the flushing of temporary tablespace pages while
shutting down */
if (!srv_undo_sources
&& fsp_is_system_temporary(bpage->id.space())) {
remove_flush:
+ if (space) {
+ space->release_for_io();
+ }
+
buf_flush_remove(bpage);
return false;
}
+ if (!space) {
+ goto remove_flush;
+ }
+
/* Ignore the flushing of freed page */
if (bpage->status == FREED) {
+#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32)
+ if (space->is_compressed()) {
+ buf_flush_do_punch_hole(bpage);
+ space->release_for_io();
+ return true;
+ }
+#endif
if (!srv_immediate_scrub_data_uncompressed) {
goto remove_flush;
}
@@ -1233,11 +1265,13 @@ remove_flush:
/* For table residing in temporary tablespace sync is done
using IO_FIX and so before scheduling for flush ensure that
page is not fixed. */
+ space->release_for_io();
return false;
} else {
rw_lock = &reinterpret_cast<buf_block_t*>(bpage)->lock;
if (flush_type != BUF_FLUSH_LIST
&& !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) {
+ space->release_for_io();
return false;
}
}
@@ -1280,7 +1314,8 @@ remove_flush:
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);
+ buf_flush_write_block_low(bpage, flush_type, sync, space);
+ space->release_for_io();
return true;
}
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 8a679f51b76..923a8091e13 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -3930,6 +3930,7 @@ inline void IORequest::set_fil_node(fil_node_t* node)
@param[in] message message for aio handler if non-sync aio
used, else ignored
@param[in] ignore whether to ignore out-of-bounds page_id
+@param[in] punch_hole punch hole the freed page
@return DB_SUCCESS, or DB_TABLESPACE_DELETED
if we are trying to do i/o on a tablespace which does not exist */
dberr_t
@@ -3942,7 +3943,8 @@ fil_io(
ulint len,
void* buf,
void* message,
- bool ignore)
+ bool ignore,
+ bool punch_hole)
{
os_offset_t offset;
IORequest req_type(type);
@@ -4121,13 +4123,21 @@ fil_io(
|| !fil_is_user_tablespace_id(page_id.space())
|| offset == page_id.page_no() * zip_size);
- /* Queue the aio request */
- dberr_t err = os_aio(
- req_type,
- mode, name, node->handle, buf, offset, len,
- space->purpose != FIL_TYPE_TEMPORARY
- && srv_read_only_mode,
- node, message);
+ dberr_t err = DB_SUCCESS;
+
+ if (punch_hole) {
+ /* Already file system supports punch hole. So
+ need to do the check again.*/
+ err = os_file_punch_hole(node->handle, offset, len);
+ } else {
+ /* Queue the aio request */
+ err = os_aio(
+ req_type,
+ mode, name, node->handle, buf, offset, len,
+ space->purpose != FIL_TYPE_TEMPORARY
+ && srv_read_only_mode,
+ node, message);
+ }
/* We an try to recover the page from the double write buffer if
the decompression fails or the page is corrupt. */
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index b57ad5cc1f5..9e5003ea3cf 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1384,6 +1384,7 @@ fil_space_extend(
@param[in] message message for aio handler if non-sync aio
used, else ignored
@param[in] ignore whether to ignore out-of-bounds page_id
+@param[in] punch_hole Punch hole the freed page
@return DB_SUCCESS, or DB_TABLESPACE_DELETED
if we are trying to do i/o on a tablespace which does not exist */
dberr_t
@@ -1396,7 +1397,8 @@ fil_io(
ulint len,
void* buf,
void* message,
- bool ignore = false);
+ bool ignore = false,
+ bool punch_hole = false);
/**********************************************************************//**
Waits for an aio operation to complete. This function is used to write the