diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2020-03-05 02:03:06 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2020-03-05 02:03:06 +0530 |
commit | 7061dc6a8a4c157f6dd183a2b9c2cf94438f369c (patch) | |
tree | 950781325b678d2c8d11fcbc469df38bd6ae52dc | |
parent | 6396b0e683640ad97f0f9e0c0a5c635bee67c0f1 (diff) | |
download | mariadb-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.cc | 59 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 26 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 4 |
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 |