return 0;
}
+int mirror_image_disable_internal(ImageCtx *ictx, bool force) {
+ CephContext *cct = ictx->cct;
+
+ 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;
+}
+
} // anonymous namespace
int detect_format(IoCtx &io_ctx, const string &name,
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;
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);
+ 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) {