Permalink
Browse files

Merge pull request #12839 from dillaman/wip-17993

librbd: delay mirror registration when creating clones

Reviewed-by: Mykola Golub <mgolub@mirantis.com>
  • Loading branch information...
2 parents 31f76d1 + 778e112 commit 3aca476a977fdd1bf321a561a9be59bb12d7e8fe @trociny trociny committed on GitHub Jan 11, 2017
View
@@ -53,25 +53,29 @@ class ThreadPoolSingleton : public ThreadPool {
template <typename I>
struct C_IsTagOwner : public Context {
- I *image_ctx;
+ librados::IoCtx &io_ctx;
+ std::string image_id;
bool *is_tag_owner;
+ ContextWQ *op_work_queue;
Context *on_finish;
+ CephContext *cct = nullptr;
Journaler *journaler;
cls::journal::Client client;
journal::ImageClientMeta client_meta;
uint64_t tag_tid;
journal::TagData tag_data;
- C_IsTagOwner(I *image_ctx, bool *is_tag_owner, Context *on_finish)
- : image_ctx(image_ctx), is_tag_owner(is_tag_owner), on_finish(on_finish),
- journaler(new Journaler(image_ctx->md_ctx, image_ctx->id,
- Journal<>::IMAGE_CLIENT_ID, {})) {
+ C_IsTagOwner(librados::IoCtx &io_ctx, const std::string &image_id,
+ bool *is_tag_owner, ContextWQ *op_work_queue, Context *on_finish)
+ : io_ctx(io_ctx), image_id(image_id), is_tag_owner(is_tag_owner),
+ op_work_queue(op_work_queue), on_finish(on_finish),
+ cct(reinterpret_cast<CephContext*>(io_ctx.cct())),
+ journaler(new Journaler(io_ctx, image_id, Journal<>::IMAGE_CLIENT_ID,
+ {})) {
}
virtual void finish(int r) {
- CephContext *cct = image_ctx->cct;
-
ldout(cct, 20) << this << " C_IsTagOwner::" << __func__ << ": r=" << r
<< dendl;
if (r < 0) {
@@ -88,7 +92,7 @@ struct C_IsTagOwner : public Context {
on_finish->complete(r);
delete journaler;
});
- image_ctx->op_work_queue->queue(ctx, r);
+ op_work_queue->queue(ctx, r);
}
};
@@ -432,7 +436,8 @@ int Journal<I>::reset(librados::IoCtx &io_ctx, const std::string &image_id) {
template <typename I>
int Journal<I>::is_tag_owner(I *image_ctx, bool *is_tag_owner) {
- return Journal<>::is_tag_owner(image_ctx->md_ctx, image_ctx->id, is_tag_owner);
+ return Journal<>::is_tag_owner(image_ctx->md_ctx, image_ctx->id,
+ is_tag_owner);
}
template <typename I>
@@ -449,13 +454,21 @@ int Journal<I>::is_tag_owner(IoCtx& io_ctx, std::string& image_id,
}
template <typename I>
-void Journal<I>::is_tag_owner(I *image_ctx, bool *is_tag_owner,
+void Journal<I>::is_tag_owner(I *image_ctx, bool *owner,
Context *on_finish) {
- CephContext *cct = image_ctx->cct;
+ is_tag_owner(image_ctx->md_ctx, image_ctx->id, owner,
+ image_ctx->op_work_queue, on_finish);
+}
+
+template <typename I>
+void Journal<I>::is_tag_owner(librados::IoCtx& io_ctx, std::string& image_id,
+ bool *is_tag_owner, ContextWQ *op_work_queue,
+ Context *on_finish) {
+ CephContext *cct = reinterpret_cast<CephContext*>(io_ctx.cct());
ldout(cct, 20) << __func__ << dendl;
C_IsTagOwner<I> *is_tag_owner_ctx = new C_IsTagOwner<I>(
- image_ctx, is_tag_owner, on_finish);
+ io_ctx, image_id, is_tag_owner, op_work_queue, on_finish);
get_tags(cct, is_tag_owner_ctx->journaler, &is_tag_owner_ctx->client,
&is_tag_owner_ctx->client_meta, &is_tag_owner_ctx->tag_tid,
&is_tag_owner_ctx->tag_data, is_tag_owner_ctx);
@@ -107,6 +107,9 @@ class Journal {
bool *is_tag_owner);
static void is_tag_owner(ImageCtxT *image_ctx, bool *is_tag_owner,
Context *on_finish);
+ static void is_tag_owner(librados::IoCtx& io_ctx, std::string& image_id,
+ bool *is_tag_owner, ContextWQ *op_work_queue,
+ Context *on_finish);
static int get_tag_owner(ImageCtxT *image_ctx, std::string *mirror_uuid);
static int get_tag_owner(librados::IoCtx& io_ctx, std::string& image_id,
std::string *mirror_uuid);
@@ -10,10 +10,11 @@
#include "common/ceph_context.h"
#include "librbd/AioCompletion.h"
#include "librbd/Journal.h"
+#include "librbd/MirroringWatcher.h"
#include "librbd/journal/CreateRequest.h"
#include "librbd/journal/RemoveRequest.h"
+#include "librbd/mirror/EnableRequest.h"
#include "journal/Journaler.h"
-#include "librbd/MirroringWatcher.h"
#define dout_subsys ceph_subsys_rbd
#undef dout_prefix
@@ -122,10 +123,12 @@ CreateRequest<I>::CreateRequest(IoCtx &ioctx, const std::string &image_name,
const ImageOptions &image_options,
const std::string &non_primary_global_image_id,
const std::string &primary_mirror_uuid,
+ bool skip_mirror_enable,
ContextWQ *op_work_queue, Context *on_finish)
: m_image_name(image_name), m_image_id(image_id), m_size(size),
m_non_primary_global_image_id(non_primary_global_image_id),
m_primary_mirror_uuid(primary_mirror_uuid),
+ m_skip_mirror_enable(skip_mirror_enable),
m_op_work_queue(op_work_queue), m_on_finish(on_finish) {
m_ioctx.dup(ioctx);
m_cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
@@ -639,134 +642,40 @@ Context* CreateRequest<I>::handle_journal_create(int *result) {
return nullptr;
}
- fetch_mirror_image();
+ mirror_image_enable();
return nullptr;
}
template<typename I>
-void CreateRequest<I>::fetch_mirror_image() {
- if ((m_mirror_mode != RBD_MIRROR_MODE_POOL) && !m_force_non_primary) {
+void CreateRequest<I>::mirror_image_enable() {
+ if (((m_mirror_mode != RBD_MIRROR_MODE_POOL) && !m_force_non_primary) ||
+ m_skip_mirror_enable) {
complete(0);
return;
}
ldout(m_cct, 20) << this << " " << __func__ << dendl;
-
- librados::ObjectReadOperation op;
- cls_client::mirror_image_get_start(&op, m_image_id);
-
- using klass = CreateRequest<I>;
- librados::AioCompletion *comp =
- create_rados_ack_callback<klass, &klass::handle_fetch_mirror_image>(this);
- m_outbl.clear();
- int r = m_ioctx.aio_operate(RBD_MIRRORING, comp, &op, &m_outbl);
- assert(r == 0);
- comp->release();
-}
-
-template<typename I>
-Context *CreateRequest<I>::handle_fetch_mirror_image(int *result) {
- ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl;
-
- if ((*result < 0) && (*result != -ENOENT)) {
- lderr(m_cct) << "cannot enable mirroring: " << cpp_strerror(*result) << dendl;
-
- m_r_saved = *result;
- journal_remove();
- return nullptr;
- }
-
- if (*result == 0) {
- bufferlist::iterator it = m_outbl.begin();
- *result = cls_client::mirror_image_get_finish(&it, &m_mirror_image_internal);
- if (*result < 0) {
- lderr(m_cct) << "cannot enable mirroring: " << cpp_strerror(*result) << dendl;
-
- m_r_saved = *result;
- journal_remove();
- return nullptr;
- }
-
- if (m_mirror_image_internal.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
- return m_on_finish;
- }
- }
-
- // enable image mirroring (-ENOENT or disabled earlier)
- mirror_image_enable();
- return nullptr;
-}
-
-template<typename I>
-void CreateRequest<I>::mirror_image_enable() {
- ldout(m_cct, 20) << this << " " << __func__ << dendl;
-
- m_mirror_image_internal.state = cls::rbd::MIRROR_IMAGE_STATE_ENABLED;
- if (m_non_primary_global_image_id.empty()) {
- uuid_d uuid_gen;
- uuid_gen.generate_random();
- m_mirror_image_internal.global_image_id = uuid_gen.to_string();
- } else {
- m_mirror_image_internal.global_image_id = m_non_primary_global_image_id;
- }
-
- librados::ObjectWriteOperation op;
- cls_client::mirror_image_set(&op, m_image_id, m_mirror_image_internal);
-
- using klass = CreateRequest<I>;
- librados::AioCompletion *comp =
- create_rados_ack_callback<klass, &klass::handle_mirror_image_enable>(this);
- int r = m_ioctx.aio_operate(RBD_MIRRORING, comp, &op);
- assert(r == 0);
- comp->release();
+ auto ctx = create_context_callback<
+ CreateRequest<I>, &CreateRequest<I>::handle_mirror_image_enable>(this);
+ auto req = mirror::EnableRequest<I>::create(m_ioctx, m_image_id,
+ m_non_primary_global_image_id,
+ m_op_work_queue, ctx);
+ req->send();
}
template<typename I>
Context *CreateRequest<I>::handle_mirror_image_enable(int *result) {
ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl;
if (*result < 0) {
- lderr(m_cct) << "cannot enable mirroring: " << cpp_strerror(*result) << dendl;
+ lderr(m_cct) << "cannot enable mirroring: " << cpp_strerror(*result)
+ << dendl;
m_r_saved = *result;
journal_remove();
return nullptr;
}
-
- send_watcher_notification();
- return nullptr;
-}
-
-// TODO: make this *really* async
-template<typename I>
-void CreateRequest<I>::send_watcher_notification() {
- ldout(m_cct, 20) << this << " " << __func__ << dendl;
-
- Context *ctx = new FunctionContext([this](int r) {
- r = MirroringWatcher<>::notify_image_updated(
- m_ioctx, cls::rbd::MIRROR_IMAGE_STATE_ENABLED,
- m_image_id, m_mirror_image_internal.global_image_id);
- handle_watcher_notify(r);
- });
-
- m_op_work_queue->queue(ctx, 0);
-}
-
-template<typename I>
-void CreateRequest<I>::handle_watcher_notify(int r) {
- ldout(m_cct, 20) << __func__ << ": r=" << r << dendl;
-
- if (r < 0) {
- // non fatal error -- watchers would cope up upon noticing missing
- // updates. just log and move on...
- ldout(m_cct, 10) << "failed to send update notification: " << cpp_strerror(r)
- << dendl;
- } else {
- ldout(m_cct, 20) << "image mirroring is enabled: global_id=" <<
- m_mirror_image_internal.global_image_id << dendl;
- }
-
- complete(0);
+ return m_on_finish;
}
template<typename I>
@@ -35,10 +35,12 @@ class CreateRequest {
const ImageOptions &image_options,
const std::string &non_primary_global_image_id,
const std::string &primary_mirror_uuid,
+ bool skip_mirror_enable,
ContextWQ *op_work_queue, Context *on_finish) {
return new CreateRequest(ioctx, image_name, image_id, size, image_options,
non_primary_global_image_id, primary_mirror_uuid,
- op_work_queue, on_finish);
+ skip_mirror_enable, op_work_queue,
+ on_finish);
}
static int validate_order(CephContext *cct, uint8_t order);
@@ -79,14 +81,9 @@ class CreateRequest {
* | |\ JOURNAL CREATE .
* | | \ / | .
* v | *<------------/ v .
- * | | FETCH MIRROR IMAGE v
+ * | | MIRROR IMAGE ENABLE .
* | | / | .
- * | JOURNAL REMOVE<--------/ v .
- * | \ MIRROR IMAGE ENABLE .
- * | \ / | .
- * | *<------------/ v .
- * | NOTIFY WATCHERS .
- * | | .
+ * | JOURNAL REMOVE*<-------/ | .
* | v .
* |_____________>___________________<finish> . . . . < . . . .
*
@@ -98,6 +95,7 @@ class CreateRequest {
const ImageOptions &image_options,
const std::string &non_primary_global_image_id,
const std::string &primary_mirror_uuid,
+ bool skip_mirror_enable,
ContextWQ *op_work_queue, Context *on_finish);
IoCtx m_ioctx;
@@ -115,6 +113,7 @@ class CreateRequest {
int64_t m_data_pool_id = -1;
const std::string m_non_primary_global_image_id;
const std::string m_primary_mirror_uuid;
+ bool m_skip_mirror_enable;
bool m_negotiate_features = false;
ContextWQ *m_op_work_queue;
@@ -157,15 +156,9 @@ class CreateRequest {
void journal_create();
Context *handle_journal_create(int *result);
- void fetch_mirror_image();
- Context *handle_fetch_mirror_image(int *result);
-
void mirror_image_enable();
Context *handle_mirror_image_enable(int *result);
- void send_watcher_notification();
- void handle_watcher_notify(int r);
-
void complete(int r);
// cleanup
Oops, something went wrong.

0 comments on commit 3aca476

Please sign in to comment.