Detected during an fsx run where a refresh and CoR were occurring
concurrently. The refresh held the snap_lock and was waiting on
the object_map_lock, while the CoR held object_map_lock and was
waiting for snap_lock.
Fixes: #11577
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit
8cbd92b1fe835b1eb3a898976f9507f51cc115b2)
m_state = LIBRBD_AIO_WRITE_PRE;
FunctionContext *ctx = new FunctionContext(
boost::bind(&AioRequest::complete, this, _1));
+ RWLock::RLocker snap_locker(m_ictx->snap_lock);
RWLock::WLocker object_map_locker(m_ictx->object_map_lock);
if (!m_ictx->object_map.aio_update(m_object_no, new_state,
current_state, ctx)) {
m_state = LIBRBD_AIO_WRITE_POST;
FunctionContext *ctx = new FunctionContext(
boost::bind(&AioRequest::complete, this, _1));
+ RWLock::RLocker snap_locker(m_ictx->snap_lock);
RWLock::WLocker object_map_locker(m_ictx->object_map_lock);
if (!m_ictx->object_map.aio_update(m_object_no, OBJECT_NONEXISTENT,
OBJECT_PENDING, ctx)) {
} else {
// flag the objects as pending deletion
Context *ctx = create_callback_context();
+ RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock);
if (!m_image_ctx.object_map.aio_update(m_delete_start, m_num_objects,
OBJECT_PENDING, OBJECT_EXISTS,
} else {
// flag the pending objects as removed
Context *ctx = create_callback_context();
+ RWLock::RLocker snap_lock(m_image_ctx.snap_lock);
RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock);
if (!m_image_ctx.object_map.aio_update(m_delete_start, m_num_objects,
OBJECT_NONEXISTENT,
bool ImageWatcher::is_lock_supported(const RWLock &) const {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.snap_lock.is_locked());
- uint64_t snap_features;
- m_image_ctx.get_features(m_image_ctx.snap_id, &snap_features);
- return ((snap_features & RBD_FEATURE_EXCLUSIVE_LOCK) != 0 &&
+ return ((m_image_ctx.features & RBD_FEATURE_EXCLUSIVE_LOCK) != 0 &&
!m_image_ctx.read_only && m_image_ctx.snap_id == CEPH_NOSNAP);
}
const boost::optional<uint8_t> ¤t_state,
Context *on_finish)
{
- assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP));
+ assert(m_image_ctx.snap_lock.is_locked());
+ assert((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) != 0);
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.image_watcher != NULL);
assert(m_image_ctx.image_watcher->is_lock_owner());