]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: request exclusive lock if current owner cannot execute op 12018/head
authorMykola Golub <mgolub@mirantis.com>
Wed, 16 Nov 2016 10:01:00 +0000 (12:01 +0200)
committerMykola Golub <mgolub@mirantis.com>
Wed, 16 Nov 2016 14:22:53 +0000 (16:22 +0200)
This is a direct commit to hammer due to librbd code has evolved
significantly in the master.

Fixes: http://tracker.ceph.com/issues/17068
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
src/librbd/AioCompletion.cc
src/librbd/internal.cc

index efbc84945ffbf25c57d837ce3ddc11692b97c9dd..cdd2f2fa9367a3fb55bb07662c373b6079890b80 100644 (file)
@@ -79,6 +79,8 @@ namespace librbd {
       ictx->perfcounter->tinc(l_librbd_aio_discard_latency, elapsed); break;
     case AIO_TYPE_FLUSH:
       ictx->perfcounter->tinc(l_librbd_aio_flush_latency, elapsed); break;
+    case AIO_TYPE_NONE:
+      break;
     default:
       lderr(cct) << "completed invalid aio_type: " << aio_type << dendl;
       break;
index f4b110eea8ce0c37c2780e1429cfd527f88e7882..c38d6ae848e26c8c8cfa3a84ba3d8f2de583fcaf 100644 (file)
@@ -87,6 +87,23 @@ int prepare_image_update(ImageCtx *ictx) {
   return r;
 }
 
+void acquire_lock(ImageCtx *ictx) {
+  assert(ictx->owner_lock.is_locked());
+  AioCompletion *comp = aio_create_completion();
+  comp->add_request();
+  comp->finish_adding_requests(ictx->cct);
+
+  ictx->image_watcher->request_lock(
+    boost::bind(&AioCompletion::complete_request, _1, ictx->cct, 0),
+    comp);
+
+  ictx->owner_lock.put_read();
+  int r = comp->wait_for_complete();
+  assert(r == 0);
+  comp->release();
+  ictx->owner_lock.get_read();
+}
+
 int invoke_async_request(ImageCtx *ictx, const std::string& request_type,
                          bool permit_snapshot,
                          const boost::function<int(Context*)>& local_request,
@@ -104,15 +121,25 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type,
         }
       }
 
+      bool request_lock = false;
       while (ictx->image_watcher->is_lock_supported()) {
+        if (request_lock) {
+          acquire_lock(ictx);
+        }
         r = prepare_image_update(ictx);
         if (r < 0) {
           return -EROFS;
         } else if (ictx->image_watcher->is_lock_owner()) {
           break;
+        } else if (request_lock) {
+          return -EOPNOTSUPP;
         }
 
         r = remote_request();
+        if (r == -EOPNOTSUPP) {
+          request_lock = true;
+          continue;
+        }
         if (r != -ETIMEDOUT && r != -ERESTART) {
           return r;
         }