]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: rbd-mirroring: Support mirroring image disable in librbd
authorRicardo Dias <rdias@suse.com>
Thu, 10 Mar 2016 13:02:59 +0000 (13:02 +0000)
committerRicardo Dias <rdias@suse.com>
Mon, 14 Mar 2016 17:56:38 +0000 (17:56 +0000)
Signed-off-by: Ricardo Dias <rdias@suse.com>
src/include/rbd/librbd.h
src/include/rbd/librbd.hpp
src/librbd/internal.cc
src/librbd/internal.h
src/librbd/librbd.cc

index 6a18b1e3dadf38b90947593053071259ae932f73..09ac2aa1904db7f9a22e4d8f3a2a7910af4b3d50 100644 (file)
@@ -588,6 +588,7 @@ CEPH_RBD_API int rbd_metadata_list(rbd_image_t image, const char *start, uint64_
 
 
 CEPH_RBD_API int rbd_mirror_image_enable(rbd_image_t image);
+CEPH_RBD_API int rbd_mirror_image_disable(rbd_image_t image, bool force);
 
 #ifdef __cplusplus
 }
index f1c8fc92e82144402a6067f6a92e95196eb96ffc..d16fd444b36495cf9bef42327065cd039e7bd0ba 100644 (file)
@@ -322,6 +322,7 @@ public:
   int metadata_list(const std::string &start, uint64_t max, std::map<std::string, ceph::bufferlist> *pairs);
 
   int mirror_image_enable();
+  int mirror_image_disable(bool force);
 
 private:
   friend class RBD;
index e8761014af4e492fede0fe545d71e9c95423470e..b282d1df493fc224fb1acea41e2df7a91a03a630 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "cls/rbd/cls_rbd.h"
 #include "cls/rbd/cls_rbd_client.h"
+#include "cls/journal/cls_journal_types.h"
+#include "cls/journal/cls_journal_client.h"
 
 #include "librbd/AioCompletion.h"
 #include "librbd/AioImageRequest.h"
@@ -32,6 +34,7 @@
 #include "librbd/ImageWatcher.h"
 #include "librbd/internal.h"
 #include "librbd/Journal.h"
+#include "librbd/journal/Types.h"
 #include "librbd/ObjectMap.h"
 #include "librbd/Operations.h"
 #include "librbd/parent_types.h"
@@ -39,6 +42,8 @@
 #include "librbd/operation/TrimRequest.h"
 #include "include/util.h"
 
+#include "journal/Journaler.h"
+
 #include <boost/bind.hpp>
 #include <boost/scope_exit.hpp>
 #include <boost/variant.hpp>
@@ -2365,6 +2370,119 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
     return 0;
   }
 
+  int mirror_image_disable(ImageCtx *ictx, bool force) {
+    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);
+    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;
+  }
+
   int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode) {
     CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
     ldout(cct, 20) << __func__ << dendl;
index 7457ddb3ad24748ce089965759e4ffb024d643dc..6a3a5bc37aac91efff59c8ab5d0e7f9919a863e8 100644 (file)
@@ -184,6 +184,7 @@ namespace librbd {
                               const std::string &cluster_name);
 
   int mirror_image_enable(ImageCtx *ictx);
+  int mirror_image_disable(ImageCtx *ictx, bool force);
 }
 
 #endif
index 57fc3fbdf67d81752f9a0beca2f1dc87e7224c57..f118488e787a62e53562cc7fb1b4fa2c99b15293 100644 (file)
@@ -1231,6 +1231,11 @@ namespace librbd {
     return librbd::mirror_image_enable(ictx);
   }
 
+  int Image::mirror_image_disable(bool force) {
+    ImageCtx *ictx = (ImageCtx *)ctx;
+    return librbd::mirror_image_disable(ictx, force);
+  }
+
 } // namespace librbd
 
 extern "C" void rbd_version(int *major, int *minor, int *extra)
@@ -2564,6 +2569,12 @@ extern "C" int rbd_mirror_image_enable(rbd_image_t image)
   return librbd::mirror_image_enable(ictx);
 }
 
+extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
+{
+  librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+  return librbd::mirror_image_disable(ictx, force);
+}
+
 extern "C" int rbd_aio_is_complete(rbd_completion_t c)
 {
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;