librbd: support creating images with non-primary journals

When rbd-mirror initially creates a replicated image in the
local pool, the journal should be flagged as non-primary to
(1) prevent local ops againsts the image and (2) provide a
clean chain of replicated tags.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2016-03-23 22:28:55 -04:00
parent f01efc8ce6
commit 7a3ffc9d70
5 changed files with 101 additions and 69 deletions

View File

@ -313,7 +313,7 @@ bool Journal<I>::is_journal_supported(I &image_ctx) {
template <typename I>
int Journal<I>::create(librados::IoCtx &io_ctx, const std::string &image_id,
uint8_t order, uint8_t splay_width,
const std::string &object_pool) {
const std::string &object_pool, bool non_primary) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
@ -341,12 +341,16 @@ int Journal<I>::create(librados::IoCtx &io_ctx, const std::string &image_id,
}
// create tag class for this image's journal events
bufferlist tag_data;
::encode(journal::TagData(), tag_data);
journal::TagData tag_data;
tag_data.mirror_uuid = (!non_primary ? LOCAL_MIRROR_UUID :
ORPHAN_MIRROR_UUID);
bufferlist tag_data_bl;
::encode(tag_data, tag_data_bl);
C_SaferCond tag_ctx;
cls::journal::Tag tag;
journaler.allocate_tag(cls::journal::Tag::TAG_CLASS_NEW, tag_data,
journaler.allocate_tag(cls::journal::Tag::TAG_CLASS_NEW, tag_data_bl,
&tag, &tag_ctx);
r = tag_ctx.wait();
if (r < 0) {

View File

@ -95,7 +95,7 @@ public:
static bool is_journal_supported(ImageCtxT &image_ctx);
static int create(librados::IoCtx &io_ctx, const std::string &image_id,
uint8_t order, uint8_t splay_width,
const std::string &object_pool);
const std::string &object_pool, bool non_primary);
static int remove(librados::IoCtx &io_ctx, const std::string &image_id);
static int reset(librados::IoCtx &io_ctx, const std::string &image_id);

View File

@ -200,6 +200,46 @@ int validate_mirroring_enabled(ImageCtx *ictx) {
return 0;
}
int mirror_image_enable(CephContext *cct, librados::IoCtx &io_ctx,
const std::string &id,
const std::string &global_image_id) {
cls::rbd::MirrorImage mirror_image_internal;
int r = cls_client::mirror_image_get(&io_ctx, id, &mirror_image_internal);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
return r;
}
if (mirror_image_internal.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
// mirroring is already enabled
return 0;
} else if (r != -ENOENT) {
lderr(cct) << "cannot enable mirroring: currently disabling" << dendl;
return -EINVAL;
}
mirror_image_internal.state =
cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
if (global_image_id.empty()) {
uuid_d uuid_gen;
uuid_gen.generate_random();
mirror_image_internal.global_image_id = uuid_gen.to_string();
} else {
mirror_image_internal.global_image_id = global_image_id;
}
r = cls_client::mirror_image_set(&io_ctx, id, mirror_image_internal);
if (r < 0) {
lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
return r;
}
ldout(cct, 20) << "image mirroring is enabled: global_id=" <<
mirror_image_internal.global_image_id << dendl;
return 0;
}
int mirror_image_enable_internal(ImageCtx *ictx) {
CephContext *cct = ictx->cct;
@ -224,42 +264,11 @@ int mirror_image_enable_internal(ImageCtx *ictx) {
return -EINVAL;
}
cls::rbd::MirrorImage mirror_image_internal;
r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id,
&mirror_image_internal);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
return r;
}
if (mirror_image_internal.state ==
cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED) {
// mirroring is already enabled
return 0;
}
else if (r != -ENOENT) {
lderr(cct) << "cannot enable mirroring: mirroring image is in "
"disabling state" << dendl;
return -EINVAL;
}
mirror_image_internal.state =
cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
uuid_d uuid_gen;
uuid_gen.generate_random();
mirror_image_internal.global_image_id = uuid_gen.to_string();
r = cls_client::mirror_image_set(&ictx->md_ctx, ictx->id,
mirror_image_internal);
r = mirror_image_enable(cct, ictx->md_ctx, ictx->id, "");
if (r < 0) {
lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
return r;
}
ldout(cct, 20) << "image mirroring is enabled: global_id=" <<
mirror_image_internal.global_image_id << dendl;
return 0;
}
@ -969,8 +978,8 @@ remove_mirroring_image:
int create_v2(IoCtx& io_ctx, const char *imgname, uint64_t bid, uint64_t size,
int order, uint64_t features, uint64_t stripe_unit,
uint64_t stripe_count, uint8_t journal_order,
uint8_t journal_splay_width,
const std::string &journal_pool)
uint8_t journal_splay_width, const std::string &journal_pool,
const std::string &non_primary_global_image_id)
{
ostringstream bid_ss;
uint32_t extra;
@ -980,6 +989,7 @@ remove_mirroring_image:
CephContext *cct = (CephContext *)io_ctx.cct();
file_layout_t layout;
bool force_non_primary = !non_primary_global_image_id.empty();
int r = validate_pool(io_ctx, cct);
if (r < 0) {
@ -1069,44 +1079,46 @@ remove_mirroring_image:
goto err_remove_object_map;
}
rbd_mirror_mode_t mirror_mode;
r = librbd::mirror_mode_get(io_ctx, &mirror_mode);
if (r < 0) {
lderr(cct) << "error in retrieving pool mirroring status: "
<< cpp_strerror(r) << dendl;
goto err_remove_object_map;
}
r = Journal<>::create(io_ctx, id, journal_order, journal_splay_width,
journal_pool);
journal_pool, force_non_primary);
if (r < 0) {
lderr(cct) << "error creating journal: " << cpp_strerror(r) << dendl;
goto err_remove_object_map;
}
rbd_mirror_mode_t mirror_mode;
r = librbd::mirror_mode_get(io_ctx, &mirror_mode);
if (r < 0) {
lderr(cct) << "error in retrieving pool mirroring status: "
<< cpp_strerror(r) << dendl;
goto err_remove_object_map;
}
if (mirror_mode == RBD_MIRROR_MODE_POOL) {
ImageCtx *img_ctx = new ImageCtx("", id, nullptr, io_ctx, false);
r = img_ctx->state->open();
if (r < 0) {
lderr(cct) << "error opening image: " << cpp_strerror(r) << dendl;
delete img_ctx;
goto err_remove_object_map;
}
r = mirror_image_enable_internal(img_ctx);
if (mirror_mode == RBD_MIRROR_MODE_POOL || force_non_primary) {
r = mirror_image_enable(cct, io_ctx, id, non_primary_global_image_id);
if (r < 0) {
lderr(cct) << "error enabling mirroring: " << cpp_strerror(r)
<< dendl;
img_ctx->state->close();
goto err_remove_object_map;
<< dendl;
goto err_remove_journal;
}
img_ctx->state->close();
}
} else if (force_non_primary) {
// journaling should have been enabled
assert(false);
}
ldout(cct, 2) << "done." << dendl;
return 0;
err_remove_journal:
if ((features & RBD_FEATURE_JOURNALING) != 0) {
remove_r = Journal<>::remove(io_ctx, id);
if (remove_r < 0) {
lderr(cct) << "error cleaning up journal after creation failed: "
<< cpp_strerror(remove_r) << dendl;
}
}
err_remove_object_map:
if ((features & RBD_FEATURE_OBJECT_MAP) != 0) {
remove_r = ObjectMap::remove(io_ctx, id);
@ -1274,7 +1286,8 @@ remove_mirroring_image:
opts.get(RBD_IMAGE_OPTION_JOURNAL_POOL, &journal_pool);
r = create_v2(io_ctx, imgname, bid, size, order, features, stripe_unit,
stripe_count, journal_order, journal_splay_width, journal_pool);
stripe_count, journal_order, journal_splay_width,
journal_pool, "");
}
int r1 = opts.set(RBD_IMAGE_OPTION_ORDER, order);
@ -1617,7 +1630,7 @@ remove_mirroring_image:
r = Journal<>::create(ictx->md_ctx, ictx->id, ictx->journal_order,
ictx->journal_splay_width,
ictx->journal_pool);
ictx->journal_pool, false);
if (r < 0) {
lderr(cct) << "error creating image journal: " << cpp_strerror(r)
<< dendl;

View File

@ -96,6 +96,12 @@ namespace librbd {
uint64_t stripe_unit, uint64_t stripe_count);
int create(IoCtx& io_ctx, const char *imgname, uint64_t size,
ImageOptions& opts);
int create_v2(IoCtx& io_ctx, const char *imgname, uint64_t bid, uint64_t size,
int order, uint64_t features, uint64_t stripe_unit,
uint64_t stripe_count, uint8_t journal_order,
uint8_t journal_splay_width,
const std::string &journal_pool,
const std::string &non_primary_global_image_id);
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,

View File

@ -49,11 +49,20 @@ struct C_CreateImage : public Context {
// TODO: rbd-mirror should offer a feature mask capability
RWLock::RLocker snap_locker(remote_image_ctx->snap_lock);
int order = remote_image_ctx->order;
r = librbd::create(local_io_ctx, local_image_name.c_str(),
remote_image_ctx->size, false,
remote_image_ctx->features, &order,
remote_image_ctx->stripe_unit,
remote_image_ctx->stripe_count);
CephContext *cct = reinterpret_cast<CephContext*>(local_io_ctx.cct());
uint64_t journal_order = cct->_conf->rbd_journal_order;
uint64_t journal_splay_width = cct->_conf->rbd_journal_splay_width;
std::string journal_pool = cct->_conf->rbd_journal_pool;
r = librbd::create_v2(local_io_ctx, local_image_name.c_str(),
reinterpret_cast<uint64_t>(this),
remote_image_ctx->size, order,
remote_image_ctx->features,
remote_image_ctx->stripe_unit,
remote_image_ctx->stripe_count,
journal_order, journal_splay_width, journal_pool,
"global-image-id");
on_finish->complete(r);
}
};