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) {
on_finish->complete(r);
delete journaler;
});
- image_ctx->op_work_queue->queue(ctx, r);
+ op_work_queue->queue(ctx, r);
}
};
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>
}
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);
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);
#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
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());
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>
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>
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);
* | |\ JOURNAL CREATE .
* | | \ / | .
* v | *<------------/ v .
- * | | FETCH MIRROR IMAGE v
+ * | | MIRROR IMAGE ENABLE .
* | | / | .
- * | JOURNAL REMOVE<--------/ v .
- * | \ MIRROR IMAGE ENABLE .
- * | \ / | .
- * | *<------------/ v .
- * | NOTIFY WATCHERS .
- * | | .
+ * | JOURNAL REMOVE*<-------/ | .
* | v .
* |_____________>___________________<finish> . . . . < . . . .
*
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;
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;
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
int r = opts.set(RBD_IMAGE_OPTION_ORDER, order_);
assert(r == 0);
- r = create(io_ctx, imgname, size, opts, "", "");
+ r = create(io_ctx, imgname, size, opts, "", "", false);
int r1 = opts.get(RBD_IMAGE_OPTION_ORDER, &order_);
assert(r1 == 0);
r = opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count);
assert(r == 0);
- r = create(io_ctx, imgname, size, opts, "", "");
+ r = create(io_ctx, imgname, size, opts, "", "", false);
int r1 = opts.get(RBD_IMAGE_OPTION_ORDER, &order_);
assert(r1 == 0);
int create(IoCtx& io_ctx, const char *imgname, uint64_t size,
ImageOptions& opts,
const std::string &non_primary_global_image_id,
- const std::string &primary_mirror_uuid)
+ const std::string &primary_mirror_uuid,
+ bool skip_mirror_enable)
{
CephContext *cct = (CephContext *)io_ctx.cct();
ldout(cct, 10) << __func__ << " name=" << imgname << ", "
std::string id = util::generate_image_id(io_ctx);
image::CreateRequest<> *req = image::CreateRequest<>::create(
io_ctx, imgname, id, size, opts, non_primary_global_image_id,
- primary_mirror_uuid, &op_work_queue, &cond);
+ primary_mirror_uuid, skip_mirror_enable, &op_work_queue, &cond);
req->send();
r = cond.wait();
c_opts.set(RBD_IMAGE_OPTION_FEATURES, features);
r = create(c_ioctx, c_name, size, c_opts, non_primary_global_image_id,
- primary_mirror_uuid);
+ primary_mirror_uuid, true);
if (r < 0) {
lderr(cct) << "error creating child: " << cpp_strerror(r) << dendl;
return r;
}
}
+ if (c_imctx->test_features(RBD_FEATURE_JOURNALING)) {
+ cls::rbd::MirrorMode mirror_mode_internal =
+ cls::rbd::MIRROR_MODE_DISABLED;
+ r = cls_client::mirror_mode_get(&c_imctx->md_ctx, &mirror_mode_internal);
+ if (r < 0 && r != -ENOENT) {
+ lderr(cct) << "failed to retrieve mirror mode: " << cpp_strerror(r)
+ << dendl;
+ goto err_remove_child;
+ }
+
+ // enable mirroring now that clone has been fully created
+ if (mirror_mode_internal == cls::rbd::MIRROR_MODE_POOL ||
+ !non_primary_global_image_id.empty()) {
+ C_SaferCond ctx;
+ mirror::EnableRequest<ImageCtx> *req =
+ mirror::EnableRequest<ImageCtx>::create(c_imctx->md_ctx, c_imctx->id,
+ non_primary_global_image_id,
+ c_imctx->op_work_queue, &ctx);
+ req->send();
+
+ r = ctx.wait();
+ if (r < 0) {
+ lderr(cct) << "failed to enable mirroring: " << cpp_strerror(r)
+ << dendl;
+ goto err_remove_child;
+ }
+ }
+ }
+
ldout(cct, 2) << "done." << dendl;
r = c_imctx->state->close();
return r;
return -ENOSYS;
}
- int r = create(dest_md_ctx, destname, src_size, opts, "", "");
+ int r = create(dest_md_ctx, destname, src_size, opts, "", "", false);
if (r < 0) {
lderr(cct) << "header creation failed" << dendl;
return r;
int create(IoCtx& io_ctx, const char *imgname, uint64_t size,
ImageOptions& opts,
const std::string &non_primary_global_image_id,
- const std::string &primary_mirror_uuid);
+ const std::string &primary_mirror_uuid,
+ bool skip_mirror_enable);
int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
IoCtx& c_ioctx, const char *c_name,
uint64_t features, int *c_order,
{
TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts.opts);
- int r = librbd::create(io_ctx, name, size, opts, "", "");
+ int r = librbd::create(io_ctx, name, size, opts, "", "", false);
tracepoint(librbd, create4_exit, r);
return r;
}
TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
tracepoint(librbd, create4_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name, size, opts);
librbd::ImageOptions opts_(opts);
- int r = librbd::create(io_ctx, name, size, opts_, "", "");
+ int r = librbd::create(io_ctx, name, size, opts_, "", "", false);
tracepoint(librbd, create4_exit, r);
return r;
}
using util::create_rados_ack_callback;
template <typename I>
-EnableRequest<I>::EnableRequest(I *image_ctx, Context *on_finish)
- : m_io_ctx(&image_ctx->md_ctx), m_image_ctx(image_ctx),
- m_on_finish(on_finish) {
+EnableRequest<I>::EnableRequest(librados::IoCtx &io_ctx,
+ const std::string &image_id,
+ const std::string &non_primary_global_image_id,
+ ContextWQ *op_work_queue, Context *on_finish)
+ : m_io_ctx(io_ctx), m_image_id(image_id),
+ m_non_primary_global_image_id(non_primary_global_image_id),
+ m_op_work_queue(op_work_queue), m_on_finish(on_finish),
+ m_cct(reinterpret_cast<CephContext*>(io_ctx.cct())) {
}
template <typename I>
template <typename I>
void EnableRequest<I>::send_get_tag_owner() {
- CephContext *cct = m_image_ctx->cct;
- ldout(cct, 10) << this << " " << __func__ << dendl;
+ if (!m_non_primary_global_image_id.empty()) {
+ return
+ send_get_mirror_image();
+ }
+ ldout(m_cct, 10) << this << " " << __func__ << dendl;
using klass = EnableRequest<I>;
Context *ctx = create_context_callback<
klass, &klass::handle_get_tag_owner>(this);
-
- librbd::Journal<>::is_tag_owner(m_image_ctx, &m_is_primary, ctx);
+ librbd::Journal<>::is_tag_owner(m_io_ctx, m_image_id, &m_is_primary,
+ m_op_work_queue, ctx);
}
template <typename I>
Context *EnableRequest<I>::handle_get_tag_owner(int *result) {
- CephContext *cct = m_image_ctx->cct;
- ldout(cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
+ ldout(m_cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
if (*result < 0) {
- lderr(cct) << "failed to check tag ownership: " << cpp_strerror(*result)
- << dendl;
+ lderr(m_cct) << "failed to check tag ownership: " << cpp_strerror(*result)
+ << dendl;
return m_on_finish;
}
if (!m_is_primary) {
- lderr(cct) << "last journal tag not owned by local cluster" << dendl;
+ lderr(m_cct) << "last journal tag not owned by local cluster" << dendl;
*result = -EINVAL;
return m_on_finish;
}
template <typename I>
void EnableRequest<I>::send_get_mirror_image() {
- CephContext *cct = m_image_ctx->cct;
- ldout(cct, 10) << this << " " << __func__ << dendl;
+ ldout(m_cct, 10) << this << " " << __func__ << dendl;
librados::ObjectReadOperation op;
- cls_client::mirror_image_get_start(&op, m_image_ctx->id);
+ cls_client::mirror_image_get_start(&op, m_image_id);
using klass = EnableRequest<I>;
librados::AioCompletion *comp =
create_rados_ack_callback<klass, &klass::handle_get_mirror_image>(this);
m_out_bl.clear();
- int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
+ int r = m_io_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
assert(r == 0);
comp->release();
}
template <typename I>
Context *EnableRequest<I>::handle_get_mirror_image(int *result) {
- CephContext *cct = m_image_ctx->cct;
- ldout(cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
+ ldout(m_cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
if (*result == 0) {
bufferlist::iterator iter = m_out_bl.begin();
if (*result == 0) {
if (m_mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
- ldout(cct, 10) << this << " " << __func__
- << ": mirroring is already enabled" << dendl;
+ ldout(m_cct, 10) << this << " " << __func__
+ << ": mirroring is already enabled" << dendl;
} else {
- lderr(cct) << "currently disabling" << dendl;
+ lderr(m_cct) << "currently disabling" << dendl;
*result = -EINVAL;
}
return m_on_finish;
}
if (*result != -ENOENT) {
- lderr(cct) << "failed to retreive mirror image: " << cpp_strerror(*result)
- << dendl;
+ lderr(m_cct) << "failed to retreive mirror image: " << cpp_strerror(*result)
+ << dendl;
return m_on_finish;
}
*result = 0;
m_mirror_image.state = cls::rbd::MIRROR_IMAGE_STATE_ENABLED;
- uuid_d uuid_gen;
- uuid_gen.generate_random();
- m_mirror_image.global_image_id = uuid_gen.to_string();
+ if (m_non_primary_global_image_id.empty()) {
+ uuid_d uuid_gen;
+ uuid_gen.generate_random();
+ m_mirror_image.global_image_id = uuid_gen.to_string();
+ } else {
+ m_mirror_image.global_image_id = m_non_primary_global_image_id;
+ }
send_set_mirror_image();
return nullptr;
template <typename I>
void EnableRequest<I>::send_set_mirror_image() {
- CephContext *cct = m_image_ctx->cct;
- ldout(cct, 10) << this << " " << __func__ << dendl;
+ ldout(m_cct, 10) << this << " " << __func__ << dendl;
librados::ObjectWriteOperation op;
- cls_client::mirror_image_set(&op, m_image_ctx->id, m_mirror_image);
+ cls_client::mirror_image_set(&op, m_image_id, m_mirror_image);
using klass = EnableRequest<I>;
librados::AioCompletion *comp =
create_rados_ack_callback<klass, &klass::handle_set_mirror_image>(this);
m_out_bl.clear();
- int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, comp, &op);
+ int r = m_io_ctx.aio_operate(RBD_MIRRORING, comp, &op);
assert(r == 0);
comp->release();
}
template <typename I>
Context *EnableRequest<I>::handle_set_mirror_image(int *result) {
- CephContext *cct = m_image_ctx->cct;
- ldout(cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
+ ldout(m_cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
if (*result < 0) {
- lderr(cct) << "failed to enable mirroring: " << cpp_strerror(*result)
- << dendl;
+ lderr(m_cct) << "failed to enable mirroring: " << cpp_strerror(*result)
+ << dendl;
return m_on_finish;
}
template <typename I>
void EnableRequest<I>::send_notify_mirroring_watcher() {
- CephContext *cct = m_image_ctx->cct;
- ldout(cct, 10) << this << " " << __func__ << dendl;
+ ldout(m_cct, 10) << this << " " << __func__ << dendl;
using klass = EnableRequest<I>;
Context *ctx = create_context_callback<
klass, &klass::handle_notify_mirroring_watcher>(this);
- MirroringWatcher<>::notify_image_updated(m_image_ctx->md_ctx,
+ MirroringWatcher<>::notify_image_updated(m_io_ctx,
cls::rbd::MIRROR_IMAGE_STATE_ENABLED,
- m_image_ctx->id,
+ m_image_id,
m_mirror_image.global_image_id, ctx);
}
template <typename I>
Context *EnableRequest<I>::handle_notify_mirroring_watcher(int *result) {
- CephContext *cct = m_image_ctx->cct;
- ldout(cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
+ ldout(m_cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
if (*result < 0) {
- lderr(cct) << "failed to send update notification: "
- << cpp_strerror(*result) << dendl;
+ lderr(m_cct) << "failed to send update notification: "
+ << cpp_strerror(*result) << dendl;
*result = 0;
}
#include <string>
class Context;
+class ContextWQ;
namespace librados { class IoCtx; }
class EnableRequest {
public:
static EnableRequest *create(ImageCtxT *image_ctx, Context *on_finish) {
- return new EnableRequest(image_ctx, on_finish);
+ return create(image_ctx->md_ctx, image_ctx->id, "",
+ image_ctx->op_work_queue, on_finish);
+ }
+ static EnableRequest *create(librados::IoCtx &io_ctx,
+ const std::string &image_id,
+ const std::string &non_primary_global_image_id,
+ ContextWQ *op_work_queue, Context *on_finish) {
+ return new EnableRequest(io_ctx, image_id, non_primary_global_image_id,
+ op_work_queue, on_finish);
}
void send();
* <start>
* |
* v
+ * GET_MIRROR_MODE * * * * * * *
+ * | *
+ * v *
* GET_TAG_OWNER * * * * * * * *
* | *
* v *
* @endverbatim
*/
- EnableRequest(ImageCtxT *image_ctx, Context *on_finish);
+ EnableRequest(librados::IoCtx &io_ctx, const std::string &image_id,
+ const std::string &non_primary_global_image_id,
+ ContextWQ *op_work_queue, Context *on_finish);
- librados::IoCtx *m_io_ctx = nullptr;
+ librados::IoCtx &m_io_ctx;
std::string m_image_id;
- ImageCtxT *m_image_ctx = nullptr;
+ std::string m_non_primary_global_image_id;
+ ContextWQ *m_op_work_queue;
Context *m_on_finish;
+ CephContext *m_cct = nullptr;
bool m_is_primary = false;
bufferlist m_out_bl;
cls::rbd::MirrorImage m_mirror_image;
// template definitions
#include "librbd/Journal.cc"
-template class librbd::Journal<librbd::MockJournalImageCtx>;
using ::testing::_;
using ::testing::DoAll;
const librbd::ImageOptions &image_options,
const std::string &non_primary_global_image_id,
const std::string &primary_mirror_uuid,
+ bool skip_mirror_enable,
MockContextWQ *op_work_queue,
Context *on_finish) {
assert(s_instance != nullptr);
+ EXPECT_FALSE(non_primary_global_image_id.empty());
+ EXPECT_FALSE(primary_mirror_uuid.empty());
+ EXPECT_FALSE(skip_mirror_enable);
s_instance->on_finish = on_finish;
s_instance->construct(ioctx);
return s_instance;
librbd::image::CreateRequest<I> *req = librbd::image::CreateRequest<I>::create(
m_local_io_ctx, m_local_image_name, id, m_remote_image_ctx->size,
- image_options, m_global_image_id, m_remote_mirror_uuid,
+ image_options, m_global_image_id, m_remote_mirror_uuid, false,
m_remote_image_ctx->op_work_queue, ctx);
req->send();
}