From a8650b64ede7330e83e84226cccd77ba8e05fa29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 10 Mar 2021 19:33:09 +0200 Subject: MDEV-25110 [FATAL] InnoDB: Trying to write ... outside the bounds In commit 118e258aaac5da75a2ac4556201aaea3688fac67 (part of MDEV-23855) we inadvertently broke crash recovery, reintroducing MDEV-11556. fil_system_t::extend_to_recv_size(): Extend all open tablespace files to the recovered size. recv_sys_t::apply(): Invoke fil_system.extend_to_recv_size() at the start of each batch. In this way, any fil_space_t::recv_size changes that were parsed after the file was opened will be applied. --- storage/innobase/fil/fil0fil.cc | 27 +++++++++++++++++++++++++++ storage/innobase/include/fil0fil.h | 5 ++++- storage/innobase/log/log0recv.cc | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index d000bc471d9..e245076a822 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1305,6 +1305,33 @@ void fil_system_t::close() #endif /* UNIV_LINUX */ } +/** Extend all open data files to the recovered size */ +ATTRIBUTE_COLD void fil_system_t::extend_to_recv_size() +{ + ut_ad(is_initialised()); + mutex_enter(&mutex); + for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); space; + space= UT_LIST_GET_NEXT(space_list, space)) + { + const uint32_t size= space->recv_size; + + if (size > space->size) + { + if (space->is_closing()) + continue; + space->reacquire(); + bool success; + while (fil_space_extend_must_retry(space, UT_LIST_GET_LAST(space->chain), + size, &success)) + mutex_enter(&mutex); + /* Crash recovery requires the file extension to succeed. */ + ut_a(success); + space->release(); + } + } + mutex_exit(&mutex); +} + /** Close all tablespace files at shutdown */ void fil_space_t::close_all() { diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index f011eb6af69..f4ca4e9a73e 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2020, MariaDB Corporation. +Copyright (c) 2013, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1422,6 +1422,9 @@ public: @retval NULL if this was the last */ inline fil_space_t* keyrotate_next(fil_space_t *space, bool recheck, bool encrypt); + + /** Extend all open data files to the recovered size */ + ATTRIBUTE_COLD void extend_to_recv_size(); }; /** The tablespace memory cache. */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 7c9d8af0859..67ac088f629 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2662,6 +2662,8 @@ void recv_sys_t::apply(bool last_batch) trim(page_id_t(id + srv_undo_space_id_start, t.pages), t.lsn); } + fil_system.extend_to_recv_size(); + buf_block_t *free_block= buf_LRU_get_free_block(false); for (map::iterator p= pages.begin(); p != pages.end(); ) -- cgit v1.2.1