diff options
Diffstat (limited to 'src/librbd/migration/RawSnapshot.cc')
-rw-r--r-- | src/librbd/migration/RawSnapshot.cc | 220 |
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>; |