]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: rbd-mirroring: Support mirroring image enable in librbd
authorRicardo Dias <rdias@suse.com>
Thu, 10 Mar 2016 12:19:24 +0000 (12:19 +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/Journal.cc
src/librbd/Journal.h
src/librbd/internal.cc
src/librbd/internal.h
src/librbd/librbd.cc

index 2b88878be0cb86b55a39c3dc23c95bf48e1abc3c..6a18b1e3dadf38b90947593053071259ae932f73 100644 (file)
@@ -587,6 +587,8 @@ CEPH_RBD_API int rbd_metadata_list(rbd_image_t image, const char *start, uint64_
     char *keys, size_t *key_len, char *values, size_t *vals_len);
 
 
+CEPH_RBD_API int rbd_mirror_image_enable(rbd_image_t image);
+
 #ifdef __cplusplus
 }
 #endif
index 1f7275adf4994d3bfa7091a63a94c6827d098494..f1c8fc92e82144402a6067f6a92e95196eb96ffc 100644 (file)
@@ -321,6 +321,8 @@ public:
    */
   int metadata_list(const std::string &start, uint64_t max, std::map<std::string, ceph::bufferlist> *pairs);
 
+  int mirror_image_enable();
+
 private:
   friend class RBD;
 
index dcb62ae8f7923cf7735dcbb0574ba3f73b9727ae..de42fefd5735469b9fad2f8aaee1b9232bc0a3eb 100644 (file)
@@ -391,6 +391,68 @@ int Journal<I>::reset(librados::IoCtx &io_ctx, const std::string &image_id) {
   return 0;
 }
 
+template <typename I>
+int Journal<I>::is_tag_owner(ImageCtx *image_ctx, bool *is_tag_owner) {
+
+  cls::journal::Client client;
+  librbd::journal::ClientData client_data;
+  bufferlist::iterator bl;
+  journal::TagData tag_data;
+  uint64_t tag_class;
+  librbd::journal::ImageClientMeta *image_client_meta;
+  Mutex lock("lock");
+  C_SaferCond get_tags_ctx;
+  C_DecodeTags *tags_ctx;
+
+  Journaler journaler(image_ctx->md_ctx, image_ctx->id, IMAGE_CLIENT_ID,
+                      image_ctx->cct->_conf->rbd_journal_commit_age);
+
+  C_SaferCond init_ctx;
+  journaler.init(&init_ctx);
+  int r = init_ctx.wait();
+  if (r < 0) {
+    return r;
+  }
+
+  r = journaler.get_cached_client(Journal<ImageCtx>::IMAGE_CLIENT_ID, &client);
+  if (r < 0) {
+    goto clean_up;
+  }
+
+  bl = client.data.begin();
+  try {
+    ::decode(client_data, bl);
+  } catch (const buffer::error &err) {
+    r = -EINVAL;
+    goto clean_up;
+  }
+
+  image_client_meta =
+    boost::get<librbd::journal::ImageClientMeta>(&client_data.client_meta);
+  if (image_client_meta == nullptr) {
+    r = -EINVAL;
+    goto clean_up;
+  }
+
+  tag_class = image_client_meta->tag_class;
+  uint64_t tag_tid;
+  tags_ctx = new C_DecodeTags(
+    image_ctx->cct, &lock, &tag_tid, &tag_data, &get_tags_ctx);
+  journaler.get_tags(tag_class, &tags_ctx->tags, tags_ctx);
+
+  r = get_tags_ctx.wait();
+  if (r < 0) {
+    goto clean_up;
+  }
+
+  *is_tag_owner = (tag_data.mirror_uuid == LOCAL_MIRROR_UUID);
+
+clean_up:
+  journaler.shut_down();
+
+  return r;
+}
+
 template <typename I>
 bool Journal<I>::is_journal_ready() const {
   Mutex::Locker locker(m_lock);
index 8648df500ef7929314c9284ef42c690bc7139c70..a8d651363c1309e289a2e00e58d2b1ae05b2fb22 100644 (file)
@@ -109,6 +109,8 @@ public:
   static int remove(librados::IoCtx &io_ctx, const std::string &image_id);
   static int reset(librados::IoCtx &io_ctx, const std::string &image_id);
 
+  static int is_tag_owner(ImageCtx *image_ctx, bool *is_tag_owner);
+
   bool is_journal_ready() const;
   bool is_journal_replaying() const;
 
index 1a2e26b6bc1fd553be077e08d52afbb0cafcee35..e8761014af4e492fede0fe545d71e9c95423470e 100644 (file)
@@ -2301,6 +2301,70 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
     return cls_client::metadata_list(&ictx->md_ctx, ictx->header_oid, start, max, pairs);
   }
 
+  int mirror_image_enable(ImageCtx *ictx) {
+    CephContext *cct = ictx->cct;
+    ldout(cct, 20) << "mirror_image_enable " << ictx << dendl;
+
+    if ((ictx->features & RBD_FEATURE_JOURNALING) == 0) {
+      lderr(cct) << "cannot enable mirroring: journaling is not enabled"
+        << dendl;
+      return -EINVAL;
+    }
+
+    bool is_primary;
+    int r = Journal<>::is_tag_owner(ictx, &is_primary);
+    if (r < 0) {
+      lderr(cct) << "cannot enable mirroring: failed to check tag ownership: "
+        << cpp_strerror(r) << dendl;
+      return r;
+    }
+
+    if (!is_primary) {
+      lderr(cct) <<
+        "cannot enable mirroring: last journal tag not owned by local cluster"
+        << dendl;
+      return -EINVAL;
+    }
+
+    cls::rbd::MirrorImage mirror_image_internal;
+    r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id,
+                                 &mirror_image_internal);
+    if (r < 0 && r != -ENOENT) {
+      lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
+      return r;
+    }
+
+    if (mirror_image_internal.state ==
+        cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED) {
+      // mirroring is already enabled
+      return 0;
+    }
+    else if (r != -ENOENT) {
+      lderr(cct) << "cannot enable mirroring: mirroring image is in "
+        "disabling state" << dendl;
+      return -EINVAL;
+    }
+
+    mirror_image_internal.state =
+      cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
+
+    uuid_d uuid_gen;
+    uuid_gen.generate_random();
+    mirror_image_internal.global_image_id = uuid_gen.to_string();
+
+    r = cls_client::mirror_image_set(&ictx->md_ctx, ictx->id,
+                                     mirror_image_internal);
+    if (r < 0) {
+      lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
+      return r;
+    }
+
+    ldout(cct, 20) << "image mirroring is enabled: global_id=" <<
+      mirror_image_internal.global_image_id << dendl;
+
+    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 3e448e2bcf84fae1d813b7ff02c1bdfd03793768..7457ddb3ad24748ce089965759e4ffb024d643dc 100644 (file)
@@ -183,6 +183,7 @@ namespace librbd {
   int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
                               const std::string &cluster_name);
 
+  int mirror_image_enable(ImageCtx *ictx);
 }
 
 #endif
index c31eecc8fb079c48c2c53ddcfc33724f736ac5c1..57fc3fbdf67d81752f9a0beca2f1dc87e7224c57 100644 (file)
@@ -1226,6 +1226,11 @@ namespace librbd {
     return r;
   }
 
+  int Image::mirror_image_enable() {
+    ImageCtx *ictx = (ImageCtx *)ctx;
+    return librbd::mirror_image_enable(ictx);
+  }
+
 } // namespace librbd
 
 extern "C" void rbd_version(int *major, int *minor, int *extra)
@@ -2553,6 +2558,12 @@ extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t
   return r;
 }
 
+extern "C" int rbd_mirror_image_enable(rbd_image_t image)
+{
+  librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+  return librbd::mirror_image_enable(ictx);
+}
+
 extern "C" int rbd_aio_is_complete(rbd_completion_t c)
 {
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;