}
};
+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;
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) {
}
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;
}