From fa1fc35bc4d22ce91f6210d96c14994753267077 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 15 Aug 2016 17:15:48 -0400 Subject: [PATCH] librbd: always respond to "release lock" request if lock owner Fixes: http://tracker.ceph.com/issues/17030 Signed-off-by: Jason Dillaman (cherry picked from commit d8e7946fff27030a3b1dc4f6dd5315884cec27c1) --- src/librbd/ExclusiveLock.cc | 4 +-- src/librbd/ExclusiveLock.h | 2 +- src/librbd/ImageWatcher.cc | 34 ++++++++++++---------- src/test/librbd/test_mock_ExclusiveLock.cc | 2 +- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/librbd/ExclusiveLock.cc b/src/librbd/ExclusiveLock.cc index 4c0501c917cf4..1d0248ca43fea 100644 --- a/src/librbd/ExclusiveLock.cc +++ b/src/librbd/ExclusiveLock.cc @@ -135,7 +135,7 @@ void ExclusiveLock::shut_down(Context *on_shut_down) { } // if stalled in request state machine -- abort - handle_lock_released(); + handle_peer_notification(); } template @@ -209,7 +209,7 @@ void ExclusiveLock::handle_watch_registered() { } template -void ExclusiveLock::handle_lock_released() { +void ExclusiveLock::handle_peer_notification() { Mutex::Locker locker(m_lock); if (m_state != STATE_WAITING_FOR_PEER) { return; diff --git a/src/librbd/ExclusiveLock.h b/src/librbd/ExclusiveLock.h index e82da208afc22..7e66037e87305 100644 --- a/src/librbd/ExclusiveLock.h +++ b/src/librbd/ExclusiveLock.h @@ -42,7 +42,7 @@ public: void release_lock(Context *on_released); void handle_watch_registered(); - void handle_lock_released(); + void handle_peer_notification(); void assert_header_locked(librados::ObjectWriteOperation *op); diff --git a/src/librbd/ImageWatcher.cc b/src/librbd/ImageWatcher.cc index 38a42a93f543b..41b5c3a1709f9 100644 --- a/src/librbd/ImageWatcher.cc +++ b/src/librbd/ImageWatcher.cc @@ -481,7 +481,7 @@ void ImageWatcher::handle_request_lock(int r) { << dendl; // treat this is a dead client -- so retest acquiring the lock - m_image_ctx.exclusive_lock->handle_lock_released(); + m_image_ctx.exclusive_lock->handle_peer_notification(); } else if (r < 0) { lderr(m_image_ctx.cct) << this << " error requesting lock: " << cpp_strerror(r) << dendl; @@ -624,6 +624,11 @@ bool ImageWatcher::handle_payload(const AcquiredLockPayload &payload, } RWLock::RLocker owner_locker(m_image_ctx.owner_lock); + if (m_image_ctx.exclusive_lock != nullptr) { + // potentially wake up the exclusive lock state machine now that + // a lock owner has advertised itself + m_image_ctx.exclusive_lock->handle_peer_notification(); + } if (cancel_async_requests && (m_image_ctx.exclusive_lock == nullptr || !m_image_ctx.exclusive_lock->is_lock_owner())) { @@ -661,7 +666,7 @@ bool ImageWatcher::handle_payload(const ReleasedLockPayload &payload, if (m_image_ctx.exclusive_lock != nullptr && !m_image_ctx.exclusive_lock->is_lock_owner()) { m_task_finisher->cancel(TASK_CODE_REQUEST_LOCK); - m_image_ctx.exclusive_lock->handle_lock_released(); + m_image_ctx.exclusive_lock->handle_peer_notification(); } return true; } @@ -675,24 +680,23 @@ bool ImageWatcher::handle_payload(const RequestLockPayload &payload, } RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - // need to send something back so the client can detect a missing leader - ::encode(ResponseMessage(0), ack_ctx->out); - - { - Mutex::Locker owner_client_id_locker(m_owner_client_id_lock); - if (!m_owner_client_id.is_valid()) { - return true; - } + if (m_image_ctx.exclusive_lock != nullptr && + m_image_ctx.exclusive_lock->is_lock_owner()) { + int r = 0; + bool accept_request = m_image_ctx.exclusive_lock->accept_requests(&r); + + // need to send something back so the client can detect a missing leader + ::encode(ResponseMessage(r), ack_ctx->out); + + if (accept_request) { + Mutex::Locker owner_client_id_locker(m_owner_client_id_lock); + if (!m_owner_client_id.is_valid()) { + return true; } ldout(m_image_ctx.cct, 10) << this << " queuing release of exclusive lock" << dendl; m_image_ctx.get_exclusive_lock_policy()->lock_requested(payload.force); - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); } } return true; diff --git a/src/test/librbd/test_mock_ExclusiveLock.cc b/src/test/librbd/test_mock_ExclusiveLock.cc index f87a319b37796..a2003a5d0a78e 100644 --- a/src/test/librbd/test_mock_ExclusiveLock.cc +++ b/src/test/librbd/test_mock_ExclusiveLock.cc @@ -142,7 +142,7 @@ public: MockExclusiveLock &mock_exclusive_lock) { EXPECT_CALL(*mock_image_ctx.image_watcher, notify_request_lock()) .WillRepeatedly(Invoke(&mock_exclusive_lock, - &MockExclusiveLock::handle_lock_released)); + &MockExclusiveLock::handle_peer_notification)); } void expect_notify_acquired_lock(MockExclusiveLockImageCtx &mock_image_ctx) { -- 2.39.5