]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: fixed race condition on demotion of snapshot-based mirrored image
authorJason Dillaman <dillaman@redhat.com>
Thu, 9 Apr 2020 03:06:05 +0000 (23:06 -0400)
committerJason Dillaman <dillaman@redhat.com>
Thu, 9 Apr 2020 14:00:28 +0000 (10:00 -0400)
A pending refresh could occur after setting the non-primary feature flag but
before the creation of the demotion snapshot. This would prevent the snapshot
from being created and would leave the image in a half-primary state.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/api/Mirror.cc

index 99aca1414f95bcb33302471a19bbb9fac8169ecd..4fafea2a7ab95451ca4601a0aba5f6bdd7e0e7b0 100644 (file)
@@ -669,21 +669,33 @@ void Mirror<I>::image_demote(I *ictx, Context *on_finish) {
   CephContext *cct = ictx->cct;
   ldout(cct, 20) << "ictx=" << ictx << dendl;
 
-  auto on_refresh = new LambdaContext([ictx, on_finish](int r) {
+  auto on_cleanup = new LambdaContext([ictx, on_finish](int r) {
+      ictx->image_lock.lock();
+      ictx->read_only_mask |= IMAGE_READ_ONLY_FLAG_NON_PRIMARY;
+      ictx->image_lock.unlock();
+
+      ictx->state->handle_update_notification();
+
+      on_finish->complete(r);
+    });
+  auto on_refresh = new LambdaContext([ictx, on_cleanup](int r) {
       if (r < 0) {
         lderr(ictx->cct) << "refresh failed: " << cpp_strerror(r) << dendl;
-        on_finish->complete(r);
+        on_cleanup->complete(r);
         return;
       }
 
-      auto req = mirror::DemoteRequest<>::create(*ictx, on_finish);
+      auto req = mirror::DemoteRequest<>::create(*ictx, on_cleanup);
       req->send();
     });
-  if (ictx->state->is_refresh_required()) {
-    ictx->state->refresh(on_refresh);
-  } else {
-    on_refresh->complete(0);
-  }
+
+  // ensure we can create a snapshot after setting the non-primary
+  // feature bit
+  ictx->image_lock.lock();
+  ictx->read_only_mask &= ~IMAGE_READ_ONLY_FLAG_NON_PRIMARY;
+  ictx->image_lock.unlock();
+
+  ictx->state->refresh(on_refresh);
 }
 
 template <typename I>