set_pool_mirror_mode ${CLUSTER2} ${POOL} 'pool'
for i in ${image2} ${image4}; do
+ enable_journaling ${CLUSTER2} ${POOL} ${i}
wait_for_image_present ${CLUSTER1} ${POOL} ${i} 'present'
wait_for_snap_present ${CLUSTER1} ${POOL} ${i} 'snap2'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${i}
start_mirrors ${CLUSTER1}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted'
set_pool_mirror_mode ${CLUSTER2} ${POOL} 'pool'
+enable_journaling ${CLUSTER2} ${POOL} ${image}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
char *keys, size_t *key_len, char *values, size_t *vals_len);
// RBD image mirroring support functions
-CEPH_RBD_API int rbd_mirror_image_enable(rbd_image_t image);
+CEPH_RBD_API int rbd_mirror_image_enable(rbd_image_t image) CEPH_RBD_DEPRECATED;
+CEPH_RBD_API int rbd_mirror_image_enable2(rbd_image_t image,
+ rbd_mirror_image_mode_t mode);
CEPH_RBD_API int rbd_mirror_image_disable(rbd_image_t image, bool force);
CEPH_RBD_API int rbd_mirror_image_promote(rbd_image_t image, bool force);
CEPH_RBD_API int rbd_mirror_image_demote(rbd_image_t image);
int metadata_list(const std::string &start, uint64_t max, std::map<std::string, ceph::bufferlist> *pairs);
// RBD image mirroring support functions
- int mirror_image_enable();
+ int mirror_image_enable() CEPH_RBD_DEPRECATED;
+ int mirror_image_enable2(mirror_image_mode_t mode);
int mirror_image_disable(bool force);
int mirror_image_promote(bool force);
int mirror_image_demote();
I **src_image_ctx, librados::IoCtx *dst_io_ctx,
std::string *dst_image_name, std::string *dst_image_id,
bool *flatten, bool *mirroring,
+ cls::rbd::MirrorImageMode *mirror_image_mode,
cls::rbd::MigrationState *state,
std::string *state_description) {
CephContext* cct = reinterpret_cast<CephContext *>(io_ctx.cct());
*dst_image_id = migration_spec.image_id;
*flatten = migration_spec.flatten;
*mirroring = migration_spec.mirroring;
+ *mirror_image_mode = migration_spec.mirror_image_mode;
*state = migration_spec.state;
*state_description = migration_spec.state_description;
ldout(cct, 20) << "updated opts=" << opts << dendl;
- Migration migration(image_ctx, dest_io_ctx, dest_image_name, "", opts, flatten > 0,
- false, cls::rbd::MIGRATION_STATE_PREPARING, "", nullptr);
+ Migration migration(image_ctx, dest_io_ctx, dest_image_name, "", opts,
+ flatten > 0, false, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+ cls::rbd::MIGRATION_STATE_PREPARING, "", nullptr);
r = migration.prepare();
features &= ~RBD_FEATURE_MIGRATING;
std::string dest_image_id;
bool flatten;
bool mirroring;
+ cls::rbd::MirrorImageMode mirror_image_mode;
cls::rbd::MigrationState state;
std::string state_description;
int r = open_source_image(io_ctx, image_name, &image_ctx, &dest_io_ctx,
&dest_image_name, &dest_image_id, &flatten,
- &mirroring, &state, &state_description);
+ &mirroring, &mirror_image_mode, &state,
+ &state_description);
if (r < 0) {
return r;
}
ImageOptions opts;
Migration migration(image_ctx, dest_io_ctx, dest_image_name, dest_image_id,
- opts, flatten, mirroring, state, state_description,
- &prog_ctx);
+ opts, flatten, mirroring, mirror_image_mode, state,
+ state_description, &prog_ctx);
r = migration.execute();
if (r < 0) {
return r;
std::string dest_image_id;
bool flatten;
bool mirroring;
+ cls::rbd::MirrorImageMode mirror_image_mode;
cls::rbd::MigrationState state;
std::string state_description;
int r = open_source_image(io_ctx, image_name, &image_ctx, &dest_io_ctx,
&dest_image_name, &dest_image_id, &flatten,
- &mirroring, &state, &state_description);
+ &mirroring, &mirror_image_mode, &state,
+ &state_description);
if (r < 0) {
return r;
}
ImageOptions opts;
Migration migration(image_ctx, dest_io_ctx, dest_image_name, dest_image_id,
- opts, flatten, mirroring, state, state_description,
- &prog_ctx);
+ opts, flatten, mirroring, mirror_image_mode, state,
+ state_description, &prog_ctx);
r = migration.abort();
image_ctx->state->close();
std::string dest_image_id;
bool flatten;
bool mirroring;
+ cls::rbd::MirrorImageMode mirror_image_mode;
cls::rbd::MigrationState state;
std::string state_description;
int r = open_source_image(io_ctx, image_name, &image_ctx, &dest_io_ctx,
&dest_image_name, &dest_image_id, &flatten,
- &mirroring, &state, &state_description);
+ &mirroring, &mirror_image_mode, &state,
+ &state_description);
if (r < 0) {
return r;
}
ImageOptions opts;
Migration migration(image_ctx, dest_io_ctx, dest_image_name, dest_image_id,
- opts, flatten, mirroring, state, state_description,
- &prog_ctx);
+ opts, flatten, mirroring, mirror_image_mode, state,
+ state_description, &prog_ctx);
r = migration.commit();
// image_ctx is closed in commit when removing src image
std::string dest_image_id;
bool flatten;
bool mirroring;
+ cls::rbd::MirrorImageMode mirror_image_mode;
cls::rbd::MigrationState state;
std::string state_description;
int r = open_source_image(io_ctx, image_name, &image_ctx, &dest_io_ctx,
&dest_image_name, &dest_image_id, &flatten,
- &mirroring, &state, &state_description);
+ &mirroring, &mirror_image_mode, &state,
+ &state_description);
if (r < 0) {
return r;
}
ImageOptions opts;
Migration migration(image_ctx, dest_io_ctx, dest_image_name, dest_image_id,
- opts, flatten, mirroring, state, state_description,
- nullptr);
+ opts, flatten, mirroring, mirror_image_mode, state,
+ state_description, nullptr);
r = migration.status(status);
image_ctx->state->close();
const std::string &dstname,
const std::string &dst_image_id,
ImageOptions& opts, bool flatten, bool mirroring,
+ cls::rbd::MirrorImageMode mirror_image_mode,
cls::rbd::MigrationState state,
const std::string &state_description,
ProgressContext *prog_ctx)
m_dst_image_id(dst_image_id.empty() ?
util::generate_image_id(m_dst_io_ctx) : dst_image_id),
m_dst_header_oid(util::header_name(m_dst_image_id)), m_image_options(opts),
- m_flatten(flatten), m_mirroring(mirroring), m_prog_ctx(prog_ctx),
+ m_flatten(flatten), m_mirroring(mirroring),
+ m_mirror_image_mode(mirror_image_mode), m_prog_ctx(prog_ctx),
m_src_migration_spec(cls::rbd::MIGRATION_HEADER_TYPE_SRC,
m_dst_io_ctx.get_id(), m_dst_io_ctx.get_namespace(),
- m_dst_image_name, m_dst_image_id, {}, 0, flatten,
- mirroring, state, state_description),
+ m_dst_image_name, m_dst_image_id, {}, 0, mirroring,
+ mirror_image_mode, flatten, state, state_description),
m_dst_migration_spec(cls::rbd::MIGRATION_HEADER_TYPE_DST,
src_image_ctx->md_ctx.get_id(),
src_image_ctx->md_ctx.get_namespace(),
m_src_image_ctx->name, m_src_image_ctx->id, {}, 0,
- flatten, mirroring, state, state_description) {
+ mirroring, mirror_image_mode, flatten, state,
+ state_description) {
m_src_io_ctx.dup(src_image_ctx->md_ctx);
}
return r;
}
- r = disable_mirroring(m_src_image_ctx, &m_mirroring);
+ r = disable_mirroring(m_src_image_ctx, &m_mirroring, &m_mirror_image_mode);
if (r < 0) {
return r;
}
r = unlink_src_image();
if (r < 0) {
- enable_mirroring(m_src_image_ctx, m_mirroring);
+ enable_mirroring(m_src_image_ctx, m_mirroring, m_mirror_image_mode);
return r;
}
r = set_migration();
if (r < 0) {
relink_src_image();
- enable_mirroring(m_src_image_ctx, m_mirroring);
+ enable_mirroring(m_src_image_ctx, m_mirroring, m_mirror_image_mode);
return r;
}
return r;
}
- r = enable_mirroring(m_src_image_ctx, m_mirroring);
+ r = enable_mirroring(m_src_image_ctx, m_mirroring, m_mirror_image_mode);
if (r < 0) {
return r;
}
return r;
}
- r = enable_mirroring(dst_image_ctx, m_mirroring);
+ r = enable_mirroring(dst_image_ctx, m_mirroring, m_mirror_image_mode);
if (r < 0) {
return r;
}
m_dst_migration_spec = {cls::rbd::MIGRATION_HEADER_TYPE_DST,
m_src_io_ctx.get_id(), m_src_io_ctx.get_namespace(),
m_src_image_name, m_src_image_id, snap_seqs, size,
- m_flatten, m_mirroring,
+ m_mirroring, m_mirror_image_mode, m_flatten,
cls::rbd::MIGRATION_STATE_PREPARING, ""};
r = cls_client::migration_set(&m_dst_io_ctx, m_dst_header_oid,
}
template <typename I>
-int Migration<I>::disable_mirroring(I *image_ctx, bool *was_enabled) {
+int Migration<I>::disable_mirroring(
+ I *image_ctx, bool *was_enabled,
+ cls::rbd::MirrorImageMode *mirror_image_mode) {
*was_enabled = false;
cls::rbd::MirrorImage mirror_image;
if (mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
*was_enabled = true;
+ *mirror_image_mode = mirror_image.mode;
}
ldout(m_cct, 10) << dendl;
}
template <typename I>
-int Migration<I>::enable_mirroring(I *image_ctx, bool was_enabled) {
+int Migration<I>::enable_mirroring(
+ I *image_ctx, bool was_enabled,
+ cls::rbd::MirrorImageMode mirror_image_mode) {
cls::rbd::MirrorMode mirror_mode;
int r = cls_client::mirror_mode_get(&image_ctx->md_ctx, &mirror_mode);
if (r < 0 && r != -ENOENT) {
ldout(m_cct, 10) << dendl;
C_SaferCond ctx;
- auto req = mirror::EnableRequest<I>::create(image_ctx->md_ctx, image_ctx->id,
- "", image_ctx->op_work_queue,
- &ctx);
+ auto req = mirror::EnableRequest<I>::create(
+ image_ctx->md_ctx, image_ctx->id,
+ static_cast<mirror_image_mode_t>(mirror_image_mode), "",
+ image_ctx->op_work_queue, &ctx);
req->send();
r = ctx.wait();
if (r < 0) {
ImageOptions &m_image_options;
bool m_flatten;
bool m_mirroring;
+ cls::rbd::MirrorImageMode m_mirror_image_mode;
ProgressContext *m_prog_ctx;
cls::rbd::MigrationSpec m_src_migration_spec;
Migration(ImageCtxT *image_ctx, librados::IoCtx& dest_io_ctx,
const std::string &dest_image_name, const std::string &dst_image_id,
ImageOptions& opts, bool flatten, bool mirroring,
+ cls::rbd::MirrorImageMode mirror_image_mode,
cls::rbd::MigrationState state, const std::string &state_desc,
ProgressContext *prog_ctx);
int list_src_snaps(std::vector<librbd::snap_info_t> *snaps);
int validate_src_snaps();
- int disable_mirroring(ImageCtxT *image_ctx, bool *was_enabled);
- int enable_mirroring(ImageCtxT *image_ctx, bool was_enabled);
+ int disable_mirroring(ImageCtxT *image_ctx, bool *was_enabled,
+ cls::rbd::MirrorImageMode *mirror_image_mode);
+ int enable_mirroring(ImageCtxT *image_ctx, bool was_enabled,
+ cls::rbd::MirrorImageMode mirror_image_mode);
int set_migration();
int unlink_src_image();
int relink_src_image();
} // anonymous namespace
template <typename I>
-int Mirror<I>::image_enable(I *ictx, bool relax_same_pool_parent_check) {
+int Mirror<I>::image_enable(I *ictx, mirror_image_mode_t mode,
+ bool relax_same_pool_parent_check) {
CephContext *cct = ictx->cct;
- ldout(cct, 20) << "ictx=" << ictx << dendl;
+ ldout(cct, 20) << "ictx=" << ictx << " mode=" << mode
+ << " relax_same_pool_parent_check="
+ << relax_same_pool_parent_check << dendl;
int r = ictx->state->refresh_if_required();
if (r < 0) {
}
}
+ if (mode == RBD_MIRROR_IMAGE_MODE_JOURNAL &&
+ !ictx->test_features(RBD_FEATURE_JOURNALING)) {
+ uint64_t features = RBD_FEATURE_JOURNALING;
+ if (!ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
+ features |= RBD_FEATURE_EXCLUSIVE_LOCK;
+ }
+ r = ictx->operations->update_features(features, true);
+ if (r < 0) {
+ lderr(cct) << "cannot enable journaling: " << cpp_strerror(r) << dendl;
+ return r;
+ }
+ }
+
C_SaferCond ctx;
- auto req = mirror::EnableRequest<ImageCtx>::create(ictx, &ctx);
+ auto req = mirror::EnableRequest<ImageCtx>::create(ictx, mode, &ctx);
req->send();
r = ctx.wait();
rollback = true;
return r;
}
+
+ if (mirror_image_internal.mode == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
+ r = ictx->operations->update_features(RBD_FEATURE_JOURNALING, false);
+ if (r < 0) {
+ lderr(cct) << "cannot disable journaling: " << cpp_strerror(r) << dendl;
+ // not fatal
+ }
+ }
}
return 0;
return r;
}
- r = image_enable(img_ctx, true);
+ r = image_enable(img_ctx, RBD_MIRROR_IMAGE_MODE_JOURNAL, true);
int close_r = img_ctx->state->close();
if (r < 0) {
lderr(cct) << "error enabling mirroring for image "
size_t max,
std::map<std::string, std::string> *ids);
- static int image_enable(ImageCtxT *ictx, bool relax_same_pool_parent_check);
+ static int image_enable(ImageCtxT *ictx, mirror_image_mode_t mode,
+ bool relax_same_pool_parent_check);
static int image_disable(ImageCtxT *ictx, bool force);
static int image_promote(ImageCtxT *ictx, bool force);
static void image_promote(ImageCtxT *ictx, bool force, Context *on_finish);
return r;
}
+ if ((features & RBD_FEATURE_JOURNALING) == 0) {
+ return 0;
+ }
+
cls::rbd::MirrorMode mirror_mode;
r = cls_client::mirror_mode_get(&io_ctx, &mirror_mode);
if (r < 0 && r != -ENOENT) {
ContextWQ *op_work_queue;
ImageCtx::get_thread_pool_instance(cct, &thread_pool, &op_work_queue);
C_SaferCond ctx;
- auto req = mirror::EnableRequest<I>::create(io_ctx, image_id, "",
+ auto req = mirror::EnableRequest<I>::create(io_ctx, image_id,
+ RBD_MIRROR_IMAGE_MODE_JOURNAL, "",
op_work_queue, &ctx);
req->send();
r = ctx.wait();
Context *ctx = create_context_callback<
klass, &klass::handle_enable_mirror>(this);
+ // TODO: in future rbd-mirror will want to enable mirroring
+ // not only in journal mode.
mirror::EnableRequest<I> *req = mirror::EnableRequest<I>::create(
- m_imctx->md_ctx, m_id, m_non_primary_global_image_id,
- m_imctx->op_work_queue, ctx);
+ m_imctx->md_ctx, m_id, RBD_MIRROR_IMAGE_MODE_JOURNAL,
+ m_non_primary_global_image_id, m_imctx->op_work_queue, ctx);
req->send();
}
ldout(m_cct, 15) << dendl;
auto ctx = create_context_callback<
CreateRequest<I>, &CreateRequest<I>::handle_mirror_image_enable>(this);
+
+ // TODO: in future rbd-mirror will want to enable mirroring
+ // not only in journal mode.
auto req = mirror::EnableRequest<I>::create(m_io_ctx, m_image_id,
+ RBD_MIRROR_IMAGE_MODE_JOURNAL,
m_non_primary_global_image_id,
m_op_work_queue, ctx);
req->send();
}
int Image::mirror_image_enable() {
+ return mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL);
+ }
+
+ int Image::mirror_image_enable2(mirror_image_mode_t mode) {
ImageCtx *ictx = (ImageCtx *)ctx;
- return librbd::api::Mirror<>::image_enable(ictx, false);
+ return librbd::api::Mirror<>::image_enable(ictx, mode, false);
}
int Image::mirror_image_disable(bool force) {
}
extern "C" int rbd_mirror_image_enable(rbd_image_t image)
+{
+ return rbd_mirror_image_enable2(image, RBD_MIRROR_IMAGE_MODE_JOURNAL);
+}
+
+extern "C" int rbd_mirror_image_enable2(rbd_image_t image,
+ rbd_mirror_image_mode_t mode)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
- return librbd::api::Mirror<>::image_enable(ictx, false);
+ return librbd::api::Mirror<>::image_enable(ictx, mode, false);
}
extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
template <typename I>
EnableRequest<I>::EnableRequest(librados::IoCtx &io_ctx,
const std::string &image_id,
+ mirror_image_mode_t mode,
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_mode(static_cast<cls::rbd::MirrorImageMode>(mode)),
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())) {
}
if (*result == 0) {
- if (m_mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
+ if (m_mirror_image.mode != m_mode) {
+ lderr(m_cct) << "invalid current image mirror mode" << dendl;
+ *result = -EINVAL;
+ } else if (m_mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
ldout(m_cct, 10) << this << " " << __func__
<< ": mirroring is already enabled" << dendl;
} else {
}
*result = 0;
+ m_mirror_image.mode = m_mode;
if (m_non_primary_global_image_id.empty()) {
uuid_d uuid_gen;
uuid_gen.generate_random();
} else {
m_mirror_image.global_image_id = m_non_primary_global_image_id;
}
-
- send_get_features();
- return nullptr;
-}
-
-template <typename I>
-void EnableRequest<I>::send_get_features() {
- ldout(m_cct, 10) << this << " " << __func__ << dendl;
-
- librados::ObjectReadOperation op;
- cls_client::get_features_start(&op, true);
-
- using klass = EnableRequest<I>;
- librados::AioCompletion *comp =
- create_rados_callback<klass, &klass::handle_get_features>(this);
- m_out_bl.clear();
- int r = m_io_ctx.aio_operate(util::header_name(m_image_id), comp, &op,
- &m_out_bl);
- ceph_assert(r == 0);
- comp->release();
-}
-
-template <typename I>
-Context *EnableRequest<I>::handle_get_features(int *result) {
- ldout(m_cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
-
- uint64_t features, incompatible_features;
- if (*result == 0) {
- auto iter = m_out_bl.cbegin();
- *result = cls_client::get_features_finish(&iter, &features,
- &incompatible_features);
- }
-
- if (*result != 0) {
- lderr(m_cct) << "failed to retrieve image features: "
- << cpp_strerror(*result) << dendl;
- return m_on_finish;
- }
-
- // TODO: be explicit about the image mirror mode
-
- m_mirror_image.mode = (features & RBD_FEATURE_JOURNALING) != 0 ?
- cls::rbd::MIRROR_IMAGE_MODE_JOURNAL : cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT;
m_mirror_image.state = cls::rbd::MIRROR_IMAGE_STATE_ENABLED;
send_get_tag_owner();
#include "include/buffer_fwd.h"
#include "include/rados/librados_fwd.hpp"
+#include "include/rbd/librbd.hpp"
#include "cls/rbd/cls_rbd_types.h"
#include <map>
#include <string>
template <typename ImageCtxT = ImageCtx>
class EnableRequest {
public:
- static EnableRequest *create(ImageCtxT *image_ctx, Context *on_finish) {
- return create(image_ctx->md_ctx, image_ctx->id, "",
+ static EnableRequest *create(ImageCtxT *image_ctx, mirror_image_mode_t mode,
+ Context *on_finish) {
+ return create(image_ctx->md_ctx, image_ctx->id, mode, "",
image_ctx->op_work_queue, on_finish);
}
static EnableRequest *create(librados::IoCtx &io_ctx,
const std::string &image_id,
+ mirror_image_mode_t mode,
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);
+ return new EnableRequest(io_ctx, image_id, mode,
+ non_primary_global_image_id, op_work_queue,
+ on_finish);
}
void send();
* GET_MIRROR_IMAGE * * * * * * *
* | * (on error)
* v *
- * GET_FEATURES * * * * * * * * *
- * | *
- * v *
* GET_TAG_OWNER * * * * * * * *
* | (skip if not needed) *
* v *
*/
EnableRequest(librados::IoCtx &io_ctx, const std::string &image_id,
+ mirror_image_mode_t mode,
const std::string &non_primary_global_image_id,
ContextWQ *op_work_queue, Context *on_finish);
librados::IoCtx &m_io_ctx;
std::string m_image_id;
+ cls::rbd::MirrorImageMode m_mode;
std::string m_non_primary_global_image_id;
ContextWQ *m_op_work_queue;
Context *m_on_finish;
#include "librbd/image/SetFlagsRequest.h"
#include "librbd/io/ImageRequestWQ.h"
#include "librbd/journal/CreateRequest.h"
-#include "librbd/mirror/DisableRequest.h"
#include "librbd/mirror/EnableRequest.h"
#include "librbd/object_map/CreateRequest.h"
CephContext *cct = image_ctx.cct;
if ((m_features & RBD_FEATURE_JOURNALING) == 0) {
- send_get_mirror_image();
+ Context *ctx = create_context_callback<
+ EnableFeaturesRequest<I>,
+ &EnableFeaturesRequest<I>::handle_get_mirror_mode>(this);
+ ctx->complete(-ENOENT);
return;
}
CephContext *cct = image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": r=" << *result << dendl;
+ cls::rbd::MirrorMode mirror_mode = cls::rbd::MIRROR_MODE_DISABLED;
if (*result == 0) {
auto it = m_out_bl.cbegin();
- *result = cls_client::mirror_mode_get_finish(&it, &m_mirror_mode);
+ *result = cls_client::mirror_mode_get_finish(&it, &mirror_mode);
} else if (*result == -ENOENT) {
*result = 0;
}
return handle_finish(*result);
}
- if (m_mirror_mode == cls::rbd::MIRROR_MODE_POOL) {
- m_enable_mirroring = true;
- }
-
- send_get_mirror_image();
- return nullptr;
-}
-
-template <typename I>
-void EnableFeaturesRequest<I>::send_get_mirror_image() {
- I &image_ctx = this->m_image_ctx;
- CephContext *cct = image_ctx.cct;
-
- if (m_mirror_mode != cls::rbd::MIRROR_MODE_IMAGE) {
- Context *ctx = create_context_callback<
- EnableFeaturesRequest<I>,
- &EnableFeaturesRequest<I>::handle_get_mirror_image>(this);
- ctx->complete(-ENOENT);
- return;
- }
-
- ldout(cct, 20) << this << " " << __func__ << dendl;
-
- librados::ObjectReadOperation op;
- cls_client::mirror_image_get_start(&op, image_ctx.id);
-
- using klass = EnableFeaturesRequest<I>;
- librados::AioCompletion *comp =
- create_rados_callback<klass, &klass::handle_get_mirror_image>(this);
- m_out_bl.clear();
- int r = image_ctx.md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
- ceph_assert(r == 0);
- comp->release();
-}
-
-template <typename I>
-Context *EnableFeaturesRequest<I>::handle_get_mirror_image(int *result) {
- I &image_ctx = this->m_image_ctx;
- CephContext *cct = image_ctx.cct;
- ldout(cct, 20) << this << " " << __func__ << ": r=" << *result << dendl;
-
- cls::rbd::MirrorImage mirror_image;
- if (*result == 0) {
- auto it = m_out_bl.cbegin();
- *result = cls_client::mirror_image_get_finish(&it, &mirror_image);
- } else if (*result == -ENOENT) {
- *result = 0;
- }
-
- if (*result < 0) {
- lderr(cct) << "failed to retrieve mirror image info: "
- << cpp_strerror(*result) << dendl;
- return handle_finish(*result);
- }
-
- if (mirror_image.mode == cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) {
- lderr(cct) << "cannot enable journaling: image snapshot mirroring enabled"
- << dendl;
- *result = -EINVAL;
- return handle_finish(*result);
- }
+ m_enable_mirroring = (mirror_mode == cls::rbd::MIRROR_MODE_POOL);
bool create_journal = false;
do {
EnableFeaturesRequest<I>,
&EnableFeaturesRequest<I>::handle_enable_mirror_image>(this);
- mirror::EnableRequest<I> *req =
- mirror::EnableRequest<I>::create(&image_ctx, ctx);
+ mirror::EnableRequest<I> *req = mirror::EnableRequest<I>::create(
+ &image_ctx, RBD_MIRROR_IMAGE_MODE_JOURNAL, ctx);
req->send();
}
#ifndef CEPH_LIBRBD_OPERATION_ENABLE_FEATURES_REQUEST_H
#define CEPH_LIBRBD_OPERATION_ENABLE_FEATURES_REQUEST_H
-#include "cls/rbd/cls_rbd_types.h"
-
#include "librbd/operation/Request.h"
class Context;
* STATE_BLOCK_WRITES
* |
* v
- * STATE_GET_MIRROR_MODE (skip if not
- * | enabling journaling)
- * v
- * STATE_GET_MIRROR_IMAGE (skip if mirror mode
- * | is not IMAGE)
+ * STATE_GET_MIRROR_MODE
+ * |
* v
* STATE_CREATE_JOURNAL (skip if not
* | required)
* STATE_CREATE_OBJECT_MAP (skip if not
* | required)
* v
- * STATE_ENABLE_MIRROR_IMAGE (skip if not
- * | required)
- * v
+ * STATE_ENABLE_MIRROR_IMAGE
+ * |
+ * V
* STATE_NOTIFY_UPDATE
* |
* | (unblock writes)
*
*/
- cls::rbd::MirrorMode m_mirror_mode = cls::rbd::MIRROR_MODE_DISABLED;
-
uint64_t m_features;
bool m_enable_mirroring = false;
void send_get_mirror_mode();
Context *handle_get_mirror_mode(int *result);
- void send_get_mirror_image();
- Context *handle_get_mirror_image(int *result);
-
void send_create_journal();
Context *handle_create_journal(int *result);
int rbd_flush(rbd_image_t image)
int rbd_invalidate_cache(rbd_image_t image)
- int rbd_mirror_image_enable(rbd_image_t image)
+ int rbd_mirror_image_enable2(rbd_image_t image,
+ rbd_mirror_image_mode_t mode)
int rbd_mirror_image_disable(rbd_image_t image, bint force)
int rbd_mirror_image_promote(rbd_image_t image, bint force)
int rbd_mirror_image_demote(rbd_image_t image)
if ret < 0:
raise make_ex(ret, 'error unlocking image')
- def mirror_image_enable(self):
+ def mirror_image_enable(self, mode=RBD_MIRROR_IMAGE_MODE_JOURNAL):
"""
Enable mirroring for the image.
"""
+ cdef rbd_mirror_image_mode_t c_mode = mode
with nogil:
- ret = rbd_mirror_image_enable(self.image)
+ ret = rbd_mirror_image_enable2(self.image, c_mode)
if ret < 0:
raise make_ex(ret, 'error enabling mirroring for image %s' % self.name)
static EnableRequest* s_instance;
static EnableRequest* create(librados::IoCtx &io_ctx,
const std::string &image_id,
+ mirror_image_mode_t mode,
const std::string &non_primary_global_image_id,
MockContextWQ *op_work_queue,
Context *on_finish) {
#include "test/librbd/mock/MockImageCtx.h"
#include "test/librbd/mock/MockJournalPolicy.h"
#include "cls/rbd/cls_rbd_client.h"
-#include "librbd/api/Mirror.h"
#include "librbd/internal.h"
#include "librbd/image/SetFlagsRequest.h"
#include "librbd/io/AioCompletion.h"
ASSERT_EQ(-EINVAL, cond_ctx.wait());
}
-TEST_F(TestMockOperationDisableFeaturesRequest, PoolMirroring) {
+TEST_F(TestMockOperationDisableFeaturesRequest, Mirroring) {
REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
MirrorModeEnabler mirror_mode_enabler(m_ioctx, cls::rbd::MIRROR_MODE_POOL);
ASSERT_EQ(0, cond_ctx.wait());
}
-TEST_F(TestMockOperationDisableFeaturesRequest, ImageMirroring) {
- REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
-
- MirrorModeEnabler mirror_mode_enabler(m_ioctx, cls::rbd::MIRROR_MODE_IMAGE);
-
- librbd::ImageCtx *ictx;
- ASSERT_EQ(0, open_image(m_image_name, &ictx));
- ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(ictx, false));
-
- MockOperationImageCtx mock_image_ctx(*ictx);
- MockExclusiveLock mock_exclusive_lock;
- MockJournal mock_journal;
- MockObjectMap mock_object_map;
- initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
- mock_object_map);
-
- expect_verify_lock_ownership(mock_image_ctx);
-
- MockRemoveJournalRequest mock_remove_journal_request;
- MockDisableMirrorRequest mock_disable_mirror_request;
-
- ::testing::InSequence seq;
- expect_prepare_lock(mock_image_ctx);
- expect_block_writes(mock_image_ctx);
- expect_is_journal_replaying(*mock_image_ctx.journal);
- expect_block_requests(mock_image_ctx);
- expect_unblock_requests(mock_image_ctx);
- expect_unblock_writes(mock_image_ctx);
- expect_handle_prepare_lock_complete(mock_image_ctx);
-
- C_SaferCond cond_ctx;
- MockDisableFeaturesRequest *req = new MockDisableFeaturesRequest(
- mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_JOURNALING, false);
- {
- std::shared_lock owner_locker{mock_image_ctx.owner_lock};
- req->send();
- }
- ASSERT_EQ(-EINVAL, cond_ctx.wait());
-}
-
TEST_F(TestMockOperationDisableFeaturesRequest, MirroringError) {
REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
#include "test/librbd/mock/MockImageCtx.h"
#include "cls/rbd/cls_rbd_client.h"
#include "librbd/Operations.h"
-#include "librbd/api/Mirror.h"
#include "librbd/internal.h"
#include "librbd/image/SetFlagsRequest.h"
#include "librbd/io/AioCompletion.h"
-#include "librbd/mirror/DisableRequest.h"
#include "librbd/mirror/EnableRequest.h"
#include "librbd/journal/CreateRequest.h"
#include "librbd/journal/Types.h"
static EnableRequest *s_instance;
Context *on_finish = nullptr;
- static EnableRequest *create(MockOperationImageCtx *image_ctx, Context *on_finish) {
+ static EnableRequest *create(MockOperationImageCtx *image_ctx,
+ mirror_image_mode_t mirror_image_mode,
+ Context *on_finish) {
ceph_assert(s_instance != nullptr);
s_instance->on_finish = on_finish;
return s_instance;
ASSERT_EQ(-EINVAL, cond_ctx.wait());
}
-TEST_F(TestMockOperationEnableFeaturesRequest, PoolMirroring) {
+TEST_F(TestMockOperationEnableFeaturesRequest, Mirroring) {
REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
MirrorModeEnabler mirror_mode_enabler(m_ioctx, cls::rbd::MIRROR_MODE_POOL);
ASSERT_EQ(0, cond_ctx.wait());
}
-TEST_F(TestMockOperationEnableFeaturesRequest, ImageMirroring) {
- REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
-
- librbd::ImageCtx *ictx;
- ASSERT_EQ(0, open_image(m_image_name, &ictx));
- ensure_features_disabled(ictx, RBD_FEATURE_JOURNALING);
-
- MirrorModeEnabler mirror_mode_enabler(m_ioctx, cls::rbd::MIRROR_MODE_IMAGE);
-
- ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(ictx, false)); // snapshot mode
-
- uint64_t features;
- ASSERT_EQ(0, librbd::get_features(ictx, &features));
-
- MockOperationImageCtx mock_image_ctx(*ictx);
- MockExclusiveLock mock_exclusive_lock;
- MockJournal mock_journal;
- MockObjectMap mock_object_map;
- initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
- mock_object_map);
-
- expect_verify_lock_ownership(mock_image_ctx);
-
- MockCreateJournalRequest mock_create_journal_request;
- MockEnableMirrorRequest mock_enable_mirror_request;
-
- ::testing::InSequence seq;
- expect_prepare_lock(mock_image_ctx);
- expect_block_writes(mock_image_ctx);
- expect_unblock_writes(mock_image_ctx);
- expect_handle_prepare_lock_complete(mock_image_ctx);
-
- C_SaferCond cond_ctx;
- MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
- mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_JOURNALING);
- {
- std::shared_lock owner_locker{mock_image_ctx.owner_lock};
- req->send();
- }
- ASSERT_EQ(-EINVAL, cond_ctx.wait());
-}
-
TEST_F(TestMockOperationEnableFeaturesRequest, JournalingError) {
REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
expect_verify_lock_ownership(mock_image_ctx);
MockCreateJournalRequest mock_create_journal_request;
+ MockEnableMirrorRequest mock_enable_mirror_request;
::testing::InSequence seq;
expect_prepare_lock(mock_image_ctx);
ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
- ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(m_ictx, false));
+ ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+ m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
librbd::mirror_image_info_t info;
ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
- ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(m_ictx, false));
+ ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+ m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
librbd::mirror_image_info_t info;
ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
- ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(m_ictx, false));
+ ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+ m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
librbd::mirror_image_info_t info;
ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(_other_pool_ioctx,
RBD_MIRROR_MODE_IMAGE));
- ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(m_ictx, false));
+ ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+ m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
librbd::mirror_image_info_t info;
ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode));
- ASSERT_EQ(expected_r, image.mirror_image_enable());
+ ASSERT_EQ(expected_r, image.mirror_image_enable2(mirror_image_mode));
librbd::mirror_image_info_t mirror_image;
ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
if (enable_mirroring) {
- ASSERT_EQ(0, image.mirror_image_enable());
+ ASSERT_EQ(0, image.mirror_image_enable2(mirror_image_mode));
}
ASSERT_EQ(expected_r, image.update_features(features, enable));
ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
if (enable_mirroring) {
- ASSERT_EQ(0, image.mirror_image_enable());
+ ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL));
}
if (demote) {
ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
if (enable_mirroring) {
- ASSERT_EQ(0, image.mirror_image_enable());
+ ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL));
}
std::string image_id;
librbd::Image image;
ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
- ASSERT_EQ(0, image.mirror_image_enable());
+ ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL));
setup_mirror_peer(m_ioctx, image);
RBD_MIRROR_MODE_IMAGE, RBD_MIRROR_IMAGE_DISABLED);
}
-TEST_F(TestMirroring, EnableJournaling_In_MirrorModeImage_MirroringEnabled) {
+TEST_F(TestMirroring, EnableJournaling_In_MirrorModeImage_SnapshotMirroringEnabled) {
uint64_t init_features = 0;
init_features |= RBD_FEATURE_OBJECT_MAP;
init_features |= RBD_FEATURE_EXCLUSIVE_LOCK;
uint64_t features = RBD_FEATURE_JOURNALING;
check_mirroring_on_update_features(init_features, true, true, features,
- -EINVAL, RBD_MIRROR_MODE_IMAGE, RBD_MIRROR_IMAGE_ENABLED,
+ 0, RBD_MIRROR_MODE_IMAGE, RBD_MIRROR_IMAGE_ENABLED,
RBD_MIRROR_IMAGE_MODE_SNAPSHOT);
}
images.emplace_back();
ASSERT_EQ(0, m_rbd.open(m_ioctx, images.back(), image_name.c_str()));
- ASSERT_EQ(0, images.back().mirror_image_enable());
+ ASSERT_EQ(0, images.back().mirror_image_enable2(
+ RBD_MIRROR_IMAGE_MODE_JOURNAL));
}
// demote all images
uint64_t features;
ASSERT_TRUE(get_features(&features));
- features &= ~RBD_FEATURE_JOURNALING;
int order = 20;
ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features,
&order));
ASSERT_EQ(-EINVAL, image.mirror_image_create_snapshot(&snap_id));
ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
ASSERT_EQ(-EINVAL, image.mirror_image_create_snapshot(&snap_id));
- ASSERT_EQ(0, image.mirror_image_enable());
+ ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT));
librbd::mirror_image_mode_t mode;
ASSERT_EQ(0, image.mirror_image_get_mode(&mode));
ASSERT_EQ(RBD_MIRROR_IMAGE_MODE_SNAPSHOT, mode);
uint64_t features;
ASSERT_TRUE(get_features(&features));
- features &= ~RBD_FEATURE_JOURNALING;
int order = 20;
ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features,
&order));
librbd::Image image;
ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
- ASSERT_EQ(0, image.mirror_image_enable());
+ ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT));
uint64_t snap_id;
ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
&order));
librbd::Image image;
ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
- ASSERT_EQ(0, image.mirror_image_enable());
+ ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT));
uint64_t snap_id;
ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
librbd::snap_mirror_primary_namespace_t mirror_snap;
uint64_t features;
ASSERT_TRUE(get_features(&features));
- features &= ~RBD_FEATURE_JOURNALING;
int order = 20;
ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features,
&order));
uint64_t features;
ASSERT_TRUE(get_features(&features));
- features &= ~RBD_FEATURE_JOURNALING;
int order = 20;
ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features,
&order));
librbd::Image image;
ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
- ASSERT_EQ(0, image.mirror_image_enable());
+ ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT));
librbd::mirror_image_mode_t mode;
ASSERT_EQ(0, image.mirror_image_get_mode(&mode));
ASSERT_EQ(RBD_MIRROR_IMAGE_MODE_SNAPSHOT, mode);
self.rbd.remove(ioctx, image_name + str(i))
def test_mirror_image_create_snapshot(self):
- if self.image.features() & RBD_FEATURE_JOURNALING != 0:
- self.image.update_features(RBD_FEATURE_JOURNALING, False)
-
assert_raises(InvalidArgument, self.image.mirror_image_create_snapshot)
peer1_uuid = self.rbd.mirror_peer_add(ioctx, "cluster1", "client")
peer2_uuid = self.rbd.mirror_peer_add(ioctx, "cluster2", "client")
self.rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_IMAGE)
- self.image.mirror_image_enable()
+ self.image.mirror_image_disable(False)
+ self.image.mirror_image_enable(RBD_MIRROR_IMAGE_MODE_SNAPSHOT)
mode = self.image.mirror_image_get_mode()
eq(RBD_MIRROR_IMAGE_MODE_SNAPSHOT, mode)
RBD_MIRROR_MODE_IMAGE));
librbd::ImageCtx *ictx;
open_remote_image(&ictx);
- ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(ictx, false));
+ ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+ ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
cls::rbd::MirrorImage mirror_image;
ASSERT_EQ(0, librbd::cls_client::mirror_image_get(&m_remote_ioctx, ictx->id,
&mirror_image));
librbd::Image image;
librbd::RBD rbd;
rbd.open(ioctx, image, name.c_str());
- image.mirror_image_enable();
+ image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL);
librbd::mirror_image_info_t mirror_image_info;
ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image_info,
librbd::Image image;
librbd::RBD rbd;
rbd.open(cioctx, image, name.c_str());
- image.mirror_image_enable();
+ image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL);
librbd::mirror_image_info_t mirror_image_info;
ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image_info,