From a1542f8a57390bbad916ddfd335e1c751ffb3de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 12 Feb 2021 17:43:10 +0200 Subject: [PATCH] MDEV-24643: Assertion failed in rw_lock::update_unlock() mtr_defer_drop_ahi(): Upgrade the U lock to X lock and downgrade it back to U lock in case the adaptive hash index needs to be dropped. This regression was introduced in commit 03ca6495df31313c96e38834b9a235245e2ae2a8 (MDEV-24142). --- storage/innobase/include/rw_lock.h | 10 +++++++++- storage/innobase/include/srw_lock.h | 1 + storage/innobase/include/sux_lock.h | 10 +++++++++- storage/innobase/mtr/mtr0mtr.cc | 6 ++---- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/storage/innobase/include/rw_lock.h b/storage/innobase/include/rw_lock.h index cae71e8f6c7..0c68758d898 100644 --- a/storage/innobase/include/rw_lock.h +++ b/storage/innobase/include/rw_lock.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2020, MariaDB Corporation. +Copyright (c) 2020, 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 @@ -104,6 +104,14 @@ protected: DBUG_ASSERT((l & ~WRITER_WAITING) == UPDATER); return true; } + /** Downgrade an exclusive lock to an update lock. */ + void downgrade() + { + IF_DBUG_ASSERT(auto l=,) + lock.fetch_xor(WRITER | UPDATER, std::memory_order_relaxed); + DBUG_ASSERT((l & ~WRITER_WAITING) == WRITER); + } + /** Wait for an exclusive lock. @return whether the exclusive lock was acquired */ bool write_lock_poll() diff --git a/storage/innobase/include/srw_lock.h b/storage/innobase/include/srw_lock.h index 161c0b7b79f..50675d2ffb3 100644 --- a/storage/innobase/include/srw_lock.h +++ b/storage/innobase/include/srw_lock.h @@ -93,6 +93,7 @@ public: void u_lock() { uint32_t l; if (!update_trylock(l)) update_lock(l); } bool u_lock_try() { uint32_t l; return update_trylock(l); } void u_wr_upgrade() { if (!upgrade_trylock()) write_lock(true); } + void wr_u_downgrade() { downgrade(); } void wr_lock() { if (!write_trylock()) write_lock(false); } void rd_unlock(); void u_unlock(); diff --git a/storage/innobase/include/sux_lock.h b/storage/innobase/include/sux_lock.h index 436c2bc6600..f967e8c81cd 100644 --- a/storage/innobase/include/sux_lock.h +++ b/storage/innobase/include/sux_lock.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2020, MariaDB Corporation. +Copyright (c) 2020, 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 @@ -193,6 +193,14 @@ public: /** Upgrade an update lock */ inline void u_x_upgrade(); inline void u_x_upgrade(const char *file, unsigned line); + /** Downgrade a single exclusive lock to an update lock */ + void x_u_downgrade() + { + ut_ad(have_u_or_x()); + ut_ad(recursive <= RECURSIVE_MAX); + recursive*= RECURSIVE_U; + lock.wr_u_downgrade(); + } /** Acquire an exclusive lock or upgrade an update lock @return whether U locks were upgraded to X */ diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 4f80bc0c7a4..0ba0ada4900 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -988,13 +988,11 @@ static void mtr_defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type) block->lock.s_lock(); break; case MTR_MEMO_PAGE_SX_FIX: - block->lock.u_unlock(); - block->lock.x_lock(); + block->lock.u_x_upgrade(); if (dict_index_t *index= block->index) if (index->freed()) btr_search_drop_page_hash_index(block); - block->lock.u_lock(); - block->lock.x_unlock(); + block->lock.x_u_downgrade(); break; default: ut_ad(fix_type == MTR_MEMO_PAGE_X_FIX);