From 872b1b1cdc6b79f6cfaeef11ac9e47d4b3e47609 Mon Sep 17 00:00:00 2001 From: Ricardo Dias Date: Mon, 28 Mar 2016 15:11:10 +0100 Subject: [PATCH] rbd: rbd-mirroring: Disable image mirroring depends on pool mirroring mode Signed-off-by: Ricardo Dias Fixes: #15267 --- src/librbd/internal.cc | 224 ++++++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 102 deletions(-) diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index f140a00f10895..3b3388182d0b2 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -263,6 +263,118 @@ int mirror_image_enable_internal(ImageCtx *ictx) { return 0; } +int mirror_image_disable_internal(ImageCtx *ictx, bool force) { + CephContext *cct = ictx->cct; + + cls::rbd::MirrorImage mirror_image_internal; + std::vector snaps; + std::set clients; + std::string header_oid; + + bool is_primary; + int r = Journal<>::is_tag_owner(ictx, &is_primary); + if (r < 0) { + lderr(cct) << "cannot disable mirroring: failed to check tag ownership: " + << cpp_strerror(r) << dendl; + return r; + } + + if (!is_primary) { + if (!force) { + lderr(cct) << "Mirrored image is not the primary, add force option to" + " disable mirroring" << dendl; + return -EINVAL; + } + goto remove_mirroring_image; + } + + r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, + &mirror_image_internal); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl; + return r; + } + else if (r == -ENOENT) { + // mirroring is not enabled for this image + ldout(cct, 20) << "ignoring disable command: mirroring is not enabled " + "for this image" << dendl; + return 0; + } + + mirror_image_internal.state = + cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_DISABLING; + r = cls_client::mirror_image_set(&ictx->md_ctx, ictx->id, + mirror_image_internal); + if (r < 0) { + lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl; + return r; + } + + header_oid = ::journal::Journaler::header_oid(ictx->id); + + while(true) { + r = cls::journal::client::client_list(ictx->md_ctx, header_oid, &clients); + if (r < 0) { + lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl; + return r; + } + + assert(clients.size() >= 1); + + if (clients.size() == 1) { + // only local journal client remains + break; + } + + for (auto client : clients) { + journal::ClientData client_data; + bufferlist::iterator bl = client.data.begin(); + ::decode(client_data, bl); + journal::ClientMetaType type = client_data.get_client_meta_type(); + + if (type != journal::ClientMetaType::MIRROR_PEER_CLIENT_META_TYPE) { + continue; + } + + journal::MirrorPeerClientMeta client_meta = + boost::get(client_data.client_meta); + + for (const auto& sync : client_meta.sync_points) { + r = ictx->operations->snap_remove(sync.snap_name.c_str()); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "cannot disable mirroring: failed to remove temporary" + " snapshot created by remote peer: " << cpp_strerror(r) << dendl; + return r; + } + } + + r = cls::journal::client::client_unregister(ictx->md_ctx, header_oid, + client.id); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "cannot disable mirroring: failed to unregister remote" + " journal client: " << cpp_strerror(r) << dendl; + return r; + } + } + } + +remove_mirroring_image: + r = cls_client::mirror_image_remove(&ictx->md_ctx, ictx->id); + if (r < 0) { + lderr(cct) << "failed to remove image from mirroring directory: " + << cpp_strerror(r) << dendl; + return r; + } + + ldout(cct, 20) << "removed image state from rbd_mirroring object" << dendl; + + if (is_primary) { + // TODO: send notification to mirroring object about update + } + + return 0; +} + } // anonymous namespace int detect_format(IoCtx &io_ctx, const string &name, @@ -1580,7 +1692,7 @@ int mirror_image_enable_internal(ImageCtx *ictx) { return -EINVAL; } } else if (mirror_mode == RBD_MIRROR_MODE_POOL) { - r = mirror_image_disable(ictx, false); + r = mirror_image_disable_internal(ictx, false); if (r < 0) { lderr(cct) << "error disabling image mirroring: " << cpp_strerror(r) << dendl; @@ -2517,113 +2629,21 @@ int mirror_image_enable_internal(ImageCtx *ictx) { CephContext *cct = ictx->cct; ldout(cct, 20) << "mirror_image_disable " << ictx << dendl; - cls::rbd::MirrorImage mirror_image_internal; - std::vector snaps; - std::set clients; - std::string header_oid; - - bool is_primary; - int r = Journal<>::is_tag_owner(ictx, &is_primary); - if (r < 0) { - lderr(cct) << "cannot disable mirroring: failed to check tag ownership: " - << cpp_strerror(r) << dendl; - return r; - } - - if (!is_primary) { - if (!force) { - lderr(cct) << "Mirrored image is not the primary, add force option to" - " disable mirroring" << dendl; - return -EINVAL; - } - goto remove_mirroring_image; - } - - r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, - &mirror_image_internal); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl; - return r; - } - else if (r == -ENOENT) { - // mirroring is not enabled for this image - ldout(cct, 20) << "ignoring disable command: mirroring is not enabled " - "for this image" << dendl; - return 0; - } - - mirror_image_internal.state = - cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_DISABLING; - r = cls_client::mirror_image_set(&ictx->md_ctx, ictx->id, - mirror_image_internal); - if (r < 0) { - lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl; - return r; - } - - header_oid = ::journal::Journaler::header_oid(ictx->id); - - while(true) { - r = cls::journal::client::client_list(ictx->md_ctx, header_oid, &clients); - if (r < 0) { - lderr(cct) << "cannot disable mirroring: " << cpp_strerror(r) << dendl; - return r; - } - - assert(clients.size() >= 1); - - if (clients.size() == 1) { - // only local journal client remains - break; - } - - for (auto client : clients) { - journal::ClientData client_data; - bufferlist::iterator bl = client.data.begin(); - ::decode(client_data, bl); - journal::ClientMetaType type = client_data.get_client_meta_type(); - - if (type != journal::ClientMetaType::MIRROR_PEER_CLIENT_META_TYPE) { - continue; - } - - journal::MirrorPeerClientMeta client_meta = - boost::get(client_data.client_meta); - - for (const auto& sync : client_meta.sync_points) { - r = ictx->operations->snap_remove(sync.snap_name.c_str()); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "cannot disable mirroring: failed to remove temporary" - " snapshot created by remote peer: " << cpp_strerror(r) << dendl; - return r; - } - } - - r = cls::journal::client::client_unregister(ictx->md_ctx, header_oid, - client.id); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "cannot disable mirroring: failed to unregister remote" - " journal client: " << cpp_strerror(r) << dendl; - return r; - } - } - } - - remove_mirroring_image: - r = cls_client::mirror_image_remove(&ictx->md_ctx, ictx->id); + cls::rbd::MirrorMode mirror_mode; + int r = cls_client::mirror_mode_get(&ictx->md_ctx, &mirror_mode); if (r < 0) { - lderr(cct) << "failed to remove image from mirroring directory: " - << cpp_strerror(r) << dendl; + lderr(cct) << "cannot disable mirroring: failed to retrieve pool " + "mirroring mode: " << cpp_strerror(r) << dendl; return r; } - ldout(cct, 20) << "removed image state from rbd_mirroring object" << dendl; - - if (is_primary) { - // TODO: send notification to mirroring object about update + if (mirror_mode != cls::rbd::MIRROR_MODE_IMAGE) { + lderr(cct) << "cannot disable mirroring in the current pool mirroring " + "mode" << dendl; + return -EINVAL; } - return 0; + return mirror_image_disable_internal(ictx, force); } int mirror_image_promote(ImageCtx *ictx, bool force) { -- 2.39.5