summaryrefslogtreecommitdiffstats
path: root/src/librbd/migration/OpenSourceImageRequest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librbd/migration/OpenSourceImageRequest.cc')
-rw-r--r--src/librbd/migration/OpenSourceImageRequest.cc249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/librbd/migration/OpenSourceImageRequest.cc b/src/librbd/migration/OpenSourceImageRequest.cc
new file mode 100644
index 000000000..8abdedf33
--- /dev/null
+++ b/src/librbd/migration/OpenSourceImageRequest.cc
@@ -0,0 +1,249 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/migration/OpenSourceImageRequest.h"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ImageState.h"
+#include "librbd/Utils.h"
+#include "librbd/io/ImageDispatcher.h"
+#include "librbd/migration/ImageDispatch.h"
+#include "librbd/migration/NativeFormat.h"
+#include "librbd/migration/SourceSpecBuilder.h"
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::migration::OpenSourceImageRequest: " \
+ << this << " " << __func__ << ": "
+
+namespace librbd {
+namespace migration {
+
+template <typename I>
+OpenSourceImageRequest<I>::OpenSourceImageRequest(
+ librados::IoCtx& io_ctx, I* dst_image_ctx, uint64_t src_snap_id,
+ const MigrationInfo &migration_info, I** src_image_ctx, Context* on_finish)
+ : m_cct(reinterpret_cast<CephContext*>(io_ctx.cct())), m_io_ctx(io_ctx),
+ m_dst_image_ctx(dst_image_ctx), m_src_snap_id(src_snap_id),
+ m_migration_info(migration_info), m_src_image_ctx(src_image_ctx),
+ m_on_finish(on_finish) {
+ ldout(m_cct, 10) << dendl;
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::send() {
+ open_source();
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::open_source() {
+ ldout(m_cct, 10) << dendl;
+
+ // note that all source image ctx properties are placeholders
+ *m_src_image_ctx = I::create("", "", CEPH_NOSNAP, m_io_ctx, true);
+ auto src_image_ctx = *m_src_image_ctx;
+ src_image_ctx->child = m_dst_image_ctx;
+
+ // use default layout values (can be overridden by source layers later)
+ src_image_ctx->order = 22;
+ src_image_ctx->layout = file_layout_t();
+ src_image_ctx->layout.stripe_count = 1;
+ src_image_ctx->layout.stripe_unit = 1ULL << src_image_ctx->order;
+ src_image_ctx->layout.object_size = 1Ull << src_image_ctx->order;
+ src_image_ctx->layout.pool_id = -1;
+
+ bool import_only = true;
+ auto source_spec = m_migration_info.source_spec;
+ if (source_spec.empty()) {
+ // implies legacy migration from RBD image in same cluster
+ source_spec = NativeFormat<I>::build_source_spec(
+ m_migration_info.pool_id, m_migration_info.pool_namespace,
+ m_migration_info.image_name, m_migration_info.image_id);
+ import_only = false;
+ }
+
+ ldout(m_cct, 15) << "source_spec=" << source_spec << ", "
+ << "source_snap_id=" << m_src_snap_id << ", "
+ << "import_only=" << import_only << dendl;
+
+ SourceSpecBuilder<I> source_spec_builder{src_image_ctx};
+ json_spirit::mObject source_spec_object;
+ int r = source_spec_builder.parse_source_spec(source_spec,
+ &source_spec_object);
+ if (r < 0) {
+ lderr(m_cct) << "failed to parse migration source-spec:" << cpp_strerror(r)
+ << dendl;
+ (*m_src_image_ctx)->state->close();
+ finish(r);
+ return;
+ }
+
+ r = source_spec_builder.build_format(source_spec_object, import_only,
+ &m_format);
+ if (r < 0) {
+ lderr(m_cct) << "failed to build migration format handler: "
+ << cpp_strerror(r) << dendl;
+ (*m_src_image_ctx)->state->close();
+ finish(r);
+ return;
+ }
+
+ auto ctx = util::create_context_callback<
+ OpenSourceImageRequest<I>,
+ &OpenSourceImageRequest<I>::handle_open_source>(this);
+ m_format->open(ctx);
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::handle_open_source(int r) {
+ ldout(m_cct, 10) << "r=" << r << dendl;
+
+ if (r < 0) {
+ lderr(m_cct) << "failed to open migration source: " << cpp_strerror(r)
+ << dendl;
+ finish(r);
+ return;
+ }
+
+ get_image_size();
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::get_image_size() {
+ ldout(m_cct, 10) << dendl;
+
+ auto ctx = util::create_context_callback<
+ OpenSourceImageRequest<I>,
+ &OpenSourceImageRequest<I>::handle_get_image_size>(this);
+ m_format->get_image_size(CEPH_NOSNAP, &m_image_size, ctx);
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::handle_get_image_size(int r) {
+ ldout(m_cct, 10) << "r=" << r << ", "
+ << "image_size=" << m_image_size << dendl;
+
+ if (r < 0) {
+ lderr(m_cct) << "failed to retrieve image size: " << cpp_strerror(r)
+ << dendl;
+ close_image(r);
+ return;
+ }
+
+ auto src_image_ctx = *m_src_image_ctx;
+ src_image_ctx->image_lock.lock();
+ src_image_ctx->size = m_image_size;
+ src_image_ctx->image_lock.unlock();
+
+ get_snapshots();
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::get_snapshots() {
+ ldout(m_cct, 10) << dendl;
+
+ auto ctx = util::create_context_callback<
+ OpenSourceImageRequest<I>,
+ &OpenSourceImageRequest<I>::handle_get_snapshots>(this);
+ m_format->get_snapshots(&m_snap_infos, ctx);
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::handle_get_snapshots(int r) {
+ ldout(m_cct, 10) << "r=" << r << dendl;
+
+ if (r < 0) {
+ lderr(m_cct) << "failed to retrieve snapshots: " << cpp_strerror(r)
+ << dendl;
+ close_image(r);
+ return;
+ }
+
+ // copy snapshot metadata to image ctx
+ auto src_image_ctx = *m_src_image_ctx;
+ src_image_ctx->image_lock.lock();
+
+ src_image_ctx->snaps.clear();
+ src_image_ctx->snap_info.clear();
+ src_image_ctx->snap_ids.clear();
+
+ ::SnapContext snapc;
+ for (auto it = m_snap_infos.rbegin(); it != m_snap_infos.rend(); ++it) {
+ auto& [snap_id, snap_info] = *it;
+ snapc.snaps.push_back(snap_id);
+
+ ldout(m_cct, 10) << "adding snap: ns=" << snap_info.snap_namespace << ", "
+ << "name=" << snap_info.name << ", "
+ << "id=" << snap_id << dendl;
+ src_image_ctx->add_snap(
+ snap_info.snap_namespace, snap_info.name, snap_id,
+ snap_info.size, snap_info.parent, snap_info.protection_status,
+ snap_info.flags, snap_info.timestamp);
+ }
+ if (!snapc.snaps.empty()) {
+ snapc.seq = snapc.snaps[0];
+ }
+ src_image_ctx->snapc = snapc;
+
+ ldout(m_cct, 15) << "read snap id: " << m_src_snap_id << ", "
+ << "write snapc={"
+ << "seq=" << snapc.seq << ", "
+ << "snaps=" << snapc.snaps << "}" << dendl;
+
+ // ensure data_ctx and data_io_context are pointing to correct snapshot
+ if (m_src_snap_id != CEPH_NOSNAP) {
+ int r = src_image_ctx->snap_set(m_src_snap_id);
+ if (r < 0) {
+ src_image_ctx->image_lock.unlock();
+
+ lderr(m_cct) << "error setting source image snap id: "
+ << cpp_strerror(r) << dendl;
+ finish(r);
+ return;
+ }
+ }
+
+ src_image_ctx->image_lock.unlock();
+
+ finish(0);
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::close_image(int r) {
+ ldout(m_cct, 10) << "r=" << r << dendl;
+
+ auto ctx = new LambdaContext([this, r](int) {
+ finish(r);
+ });
+ (*m_src_image_ctx)->state->close(ctx);
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::register_image_dispatch() {
+ ldout(m_cct, 10) << dendl;
+
+ // intercept any IO requests to the source image
+ auto io_image_dispatch = ImageDispatch<I>::create(
+ *m_src_image_ctx, std::move(m_format));
+ (*m_src_image_ctx)->io_image_dispatcher->register_dispatch(io_image_dispatch);
+}
+
+template <typename I>
+void OpenSourceImageRequest<I>::finish(int r) {
+ ldout(m_cct, 10) << "r=" << r << dendl;
+
+ if (r < 0) {
+ *m_src_image_ctx = nullptr;
+ } else {
+ register_image_dispatch();
+ }
+
+ m_on_finish->complete(r);
+ delete this;
+}
+
+} // namespace migration
+} // namespace librbd
+
+template class librbd::migration::OpenSourceImageRequest<librbd::ImageCtx>;