#include "cls/rbd/cls_rbd.h"
#include "cls/rbd/cls_rbd_client.h"
+#include "cls/journal/cls_journal_types.h"
+#include "cls/journal/cls_journal_client.h"
#include "librbd/AioCompletion.h"
#include "librbd/AioImageRequest.h"
#include "librbd/ImageWatcher.h"
#include "librbd/internal.h"
#include "librbd/Journal.h"
+#include "librbd/journal/Types.h"
#include "librbd/ObjectMap.h"
#include "librbd/Operations.h"
#include "librbd/parent_types.h"
#include "librbd/operation/TrimRequest.h"
#include "include/util.h"
+#include "journal/Journaler.h"
+
#include <boost/bind.hpp>
#include <boost/scope_exit.hpp>
#include <boost/variant.hpp>
return 0;
}
+ int mirror_image_disable(ImageCtx *ictx, bool force) {
+ CephContext *cct = ictx->cct;
+ ldout(cct, 20) << "mirror_image_disable " << ictx << dendl;
+
+ cls::rbd::MirrorImage mirror_image_internal;
+ std::vector<snap_info_t> snaps;
+ std::set<cls::journal::Client> 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<journal::MirrorPeerClientMeta>(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;
+ }
+
int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
ldout(cct, 20) << __func__ << dendl;