MDEV-26293 InnoDB: Failing assertion: space->is_ready_to_close() ...
fil_space_t::acquire_low(): Introduce a parameter that specifies which flags should be avoided. At all times, referenced() must not be incremented if the STOPPING flag is set. When fil_system.mutex is not being held by the current thread, the reference must not be incremented if the CLOSING flag is set (unless NEEDS_FSYNC is set, in fil_space_t::flush()). fil_space_t::acquire(): Invoke acquire_low(STOPPING | CLOSING). In this way, the reference count cannot be incremented after fil_space_t::try_to_close() invoked fil_space_t::set_closing(). If the CLOSING flag was set, we must retry acquire_low() after acquiring fil_system.mutex. fil_space_t::prepare_acquired(): Replaces prepare(true). fil_space_t::acquire_and_prepare(): Replaces prepare(). This basically retries fil_space_t::acquire() after acquiring fil_system.mutex.
This commit is contained in:
parent
afe607dffa
commit
a1267724cb
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
|
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
|
||||||
Copyright (c) 2014, 2021, MariaDB Corporation.
|
Copyright (c) 2014, 2022, 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
|
||||||
@ -1456,7 +1456,7 @@ inline bool fil_space_t::acquire_if_not_stopped()
|
|||||||
return true;
|
return true;
|
||||||
if (UNIV_UNLIKELY(n & STOPPING))
|
if (UNIV_UNLIKELY(n & STOPPING))
|
||||||
return false;
|
return false;
|
||||||
return UNIV_LIKELY(!(n & CLOSING)) || prepare(true);
|
return UNIV_LIKELY(!(n & CLOSING)) || prepare_acquired();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fil_crypt_must_default_encrypt()
|
bool fil_crypt_must_default_encrypt()
|
||||||
@ -1567,7 +1567,7 @@ inline fil_space_t *fil_space_t::next(fil_space_t *space, bool recheck,
|
|||||||
const uint32_t n= space->acquire_low();
|
const uint32_t n= space->acquire_low();
|
||||||
if (UNIV_LIKELY(!(n & (STOPPING | CLOSING))))
|
if (UNIV_LIKELY(!(n & (STOPPING | CLOSING))))
|
||||||
break;
|
break;
|
||||||
if (!(n & STOPPING) && space->prepare(true))
|
if (!(n & STOPPING) && space->prepare_acquired())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -665,11 +665,9 @@ fil_space_extend_must_retry(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return whether the file is usable for io() */
|
/** @return whether the file is usable for io() */
|
||||||
ATTRIBUTE_COLD bool fil_space_t::prepare(bool have_mutex)
|
ATTRIBUTE_COLD bool fil_space_t::prepare_acquired()
|
||||||
{
|
{
|
||||||
ut_ad(referenced());
|
ut_ad(referenced());
|
||||||
if (!have_mutex)
|
|
||||||
mutex_enter(&fil_system.mutex);
|
|
||||||
ut_ad(mutex_own(&fil_system.mutex));
|
ut_ad(mutex_own(&fil_system.mutex));
|
||||||
fil_node_t *node= UT_LIST_GET_LAST(chain);
|
fil_node_t *node= UT_LIST_GET_LAST(chain);
|
||||||
ut_ad(!id || purpose == FIL_TYPE_TEMPORARY ||
|
ut_ad(!id || purpose == FIL_TYPE_TEMPORARY ||
|
||||||
@ -714,7 +712,15 @@ ATTRIBUTE_COLD bool fil_space_t::prepare(bool have_mutex)
|
|||||||
clear:
|
clear:
|
||||||
n_pending.fetch_and(~CLOSING, std::memory_order_relaxed);
|
n_pending.fetch_and(~CLOSING, std::memory_order_relaxed);
|
||||||
|
|
||||||
if (!have_mutex)
|
return is_open;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return whether the file is usable for io() */
|
||||||
|
ATTRIBUTE_COLD bool fil_space_t::acquire_and_prepare()
|
||||||
|
{
|
||||||
|
mutex_enter(&fil_system.mutex);
|
||||||
|
const auto flags= acquire_low() & (STOPPING | CLOSING);
|
||||||
|
const bool is_open= !flags || (flags == CLOSING && prepare_acquired());
|
||||||
mutex_exit(&fil_system.mutex);
|
mutex_exit(&fil_system.mutex);
|
||||||
return is_open;
|
return is_open;
|
||||||
}
|
}
|
||||||
@ -1488,13 +1494,13 @@ fil_space_t *fil_space_t::get(ulint id)
|
|||||||
mutex_enter(&fil_system.mutex);
|
mutex_enter(&fil_system.mutex);
|
||||||
fil_space_t *space= fil_space_get_by_id(id);
|
fil_space_t *space= fil_space_get_by_id(id);
|
||||||
const uint32_t n= space ? space->acquire_low() : 0;
|
const uint32_t n= space ? space->acquire_low() : 0;
|
||||||
mutex_exit(&fil_system.mutex);
|
|
||||||
|
|
||||||
if (n & STOPPING)
|
if (n & STOPPING)
|
||||||
space= nullptr;
|
space= nullptr;
|
||||||
else if ((n & CLOSING) && !space->prepare())
|
else if ((n & CLOSING) && !space->prepare_acquired())
|
||||||
space= nullptr;
|
space= nullptr;
|
||||||
|
|
||||||
|
mutex_exit(&fil_system.mutex);
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
Copyright (c) 2013, 2021, MariaDB Corporation.
|
Copyright (c) 2013, 2022, 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
|
||||||
@ -507,15 +507,16 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
MY_ATTRIBUTE((warn_unused_result))
|
MY_ATTRIBUTE((warn_unused_result))
|
||||||
/** Try to acquire a tablespace reference.
|
/** Try to acquire a tablespace reference (increment referenced()).
|
||||||
@return the old reference count (if STOPPING is set, it was not acquired) */
|
@param avoid when these flags are set, nothing will be acquired
|
||||||
uint32_t acquire_low()
|
@return the old reference count */
|
||||||
|
uint32_t acquire_low(uint32_t avoid= STOPPING)
|
||||||
{
|
{
|
||||||
uint32_t n= 0;
|
uint32_t n= 0;
|
||||||
while (!n_pending.compare_exchange_strong(n, n + 1,
|
while (!n_pending.compare_exchange_strong(n, n + 1,
|
||||||
std::memory_order_acquire,
|
std::memory_order_acquire,
|
||||||
std::memory_order_relaxed) &&
|
std::memory_order_relaxed) &&
|
||||||
!(n & STOPPING));
|
!(n & avoid));
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@ -529,10 +530,8 @@ public:
|
|||||||
@return whether the file is usable */
|
@return whether the file is usable */
|
||||||
bool acquire()
|
bool acquire()
|
||||||
{
|
{
|
||||||
uint32_t n= acquire_low();
|
const auto flags= acquire_low(STOPPING | CLOSING) & (STOPPING | CLOSING);
|
||||||
if (UNIV_LIKELY(!(n & (STOPPING | CLOSING))))
|
return UNIV_LIKELY(!flags) || (flags == CLOSING && acquire_and_prepare());
|
||||||
return true;
|
|
||||||
return UNIV_LIKELY(!(n & STOPPING)) && prepare();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Acquire another tablespace reference for I/O. */
|
/** Acquire another tablespace reference for I/O. */
|
||||||
@ -999,7 +998,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/** @return whether the file is usable for io() */
|
/** @return whether the file is usable for io() */
|
||||||
ATTRIBUTE_COLD bool prepare(bool have_mutex= false);
|
ATTRIBUTE_COLD bool prepare_acquired();
|
||||||
|
/** @return whether the file is usable for io() */
|
||||||
|
ATTRIBUTE_COLD bool acquire_and_prepare();
|
||||||
#endif /*!UNIV_INNOCHECKSUM */
|
#endif /*!UNIV_INNOCHECKSUM */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user