]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: removed synchronous watcher check from remove image state machine 15734/head
authorJason Dillaman <dillaman@redhat.com>
Fri, 16 Jun 2017 17:28:01 +0000 (13:28 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 20 Jun 2017 11:50:43 +0000 (07:50 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/image/RemoveRequest.cc
src/librbd/image/RemoveRequest.h

index 48da5221e88459ce43c00d83dd975b191ccb34ca..5782702d78f926640edc68b57e7088764e181e16 100644 (file)
@@ -165,11 +165,11 @@ void RemoveRequest<I>::check_image_snaps() {
     return;
   }
 
-  check_image_watchers();
+  list_image_watchers();
 }
 
 template<typename I>
-void RemoveRequest<I>::check_image_watchers() {
+void RemoveRequest<I>::list_image_watchers() {
   ldout(m_cct, 20) << dendl;
 
   librados::ObjectReadOperation op;
@@ -177,7 +177,7 @@ void RemoveRequest<I>::check_image_watchers() {
 
   using klass = RemoveRequest<I>;
   librados::AioCompletion *rados_completion =
-    create_rados_callback<klass, &klass::handle_check_image_watchers>(this);
+    create_rados_callback<klass, &klass::handle_list_image_watchers>(this);
 
   int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion,
                                           &op, &m_out_bl);
@@ -186,62 +186,98 @@ void RemoveRequest<I>::check_image_watchers() {
 }
 
 template<typename I>
-void RemoveRequest<I>::filter_out_mirror_watchers() {
-  if (m_watchers.empty()) {
-    return;
-  }
+void RemoveRequest<I>::handle_list_image_watchers(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0) {
-    return;
+  if (r == 0 && m_ret_val < 0) {
+    r = m_ret_val;
   }
-
-  cls::rbd::MirrorImage mirror_image;
-  int r = cls_client::mirror_image_get(&m_image_ctx->md_ctx, m_image_ctx->id,
-                                       &mirror_image);
   if (r < 0) {
-    if (r != -ENOENT) {
-      lderr(m_cct) << "failed to retrieve mirroring state: "
-                       << cpp_strerror(r) << dendl;
-    }
+    lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r)
+                 << dendl;
+    send_close_image(r);
     return;
   }
 
-  if (mirror_image.state != cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
+  get_mirror_image();
+}
+
+template<typename I>
+void RemoveRequest<I>::get_mirror_image() {
+  ldout(m_cct, 20) << dendl;
+  if ((m_watchers.empty()) ||
+      ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0)) {
+    check_image_watchers();
     return;
   }
 
-  std::list<obj_watch_t> mirror_watchers;
-  r = m_image_ctx->md_ctx.list_watchers(RBD_MIRRORING, &mirror_watchers);
-  if (r < 0) {
-    if (r != -ENOENT) {
-      lderr(m_cct) << "error listing mirroring watchers: "
-                       << cpp_strerror(r) << dendl;
-    }
+  librados::ObjectReadOperation op;
+  cls_client::mirror_image_get_start(&op, m_image_id);
+
+  using klass = RemoveRequest<I>;
+  librados::AioCompletion *comp =
+    create_rados_callback<klass, &klass::handle_get_mirror_image>(this);
+  m_out_bl.clear();
+  int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
+  assert(r == 0);
+  comp->release();
+}
+
+template<typename I>
+void RemoveRequest<I>::handle_get_mirror_image(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
+
+  if (r == -ENOENT || r == -EOPNOTSUPP) {
+    check_image_watchers();
     return;
+  } else if (r < 0) {
+    ldout(m_cct, 5) << "error retrieving mirror image: " << cpp_strerror(r)
+                    << dendl;
   }
-  for (auto &watcher : mirror_watchers) {
-    m_watchers.remove_if([watcher] (obj_watch_t &w) {
-        return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0);
-      });
-  }
+
+  list_mirror_watchers();
 }
 
 template<typename I>
-void RemoveRequest<I>::handle_check_image_watchers(int r) {
+void RemoveRequest<I>::list_mirror_watchers() {
+  ldout(m_cct, 20) << dendl;
+
+  librados::ObjectReadOperation op;
+  op.list_watchers(&m_mirror_watchers, &m_ret_val);
+
+  using klass = RemoveRequest<I>;
+  librados::AioCompletion *rados_completion =
+    create_rados_callback<klass, &klass::handle_list_mirror_watchers>(this);
+  m_out_bl.clear();
+  int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, rados_completion,
+                                          &op, &m_out_bl);
+  assert(r == 0);
+  rados_completion->release();
+}
+
+template<typename I>
+void RemoveRequest<I>::handle_list_mirror_watchers(int r) {
   ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (r < 0) {
-    lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r)
-                 << dendl;
-    send_close_image(r);
-    return;
+  if (r == 0 && m_ret_val < 0) {
+    r = m_ret_val;
+  }
+  if (r < 0 && r != -ENOENT) {
+    ldout(m_cct, 5) << "error listing mirror watchers: " << cpp_strerror(r)
+                    << dendl;
+  }
+
+  for (auto &watcher : m_mirror_watchers) {
+    m_watchers.remove_if([watcher] (obj_watch_t &w) {
+        return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0);
+      });
   }
 
-  // If an image is being bootstrapped by rbd-mirror, it implies
-  // that the rbd-mirror daemon currently has the image open.
-  // Permit removal if this is the case.
-  filter_out_mirror_watchers();
+  check_image_watchers();
+}
 
+template<typename I>
+void RemoveRequest<I>::check_image_watchers() {
   if (m_watchers.size() > 1) {
     lderr(m_cct) << "image has watchers - not removing" << dendl;
     send_close_image(-EBUSY);
index 24d94d86b9c8fa558502587aa94d3cd49bc947f2..05adeaa18fd7997e0f67c730ff94c5e81736853e 100644 (file)
@@ -123,6 +123,7 @@ private:
   int m_ret_val = 0;
   bufferlist m_out_bl;
   std::list<obj_watch_t> m_watchers;
+  std::list<obj_watch_t> m_mirror_watchers;
 
   void open_image();
   void handle_open_image(int r);
@@ -145,9 +146,16 @@ private:
   void validate_image_removal();
   void check_image_snaps();
 
-  void filter_out_mirror_watchers();
+  void list_image_watchers();
+  void handle_list_image_watchers(int r);
+
+  void get_mirror_image();
+  void handle_get_mirror_image(int r);
+
+  void list_mirror_watchers();
+  void handle_list_mirror_watchers(int r);
+
   void check_image_watchers();
-  void handle_check_image_watchers(int r);
 
   void check_group();
   void handle_check_group(int r);