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) ...@@ -1430,6 +1430,19 @@ static void fil_crypt_return_iops(rotate_thread_t *state, bool wake= true)
fil_crypt_update_total_stat(state); 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. /** Return the next tablespace from rotation_list.
@param space previous tablespace (NULL to start from the start) @param space previous tablespace (NULL to start from the start)
@param recheck whether the removal condition needs to be rechecked after @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, ...@@ -1478,7 +1491,7 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space,
do do
{ {
space= &*it; space= &*it;
if (space->acquire_if_not_stopped(true)) if (space->acquire_if_not_stopped())
return space; return space;
if (++it == end) if (++it == end)
return nullptr; return nullptr;
...@@ -2007,12 +2020,10 @@ fil_crypt_flush_space( ...@@ -2007,12 +2020,10 @@ fil_crypt_flush_space(
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
dberr_t err;
if (buf_block_t* block = buf_page_get_gen( if (buf_block_t* block = buf_page_get_gen(
page_id_t(space->id, 0), space->zip_size(), page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr, &err)) { __FILE__, __LINE__, &mtr)) {
mtr.set_named_space(space); mtr.set_named_space(space);
crypt_data->write_page0(block, &mtr); crypt_data->write_page0(block, &mtr);
} }
...@@ -2250,7 +2261,7 @@ static void fil_crypt_rotation_list_fill() ...@@ -2250,7 +2261,7 @@ static void fil_crypt_rotation_list_fill()
if (space->purpose != FIL_TYPE_TABLESPACE if (space->purpose != FIL_TYPE_TABLESPACE
|| space->is_in_rotation_list || space->is_in_rotation_list
|| UT_LIST_GET_LEN(space->chain) == 0 || UT_LIST_GET_LEN(space->chain) == 0
|| !space->acquire_if_not_stopped(true)) { || !space->acquire_if_not_stopped()) {
continue; continue;
} }
......
...@@ -520,8 +520,9 @@ struct fil_space_t final ...@@ -520,8 +520,9 @@ struct fil_space_t final
} }
public: public:
MY_ATTRIBUTE((warn_unused_result)) MY_ATTRIBUTE((warn_unused_result))
/** @return whether a tablespace reference was successfully acquired */ /** Acquire a tablespace reference.
inline bool acquire_if_not_stopped(bool have_mutex= false); @return whether a tablespace reference was successfully acquired */
inline bool acquire_if_not_stopped();
MY_ATTRIBUTE((warn_unused_result)) MY_ATTRIBUTE((warn_unused_result))
/** Acquire a tablespace reference for I/O. /** Acquire a tablespace reference for I/O.
...@@ -1434,15 +1435,6 @@ inline void fil_space_t::reacquire() ...@@ -1434,15 +1435,6 @@ inline void fil_space_t::reacquire()
ut_ad(UT_LIST_GET_FIRST(chain)->is_open()); 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 */ /** Note that operations on the tablespace must stop or can resume */
inline void fil_space_t::set_stopping(bool stopping) 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