From c45324a14f6bb02896549d5f79ad42f942afb5d1 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Thu, 14 May 2020 14:01:35 -0400 Subject: [PATCH] librbd: avoid completing mirror:DisableRequest while holding its lock Ensure that the lock is released before another thread has the chance to complete the state machine and attempt to destruct the in-use lock. Fixes: https://tracker.ceph.com/issues/45544 Signed-off-by: Jason Dillaman --- src/librbd/mirror/DisableRequest.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/librbd/mirror/DisableRequest.cc b/src/librbd/mirror/DisableRequest.cc index 2d2dd874a80a4..05652d1c9dd3c 100644 --- a/src/librbd/mirror/DisableRequest.cc +++ b/src/librbd/mirror/DisableRequest.cc @@ -219,16 +219,15 @@ Context *DisableRequest::handle_get_clients(int *result) { CephContext *cct = m_image_ctx->cct; ldout(cct, 10) << "r=" << *result << dendl; + std::unique_lock locker{m_lock}; + ceph_assert(m_current_ops.empty()); + if (*result < 0) { lderr(cct) << "failed to get registered clients: " << cpp_strerror(*result) << dendl; return m_on_finish; } - std::lock_guard locker{m_lock}; - - ceph_assert(m_current_ops.empty()); - for (auto client : m_clients) { journal::ClientData client_data; auto bl_it = client.data.cbegin(); @@ -276,6 +275,7 @@ Context *DisableRequest::handle_get_clients(int *result) { } else if (!m_remove) { return m_on_finish; } + locker.unlock(); // no mirror clients to unregister send_remove_mirror_image(); @@ -342,7 +342,7 @@ Context *DisableRequest::handle_remove_snap(int *result, CephContext *cct = m_image_ctx->cct; ldout(cct, 10) << "r=" << *result << dendl; - std::lock_guard locker{m_lock}; + std::unique_lock locker{m_lock}; ceph_assert(m_current_ops[client_id] > 0); m_current_ops[client_id]--; @@ -360,6 +360,8 @@ Context *DisableRequest::handle_remove_snap(int *result, if (m_ret[client_id] < 0) { return m_on_finish; } + locker.unlock(); + send_remove_mirror_image(); return nullptr; } @@ -404,7 +406,7 @@ Context *DisableRequest::handle_unregister_client( CephContext *cct = m_image_ctx->cct; ldout(cct, 10) << "r=" << *result << dendl; - std::lock_guard locker{m_lock}; + std::unique_lock locker{m_lock}; ceph_assert(m_current_ops[client_id] == 0); m_current_ops.erase(client_id); @@ -422,6 +424,7 @@ Context *DisableRequest::handle_unregister_client( *result = m_error_result; return m_on_finish; } + locker.unlock(); send_get_clients(); return nullptr; -- 2.39.5