From 8d6a479332691e340dec293cb33a3f36bf8edc65 Mon Sep 17 00:00:00 2001 From: Or Ozeri Date: Mon, 2 Nov 2020 16:41:53 +0200 Subject: [PATCH] librbd: add crypto image dispatch layer This commit adds a crypto image dispatch layer, in addition to the existing crypto object dispatch layer. The single purpose of this layer is to translate logical image offset to "on-disk" offsets, given a crypto header which occupies the beginning of the image data. This calculation is done via a new remap_extents api, which is used in to wrap existing Striper translations between object and image extents. Signed-off-by: Or Ozeri --- src/librbd/CMakeLists.txt | 1 + src/librbd/cache/ObjectCacherWriteback.cc | 8 +- src/librbd/crypto/CryptoImageDispatch.cc | 28 +++++ src/librbd/crypto/CryptoImageDispatch.h | 104 ++++++++++++++++++ src/librbd/crypto/CryptoObjectDispatch.cc | 8 +- src/librbd/deep_copy/ObjectCopyRequest.cc | 15 +-- src/librbd/io/CopyupRequest.cc | 22 ++-- src/librbd/io/ImageDispatchInterface.h | 4 + src/librbd/io/ImageDispatcher.cc | 19 ++++ src/librbd/io/ImageDispatcher.h | 3 + src/librbd/io/ImageDispatcherInterface.h | 2 + src/librbd/io/ImageRequest.cc | 25 ++--- src/librbd/io/ObjectRequest.cc | 17 ++- src/librbd/io/Types.h | 6 + src/librbd/io/Utils.cc | 49 ++++++++- src/librbd/io/Utils.h | 14 +++ src/librbd/journal/ObjectDispatch.cc | 5 +- .../crypto/test_mock_CryptoObjectDispatch.cc | 6 + .../deep_copy/test_mock_ObjectCopyRequest.cc | 24 ++++ src/test/librbd/io/test_mock_CopyupRequest.cc | 21 ++++ src/test/librbd/io/test_mock_ImageRequest.cc | 22 ++++ src/test/librbd/io/test_mock_ObjectRequest.cc | 16 +++ src/test/librbd/mock/io/MockImageDispatcher.h | 2 + 23 files changed, 365 insertions(+), 56 deletions(-) create mode 100644 src/librbd/crypto/CryptoImageDispatch.cc create mode 100644 src/librbd/crypto/CryptoImageDispatch.h diff --git a/src/librbd/CMakeLists.txt b/src/librbd/CMakeLists.txt index ac4b196def1..7fbadfd49ba 100644 --- a/src/librbd/CMakeLists.txt +++ b/src/librbd/CMakeLists.txt @@ -56,6 +56,7 @@ set(librbd_internal_srcs cache/WriteAroundObjectDispatch.cc crypto/BlockCrypto.cc crypto/CryptoContextPool.cc + crypto/CryptoImageDispatch.cc crypto/CryptoObjectDispatch.cc crypto/openssl/DataCryptor.cc deep_copy/ImageCopyRequest.cc diff --git a/src/librbd/cache/ObjectCacherWriteback.cc b/src/librbd/cache/ObjectCacherWriteback.cc index 50655b6a111..9f3d5c8953e 100644 --- a/src/librbd/cache/ObjectCacherWriteback.cc +++ b/src/librbd/cache/ObjectCacherWriteback.cc @@ -24,6 +24,7 @@ #include "librbd/io/ObjectDispatchSpec.h" #include "librbd/io/ObjectDispatcherInterface.h" #include "librbd/io/ReadResult.h" +#include "librbd/io/Utils.h" #include "include/ceph_assert.h" @@ -167,8 +168,8 @@ bool ObjectCacherWriteback::may_copy_on_write(const object_t& oid, // reverse map this object extent onto the parent vector > objectx; - Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, - object_no, 0, m_ictx->layout.object_size, objectx); + io::util::extent_to_file( + m_ictx, object_no, 0, m_ictx->layout.object_size, objectx); uint64_t object_overlap = m_ictx->prune_parent_extents(objectx, overlap); bool may = object_overlap > 0; ldout(m_ictx->cct, 10) << "may_copy_on_write " << oid << " " << read_off @@ -240,8 +241,7 @@ void ObjectCacherWriteback::overwrite_extent(const object_t& oid, uint64_t off, ceph_assert(original_journal_tid != 0 && m_ictx->journal != NULL); Extents file_extents; - Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, object_no, off, - len, file_extents); + io::util::extent_to_file(m_ictx, object_no, off, len, file_extents); for (Extents::iterator it = file_extents.begin(); it != file_extents.end(); ++it) { if (new_journal_tid != 0) { diff --git a/src/librbd/crypto/CryptoImageDispatch.cc b/src/librbd/crypto/CryptoImageDispatch.cc new file mode 100644 index 00000000000..84c9a59be9a --- /dev/null +++ b/src/librbd/crypto/CryptoImageDispatch.cc @@ -0,0 +1,28 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/crypto/CryptoImageDispatch.h" + +namespace librbd { +namespace crypto { + +CryptoImageDispatch::CryptoImageDispatch( + uint64_t data_offset) : m_data_offset(data_offset) { +} + + +void CryptoImageDispatch::remap_extents( + io::Extents&& image_extents, io::ImageExtentsMapType type) { + if (type == io::IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL) { + for (auto& extent: image_extents) { + extent.first += m_data_offset; + } + } else if (type == io::IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL) { + for (auto& extent: image_extents) { + extent.first -= m_data_offset; + } + } +} + +} // namespace crypto +} // namespace librbd diff --git a/src/librbd/crypto/CryptoImageDispatch.h b/src/librbd/crypto/CryptoImageDispatch.h new file mode 100644 index 00000000000..afc3c84543c --- /dev/null +++ b/src/librbd/crypto/CryptoImageDispatch.h @@ -0,0 +1,104 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_CRYPTO_CRYPTO_IMAGE_DISPATCH_H +#define CEPH_LIBRBD_CRYPTO_CRYPTO_IMAGE_DISPATCH_H + +#include "librbd/io/ImageDispatchInterface.h" + +namespace librbd { +namespace crypto { + +class CryptoImageDispatch : public io::ImageDispatchInterface { +public: + CryptoImageDispatch(uint64_t data_offset); + + io::ImageDispatchLayer get_dispatch_layer() const override { + return io::IMAGE_DISPATCH_LAYER_CRYPTO; + } + + void shut_down(Context* on_finish) override { + on_finish->complete(0); + } + + bool read( + io::AioCompletion* aio_comp, io::Extents &&image_extents, + io::ReadResult &&read_result, IOContext io_context, int op_flags, + int read_flags, const ZTracer::Trace &parent_trace, uint64_t tid, + std::atomic* image_dispatch_flags, + io::DispatchResult* dispatch_result, Context** on_finish, + Context* on_dispatched) override { + return false; + } + + bool write( + io::AioCompletion* aio_comp, io::Extents &&image_extents, + bufferlist &&bl, IOContext io_context, int op_flags, + const ZTracer::Trace &parent_trace, uint64_t tid, + std::atomic* image_dispatch_flags, + io::DispatchResult* dispatch_result, Context** on_finish, + Context* on_dispatched) override { + return false; + } + + bool discard( + io::AioCompletion* aio_comp, io::Extents &&image_extents, + uint32_t discard_granularity_bytes, IOContext io_context, + const ZTracer::Trace &parent_trace, uint64_t tid, + std::atomic* image_dispatch_flags, + io::DispatchResult* dispatch_result, Context** on_finish, + Context* on_dispatched) override { + return false; + } + + bool write_same( + io::AioCompletion* aio_comp, io::Extents &&image_extents, + bufferlist &&bl, IOContext io_context, int op_flags, + const ZTracer::Trace &parent_trace, uint64_t tid, + std::atomic* image_dispatch_flags, + io::DispatchResult* dispatch_result, Context** on_finish, + Context* on_dispatched) override { + return false; + } + + bool compare_and_write( + io::AioCompletion* aio_comp, io::Extents &&image_extents, + bufferlist &&cmp_bl, bufferlist &&bl, uint64_t *mismatch_offset, + IOContext io_context, int op_flags, const ZTracer::Trace &parent_trace, + uint64_t tid, std::atomic* image_dispatch_flags, + io::DispatchResult* dispatch_result, Context** on_finish, + Context* on_dispatched) override { + return false; + } + + bool flush( + io::AioCompletion* aio_comp, io::FlushSource flush_source, + const ZTracer::Trace &parent_trace, uint64_t tid, + std::atomic* image_dispatch_flags, + io::DispatchResult* dispatch_result, Context** on_finish, + Context* on_dispatched) override { + return false; + } + + bool list_snaps( + io::AioCompletion* aio_comp, io::Extents&& image_extents, + io::SnapIds&& snap_ids, int list_snaps_flags, + io::SnapshotDelta* snapshot_delta, const ZTracer::Trace &parent_trace, + uint64_t tid, std::atomic* image_dispatch_flags, + io::DispatchResult* dispatch_result, Context** on_finish, + Context* on_dispatched) override { + return false; + } + + void remap_extents(io::Extents&& image_extents, + io::ImageExtentsMapType type) override; + +private: + uint64_t m_data_offset; + +}; + +} // namespace crypto +} // namespace librbd + +#endif // CEPH_LIBRBD_CRYPTO_CRYPTO_IMAGE_DISPATCH_H diff --git a/src/librbd/crypto/CryptoObjectDispatch.cc b/src/librbd/crypto/CryptoObjectDispatch.cc index b09aad720a6..25f47f50743 100644 --- a/src/librbd/crypto/CryptoObjectDispatch.cc +++ b/src/librbd/crypto/CryptoObjectDispatch.cc @@ -77,8 +77,8 @@ struct C_AlignedObjectReadRequest : public Context { for (auto& extent: *extents) { auto crypto_ret = crypto->decrypt_aligned_extent( extent, - Striper::get_file_offset( - cct, &image_ctx->layout, object_no, extent.offset)); + io::util::get_file_offset( + image_ctx, object_no, extent.offset)); if (crypto_ret != 0) { ceph_assert(crypto_ret < 0); r = crypto_ret; @@ -483,9 +483,7 @@ bool CryptoObjectDispatch::write( if (m_crypto->is_aligned(object_off, data.length())) { auto r = m_crypto->encrypt( &data, - Striper::get_file_offset( - m_image_ctx->cct, &m_image_ctx->layout, object_no, - object_off)); + io::util::get_file_offset(m_image_ctx, object_no, object_off)); *dispatch_result = r == 0 ? io::DISPATCH_RESULT_CONTINUE : io::DISPATCH_RESULT_COMPLETE; on_dispatched->complete(r); diff --git a/src/librbd/deep_copy/ObjectCopyRequest.cc b/src/librbd/deep_copy/ObjectCopyRequest.cc index aa8dfdfe8c3..b1680a1b471 100644 --- a/src/librbd/deep_copy/ObjectCopyRequest.cc +++ b/src/librbd/deep_copy/ObjectCopyRequest.cc @@ -15,6 +15,7 @@ #include "librbd/io/ImageDispatchSpec.h" #include "librbd/io/ObjectDispatcherInterface.h" #include "librbd/io/ReadResult.h" +#include "librbd/io/Utils.h" #include "osdc/Striper.h" #define dout_subsys ceph_subsys_rbd @@ -67,9 +68,9 @@ void ObjectCopyRequest::send() { template void ObjectCopyRequest::send_list_snaps() { // image extents are consistent across src and dst so compute once - Striper::extent_to_file(m_cct, &m_dst_image_ctx->layout, m_dst_object_number, - 0, m_dst_image_ctx->layout.object_size, - m_image_extents); + io::util::extent_to_file( + m_dst_image_ctx, m_dst_object_number, 0, + m_dst_image_ctx->layout.object_size, m_image_extents); ldout(m_cct, 20) << "image_extents=" << m_image_extents << dendl; io::SnapIds snap_ids; @@ -578,8 +579,8 @@ void ObjectCopyRequest::merge_write_ops() { for (auto [image_offset, image_length] : read_op.image_extent_map) { // convert image extents back to object extents for the write op striper::LightweightObjectExtents object_extents; - Striper::file_to_extents(m_cct, &m_dst_image_ctx->layout, image_offset, - image_length, 0, buffer_offset, &object_extents); + io::util::file_to_extents(m_dst_image_ctx, image_offset, + image_length, buffer_offset, &object_extents); for (auto& object_extent : object_extents) { ldout(m_cct, 20) << "src_snap_seq=" << src_snap_seq << ", " << "object_offset=" << object_extent.offset << ", " @@ -722,8 +723,8 @@ void ObjectCopyRequest::compute_zero_ops() { for (auto z = zero_interval.begin(); z != zero_interval.end(); ++z) { // convert image extents back to object extents for the write op striper::LightweightObjectExtents object_extents; - Striper::file_to_extents(m_cct, &m_dst_image_ctx->layout, z.get_start(), - z.get_len(), 0, 0, &object_extents); + io::util::file_to_extents(m_dst_image_ctx, z.get_start(), z.get_len(), 0, + &object_extents); for (auto& object_extent : object_extents) { ceph_assert(object_extent.offset + object_extent.length <= m_dst_image_ctx->layout.object_size); diff --git a/src/librbd/io/CopyupRequest.cc b/src/librbd/io/CopyupRequest.cc index 93effcb1cbb..fb5dfe4a70d 100644 --- a/src/librbd/io/CopyupRequest.cc +++ b/src/librbd/io/CopyupRequest.cc @@ -21,6 +21,7 @@ #include "librbd/io/ObjectDispatcherInterface.h" #include "librbd/io/ObjectRequest.h" #include "librbd/io/ReadResult.h" +#include "librbd/io/Utils.h" #include #include @@ -118,10 +119,10 @@ CopyupRequest::CopyupRequest(I *ictx, uint64_t objectno, Extents &&image_extents, const ZTracer::Trace &parent_trace) : m_image_ctx(ictx), m_object_no(objectno), m_image_extents(image_extents), - m_trace(util::create_trace(*m_image_ctx, "copy-up", parent_trace)) + m_trace(librbd::util::create_trace(*m_image_ctx, "copy-up", parent_trace)) { ceph_assert(m_image_ctx->data_ctx.is_valid()); - m_async_op.start_op(*util::get_image_ctx(m_image_ctx)); + m_async_op.start_op(*librbd::util::get_image_ctx(m_image_ctx)); } template @@ -175,7 +176,7 @@ void CopyupRequest::read_from_parent() { auto comp = AioCompletion::create_and_start< CopyupRequest, &CopyupRequest::handle_read_from_parent>( - this, util::get_image_ctx(m_image_ctx->parent), AIO_TYPE_READ); + this, librbd::util::get_image_ctx(m_image_ctx->parent), AIO_TYPE_READ); ldout(cct, 20) << "completion=" << comp << ", " << "extents=" << m_image_extents @@ -248,7 +249,7 @@ void CopyupRequest::deep_copy() { ldout(cct, 20) << "flatten=" << m_flatten << dendl; - auto ctx = util::create_context_callback< + auto ctx = librbd::util::create_context_callback< CopyupRequest, &CopyupRequest::handle_deep_copy>(this); auto req = deep_copy::ObjectCopyRequest::create( m_image_ctx->parent, m_image_ctx, 0, 0, @@ -354,7 +355,7 @@ void CopyupRequest::update_object_maps() { boost::lambda::bind(boost::lambda::new_ptr>(), boost::lambda::_1, m_image_ctx, m_object_no, head_object_map_state, &m_snap_ids, m_first_snap_is_clean, m_trace, boost::lambda::_2)); - auto ctx = util::create_context_callback< + auto ctx = librbd::util::create_context_callback< CopyupRequest, &CopyupRequest::handle_update_object_maps>(this); auto throttle = new AsyncObjectThrottle( nullptr, *m_image_ctx, context_factory, ctx, nullptr, 0, m_snap_ids.size()); @@ -643,10 +644,8 @@ void CopyupRequest::compute_deep_copy_snap_ids() { return false; } std::vector> extents; - Striper::extent_to_file(cct, &m_image_ctx->layout, - m_object_no, 0, - m_image_ctx->layout.object_size, - extents); + util::extent_to_file(m_image_ctx, m_object_no, 0, + m_image_ctx->layout.object_size, extents); auto overlap = m_image_ctx->prune_parent_extents( extents, parent_overlap); return overlap > 0; @@ -664,9 +663,8 @@ void CopyupRequest::convert_copyup_extent_map() { // convert the image-extent extent map to object-extents for (auto [image_offset, image_length] : image_extent_map) { striper::LightweightObjectExtents object_extents; - Striper::file_to_extents( - cct, &m_image_ctx->layout, image_offset, image_length, 0, 0, - &object_extents); + util::file_to_extents( + m_image_ctx, image_offset, image_length, 0, &object_extents); for (auto& object_extent : object_extents) { m_copyup_extent_map.emplace_back( object_extent.offset, object_extent.length); diff --git a/src/librbd/io/ImageDispatchInterface.h b/src/librbd/io/ImageDispatchInterface.h index 205c18c474f..2341107179c 100644 --- a/src/librbd/io/ImageDispatchInterface.h +++ b/src/librbd/io/ImageDispatchInterface.h @@ -80,6 +80,10 @@ struct ImageDispatchInterface { Context* on_dispatched) = 0; virtual bool invalidate_cache(Context* on_finish) = 0; + + virtual void remap_extents(Extents&& image_extents, + ImageExtentsMapType type) {} + }; } // namespace io diff --git a/src/librbd/io/ImageDispatcher.cc b/src/librbd/io/ImageDispatcher.cc index fb5908b01c0..a9c1c985522 100644 --- a/src/librbd/io/ImageDispatcher.cc +++ b/src/librbd/io/ImageDispatcher.cc @@ -260,6 +260,25 @@ void ImageDispatcher::wait_on_writes_unblocked(Context *on_unblocked) { m_write_block_dispatch->wait_on_writes_unblocked(on_unblocked); } +template +void ImageDispatcher::remap_extents(Extents&& image_extents, + ImageExtentsMapType type) { + auto loop = [&image_extents, type](auto begin, auto end) { + for (auto it = begin; it != end; ++it) { + auto& image_dispatch_meta = it->second; + auto image_dispatch = image_dispatch_meta.dispatch; + image_dispatch->remap_extents(std::move(image_extents), type); + } + }; + + std::shared_lock locker{this->m_lock}; + if (type == IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL) { + loop(this->m_dispatches.cbegin(), this->m_dispatches.cend()); + } else if (type == IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL) { + loop(this->m_dispatches.crbegin(), this->m_dispatches.crend()); + } +} + template bool ImageDispatcher::send_dispatch( ImageDispatchInterface* image_dispatch, diff --git a/src/librbd/io/ImageDispatcher.h b/src/librbd/io/ImageDispatcher.h index 26efd9d8124..d1176ae050e 100644 --- a/src/librbd/io/ImageDispatcher.h +++ b/src/librbd/io/ImageDispatcher.h @@ -45,6 +45,9 @@ public: void unblock_writes() override; void wait_on_writes_unblocked(Context *on_unblocked) override; + void remap_extents(Extents&& image_extents, + ImageExtentsMapType type) override; + protected: bool send_dispatch( ImageDispatchInterface* image_dispatch, diff --git a/src/librbd/io/ImageDispatcherInterface.h b/src/librbd/io/ImageDispatcherInterface.h index 8bff8566ed2..f6b572c5d9e 100644 --- a/src/librbd/io/ImageDispatcherInterface.h +++ b/src/librbd/io/ImageDispatcherInterface.h @@ -29,6 +29,8 @@ public: virtual void wait_on_writes_unblocked(Context *on_unblocked) = 0; virtual void invalidate_cache(Context* on_finish) = 0; + virtual void remap_extents(Extents&& image_extents, + ImageExtentsMapType type) = 0; }; } // namespace io diff --git a/src/librbd/io/ImageRequest.cc b/src/librbd/io/ImageRequest.cc index 17b97f9edf8..4b31f2c7ae8 100644 --- a/src/librbd/io/ImageRequest.cc +++ b/src/librbd/io/ImageRequest.cc @@ -87,14 +87,11 @@ struct C_AssembleSnapshotDeltas : public C_AioRequest { uint64_t object_no, const SnapshotDelta& object_snapshot_delta, SnapshotDelta* image_snapshot_delta, SnapshotDelta* assembled_image_snapshot_delta) { - auto cct = image_ctx->cct; for (auto& [key, object_extents] : object_snapshot_delta) { for (auto& object_extent : object_extents) { Extents image_extents; - Striper::extent_to_file(cct, &image_ctx->layout, object_no, - object_extent.get_off(), - object_extent.get_len(), - image_extents); + io::util::extent_to_file(image_ctx, object_no, object_extent.get_off(), + object_extent.get_len(), image_extents); auto& intervals = (*image_snapshot_delta)[key]; auto& assembled_intervals = (*assembled_image_snapshot_delta)[key]; @@ -159,9 +156,8 @@ void readahead(I *ictx, const Extents& image_extents, IOContext io_context) { ldout(ictx->cct, 20) << "(readahead logical) " << readahead_offset << "~" << readahead_length << dendl; LightweightObjectExtents readahead_object_extents; - Striper::file_to_extents(ictx->cct, &ictx->layout, - readahead_offset, readahead_length, 0, 0, - &readahead_object_extents); + io::util::file_to_extents(ictx, readahead_offset, readahead_length, 0, + &readahead_object_extents); for (auto& object_extent : readahead_object_extents) { ldout(ictx->cct, 20) << "(readahead) " << data_object_name(ictx, @@ -397,8 +393,8 @@ void ImageReadRequest::send_request() { continue; } - Striper::file_to_extents(cct, &image_ctx.layout, extent.first, - extent.second, 0, buffer_ofs, &object_extents); + util::file_to_extents(&image_ctx, extent.first, extent.second, buffer_ofs, + &object_extents); buffer_ofs += extent.second; } @@ -428,7 +424,6 @@ void ImageReadRequest::send_request() { template void AbstractImageWriteRequest::send_request() { I &image_ctx = this->m_image_ctx; - CephContext *cct = image_ctx.cct; bool journaling = false; @@ -449,8 +444,8 @@ void AbstractImageWriteRequest::send_request() { } // map to object extents - Striper::file_to_extents(cct, &image_ctx.layout, extent.first, - extent.second, 0, clip_len, &object_extents); + io::util::file_to_extents(&image_ctx, extent.first, extent.second, clip_len, + &object_extents); clip_len += extent.second; } @@ -840,8 +835,8 @@ void ImageListSnapsRequest::send_request() { } striper::LightweightObjectExtents object_extents; - Striper::file_to_extents(cct, &image_ctx.layout, image_extent.first, - image_extent.second, 0, 0, &object_extents); + io::util::file_to_extents(&image_ctx, image_extent.first, + image_extent.second, 0, &object_extents); for (auto& object_extent : object_extents) { object_number_extents[object_extent.object_no].emplace_back( object_extent.offset, object_extent.length); diff --git a/src/librbd/io/ObjectRequest.cc b/src/librbd/io/ObjectRequest.cc index 0964bec9912..0914d08ef19 100644 --- a/src/librbd/io/ObjectRequest.cc +++ b/src/librbd/io/ObjectRequest.cc @@ -170,8 +170,8 @@ bool ObjectRequest::compute_parent_extents(Extents *parent_extents, return false; } - Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, m_object_no, 0, - m_ictx->layout.object_size, *parent_extents); + io::util::extent_to_file(m_ictx, m_object_no, 0, m_ictx->layout.object_size, + *parent_extents); uint64_t object_overlap = m_ictx->prune_parent_extents(*parent_extents, parent_overlap); if (object_overlap > 0) { @@ -704,9 +704,8 @@ int ObjectCompareAndWriteRequest::filter_write_result(int r) const { // object extent compare mismatch uint64_t offset = -MAX_ERRNO - r; - Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, - this->m_object_no, offset, this->m_object_len, - image_extents); + io::util::extent_to_file(image_ctx, this->m_object_no, offset, + this->m_object_len, image_extents); ceph_assert(image_extents.size() == 1); if (m_mismatch_offset) { @@ -951,8 +950,8 @@ void ObjectListSnapsRequest::list_from_parent() { // calculate reverse mapping onto the parent image Extents parent_image_extents; for (auto [object_off, object_len]: m_object_extents) { - Striper::extent_to_file(cct, &image_ctx->layout, this->m_object_no, - object_off, object_len, parent_image_extents); + io::util::extent_to_file(image_ctx, this->m_object_no, object_off, + object_len, parent_image_extents); } uint64_t parent_overlap = 0; @@ -1014,8 +1013,8 @@ void ObjectListSnapsRequest::handle_list_from_parent(int r) { // map image-extents back to this object striper::LightweightObjectExtents object_extents; - Striper::file_to_extents(cct, &image_ctx->layout, image_extent.get_off(), - image_extent.get_len(), 0, 0, &object_extents); + io::util::file_to_extents(image_ctx, image_extent.get_off(), + image_extent.get_len(), 0, &object_extents); for (auto& object_extent : object_extents) { ceph_assert(object_extent.object_no == this->m_object_no); intervals.insert( diff --git a/src/librbd/io/Types.h b/src/librbd/io/Types.h index b0428a0ba75..8d91c55158c 100644 --- a/src/librbd/io/Types.h +++ b/src/librbd/io/Types.h @@ -66,6 +66,7 @@ enum ImageDispatchLayer { IMAGE_DISPATCH_LAYER_JOURNAL, IMAGE_DISPATCH_LAYER_WRITE_BLOCK, IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, + IMAGE_DISPATCH_LAYER_CRYPTO, IMAGE_DISPATCH_LAYER_CORE, IMAGE_DISPATCH_LAYER_LAST }; @@ -96,6 +97,11 @@ enum { IMAGE_DISPATCH_FLAG_QOS_IOPS_MASK), }; +enum ImageExtentsMapType { + IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL, + IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL, +}; + enum ObjectDispatchLayer { OBJECT_DISPATCH_LAYER_NONE = 0, OBJECT_DISPATCH_LAYER_CACHE, diff --git a/src/librbd/io/Utils.cc b/src/librbd/io/Utils.cc index 99a911410aa..4d11863a97b 100644 --- a/src/librbd/io/Utils.cc +++ b/src/librbd/io/Utils.cc @@ -11,6 +11,7 @@ #include "librbd/io/AioCompletion.h" #include "librbd/io/ImageDispatchSpec.h" #include "librbd/io/ObjectRequest.h" +#include "librbd/io/ImageDispatcherInterface.h" #include "osd/osd_types.h" #include "osdc/Striper.h" @@ -94,8 +95,8 @@ void read_parent(I *image_ctx, uint64_t object_no, ReadExtents* extents, // calculate reverse mapping onto the image Extents parent_extents; for (auto& extent: *extents) { - Striper::extent_to_file(cct, &image_ctx->layout, object_no, extent.offset, - extent.length, parent_extents); + extent_to_file(image_ctx, object_no, extent.offset, extent.length, + parent_extents); } uint64_t parent_overlap = 0; @@ -180,6 +181,39 @@ bool trigger_copyup(I* image_ctx, uint64_t object_no, IOContext io_context, return true; } +template +void file_to_extents(I* image_ctx, uint64_t offset, uint64_t length, + uint64_t buffer_offset, + striper::LightweightObjectExtents* object_extents) { + Extents extents = {{offset, length}}; + image_ctx->io_image_dispatcher->remap_extents( + std::move(extents), IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL); + for (auto [off, len] : extents) { + Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, off, len, 0, + buffer_offset, object_extents); + } +} + +template +void extent_to_file(I* image_ctx, uint64_t object_no, uint64_t offset, + uint64_t length, + std::vector >& extents) { + Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no, + offset, length, extents); + image_ctx->io_image_dispatcher->remap_extents( + std::move(extents), IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL); +} + +template +uint64_t get_file_offset(I* image_ctx, uint64_t object_no, uint64_t offset) { + auto off = Striper::get_file_offset(image_ctx->cct, &image_ctx->layout, + object_no, offset); + Extents extents = {{off, 0}}; + image_ctx->io_image_dispatcher->remap_extents( + std::move(extents), IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL); + return extents[0].first; +} + } // namespace util } // namespace io } // namespace librbd @@ -192,3 +226,14 @@ template int librbd::io::util::clip_request( template bool librbd::io::util::trigger_copyup( librbd::ImageCtx *image_ctx, uint64_t object_no, IOContext io_context, Context* on_finish); +template void librbd::io::util::file_to_extents( + librbd::ImageCtx *image_ctx, uint64_t offset, uint64_t length, + uint64_t buffer_offset, + striper::LightweightObjectExtents* object_extents); +template void librbd::io::util::extent_to_file( + librbd::ImageCtx *image_ctx, uint64_t object_no, uint64_t offset, + uint64_t length, + std::vector >& extents); +template uint64_t librbd::io::util::get_file_offset( + librbd::ImageCtx *image_ctx, uint64_t object_no, uint64_t offset); + diff --git a/src/librbd/io/Utils.h b/src/librbd/io/Utils.h index 22b86058a8b..fbcc6900891 100644 --- a/src/librbd/io/Utils.h +++ b/src/librbd/io/Utils.h @@ -53,6 +53,20 @@ void unsparsify(CephContext* cct, ceph::bufferlist* bl, template bool trigger_copyup(ImageCtxT *image_ctx, uint64_t object_no, IOContext io_context, Context* on_finish); + +template +void file_to_extents(ImageCtxT *image_ctx, uint64_t offset, uint64_t length, + uint64_t buffer_offset, + striper::LightweightObjectExtents* object_extents); + +template +void extent_to_file(ImageCtxT *image_ctx, uint64_t object_no, uint64_t offset, + uint64_t length, + std::vector >& extents); + +template +uint64_t get_file_offset(ImageCtxT *image_ctx, uint64_t object_no, + uint64_t offset); } // namespace util } // namespace io diff --git a/src/librbd/journal/ObjectDispatch.cc b/src/librbd/journal/ObjectDispatch.cc index 1c42573664f..5623c635d8f 100644 --- a/src/librbd/journal/ObjectDispatch.cc +++ b/src/librbd/journal/ObjectDispatch.cc @@ -10,6 +10,7 @@ #include "librbd/asio/ContextWQ.h" #include "librbd/io/ObjectDispatchSpec.h" #include "librbd/io/ObjectDispatcherInterface.h" +#include "librbd/io/Utils.h" #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -51,8 +52,8 @@ struct C_CommitIOEvent : public Context { (object_dispatch_flags & io::OBJECT_DISPATCH_FLAG_WILL_RETRY_ON_ERROR) == 0) { io::Extents file_extents; - Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no, - object_off, object_len, file_extents); + io::util::extent_to_file(image_ctx, object_no, object_off, object_len, + file_extents); for (auto& extent : file_extents) { journal->commit_io_event_extent(journal_tid, extent.first, extent.second, r); diff --git a/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc b/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc index 805a83d75bd..e4e4493cc52 100644 --- a/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc +++ b/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc @@ -55,6 +55,12 @@ CopyupRequest* CopyupRequest< namespace util { +template <> uint64_t get_file_offset( + MockImageCtx *image_ctx, uint64_t object_no, uint64_t offset) { + return Striper::get_file_offset(image_ctx->cct, &image_ctx->layout, + object_no, offset); +} + namespace { struct Mock { diff --git a/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc b/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc index 3860a9aa1c9..56ae4c19520 100644 --- a/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc +++ b/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc @@ -15,6 +15,7 @@ #include "librbd/api/Io.h" #include "librbd/deep_copy/ObjectCopyRequest.h" #include "librbd/io/ReadResult.h" +#include "librbd/io/Utils.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "test/librbd/mock/MockImageCtx.h" #include "test/librbd/test_support.h" @@ -39,6 +40,29 @@ inline ImageCtx* get_image_ctx(MockTestImageCtx* image_ctx) { } } // namespace util + +namespace io { +namespace util { + +template <> void file_to_extents( + MockTestImageCtx* image_ctx, uint64_t offset, uint64_t length, + uint64_t buffer_offset, + striper::LightweightObjectExtents* object_extents) { + Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, offset, length, + 0, buffer_offset, object_extents); +} + +template <> void extent_to_file( + MockTestImageCtx* image_ctx, uint64_t object_no, uint64_t offset, + uint64_t length, + std::vector >& extents) { + Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no, + offset, length, extents); +} + +} // namespace util +} // namespace io + } // namespace librbd // template definitions diff --git a/src/test/librbd/io/test_mock_CopyupRequest.cc b/src/test/librbd/io/test_mock_CopyupRequest.cc index ee7a911c43e..413400b81b7 100644 --- a/src/test/librbd/io/test_mock_CopyupRequest.cc +++ b/src/test/librbd/io/test_mock_CopyupRequest.cc @@ -16,6 +16,7 @@ #include "librbd/io/ImageDispatchSpec.h" #include "librbd/io/ObjectRequest.h" #include "librbd/io/ReadResult.h" +#include "librbd/io/Utils.h" namespace librbd { namespace { @@ -80,6 +81,26 @@ ObjectCopyRequest* ObjectCopyRequest void file_to_extents( + MockTestImageCtx* image_ctx, uint64_t offset, uint64_t length, + uint64_t buffer_offset, + striper::LightweightObjectExtents* object_extents) { + Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, offset, length, + 0, buffer_offset, object_extents); +} + +template <> void extent_to_file( + MockTestImageCtx* image_ctx, uint64_t object_no, uint64_t offset, + uint64_t length, + std::vector >& extents) { + Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no, + offset, length, extents); +} + +} // namespace util + template <> struct ObjectRequest { static void add_write_hint(librbd::MockTestImageCtx&, diff --git a/src/test/librbd/io/test_mock_ImageRequest.cc b/src/test/librbd/io/test_mock_ImageRequest.cc index c17e55ca45f..d1390bcf85d 100644 --- a/src/test/librbd/io/test_mock_ImageRequest.cc +++ b/src/test/librbd/io/test_mock_ImageRequest.cc @@ -8,6 +8,7 @@ #include "test/librbd/mock/cache/MockImageCache.h" #include "librbd/io/ImageRequest.h" #include "librbd/io/ObjectDispatchSpec.h" +#include "librbd/io/Utils.h" namespace librbd { namespace { @@ -53,6 +54,27 @@ inline ImageCtx *get_image_ctx(MockTestImageCtx *image_ctx) { namespace librbd { namespace io { +namespace util { + +template<> +void file_to_extents( + MockTestImageCtx *image_ctx, uint64_t offset, uint64_t length, + uint64_t buffer_offset, + striper::LightweightObjectExtents *object_extents) { + Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, offset, length, + 0, buffer_offset, object_extents); +} + +template <> void extent_to_file( + MockTestImageCtx* image_ctx, uint64_t object_no, uint64_t offset, + uint64_t length, + std::vector >& extents) { + Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no, + offset, length, extents); +} + +} // namespace util + using ::testing::_; using ::testing::InSequence; using ::testing::Invoke; diff --git a/src/test/librbd/io/test_mock_ObjectRequest.cc b/src/test/librbd/io/test_mock_ObjectRequest.cc index 559de694e5e..5a451bcfbc5 100644 --- a/src/test/librbd/io/test_mock_ObjectRequest.cc +++ b/src/test/librbd/io/test_mock_ObjectRequest.cc @@ -90,6 +90,22 @@ ImageListSnapsRequest* ImageListSnapsRequest void file_to_extents( + MockTestImageCtx* image_ctx, uint64_t offset, uint64_t length, + uint64_t buffer_offset, + striper::LightweightObjectExtents* object_extents) { + Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, offset, length, + 0, buffer_offset, object_extents); +} + +template <> void extent_to_file( + MockTestImageCtx* image_ctx, uint64_t object_no, uint64_t offset, + uint64_t length, + std::vector >& extents) { + Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no, + offset, length, extents); +} + namespace { struct Mock { diff --git a/src/test/librbd/mock/io/MockImageDispatcher.h b/src/test/librbd/mock/io/MockImageDispatcher.h index 14669133048..7d63044cda8 100644 --- a/src/test/librbd/mock/io/MockImageDispatcher.h +++ b/src/test/librbd/mock/io/MockImageDispatcher.h @@ -37,6 +37,8 @@ public: MOCK_METHOD0(unblock_writes, void()); MOCK_METHOD1(wait_on_writes_unblocked, void(Context*)); + + MOCK_METHOD2(remap_extents, void(Extents&&, ImageExtentsMapType)); }; } // namespace io -- 2.39.5