using librbd::util::create_context_callback;
using librbd::util::create_rados_callback;
+template <typename I>
+GetInfoRequest<I>::GetInfoRequest(librados::IoCtx& io_ctx,
+ ContextWQ *op_work_queue,
+ const std::string &image_id,
+ cls::rbd::MirrorImage *mirror_image,
+ PromotionState *promotion_state,
+ Context *on_finish)
+ : m_io_ctx(io_ctx), m_op_work_queue(op_work_queue), m_image_id(image_id),
+ m_mirror_image(mirror_image), m_promotion_state(promotion_state),
+ m_on_finish(on_finish),
+ m_cct(reinterpret_cast<CephContext *>(io_ctx.cct())) {
+}
+
+template <typename I>
+GetInfoRequest<I>::GetInfoRequest(I &image_ctx,
+ cls::rbd::MirrorImage *mirror_image,
+ PromotionState *promotion_state,
+ Context *on_finish)
+ : m_image_ctx(&image_ctx), m_io_ctx(image_ctx.md_ctx),
+ m_op_work_queue(image_ctx.op_work_queue), m_image_id(image_ctx.id),
+ m_mirror_image(mirror_image), m_promotion_state(promotion_state),
+ m_on_finish(on_finish), m_cct(image_ctx.cct) {
+}
+
template <typename I>
void GetInfoRequest<I>::send() {
get_mirror_image();
template <typename I>
void GetInfoRequest<I>::get_mirror_image() {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 20) << dendl;
+ ldout(m_cct, 20) << dendl;
librados::ObjectReadOperation op;
- cls_client::mirror_image_get_start(&op, m_image_ctx.id);
+ cls_client::mirror_image_get_start(&op, m_image_id);
librados::AioCompletion *comp = create_rados_callback<
GetInfoRequest<I>, &GetInfoRequest<I>::handle_get_mirror_image>(this);
- int r = m_image_ctx.md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
+ int r = m_io_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
ceph_assert(r == 0);
comp->release();
}
template <typename I>
void GetInfoRequest<I>::handle_get_mirror_image(int r) {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 20) << "r=" << r << dendl;
+ ldout(m_cct, 20) << "r=" << r << dendl;
m_mirror_image->state = cls::rbd::MIRROR_IMAGE_STATE_DISABLED;
*m_promotion_state = PROMOTION_STATE_NON_PRIMARY;
}
if (r == -ENOENT) {
- ldout(cct, 20) << "mirroring is disabled" << dendl;
+ ldout(m_cct, 20) << "mirroring is disabled" << dendl;
finish(r);
return;
} else if (r < 0) {
- lderr(cct) << "failed to retrieve mirroring state: " << cpp_strerror(r)
+ lderr(m_cct) << "failed to retrieve mirroring state: " << cpp_strerror(r)
<< dendl;
finish(r);
return;
if (m_mirror_image->mode == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
get_journal_tag_owner();
} else if (m_mirror_image->mode == cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) {
- get_snapshot_promotion_state();
+ get_snapcontext();
} else {
- ldout(cct, 20) << "unknown mirror image mode: " << m_mirror_image->mode
- << dendl;
+ ldout(m_cct, 20) << "unknown mirror image mode: " << m_mirror_image->mode
+ << dendl;
finish(-EOPNOTSUPP);
}
}
template <typename I>
void GetInfoRequest<I>::get_journal_tag_owner() {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 20) << dendl;
+ ldout(m_cct, 20) << dendl;
auto ctx = create_context_callback<
GetInfoRequest<I>, &GetInfoRequest<I>::handle_get_journal_tag_owner>(this);
- Journal<I>::get_tag_owner(m_image_ctx.md_ctx, m_image_ctx.id,
- &m_mirror_uuid, m_image_ctx.op_work_queue, ctx);
+ Journal<I>::get_tag_owner(m_io_ctx, m_image_id, &m_mirror_uuid,
+ m_op_work_queue, ctx);
}
template <typename I>
void GetInfoRequest<I>::handle_get_journal_tag_owner(int r) {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 20) << "r=" << r << dendl;
+ ldout(m_cct, 20) << "r=" << r << dendl;
if (r < 0) {
- lderr(cct) << "failed to determine tag ownership: " << cpp_strerror(r)
- << dendl;
+ lderr(m_cct) << "failed to determine tag ownership: " << cpp_strerror(r)
+ << dendl;
finish(r);
return;
}
}
template <typename I>
-void GetInfoRequest<I>::get_snapshot_promotion_state() {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 20) << dendl;
+void GetInfoRequest<I>::get_snapcontext() {
+ if (m_image_ctx != nullptr) {
+ {
+ std::shared_lock image_locker{m_image_ctx->image_lock};
+ calc_promotion_state(m_image_ctx->snap_info);
+ }
+ finish(0);
+ return;
+ }
- *m_promotion_state = PROMOTION_STATE_PRIMARY;
- {
- std::shared_lock image_locker{m_image_ctx.image_lock};
- for (auto it = m_image_ctx.snap_info.rbegin();
- it != m_image_ctx.snap_info.rend(); it++) {
- auto primary = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
- &it->second.snap_namespace);
- if (primary != nullptr) {
- if (primary->demoted) {
- *m_promotion_state = PROMOTION_STATE_ORPHAN;
- }
- break;
- }
- auto non_primary =
- boost::get<cls::rbd::MirrorNonPrimarySnapshotNamespace>(
- &it->second.snap_namespace);
- if (non_primary != nullptr) {
- if (non_primary->primary_mirror_uuid.empty()) {
- *m_promotion_state = PROMOTION_STATE_ORPHAN;
- } else {
- *m_promotion_state = PROMOTION_STATE_NON_PRIMARY;
- }
- break;
- }
+ ldout(m_cct, 20) << dendl;
+
+ librados::ObjectReadOperation op;
+ cls_client::get_snapcontext_start(&op);
+
+ librados::AioCompletion *comp = create_rados_callback<
+ GetInfoRequest<I>, &GetInfoRequest<I>::handle_get_snapcontext>(this);
+ m_out_bl.clear();
+ int r = m_io_ctx.aio_operate(util::header_name(m_image_id), comp, &op,
+ &m_out_bl);
+ ceph_assert(r == 0);
+ comp->release();
+}
+
+template <typename I>
+void GetInfoRequest<I>::handle_get_snapcontext(int r) {
+ ldout(m_cct, 20) << "r=" << r << dendl;
+
+ if (r >= 0) {
+ auto it = m_out_bl.cbegin();
+ r = cls_client::get_snapcontext_finish(&it, &m_snapc);
+ }
+
+ if (r < 0) {
+ lderr(m_cct) << "failed to get snapcontext: " << cpp_strerror(r)
+ << dendl;
+ finish(r);
+ return;
+ }
+
+ get_snapshots();
+}
+
+
+template <typename I>
+void GetInfoRequest<I>::get_snapshots() {
+ ldout(m_cct, 20) << dendl;
+
+ if (m_snapc.snaps.empty()) {
+ handle_get_snapshots(0);
+ return;
+ }
+
+ librados::ObjectReadOperation op;
+ for (auto snap_id : m_snapc.snaps) {
+ cls_client::snapshot_get_start(&op, snap_id);
+ }
+
+ librados::AioCompletion *comp = create_rados_callback<
+ GetInfoRequest<I>, &GetInfoRequest<I>::handle_get_snapshots>(this);
+ m_out_bl.clear();
+ int r = m_io_ctx.aio_operate(util::header_name(m_image_id), comp, &op,
+ &m_out_bl);
+ ceph_assert(r == 0);
+ comp->release();
+}
+
+template <typename I>
+void GetInfoRequest<I>::handle_get_snapshots(int r) {
+ ldout(m_cct, 20) << "r=" << r << dendl;
+
+ std::map<librados::snap_t, SnapInfo> snap_info;
+
+ auto it = m_out_bl.cbegin();
+ for (auto snap_id : m_snapc.snaps) {
+ cls::rbd::SnapshotInfo snap;
+ if (r >= 0) {
+ r = cls_client::snapshot_get_finish(&it, &snap);
}
+ snap_info.emplace(
+ snap_id, SnapInfo(snap.name, snap.snapshot_namespace, 0, {}, 0, 0, {}));
+ }
+
+ if (r == -ENOENT) {
+ // restart
+ get_snapcontext();
+ return;
+ }
+
+ if (r < 0) {
+ lderr(m_cct) << "failed to get snapshots: " << cpp_strerror(r)
+ << dendl;
+ finish(r);
+ return;
}
+
+ calc_promotion_state(snap_info);
finish(0);
}
-
template <typename I>
void GetInfoRequest<I>::finish(int r) {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 20) << "r=" << r << dendl;
+ ldout(m_cct, 20) << "r=" << r << dendl;
m_on_finish->complete(r);
delete this;
}
+template <typename I>
+void GetInfoRequest<I>::calc_promotion_state(
+ const std::map<librados::snap_t, SnapInfo> &snap_info) {
+ *m_promotion_state = PROMOTION_STATE_PRIMARY;
+
+ for (auto it = snap_info.rbegin(); it != snap_info.rend(); it++) {
+ auto primary = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ &it->second.snap_namespace);
+ if (primary != nullptr) {
+ if (primary->demoted) {
+ *m_promotion_state = PROMOTION_STATE_ORPHAN;
+ }
+ break;
+ }
+ auto non_primary =
+ boost::get<cls::rbd::MirrorNonPrimarySnapshotNamespace>(
+ &it->second.snap_namespace);
+ if (non_primary != nullptr) {
+ if (non_primary->primary_mirror_uuid.empty()) {
+ *m_promotion_state = PROMOTION_STATE_ORPHAN;
+ } else {
+ *m_promotion_state = PROMOTION_STATE_NON_PRIMARY;
+ }
+ break;
+ }
+ }
+
+ ldout(m_cct, 20) << *m_promotion_state << dendl;
+}
+
} // namespace mirror
} // namespace librbd
#ifndef CEPH_LIBRBD_MIRROR_GET_INFO_REQUEST_H
#define CEPH_LIBRBD_MIRROR_GET_INFO_REQUEST_H
+#include "common/snap_types.h"
#include "include/buffer.h"
+#include "include/rados/librados.hpp"
+#include "librbd/Types.h"
#include "librbd/mirror/Types.h"
#include <string>
+class CephContext;
+class ContextWQ;
struct Context;
+
namespace cls { namespace rbd { struct MirrorImage; } }
namespace librbd {
template <typename ImageCtxT = librbd::ImageCtx>
class GetInfoRequest {
public:
+ static GetInfoRequest *create(librados::IoCtx &io_ctx,
+ ContextWQ *op_work_queue,
+ const std::string &image_id,
+ cls::rbd::MirrorImage *mirror_image,
+ PromotionState *promotion_state,
+ Context *on_finish) {
+ return new GetInfoRequest(io_ctx, op_work_queue, image_id, mirror_image,
+ promotion_state, on_finish);
+ }
static GetInfoRequest *create(ImageCtxT &image_ctx,
cls::rbd::MirrorImage *mirror_image,
PromotionState *promotion_state,
on_finish);
}
+ GetInfoRequest(librados::IoCtx& io_ctx, ContextWQ *op_work_queue,
+ const std::string &image_id,
+ cls::rbd::MirrorImage *mirror_image,
+ PromotionState *promotion_state, Context *on_finish);
GetInfoRequest(ImageCtxT &image_ctx, cls::rbd::MirrorImage *mirror_image,
- PromotionState *promotion_state, Context *on_finish)
- : m_image_ctx(image_ctx), m_mirror_image(mirror_image),
- m_promotion_state(promotion_state), m_on_finish(on_finish) {
- }
+ PromotionState *promotion_state, Context *on_finish);
void send();
/**
* @verbatim
*
- * <start>
- * |
- * v
- * GET_MIRROR_IMAGE
- * |
- * v
- * GET_JOURNAL_TAG_OWNER (if journal)
- * |
- * v
- * <finish>
+ * <start>
+ * |
+ * v
+ * GET_MIRROR_IMAGE
+ * |
+ * (journal /--------/ \--------\ (snapshot
+ * mode) | | mode)
+ * v v
+ * GET_JOURNAL_TAG_OWNER GET_SNAPCONTEXT (skip if
+ * | | cached)
+ * | v
+ * | GET_SNAPSHOTS (skip if
+ * | | cached)
+ * \--------\ /--------/
+ * |
+ * v
+ * <finish>
*
* @endverbatim
*/
- ImageCtxT &m_image_ctx;
+ ImageCtxT *m_image_ctx = nullptr;
+ librados::IoCtx &m_io_ctx;
+ ContextWQ *m_op_work_queue;
+ std::string m_image_id;
cls::rbd::MirrorImage *m_mirror_image;
PromotionState *m_promotion_state;
Context *m_on_finish;
+ CephContext *m_cct;
+
bufferlist m_out_bl;
std::string m_mirror_uuid;
+ ::SnapContext m_snapc;
void get_mirror_image();
void handle_get_mirror_image(int r);
void get_journal_tag_owner();
void handle_get_journal_tag_owner(int r);
- void get_snapshot_promotion_state();
+ void get_snapcontext();
+ void handle_get_snapcontext(int r);
+
+ void get_snapshots();
+ void handle_get_snapshots(int r);
void finish(int r);
+ void calc_promotion_state(
+ const std::map<librados::snap_t, SnapInfo> &snap_info);
};
} // namespace mirror