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).
This commit is contained in:
Marko Mäkelä 2021-02-12 17:43:10 +02:00
parent 26d6224dd6
commit a1542f8a57
4 changed files with 21 additions and 6 deletions

View File

@ -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 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 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); DBUG_ASSERT((l & ~WRITER_WAITING) == UPDATER);
return true; 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. /** Wait for an exclusive lock.
@return whether the exclusive lock was acquired */ @return whether the exclusive lock was acquired */
bool write_lock_poll() bool write_lock_poll()

View File

@ -93,6 +93,7 @@ public:
void u_lock() { uint32_t l; if (!update_trylock(l)) update_lock(l); } void u_lock() { uint32_t l; if (!update_trylock(l)) update_lock(l); }
bool u_lock_try() { uint32_t l; return update_trylock(l); } bool u_lock_try() { uint32_t l; return update_trylock(l); }
void u_wr_upgrade() { if (!upgrade_trylock()) write_lock(true); } 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 wr_lock() { if (!write_trylock()) write_lock(false); }
void rd_unlock(); void rd_unlock();
void u_unlock(); void u_unlock();

View File

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -193,6 +193,14 @@ public:
/** Upgrade an update lock */ /** Upgrade an update lock */
inline void u_x_upgrade(); inline void u_x_upgrade();
inline void u_x_upgrade(const char *file, unsigned line); 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 /** Acquire an exclusive lock or upgrade an update lock
@return whether U locks were upgraded to X */ @return whether U locks were upgraded to X */

View File

@ -988,13 +988,11 @@ static void mtr_defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type)
block->lock.s_lock(); block->lock.s_lock();
break; break;
case MTR_MEMO_PAGE_SX_FIX: case MTR_MEMO_PAGE_SX_FIX:
block->lock.u_unlock(); block->lock.u_x_upgrade();
block->lock.x_lock();
if (dict_index_t *index= block->index) if (dict_index_t *index= block->index)
if (index->freed()) if (index->freed())
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
block->lock.u_lock(); block->lock.x_u_downgrade();
block->lock.x_unlock();
break; break;
default: default:
ut_ad(fix_type == MTR_MEMO_PAGE_X_FIX); ut_ad(fix_type == MTR_MEMO_PAGE_X_FIX);