Commit cd093d79 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-24442 Assertion space->referenced() failed in fil_crypt_space_needs_rotation

A race condition between deleting an .ibd file and fil_crypt_thread
marking pages dirty was introduced in
commit 118e258a (part of MDEV-23855).

fil_space_t::acquire_if_not_stopped(): Correctly return false
if the STOPPING flag is set, indicating that any further activity
on the tablespace must be avoided. Also, remove the constant parameter
have_mutex=true and move the function declaration to the same
compilation unit with the only callers.

fil_crypt_flush_space(): Remove an unused variable.
parent a1974d19
......@@ -1430,6 +1430,19 @@ static void fil_crypt_return_iops(rotate_thread_t *state, bool wake= true)
fil_crypt_update_total_stat(state);
}
/** Acquire a tablespace reference.
@return whether a tablespace reference was successfully acquired */
inline bool fil_space_t::acquire_if_not_stopped()
{
ut_ad(mutex_own(&fil_system.mutex));
const uint32_t n= acquire_low();
if (UNIV_LIKELY(!(n & (STOPPING | CLOSING))))
return true;
if (UNIV_UNLIKELY(n & STOPPING))
return false;
return UNIV_LIKELY(!(n & CLOSING)) || prepare(true);
}
/** Return the next tablespace from rotation_list.
@param space previous tablespace (NULL to start from the start)
@param recheck whether the removal condition needs to be rechecked after
......@@ -1478,7 +1491,7 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space,
do
{
space= &*it;
if (space->acquire_if_not_stopped(true))
if (space->acquire_if_not_stopped())
return space;
if (++it == end)
return nullptr;
......@@ -2007,12 +2020,10 @@ fil_crypt_flush_space(
mtr_t mtr;
mtr.start();
dberr_t err;
if (buf_block_t* block = buf_page_get_gen(
page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr, &err)) {
__FILE__, __LINE__, &mtr)) {
mtr.set_named_space(space);
crypt_data->write_page0(block, &mtr);
}
......@@ -2250,7 +2261,7 @@ static void fil_crypt_rotation_list_fill()
if (space->purpose != FIL_TYPE_TABLESPACE
|| space->is_in_rotation_list
|| UT_LIST_GET_LEN(space->chain) == 0
|| !space->acquire_if_not_stopped(true)) {
|| !space->acquire_if_not_stopped()) {
continue;
}
......
......@@ -520,8 +520,9 @@ struct fil_space_t final
}
public:
MY_ATTRIBUTE((warn_unused_result))
/** @return whether a tablespace reference was successfully acquired */
inline bool acquire_if_not_stopped(bool have_mutex= false);
/** Acquire a tablespace reference.
@return whether a tablespace reference was successfully acquired */
inline bool acquire_if_not_stopped();
MY_ATTRIBUTE((warn_unused_result))
/** Acquire a tablespace reference for I/O.
......@@ -1434,15 +1435,6 @@ inline void fil_space_t::reacquire()
ut_ad(UT_LIST_GET_FIRST(chain)->is_open());
}
inline bool fil_space_t::acquire_if_not_stopped(bool have_mutex)
{
ut_ad(mutex_own(&fil_system.mutex) == have_mutex);
const uint32_t n= acquire_low();
if (UNIV_LIKELY(!(n & (STOPPING | CLOSING))))
return true;
return UNIV_LIKELY(!(n & CLOSING)) || prepare(have_mutex);
}
/** Note that operations on the tablespace must stop or can resume */
inline void fil_space_t::set_stopping(bool stopping)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment