]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: track if a mirror image resync has been requested
authorJason Dillaman <dillaman@redhat.com>
Tue, 15 Mar 2016 20:20:20 +0000 (16:20 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 16 Mar 2016 00:38:34 +0000 (20:38 -0400)
A secondary image will store its resync request to the primary
image's journal. When the local rbd mirror process detects the
flag being set, it can initiate a resync from the remote.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/Journal.cc
src/librbd/Journal.h
src/librbd/journal/Types.cc
src/librbd/journal/Types.h
src/test/librbd/test_mock_Journal.cc

index a775c5ac16621c52fca6ec3030694228806513c4..ec000f986518789d30db3300e29c4a51550267b1 100644 (file)
@@ -15,6 +15,7 @@
 #include "common/errno.h"
 #include "common/Timer.h"
 #include "common/WorkQueue.h"
+#include <boost/scope_exit.hpp>
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
@@ -161,7 +162,8 @@ public:
 
 template <typename I, typename J>
 int open_journaler(I *image_ctx, J *journaler, bool *initialized,
-                   uint64_t *tag_class, journal::TagData *tag_data) {
+                   journal::ImageClientMeta *client_meta,
+                   journal::TagData *tag_data) {
   C_SaferCond init_ctx;
   journaler->init(&init_ctx);
   int r = init_ctx.wait();
@@ -184,19 +186,19 @@ int open_journaler(I *image_ctx, J *journaler, bool *initialized,
     return -EINVAL;
   }
 
-  librbd::journal::ImageClientMeta *image_client_meta =
-    boost::get<librbd::journal::ImageClientMeta>(&client_data.client_meta);
+  journal::ImageClientMeta *image_client_meta =
+    boost::get<journal::ImageClientMeta>(&client_data.client_meta);
   if (image_client_meta == nullptr) {
     return -EINVAL;
   }
+  *client_meta = *image_client_meta;
 
   C_SaferCond get_tags_ctx;
   Mutex lock("lock");
-  *tag_class = image_client_meta->tag_class;
   uint64_t tag_tid;
   C_DecodeTags *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);
+  journaler->get_tags(client_meta->tag_class, &tags_ctx->tags, tags_ctx);
 
   r = get_tags_ctx.wait();
   if (r < 0) {
@@ -462,9 +464,9 @@ int Journal<I>::get_tag_owner(I *image_ctx, std::string *mirror_uuid) {
                       image_ctx->cct->_conf->rbd_journal_commit_age);
 
   bool initialized;
-  uint64_t tag_class;
+  journal::ImageClientMeta client_meta;
   journal::TagData tag_data;
-  int r = open_journaler(image_ctx, &journaler, &initialized, &tag_class,
+  int r = open_journaler(image_ctx, &journaler, &initialized, &client_meta,
                          &tag_data);
   if (r >= 0) {
     *mirror_uuid = tag_data.mirror_uuid;
@@ -485,34 +487,79 @@ int Journal<I>::allocate_tag(I *image_ctx, const std::string &mirror_uuid) {
                       image_ctx->cct->_conf->rbd_journal_commit_age);
 
   bool initialized;
-  uint64_t tag_class;
+  journal::ImageClientMeta client_meta;
   journal::TagData tag_data;
-  int r = open_journaler(image_ctx, &journaler, &initialized, &tag_class,
+  int r = open_journaler(image_ctx, &journaler, &initialized, &client_meta,
                          &tag_data);
-  if (r >= 0) {
-    journal::TagData tag_data;
-    tag_data.mirror_uuid = mirror_uuid;
+  BOOST_SCOPE_EXIT_ALL(&journaler, &initialized) {
+    if (initialized) {
+      journaler.shut_down();
+    }
+  };
 
-    // TODO: inject current commit position into tag data
-    tag_data.predecessor_mirror_uuid = mirror_uuid;
+  if (r < 0) {
+    return r;
+  }
 
-    bufferlist tag_bl;
-    ::encode(tag_data, tag_bl);
+  // TODO: inject current commit position into tag data
+  tag_data.mirror_uuid = mirror_uuid;
+  tag_data.predecessor_mirror_uuid = mirror_uuid;
 
-    C_SaferCond allocate_tag_ctx;
-    cls::journal::Tag tag;
-    journaler.allocate_tag(tag_class, tag_bl, &tag, &allocate_tag_ctx);
+  bufferlist tag_bl;
+  ::encode(tag_data, tag_bl);
 
-    r = allocate_tag_ctx.wait();
-    if (r < 0) {
-      lderr(cct) << "failed to allocate tag: " << cpp_strerror(r) << dendl;
+  C_SaferCond allocate_tag_ctx;
+  cls::journal::Tag tag;
+  journaler.allocate_tag(client_meta.tag_class, tag_bl, &tag,
+                         &allocate_tag_ctx);
+
+  r = allocate_tag_ctx.wait();
+  if (r < 0) {
+    lderr(cct) << "failed to allocate tag: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  return 0;
+}
+
+template <typename I>
+int Journal<I>::request_resync(I *image_ctx) {
+  CephContext *cct = image_ctx->cct;
+  ldout(cct, 20) << __func__ << dendl;
+
+  Journaler journaler(image_ctx->md_ctx, image_ctx->id, IMAGE_CLIENT_ID,
+                      image_ctx->cct->_conf->rbd_journal_commit_age);
+
+  bool initialized;
+  journal::ImageClientMeta client_meta;
+  journal::TagData tag_data;
+  int r = open_journaler(image_ctx, &journaler, &initialized, &client_meta,
+                         &tag_data);
+  BOOST_SCOPE_EXIT_ALL(&journaler, &initialized) {
+    if (initialized) {
+      journaler.shut_down();
     }
+  };
+
+  if (r < 0) {
+    return r;
   }
 
-  if (initialized) {
-    journaler.shut_down();
+  client_meta.resync_requested = true;
+
+  journal::ClientData client_data(client_meta);
+  bufferlist client_data_bl;
+  ::encode(client_data, client_data_bl);
+
+  C_SaferCond update_client_ctx;
+  journaler.update_client(client_data_bl, &update_client_ctx);
+
+  r = update_client_ctx.wait();
+  if (r < 0) {
+    lderr(cct) << "failed to update client: " << cpp_strerror(r) << dendl;
+    return r;
   }
-  return r;
+  return 0;
 }
 
 template <typename I>
@@ -972,8 +1019,8 @@ void Journal<I>::handle_initialized(int r) {
     return;
   }
 
-  librbd::journal::ImageClientMeta *image_client_meta =
-    boost::get<librbd::journal::ImageClientMeta>(&client_data.client_meta);
+  journal::ImageClientMeta *image_client_meta =
+    boost::get<journal::ImageClientMeta>(&client_data.client_meta);
   if (image_client_meta == nullptr) {
     lderr(cct) << "failed to extract client meta data" << dendl;
     destroy_journaler(-EINVAL);
index 871b8d047d038b5ed70fcd1d40f422da19329ab4..065b202f2246961fdd883146a09b47da2ecb9949 100644 (file)
@@ -113,6 +113,7 @@ public:
   static int is_tag_owner(ImageCtxT *image_ctx, bool *is_tag_owner);
   static int get_tag_owner(ImageCtxT *image_ctx, std::string *mirror_uuid);
   static int allocate_tag(ImageCtxT *image_ctx, const std::string &mirror_uuid);
+  static int request_resync(ImageCtxT *image_ctx);
 
   bool is_journal_ready() const;
   bool is_journal_replaying() const;
index 86d7ec127d33a8a6e87cd3c95277be12123ae990..86fc7e00ca36f2c82358a29a20ff53cfcc4708c9 100644 (file)
@@ -324,14 +324,17 @@ void EventEntry::generate_test_instances(std::list<EventEntry *> &o) {
 
 void ImageClientMeta::encode(bufferlist& bl) const {
   ::encode(tag_class, bl);
+  ::encode(resync_requested, bl);
 }
 
 void ImageClientMeta::decode(__u8 version, bufferlist::iterator& it) {
   ::decode(tag_class, it);
+  ::decode(resync_requested, it);
 }
 
 void ImageClientMeta::dump(Formatter *f) const {
   f->dump_unsigned("tag_class", tag_class);
+  f->dump_bool("resync_requested", resync_requested);
 }
 
 void MirrorPeerSyncPoint::encode(bufferlist& bl) const {
index b19850daa675f9a8d25a0e1b57c3a6a673f9ad8e..20803995b5df387a0d75cb7464cb49f1e55ffe36 100644 (file)
@@ -308,6 +308,7 @@ struct ImageClientMeta {
   static const ClientMetaType TYPE = IMAGE_CLIENT_META_TYPE;
 
   uint64_t tag_class = 0;
+  bool resync_requested = false;
 
   ImageClientMeta() {
   }
index 7c64611dc2846c0fc131786703330d00ddc8c380..050a4d06a89adddf74848d0c908db2598ba74024 100644 (file)
@@ -90,6 +90,7 @@ struct MockJournaler {
   MOCK_METHOD1(flush_commit_position, void(Context*));
 
   MOCK_METHOD2(get_cached_client, int(const std::string&, cls::journal::Client*));
+  MOCK_METHOD2(update_client, void(const bufferlist &, Context *));
   MOCK_METHOD3(get_tags, void(uint64_t, journal::Journaler::Tags*, Context*));
 
   MOCK_METHOD1(start_replay, void(::journal::ReplayHandler *replay_handler));
@@ -153,6 +154,9 @@ struct MockJournalerProxy {
                         cls::journal::Client* client) {
     return MockJournaler::get_instance().get_cached_client(client_id, client);
   }
+  void update_client(const bufferlist &client_data, Context *on_finish) {
+    MockJournaler::get_instance().update_client(client_data, on_finish);
+  }
 
   void get_tags(uint64_t tag_class, journal::Journaler::Tags *tags,
                 Context *on_finish) {