]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: retry lock requests periodically until acquired
authorJason Dillaman <dillaman@redhat.com>
Thu, 7 May 2015 16:51:49 +0000 (12:51 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 29 Jul 2015 17:29:54 +0000 (13:29 -0400)
If the exclusive lock owner acks the lock release request but crashes
before it actually releases the lock, the requestor will wait forever.
Therefore, after a certain timeout, retry the request again until it
succeeds.

Fixes: #11537
Backport: hammer
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 37c74e6e5274208d1b6efaf315afec03ea7eaa82)

src/librbd/ImageWatcher.cc

index 798b4320343eadd7c837cf12bfe8402eadef8226..477e9cdb32bbf5059f767f7f7986bb4a860b57fd 100644 (file)
@@ -602,6 +602,13 @@ void ImageWatcher::notify_request_lock() {
     lderr(m_image_ctx.cct) << "error requesting lock: " << cpp_strerror(r)
                           << dendl;
     schedule_retry_aio_requests(true);
+  } else {
+    // lock owner acked -- but resend if we don't see them release the lock
+    int retry_timeout = m_image_ctx.cct->_conf->client_notify_timeout;
+    FunctionContext *ctx = new FunctionContext(
+      boost::bind(&ImageWatcher::notify_request_lock, this));
+    m_task_finisher->add_event_after(TASK_CODE_REQUEST_LOCK,
+                                     retry_timeout, ctx);
   }
 }
 
@@ -728,6 +735,7 @@ void ImageWatcher::handle_payload(const HeaderUpdatePayload &payload,
 void ImageWatcher::handle_payload(const AcquiredLockPayload &payload,
                                   bufferlist *out) {
   ldout(m_image_ctx.cct, 10) << "image exclusively locked announcement" << dendl;
+  m_task_finisher->cancel(TASK_CODE_REQUEST_LOCK);
   if (payload.client_id.is_valid()) {
     Mutex::Locker l(m_owner_client_id_lock);
     if (payload.client_id == m_owner_client_id) {
@@ -747,6 +755,7 @@ void ImageWatcher::handle_payload(const AcquiredLockPayload &payload,
 void ImageWatcher::handle_payload(const ReleasedLockPayload &payload,
                                   bufferlist *out) {
   ldout(m_image_ctx.cct, 10) << "exclusive lock released" << dendl;
+  m_task_finisher->cancel(TASK_CODE_REQUEST_LOCK);
   if (payload.client_id.is_valid()) {
     Mutex::Locker l(m_owner_client_id_lock);
     if (payload.client_id != m_owner_client_id) {