#include "librbd/io/ObjectDispatcher.h"
#include "librbd/io/QosImageDispatch.h"
#include "librbd/io/IoOperations.h"
+#include "librbd/io/Utils.h"
#include "librbd/journal/StandardPolicy.h"
#include "librbd/operation/ResizeRequest.h"
return 0;
}
- io::Extents extents = {{raw_size, 0}};
- io_image_dispatcher->remap_extents(
- extents, io::IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL);
- return extents.front().first;
+ return io::util::raw_to_area_offset(*this, raw_size).first;
}
uint64_t ImageCtx::get_object_count(snap_t in_snap_id) const {
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;
+void CryptoImageDispatch::remap_to_physical(io::Extents& image_extents,
+ io::ImageArea area) {
+ switch (area) {
+ case io::ImageArea::DATA:
+ for (auto& [off, _] : image_extents) {
+ off += m_data_offset;
}
- } else if (type == io::IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL) {
- for (auto& extent: image_extents) {
- extent.first -= m_data_offset;
+ break;
+ case io::ImageArea::CRYPTO_HEADER:
+ // direct mapping
+ break;
+ default:
+ ceph_abort();
+ }
+}
+
+io::ImageArea CryptoImageDispatch::remap_to_logical(
+ io::Extents& image_extents) {
+ bool saw_data = false;
+ bool saw_crypto_header = false;
+ for (auto& [off, _] : image_extents) {
+ if (off >= m_data_offset) {
+ off -= m_data_offset;
+ saw_data = true;
+ } else {
+ saw_crypto_header = true;
}
}
+ if (saw_crypto_header) {
+ ceph_assert(!saw_data);
+ return io::ImageArea::CRYPTO_HEADER;
+ }
+ return io::ImageArea::DATA;
}
} // namespace crypto
return false;
}
- void remap_extents(io::Extents& image_extents,
- io::ImageExtentsMapType type) override;
+ // called directly by ImageDispatcher
+ // TODO: hoist these out and remove CryptoImageDispatch since it's
+ // just a placeholder
+ void remap_to_physical(io::Extents& image_extents, io::ImageArea area);
+ io::ImageArea remap_to_logical(io::Extents& image_extents);
private:
uint64_t m_data_offset;
Context* on_dispatched) = 0;
virtual bool invalidate_cache(Context* on_finish) = 0;
-
- virtual void remap_extents(Extents& image_extents,
- ImageExtentsMapType type) {}
-
};
} // namespace io
#include "common/AsyncOpTracker.h"
#include "common/dout.h"
#include "librbd/ImageCtx.h"
+#include "librbd/crypto/CryptoImageDispatch.h"
#include "librbd/io/ImageDispatch.h"
#include "librbd/io/ImageDispatchInterface.h"
#include "librbd/io/ImageDispatchSpec.h"
}
template <typename I>
-void ImageDispatcher<I>::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(image_extents, type);
- }
- };
+void ImageDispatcher<I>::remap_to_physical(Extents& image_extents,
+ ImageArea area) {
+ std::shared_lock locker{this->m_lock};
+ auto it = this->m_dispatches.find(IMAGE_DISPATCH_LAYER_CRYPTO);
+ if (it == this->m_dispatches.end()) {
+ ceph_assert(area == ImageArea::DATA);
+ return;
+ }
+ auto crypto_image_dispatch = static_cast<crypto::CryptoImageDispatch*>(
+ it->second.dispatch);
+ crypto_image_dispatch->remap_to_physical(image_extents, area);
+}
+template <typename I>
+ImageArea ImageDispatcher<I>::remap_to_logical(Extents& image_extents) {
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());
+ auto it = this->m_dispatches.find(IMAGE_DISPATCH_LAYER_CRYPTO);
+ if (it == this->m_dispatches.end()) {
+ return ImageArea::DATA;
}
+ auto crypto_image_dispatch = static_cast<crypto::CryptoImageDispatch*>(
+ it->second.dispatch);
+ return crypto_image_dispatch->remap_to_logical(image_extents);
}
template <typename I>
void unblock_writes() override;
void wait_on_writes_unblocked(Context *on_unblocked) override;
- void remap_extents(Extents& image_extents,
- ImageExtentsMapType type) override;
+ void remap_to_physical(Extents& image_extents, ImageArea area) override;
+ ImageArea remap_to_logical(Extents& image_extents) override;
protected:
bool send_dispatch(
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;
+
+ virtual void remap_to_physical(Extents& image_extents, ImageArea area) = 0;
+ virtual ImageArea remap_to_logical(Extents& image_extents) = 0;
};
} // namespace io
return os;
}
+std::ostream& operator<<(std::ostream& os, ImageArea area) {
+ switch (area) {
+ case ImageArea::DATA:
+ return os << "data";
+ case ImageArea::CRYPTO_HEADER:
+ return os << "crypto_header";
+ default:
+ ceph_abort();
+ }
+}
+
} // namespace io
} // namespace librbd
RBD_IO_OPERATION_COMPARE_AND_WRITE)
};
-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,
typedef std::pair<uint64_t,uint64_t> Extent;
typedef std::vector<Extent> Extents;
+enum class ImageArea {
+ DATA,
+ CRYPTO_HEADER
+};
+
+std::ostream& operator<<(std::ostream& os, ImageArea area);
+
struct ReadExtent {
const uint64_t offset;
const uint64_t length;
uint64_t buffer_offset,
striper::LightweightObjectExtents* object_extents) {
Extents extents = {{offset, length}};
- image_ctx->io_image_dispatcher->remap_extents(
- extents, IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL);
+ // TODO: pass area
+ image_ctx->io_image_dispatcher->remap_to_physical(extents, ImageArea::DATA);
for (auto [off, len] : extents) {
Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, off, len, 0,
buffer_offset, object_extents);
std::vector<std::pair<uint64_t, uint64_t> >& extents) {
Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no,
offset, length, extents);
- image_ctx->io_image_dispatcher->remap_extents(
- extents, IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL);
+ // TODO: return area
+ image_ctx->io_image_dispatcher->remap_to_logical(extents);
+}
+
+template <typename I>
+uint64_t area_to_raw_offset(const I& image_ctx, uint64_t offset,
+ ImageArea area) {
+ Extents extents = {{offset, 0}};
+ image_ctx.io_image_dispatcher->remap_to_physical(extents, area);
+ return extents[0].first;
+}
+
+template <typename I>
+std::pair<uint64_t, ImageArea> raw_to_area_offset(const I& image_ctx,
+ uint64_t offset) {
+ Extents extents = {{offset, 0}};
+ auto area = image_ctx.io_image_dispatcher->remap_to_logical(extents);
+ return {extents[0].first, area};
}
template <typename I>
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(
- extents, IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL);
+ image_ctx->io_image_dispatcher->remap_to_logical(extents);
return extents[0].first;
}
librbd::ImageCtx *image_ctx, uint64_t object_no, uint64_t offset,
uint64_t length,
std::vector<std::pair<uint64_t, uint64_t> >& extents);
+template uint64_t librbd::io::util::area_to_raw_offset(
+ const librbd::ImageCtx& image_ctx, uint64_t offset, ImageArea area);
+template auto librbd::io::util::raw_to_area_offset(
+ const librbd::ImageCtx& image_ctx, uint64_t offset)
+ -> std::pair<uint64_t, ImageArea>;
template uint64_t librbd::io::util::get_file_offset(
librbd::ImageCtx *image_ctx, uint64_t object_no, uint64_t offset);
uint64_t length,
std::vector<std::pair<uint64_t, uint64_t> >& extents);
+template <typename ImageCtxT = librbd::ImageCtx>
+uint64_t area_to_raw_offset(const ImageCtxT& image_ctx, uint64_t offset,
+ ImageArea area);
+
+template <typename ImageCtxT = librbd::ImageCtx>
+std::pair<uint64_t, ImageArea> raw_to_area_offset(const ImageCtxT& image_ctx,
+ uint64_t offset);
+
template <typename ImageCtxT = librbd::ImageCtx>
uint64_t get_file_offset(ImageCtxT *image_ctx, uint64_t object_no,
uint64_t offset);
mock_image_ctx->layout.object_size));
}
- void expect_remap_extents(uint64_t offset, uint64_t length) {
- EXPECT_CALL(*mock_image_ctx->io_image_dispatcher, remap_extents(
- ElementsAre(Pair(offset, length)),
- io::IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL));
+ void expect_remap_to_logical(uint64_t offset, uint64_t length) {
+ EXPECT_CALL(*mock_image_ctx->io_image_dispatcher, remap_to_logical(
+ ElementsAre(Pair(offset, length))));
}
void expect_get_parent_overlap(uint64_t overlap) {
expect_get_object_size();
expect_get_parent_overlap(mock_image_ctx->layout.object_size);
- expect_remap_extents(0, mock_image_ctx->layout.object_size);
+ expect_remap_to_logical(0, mock_image_ctx->layout.object_size);
expect_prune_parent_extents(mock_image_ctx->layout.object_size);
EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillRepeatedly(
Return(true));
expect_get_object_size();
expect_get_parent_overlap(mock_image_ctx->layout.object_size);
- expect_remap_extents(0, mock_image_ctx->layout.object_size);
+ expect_remap_to_logical(0, mock_image_ctx->layout.object_size);
expect_prune_parent_extents(mock_image_ctx->layout.object_size);
EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillRepeatedly(
Return(true));
expect_get_object_size();
expect_encrypt(6);
InSequence seq;
- expect_remap_extents(0, 4096);
- expect_remap_extents(4096, 4096);
- expect_remap_extents(8192, 4096);
- expect_remap_extents(0, 4096);
- expect_remap_extents(4096, 8192);
- expect_remap_extents(16384, 4096);
+ expect_remap_to_logical(0, 4096);
+ expect_remap_to_logical(4096, 4096);
+ expect_remap_to_logical(8192, 4096);
+ expect_remap_to_logical(0, 4096);
+ expect_remap_to_logical(4096, 8192);
+ expect_remap_to_logical(16384, 4096);
ASSERT_EQ(0, mock_crypto_object_dispatch->prepare_copyup(
0, &snapshot_sparse_bufferlist));
MOCK_METHOD0(unblock_writes, void());
MOCK_METHOD1(wait_on_writes_unblocked, void(Context*));
- MOCK_METHOD2(remap_extents, void(Extents&, ImageExtentsMapType));
+ MOCK_METHOD2(remap_to_physical, void(Extents&, ImageArea));
+ MOCK_METHOD1(remap_to_logical, ImageArea(Extents&));
};
} // namespace io