From: Ricardo Dias Date: Thu, 10 Mar 2016 12:19:24 +0000 (+0000) Subject: rbd: rbd-mirroring: Support mirroring image enable in librbd X-Git-Tag: v10.1.0~94^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=601867ef8f08673edb2071ba5abfb2d583a9e2f4;p=ceph.git rbd: rbd-mirroring: Support mirroring image enable in librbd Signed-off-by: Ricardo Dias --- diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 2b88878be0cb..6a18b1e3dadf 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -587,6 +587,8 @@ CEPH_RBD_API int rbd_metadata_list(rbd_image_t image, const char *start, uint64_ char *keys, size_t *key_len, char *values, size_t *vals_len); +CEPH_RBD_API int rbd_mirror_image_enable(rbd_image_t image); + #ifdef __cplusplus } #endif diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 1f7275adf499..f1c8fc92e821 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -321,6 +321,8 @@ public: */ int metadata_list(const std::string &start, uint64_t max, std::map *pairs); + int mirror_image_enable(); + private: friend class RBD; diff --git a/src/librbd/Journal.cc b/src/librbd/Journal.cc index dcb62ae8f792..de42fefd5735 100644 --- a/src/librbd/Journal.cc +++ b/src/librbd/Journal.cc @@ -391,6 +391,68 @@ int Journal::reset(librados::IoCtx &io_ctx, const std::string &image_id) { return 0; } +template +int Journal::is_tag_owner(ImageCtx *image_ctx, bool *is_tag_owner) { + + cls::journal::Client client; + librbd::journal::ClientData client_data; + bufferlist::iterator bl; + journal::TagData tag_data; + uint64_t tag_class; + librbd::journal::ImageClientMeta *image_client_meta; + Mutex lock("lock"); + C_SaferCond get_tags_ctx; + C_DecodeTags *tags_ctx; + + Journaler journaler(image_ctx->md_ctx, image_ctx->id, IMAGE_CLIENT_ID, + image_ctx->cct->_conf->rbd_journal_commit_age); + + C_SaferCond init_ctx; + journaler.init(&init_ctx); + int r = init_ctx.wait(); + if (r < 0) { + return r; + } + + r = journaler.get_cached_client(Journal::IMAGE_CLIENT_ID, &client); + if (r < 0) { + goto clean_up; + } + + bl = client.data.begin(); + try { + ::decode(client_data, bl); + } catch (const buffer::error &err) { + r = -EINVAL; + goto clean_up; + } + + image_client_meta = + boost::get(&client_data.client_meta); + if (image_client_meta == nullptr) { + r = -EINVAL; + goto clean_up; + } + + tag_class = image_client_meta->tag_class; + uint64_t tag_tid; + tags_ctx = new C_DecodeTags( + image_ctx->cct, &lock, &tag_tid, &tag_data, &get_tags_ctx); + journaler.get_tags(tag_class, &tags_ctx->tags, tags_ctx); + + r = get_tags_ctx.wait(); + if (r < 0) { + goto clean_up; + } + + *is_tag_owner = (tag_data.mirror_uuid == LOCAL_MIRROR_UUID); + +clean_up: + journaler.shut_down(); + + return r; +} + template bool Journal::is_journal_ready() const { Mutex::Locker locker(m_lock); diff --git a/src/librbd/Journal.h b/src/librbd/Journal.h index 8648df500ef7..a8d651363c13 100644 --- a/src/librbd/Journal.h +++ b/src/librbd/Journal.h @@ -109,6 +109,8 @@ public: static int remove(librados::IoCtx &io_ctx, const std::string &image_id); static int reset(librados::IoCtx &io_ctx, const std::string &image_id); + static int is_tag_owner(ImageCtx *image_ctx, bool *is_tag_owner); + bool is_journal_ready() const; bool is_journal_replaying() const; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 1a2e26b6bc1f..e8761014af4e 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -2301,6 +2301,70 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { return cls_client::metadata_list(&ictx->md_ctx, ictx->header_oid, start, max, pairs); } + int mirror_image_enable(ImageCtx *ictx) { + CephContext *cct = ictx->cct; + ldout(cct, 20) << "mirror_image_enable " << ictx << dendl; + + if ((ictx->features & RBD_FEATURE_JOURNALING) == 0) { + lderr(cct) << "cannot enable mirroring: journaling is not enabled" + << dendl; + return -EINVAL; + } + + bool is_primary; + int r = Journal<>::is_tag_owner(ictx, &is_primary); + if (r < 0) { + lderr(cct) << "cannot enable mirroring: failed to check tag ownership: " + << cpp_strerror(r) << dendl; + return r; + } + + if (!is_primary) { + lderr(cct) << + "cannot enable mirroring: last journal tag not owned by local cluster" + << dendl; + 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); + 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_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode) { CephContext *cct = reinterpret_cast(io_ctx.cct()); ldout(cct, 20) << __func__ << dendl; diff --git a/src/librbd/internal.h b/src/librbd/internal.h index 3e448e2bcf84..7457ddb3ad24 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -183,6 +183,7 @@ namespace librbd { int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid, const std::string &cluster_name); + int mirror_image_enable(ImageCtx *ictx); } #endif diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index c31eecc8fb07..57fc3fbdf67d 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1226,6 +1226,11 @@ namespace librbd { return r; } + int Image::mirror_image_enable() { + ImageCtx *ictx = (ImageCtx *)ctx; + return librbd::mirror_image_enable(ictx); + } + } // namespace librbd extern "C" void rbd_version(int *major, int *minor, int *extra) @@ -2553,6 +2558,12 @@ extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t return r; } +extern "C" int rbd_mirror_image_enable(rbd_image_t image) +{ + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + return librbd::mirror_image_enable(ictx); +} + extern "C" int rbd_aio_is_complete(rbd_completion_t c) { librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;