diff --git a/src/librbd/Journal.cc b/src/librbd/Journal.cc index ad8900d1d06..0e905776bce 100644 --- a/src/librbd/Journal.cc +++ b/src/librbd/Journal.cc @@ -313,7 +313,7 @@ bool Journal::is_journal_supported(I &image_ctx) { template int Journal::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(io_ctx.cct()); ldout(cct, 5) << __func__ << ": image=" << image_id << dendl; @@ -341,12 +341,16 @@ int Journal::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) { diff --git a/src/librbd/Journal.h b/src/librbd/Journal.h index ca294fe27d1..5258ae7db3f 100644 --- a/src/librbd/Journal.h +++ b/src/librbd/Journal.h @@ -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); diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 3b3388182d0..270076d5922 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -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; diff --git a/src/librbd/internal.h b/src/librbd/internal.h index b92e57274b8..ae7b1732b08 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -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, diff --git a/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc b/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc index cd0646b0abc..5b112222c1f 100644 --- a/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc @@ -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(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(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); } };