From 8678a1052d5d4c2f2c7ac7f9ae4dff0c3030824b Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 7 Mar 2019 11:33:42 +1100 Subject: [PATCH 1/2] MDEV-18946: innodb: buffer_pool - unallocate large pages requires size MDEV-10814 introduce a bug where the size argument to deallocate_large was passed true, evaluating to 1, as the size. When this is passed to munmap this resulted in EINVAL and the page not being released. This only occured the buf_pool_free_instance when called on shutdown so no impact as the process termination correctly frees the memory. --- storage/innobase/buf/buf0buf.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 0960a3e84ce..6ff0bd1de0c 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2015,7 +2015,7 @@ buf_pool_free_instance( } buf_pool->allocator.deallocate_large( - chunk->mem, &chunk->mem_pfx, true); + chunk->mem, &chunk->mem_pfx, chunk->mem_size(), true); } for (ulint i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; ++i) { @@ -2893,7 +2893,7 @@ withdraw_retry: } buf_pool->allocator.deallocate_large( - chunk->mem, &chunk->mem_pfx, true); + chunk->mem, &chunk->mem_pfx, chunk->mem_size(), true); sum_freed += chunk->size; From a9056a2b89280c1f2272759b56b70eebe4a00fb3 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 7 Mar 2019 18:39:20 +1100 Subject: [PATCH 2/2] MDEV-18946: innodb: {de|}allocate_large_{dodump|dontdump} added In 1dc78d35a0beb9620bae1f4841cc07389b425707 the arguments to a deallocate_large(dontdump=true) was passed a wrong value. To avoid accidential calling large memory function that have DODUMP/DONTDUMP options and missing arguments, the functions have been given distinct names. --- storage/innobase/buf/buf0buf.cc | 16 ++++++-------- storage/innobase/include/ut0new.h | 36 ++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 6ff0bd1de0c..576c6e156fa 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1571,8 +1571,7 @@ buf_chunk_init( DBUG_EXECUTE_IF("ib_buf_chunk_init_fails", return(NULL);); - chunk->mem = buf_pool->allocator.allocate_large(mem_size, - &chunk->mem_pfx, true); + chunk->mem = buf_pool->allocator.allocate_large_dontdump(mem_size, &chunk->mem_pfx); if (UNIV_UNLIKELY(chunk->mem == NULL)) { @@ -1865,9 +1864,8 @@ buf_pool_init_instance( &block->debug_latch)); } - buf_pool->allocator.deallocate_large( - chunk->mem, &chunk->mem_pfx, chunk->mem_size(), - true); + buf_pool->allocator.deallocate_large_dodump( + chunk->mem, &chunk->mem_pfx, chunk->mem_size()); } ut_free(buf_pool->chunks); buf_pool_mutex_exit(buf_pool); @@ -2014,8 +2012,8 @@ buf_pool_free_instance( ut_d(rw_lock_free(&block->debug_latch)); } - buf_pool->allocator.deallocate_large( - chunk->mem, &chunk->mem_pfx, chunk->mem_size(), true); + buf_pool->allocator.deallocate_large_dodump( + chunk->mem, &chunk->mem_pfx, chunk->mem_size()); } for (ulint i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; ++i) { @@ -2892,8 +2890,8 @@ withdraw_retry: &block->debug_latch)); } - buf_pool->allocator.deallocate_large( - chunk->mem, &chunk->mem_pfx, chunk->mem_size(), true); + buf_pool->allocator.deallocate_large_dodump( + chunk->mem, &chunk->mem_pfx, chunk->mem_size()); sum_freed += chunk->size; diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h index b79d03f1b0b..117913c9b71 100644 --- a/storage/innobase/include/ut0new.h +++ b/storage/innobase/include/ut0new.h @@ -654,13 +654,18 @@ public: return(ptr); } + pointer + allocate_large_dontdump( + size_type n_elements, + ut_new_pfx_t* pfx) + { + return allocate_large(n_elements, pfx, true); + } /** Free a memory allocated by allocate_large() and trace the deallocation. @param[in,out] ptr pointer to memory to free @param[in] pfx descriptor of the memory, as returned by - allocate_large(). - @param[in] dodump if true, advise the OS to include this - memory again if a core dump occurs. */ + allocate_large(). */ void deallocate_large( pointer ptr, @@ -669,12 +674,8 @@ public: pfx #endif , - size_t size, - bool dodump = false) + size_t size) { - if (dodump) { - ut_dodump(ptr, size); - } #ifdef UNIV_PFS_MEMORY if (pfx) { deallocate_trace(pfx); @@ -684,8 +685,27 @@ public: os_mem_free_large(ptr, size); } + void + deallocate_large_dodump( + pointer ptr, + const ut_new_pfx_t* #ifdef UNIV_PFS_MEMORY + pfx +#endif + , + size_t size) + { + ut_dodump(ptr, size); + deallocate_large(ptr, +#ifdef UNIV_PFS_MEMORY + pfx, +#else + NULL, +#endif + size); + } +#ifdef UNIV_PFS_MEMORY /** Get the performance schema key to use for tracing allocations. @param[in] file file name of the caller or NULL if unknown @return performance schema key */