From e5f2bb080e401da89e9d33cdc9d7cd021be726d5 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Tue, 15 Mar 2016 15:26:05 -0400 Subject: [PATCH] librbd: initial implementation of mirror image promote/demote Signed-off-by: Jason Dillaman --- src/librbd/internal.cc | 85 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 0dd1fd33ac24..8b10bd1bcdb9 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -183,6 +183,23 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { return 0; } +int validate_mirroring_enabled(ImageCtx *ictx) { + CephContext *cct = ictx->cct; + cls::rbd::MirrorImage mirror_image_internal; + int r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, + &mirror_image_internal); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "failed to retrieve mirroring state: " << cpp_strerror(r) + << dendl; + return r; + } else if (mirror_image_internal.state != + cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED) { + lderr(cct) << "mirroring is not currently enabled" << dendl; + return -EINVAL; + } + return 0; +} + } // anonymous namespace int detect_format(IoCtx &io_ctx, const string &name, @@ -2487,13 +2504,77 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { CephContext *cct = ictx->cct; ldout(cct, 20) << __func__ << ": ictx=" << ictx << ", " << "force=" << force << dendl; - return -EOPNOTSUPP; + + int r = validate_mirroring_enabled(ictx); + if (r < 0) { + return r; + } + + std::string mirror_uuid; + r = Journal<>::get_tag_owner(ictx, &mirror_uuid); + if (r < 0) { + lderr(cct) << "failed to determine tag ownership: " << cpp_strerror(r) + << dendl; + return r; + } else if (mirror_uuid == Journal<>::LOCAL_MIRROR_UUID) { + lderr(cct) << "image is already primary" << dendl; + return -EINVAL; + } else if (mirror_uuid != Journal<>::ORPHAN_MIRROR_UUID && !force) { + lderr(cct) << "image is still primary within a remote cluster" << dendl; + return -EBUSY; + } + + // TODO: need interlock with local rbd-mirror daemon to ensure it has stopped + // replay + + r = Journal<>::allocate_tag(ictx, Journal<>::LOCAL_MIRROR_UUID); + if (r < 0) { + lderr(cct) << "failed to promote image: " << cpp_strerror(r) + << dendl; + return r; + } + return 0; } int mirror_image_demote(ImageCtx *ictx) { CephContext *cct = ictx->cct; ldout(cct, 20) << __func__ << ": ictx=" << ictx << dendl; - return -EOPNOTSUPP; + + int r = validate_mirroring_enabled(ictx); + if (r < 0) { + return r; + } + + bool is_primary; + r = Journal<>::is_tag_owner(ictx, &is_primary); + if (r < 0) { + lderr(cct) << "failed to determine tag ownership: " << cpp_strerror(r) + << dendl; + return r; + } + + if (!is_primary) { + lderr(cct) << "image is not currently the primary" << dendl; + return -EINVAL; + } + + RWLock::RLocker owner_lock(ictx->owner_lock); + C_SaferCond lock_ctx; + ictx->exclusive_lock->request_lock(&lock_ctx); + r = lock_ctx.wait(); + if (r < 0) { + lderr(cct) << "failed to lock image: " << cpp_strerror(r) << dendl; + } else if (!ictx->exclusive_lock->is_lock_owner()) { + lderr(cct) << "failed to acquire exclusive lock" << dendl; + } + + r = Journal<>::allocate_tag(ictx, Journal<>::ORPHAN_MIRROR_UUID); + if (r < 0) { + lderr(cct) << "failed to demote image: " << cpp_strerror(r) + << dendl; + return r; + } + return 0; } int mirror_image_resync(ImageCtx *ictx) { -- 2.47.3