]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: rbd-mirroring: Disable image mirroring depends on pool mirroring mode
authorRicardo Dias <rdias@suse.com>
Mon, 28 Mar 2016 14:11:10 +0000 (15:11 +0100)
committerRicardo Dias <rdias@suse.com>
Tue, 29 Mar 2016 16:26:53 +0000 (17:26 +0100)
Signed-off-by: Ricardo Dias <rdias@suse.com>
Fixes: #15267
src/librbd/internal.cc

index f140a00f10895ae8f0282fce74e967c9535c31c2..3b3388182d0b20f33b1f724f13848bcebe08d900 100644 (file)
@@ -263,6 +263,118 @@ int mirror_image_enable_internal(ImageCtx *ictx) {
   return 0;
 }
 
+int mirror_image_disable_internal(ImageCtx *ictx, bool force) {
+  CephContext *cct = ictx->cct;
+
+  cls::rbd::MirrorImage mirror_image_internal;
+  std::vector<snap_info_t> snaps;
+  std::set<cls::journal::Client> clients;
+  std::string header_oid;
+
+  bool is_primary;
+  int r = Journal<>::is_tag_owner(ictx, &is_primary);
+  if (r < 0) {
+    lderr(cct) << "cannot disable mirroring: failed to check tag ownership: "
+      << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  if (!is_primary) {
+    if (!force) {
+      lderr(cct) << "Mirrored image is not the primary, add force option to"
+        " disable mirroring" << dendl;
+      return -EINVAL;
+    }
+    goto remove_mirroring_image;
+  }
+
+  r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id,
+      &mirror_image_internal);
+  if (r < 0 && r != -ENOENT) {
+    lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+  else if (r == -ENOENT) {
+    // mirroring is not enabled for this image
+    ldout(cct, 20) << "ignoring disable command: mirroring is not enabled "
+      "for this image" << dendl;
+    return 0;
+  }
+
+  mirror_image_internal.state =
+    cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_DISABLING;
+  r = cls_client::mirror_image_set(&ictx->md_ctx, ictx->id,
+      mirror_image_internal);
+  if (r < 0) {
+    lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  header_oid = ::journal::Journaler::header_oid(ictx->id);
+
+  while(true) {
+    r = cls::journal::client::client_list(ictx->md_ctx, header_oid, &clients);
+    if (r < 0) {
+      lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl;
+      return r;
+    }
+
+    assert(clients.size() >= 1);
+
+    if (clients.size() == 1) {
+      // only local journal client remains
+      break;
+    }
+
+    for (auto client : clients) {
+      journal::ClientData client_data;
+      bufferlist::iterator bl = client.data.begin();
+      ::decode(client_data, bl);
+      journal::ClientMetaType type = client_data.get_client_meta_type();
+
+      if (type != journal::ClientMetaType::MIRROR_PEER_CLIENT_META_TYPE) {
+        continue;
+      }
+
+      journal::MirrorPeerClientMeta client_meta =
+        boost::get<journal::MirrorPeerClientMeta>(client_data.client_meta);
+
+      for (const auto& sync : client_meta.sync_points) {
+        r = ictx->operations->snap_remove(sync.snap_name.c_str());
+        if (r < 0 && r != -ENOENT) {
+          lderr(cct) << "cannot disable mirroring: failed to remove temporary"
+            " snapshot created by remote peer: " << cpp_strerror(r) << dendl;
+          return r;
+        }
+      }
+
+      r = cls::journal::client::client_unregister(ictx->md_ctx, header_oid,
+          client.id);
+      if (r < 0 && r != -ENOENT) {
+        lderr(cct) << "cannot disable mirroring: failed to unregister remote"
+          " journal client: " << cpp_strerror(r) << dendl;
+        return r;
+      }
+    }
+  }
+
+remove_mirroring_image:
+  r = cls_client::mirror_image_remove(&ictx->md_ctx, ictx->id);
+  if (r < 0) {
+    lderr(cct) << "failed to remove image from mirroring directory: "
+      << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  ldout(cct, 20) << "removed image state from rbd_mirroring object" << dendl;
+
+  if (is_primary) {
+    // TODO: send notification to mirroring object about update
+  }
+
+  return 0;
+}
+
 } // anonymous namespace
 
   int detect_format(IoCtx &io_ctx, const string &name,
@@ -1580,7 +1692,7 @@ int mirror_image_enable_internal(ImageCtx *ictx) {
               return -EINVAL;
             }
           } else if (mirror_mode == RBD_MIRROR_MODE_POOL) {
-            r = mirror_image_disable(ictx, false);
+            r = mirror_image_disable_internal(ictx, false);
             if (r < 0) {
               lderr(cct) << "error disabling image mirroring: "
                 << cpp_strerror(r) << dendl;
@@ -2517,113 +2629,21 @@ int mirror_image_enable_internal(ImageCtx *ictx) {
     CephContext *cct = ictx->cct;
     ldout(cct, 20) << "mirror_image_disable " << ictx << dendl;
 
-    cls::rbd::MirrorImage mirror_image_internal;
-    std::vector<snap_info_t> snaps;
-    std::set<cls::journal::Client> clients;
-    std::string header_oid;
-
-    bool is_primary;
-    int r = Journal<>::is_tag_owner(ictx, &is_primary);
-    if (r < 0) {
-      lderr(cct) << "cannot disable mirroring: failed to check tag ownership: "
-        << cpp_strerror(r) << dendl;
-      return r;
-    }
-
-    if (!is_primary) {
-      if (!force) {
-        lderr(cct) << "Mirrored image is not the primary, add force option to"
-          " disable mirroring" << dendl;
-        return -EINVAL;
-      }
-      goto remove_mirroring_image;
-    }
-
-    r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id,
-                                     &mirror_image_internal);
-    if (r < 0 && r != -ENOENT) {
-      lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl;
-      return r;
-    }
-    else if (r == -ENOENT) {
-      // mirroring is not enabled for this image
-      ldout(cct, 20) << "ignoring disable command: mirroring is not enabled "
-        "for this image" << dendl;
-      return 0;
-    }
-
-    mirror_image_internal.state =
-      cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_DISABLING;
-    r = cls_client::mirror_image_set(&ictx->md_ctx, ictx->id,
-                                     mirror_image_internal);
-    if (r < 0) {
-      lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl;
-      return r;
-    }
-
-    header_oid = ::journal::Journaler::header_oid(ictx->id);
-
-    while(true) {
-      r = cls::journal::client::client_list(ictx->md_ctx, header_oid, &clients);
-      if (r < 0) {
-        lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl;
-        return r;
-      }
-
-      assert(clients.size() >= 1);
-
-      if (clients.size() == 1) {
-        // only local journal client remains
-        break;
-      }
-
-      for (auto client : clients) {
-        journal::ClientData client_data;
-        bufferlist::iterator bl = client.data.begin();
-        ::decode(client_data, bl);
-        journal::ClientMetaType type = client_data.get_client_meta_type();
-
-        if (type != journal::ClientMetaType::MIRROR_PEER_CLIENT_META_TYPE) {
-          continue;
-        }
-
-        journal::MirrorPeerClientMeta client_meta =
-          boost::get<journal::MirrorPeerClientMeta>(client_data.client_meta);
-
-        for (const auto& sync : client_meta.sync_points) {
-          r = ictx->operations->snap_remove(sync.snap_name.c_str());
-          if (r < 0 && r != -ENOENT) {
-            lderr(cct) << "cannot disable mirroring: failed to remove temporary"
-              " snapshot created by remote peer: " << cpp_strerror(r) << dendl;
-            return r;
-          }
-        }
-
-        r = cls::journal::client::client_unregister(ictx->md_ctx, header_oid,
-                                                    client.id);
-        if (r < 0 && r != -ENOENT) {
-          lderr(cct) << "cannot disable mirroring: failed to unregister remote"
-            " journal client: " << cpp_strerror(r) << dendl;
-          return r;
-        }
-      }
-    }
-
-  remove_mirroring_image:
-    r = cls_client::mirror_image_remove(&ictx->md_ctx, ictx->id);
+    cls::rbd::MirrorMode mirror_mode;
+    int r = cls_client::mirror_mode_get(&ictx->md_ctx, &mirror_mode);
     if (r < 0) {
-      lderr(cct) << "failed to remove image from mirroring directory: "
-        << cpp_strerror(r) << dendl;
+      lderr(cct) << "cannot disable mirroring: failed to retrieve pool "
+        "mirroring mode: " << cpp_strerror(r) << dendl;
       return r;
     }
 
-    ldout(cct, 20) << "removed image state from rbd_mirroring object" << dendl;
-
-    if (is_primary) {
-      // TODO: send notification to mirroring object about update
+    if (mirror_mode != cls::rbd::MIRROR_MODE_IMAGE) {
+      lderr(cct) << "cannot disable mirroring in the current pool mirroring "
+        "mode" << dendl;
+      return -EINVAL;
     }
 
-    return 0;
+    return mirror_image_disable_internal(ictx, force);
   }
 
   int mirror_image_promote(ImageCtx *ictx, bool force) {