]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd/ImageWatcher: kick-start ExclusiveLock state machine
authorRamana Raja <rraja@redhat.com>
Mon, 14 Aug 2023 15:27:13 +0000 (11:27 -0400)
committerRamana Raja <rraja@redhat.com>
Tue, 5 Sep 2023 18:19:12 +0000 (14:19 -0400)
... that is stalled on waiting for lock and let it detect client
blocklisting. This would propagate the blocklist error to the caller
requesting an operation needing an exclusive lock.

When a caller requests a librbd operation that requires an exclusive
lock, the librbd client checks whether the exclusive lock is
held by another client. If the lock is held by another client, librbd
stalls its ExclusiveLock state machine and through its ImageWatcher
notifies the lock owner that it wants the exclusive lock. After
receiving the response from the lock owner, the ImageWatcher schedules
another lock request. Meanwhile if the client gets blocklisted, the
ImageWatcher fails to schedule another lock request and returns. The
ExclusiveLock state machine remains stalled and the blocklist error is
not propagated to the caller. Instead, when scheduling another lock
request, make the ImageWatcher call the ExclusiveLock state machine's
peer notification handler if the client is blocklisted. This allows
the Exclusive lock state machine to detect that the client has been
blocklisted in its send_acquire_lock() member function and propagate
the blocklist error to the caller.

Fixes: https://tracker.ceph.com/issues/61607
Signed-off-by: Ramana Raja <rraja@redhat.com>
(cherry picked from commit e66db76354093009c254aabce9e4654e27045375)

src/librbd/ImageWatcher.cc

index 789d7694ab4e10d9be155708289e834953ee3ada..6cf86bae769b17444f39d55d2fec23d336571fb4 100644 (file)
@@ -578,8 +578,7 @@ void ImageWatcher<I>::schedule_request_lock(bool use_timer, int timer_delay) {
     return;
   }
 
-  std::shared_lock watch_locker{this->m_watch_lock};
-  if (this->is_registered(this->m_watch_lock)) {
+  if (is_registered()) {
     ldout(m_image_ctx.cct, 15) << this << " requesting exclusive lock" << dendl;
 
     auto ctx = new LambdaContext([this](int r) {
@@ -597,6 +596,10 @@ void ImageWatcher<I>::schedule_request_lock(bool use_timer, int timer_delay) {
     } else {
       m_task_finisher->queue(TASK_CODE_REQUEST_LOCK, ctx);
     }
+  } else if (is_blocklisted()) {
+    lderr(m_image_ctx.cct) << this << " blocklisted waiting for exclusive lock"
+                           << dendl;
+    m_image_ctx.exclusive_lock->handle_peer_notification(0);
   }
 }