diff --git a/include/ilist.h b/include/ilist.h index dc8be5d5044ea..76c250f546f6a 100644 --- a/include/ilist.h +++ b/include/ilist.h @@ -185,6 +185,9 @@ template class ilist ListNode *prev= pos.node_->prev; ListNode *next= pos.node_->next; + DBUG_ASSERT(prev->next == pos.node_); + DBUG_ASSERT(next->prev == pos.node_); + prev->next= next; next->prev= prev; @@ -198,7 +201,7 @@ template class ilist } void push_back(reference value) noexcept { insert(end(), value); } - void pop_back() noexcept { erase(end()); } + void pop_back() noexcept { erase(--end()); } void push_front(reference value) noexcept { insert(begin(), value); } void pop_front() noexcept { erase(begin()); } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index efb728ab7c23e..cfa1534c37f7b 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -861,13 +861,7 @@ static void fil_space_free_low(fil_space_t *space) noexcept /* The tablespace must not be in fil_system.named_spaces. */ ut_ad(srv_fast_shutdown == 2 || !srv_was_started || space->max_lsn == 0); - - /* Wait for fil_space_t::release() after - fil_system_t::detach(), the tablespace cannot be found, so - fil_space_t::get() would return NULL */ - while (space->referenced()) { - std::this_thread::sleep_for(std::chrono::microseconds(100)); - } + ut_ad(!space->referenced()); for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain); node != NULL; ) { @@ -911,7 +905,7 @@ bool fil_space_free(ulint id, bool x_latched) noexcept mysql_mutex_assert_owner(&log_sys.mutex); if (space->max_lsn != 0) { - ut_d(space->max_lsn = 0); + space->max_lsn = 0; fil_system.named_spaces.remove(*space); } @@ -1604,10 +1598,24 @@ fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle) pfs_os_file_t handle= fil_system.detach(space, true); mysql_mutex_unlock(&fil_system.mutex); + /* The above mtr.commit_file(*space, nullptr) should remove the space from + fil_system.named_spaces. Before we set the STOPPING_WRITES flag, another + concurrent operation could have marked the tablespace dirty again. + This clean-up corresponds to fil_space_free(). */ + mysql_mutex_lock(&log_sys.mutex); + ut_ad((space->pending() & ~NEEDS_FSYNC) == (STOPPING | CLOSING)); + if (space->max_lsn != 0) + { + space->max_lsn= 0; + fil_system.named_spaces.remove(*space); + } + mysql_mutex_unlock(&log_sys.mutex); + if (detached_handle) *detached_handle = handle; else os_file_close(handle); + return space; } @@ -1630,12 +1638,6 @@ void fil_close_tablespace(ulint id) noexcept while (buf_flush_list_space(space)); space->x_unlock(); - mysql_mutex_lock(&log_sys.mutex); - if (space->max_lsn != 0) { - ut_d(space->max_lsn = 0); - fil_system.named_spaces.remove(*space); - } - mysql_mutex_unlock(&log_sys.mutex); fil_space_free_low(space); } diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index d8f694d80f052..25a66efdef9da 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -375,7 +375,7 @@ bool mtr_t::commit_file(fil_space_t &space, const char *name) if (!name && space.max_lsn) { - ut_d(space.max_lsn= 0); + space.max_lsn= 0; fil_system.named_spaces.remove(space); }