summaryrefslogtreecommitdiffstats
path: root/src/librbd/migration/RawSnapshot.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librbd/migration/RawSnapshot.cc')
-rw-r--r--src/librbd/migration/RawSnapshot.cc220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/librbd/migration/RawSnapshot.cc b/src/librbd/migration/RawSnapshot.cc
new file mode 100644
index 000000000..4a83fd8ad
--- /dev/null
+++ b/src/librbd/migration/RawSnapshot.cc
@@ -0,0 +1,220 @@
+// -*- mode:c++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/migration/RawSnapshot.h"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/Utils.h"
+#include "librbd/io/AioCompletion.h"
+#include "librbd/io/ReadResult.h"
+#include "librbd/migration/SourceSpecBuilder.h"
+#include "librbd/migration/StreamInterface.h"
+
+namespace librbd {
+namespace migration {
+
+namespace {
+
+const std::string NAME_KEY{"name"};
+
+} // anonymous namespace
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::migration::RawSnapshot::OpenRequest " \
+ << this << " " << __func__ << ": "
+
+template <typename I>
+struct RawSnapshot<I>::OpenRequest {
+ RawSnapshot* raw_snapshot;
+ Context* on_finish;
+
+ OpenRequest(RawSnapshot* raw_snapshot, Context* on_finish)
+ : raw_snapshot(raw_snapshot), on_finish(on_finish) {
+ }
+
+ void send() {
+ open_stream();
+ }
+
+ void open_stream() {
+ auto cct = raw_snapshot->m_image_ctx->cct;
+ ldout(cct, 10) << dendl;
+
+ auto ctx = util::create_context_callback<
+ OpenRequest, &OpenRequest::handle_open_stream>(this);
+ raw_snapshot->m_stream->open(ctx);
+ }
+
+ void handle_open_stream(int r) {
+ auto cct = raw_snapshot->m_image_ctx->cct;
+ ldout(cct, 10) << "r=" << r << dendl;
+
+ if (r < 0) {
+ lderr(cct) << "failed to open stream: " << cpp_strerror(r) << dendl;
+ finish(r);
+ return;
+ }
+
+ get_image_size();
+ }
+
+ void get_image_size() {
+ auto cct = raw_snapshot->m_image_ctx->cct;
+ ldout(cct, 10) << dendl;
+
+ auto ctx = util::create_context_callback<
+ OpenRequest, &OpenRequest::handle_get_image_size>(this);
+ raw_snapshot->m_stream->get_size(&raw_snapshot->m_snap_info.size, ctx);
+ }
+
+ void handle_get_image_size(int r) {
+ auto cct = raw_snapshot->m_image_ctx->cct;
+ ldout(cct, 10) << "r=" << r << ", "
+ << "image_size=" << raw_snapshot->m_snap_info.size << dendl;
+
+ if (r < 0) {
+ lderr(cct) << "failed to open stream: " << cpp_strerror(r) << dendl;
+ close_stream(r);
+ return;
+ }
+
+ finish(0);
+ }
+
+ void close_stream(int r) {
+ auto cct = raw_snapshot->m_image_ctx->cct;
+ ldout(cct, 10) << dendl;
+
+ auto ctx = new LambdaContext([this, r](int) {
+ handle_close_stream(r);
+ });
+ raw_snapshot->m_stream->close(ctx);
+ }
+
+ void handle_close_stream(int r) {
+ auto cct = raw_snapshot->m_image_ctx->cct;
+ ldout(cct, 10) << "r=" << r << dendl;
+
+ raw_snapshot->m_stream.reset();
+
+ finish(r);
+ }
+
+ void finish(int r) {
+ auto cct = raw_snapshot->m_image_ctx->cct;
+ ldout(cct, 10) << "r=" << r << dendl;
+
+ on_finish->complete(r);
+ delete this;
+ }
+};
+
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::migration::RawSnapshot: " << this \
+ << " " << __func__ << ": "
+
+template <typename I>
+RawSnapshot<I>::RawSnapshot(I* image_ctx,
+ const json_spirit::mObject& json_object,
+ const SourceSpecBuilder<I>* source_spec_builder,
+ uint64_t index)
+ : m_image_ctx(image_ctx), m_json_object(json_object),
+ m_source_spec_builder(source_spec_builder), m_index(index),
+ m_snap_info({}, {}, 0, {}, 0, 0, {}) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 10) << dendl;
+}
+
+template <typename I>
+void RawSnapshot<I>::open(SnapshotInterface* previous_snapshot,
+ Context* on_finish) {
+ auto cct = m_image_ctx->cct;
+
+ // special-case for treating the HEAD revision as a snapshot
+ if (m_index != CEPH_NOSNAP) {
+ auto& name_val = m_json_object[NAME_KEY];
+ if (name_val.type() == json_spirit::str_type) {
+ m_snap_info.name = name_val.get_str();
+ } else if (name_val.type() == json_spirit::null_type) {
+ uuid_d uuid_gen;
+ uuid_gen.generate_random();
+
+ m_snap_info.name = uuid_gen.to_string();
+ } else {
+ lderr(cct) << "invalid snapshot name" << dendl;
+ on_finish->complete(-EINVAL);
+ return;
+ }
+ }
+
+ ldout(cct, 10) << "name=" << m_snap_info.name << dendl;
+
+ int r = m_source_spec_builder->build_stream(m_json_object, &m_stream);
+ if (r < 0) {
+ lderr(cct) << "failed to build migration stream handler" << cpp_strerror(r)
+ << dendl;
+ on_finish->complete(r);
+ return;
+ }
+
+ auto req = new OpenRequest(this, on_finish);
+ req->send();
+}
+
+template <typename I>
+void RawSnapshot<I>::close(Context* on_finish) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 10) << dendl;
+
+ if (!m_stream) {
+ on_finish->complete(0);
+ return;
+ }
+
+ m_stream->close(on_finish);
+}
+
+template <typename I>
+void RawSnapshot<I>::read(io::AioCompletion* aio_comp,
+ io::Extents&& image_extents,
+ io::ReadResult&& read_result, int op_flags,
+ int read_flags,
+ const ZTracer::Trace &parent_trace) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << "image_extents=" << image_extents << dendl;
+
+ aio_comp->read_result = std::move(read_result);
+ aio_comp->read_result.set_image_extents(image_extents);
+
+ aio_comp->set_request_count(1);
+ auto ctx = new io::ReadResult::C_ImageReadRequest(aio_comp,
+ 0, image_extents);
+
+ // raw directly maps the image-extent IO down to a byte IO extent
+ m_stream->read(std::move(image_extents), &ctx->bl, ctx);
+}
+
+template <typename I>
+void RawSnapshot<I>::list_snap(io::Extents&& image_extents,
+ int list_snaps_flags,
+ io::SparseExtents* sparse_extents,
+ const ZTracer::Trace &parent_trace,
+ Context* on_finish) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << "image_extents=" << image_extents << dendl;
+
+ // raw does support sparse extents so list the full IO extent as a delta
+ for (auto& [image_offset, image_length] : image_extents) {
+ sparse_extents->insert(image_offset, image_length,
+ {io::SPARSE_EXTENT_STATE_DATA, image_length});
+ }
+
+ on_finish->complete(0);
+}
+
+} // namespace migration
+} // namespace librbd
+
+template class librbd::migration::RawSnapshot<librbd::ImageCtx>;