]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: helper methods for manipulating journal tags from API
authorJason Dillaman <dillaman@redhat.com>
Tue, 15 Mar 2016 19:25:06 +0000 (15:25 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 16 Mar 2016 00:14:45 +0000 (20:14 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/Journal.cc
src/librbd/Journal.h

index de42fefd5735469b9fad2f8aaee1b9232bc0a3eb..a775c5ac16621c52fca6ec3030694228806513c4 100644 (file)
@@ -159,6 +159,52 @@ public:
   }
 };
 
+template <typename I, typename J>
+int open_journaler(I *image_ctx, J *journaler, bool *initialized,
+                   uint64_t *tag_class, journal::TagData *tag_data) {
+  C_SaferCond init_ctx;
+  journaler->init(&init_ctx);
+  int r = init_ctx.wait();
+  *initialized = (r >= 0);
+  if (r < 0) {
+    return r;
+  }
+
+  cls::journal::Client client;
+  r = journaler->get_cached_client(Journal<ImageCtx>::IMAGE_CLIENT_ID, &client);
+  if (r < 0) {
+    return r;
+  }
+
+  librbd::journal::ClientData client_data;
+  bufferlist::iterator bl_it = client.data.begin();
+  try {
+    ::decode(client_data, bl_it);
+  } catch (const buffer::error &err) {
+    return -EINVAL;
+  }
+
+  librbd::journal::ImageClientMeta *image_client_meta =
+    boost::get<librbd::journal::ImageClientMeta>(&client_data.client_meta);
+  if (image_client_meta == nullptr) {
+    return -EINVAL;
+  }
+
+  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);
+
+  r = get_tags_ctx.wait();
+  if (r < 0) {
+    return r;
+  }
+  return 0;
+}
+
 } // anonymous namespace
 
 using util::create_async_context_callback;
@@ -172,6 +218,10 @@ const std::string Journal<I>::IMAGE_CLIENT_ID("");
 template <typename I>
 const std::string Journal<I>::LOCAL_MIRROR_UUID("");
 
+// mirror uuid to use for orphaned (demoted) images
+template <typename I>
+const std::string Journal<I>::ORPHAN_MIRROR_UUID("<orphan>");
+
 template <typename I>
 std::ostream &operator<<(std::ostream &os,
                          const typename Journal<I>::State &state) {
@@ -392,64 +442,76 @@ int Journal<I>::reset(librados::IoCtx &io_ctx, const std::string &image_id) {
 }
 
 template <typename I>
-int Journal<I>::is_tag_owner(ImageCtx *image_ctx, bool *is_tag_owner) {
+int Journal<I>::is_tag_owner(I *image_ctx, bool *is_tag_owner) {
+  std::string mirror_uuid;
+  int r = get_tag_owner(image_ctx, &mirror_uuid);
+  if (r < 0) {
+    return r;
+  }
 
-  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;
+  *is_tag_owner = (mirror_uuid == LOCAL_MIRROR_UUID);
+  return 0;
+}
+
+template <typename I>
+int Journal<I>::get_tag_owner(I *image_ctx, std::string *mirror_uuid) {
+  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);
 
-  C_SaferCond init_ctx;
-  journaler.init(&init_ctx);
-  int r = init_ctx.wait();
-  if (r < 0) {
-    return r;
+  bool initialized;
+  uint64_t tag_class;
+  journal::TagData tag_data;
+  int r = open_journaler(image_ctx, &journaler, &initialized, &tag_class,
+                         &tag_data);
+  if (r >= 0) {
+    *mirror_uuid = tag_data.mirror_uuid;
   }
 
-  r = journaler.get_cached_client(Journal<ImageCtx>::IMAGE_CLIENT_ID, &client);
-  if (r < 0) {
-    goto clean_up;
+  if (initialized) {
+    journaler.shut_down();
   }
+  return r;
+}
 
-  bl = client.data.begin();
-  try {
-    ::decode(client_data, bl);
-  } catch (const buffer::error &err) {
-    r = -EINVAL;
-    goto clean_up;
-  }
+template <typename I>
+int Journal<I>::allocate_tag(I *image_ctx, const std::string &mirror_uuid) {
+  CephContext *cct = image_ctx->cct;
+  ldout(cct, 20) << __func__ << ": mirror_uuid=" << mirror_uuid << dendl;
 
-  image_client_meta =
-    boost::get<librbd::journal::ImageClientMeta>(&client_data.client_meta);
-  if (image_client_meta == nullptr) {
-    r = -EINVAL;
-    goto clean_up;
-  }
+  Journaler journaler(image_ctx->md_ctx, image_ctx->id, IMAGE_CLIENT_ID,
+                      image_ctx->cct->_conf->rbd_journal_commit_age);
 
-  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);
+  bool initialized;
+  uint64_t tag_class;
+  journal::TagData tag_data;
+  int r = open_journaler(image_ctx, &journaler, &initialized, &tag_class,
+                         &tag_data);
+  if (r >= 0) {
+    journal::TagData tag_data;
+    tag_data.mirror_uuid = mirror_uuid;
 
-  r = get_tags_ctx.wait();
-  if (r < 0) {
-    goto clean_up;
-  }
+    // TODO: inject current commit position into tag data
+    tag_data.predecessor_mirror_uuid = mirror_uuid;
 
-  *is_tag_owner = (tag_data.mirror_uuid == LOCAL_MIRROR_UUID);
+    bufferlist tag_bl;
+    ::encode(tag_data, tag_bl);
 
-clean_up:
-  journaler.shut_down();
+    C_SaferCond allocate_tag_ctx;
+    cls::journal::Tag tag;
+    journaler.allocate_tag(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;
+    }
+  }
+
+  if (initialized) {
+    journaler.shut_down();
+  }
   return r;
 }
 
index a8d651363c1309e289a2e00e58d2b1ae05b2fb22..871b8d047d038b5ed70fcd1d40f422da19329ab4 100644 (file)
@@ -96,6 +96,7 @@ public:
 
   static const std::string IMAGE_CLIENT_ID;
   static const std::string LOCAL_MIRROR_UUID;
+  static const std::string ORPHAN_MIRROR_UUID;
 
   typedef std::list<AioObjectRequest *> AioObjectRequests;
 
@@ -109,7 +110,9 @@ 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);
+  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);
 
   bool is_journal_ready() const;
   bool is_journal_replaying() const;