This commit removes the crypto image dispatch layer.
Instead, data offset calculation is taken from ImageCtx->encryption_format.
This change makes the remap_to_* api unnecessary, so it is removed.
Signed-off-by: Or Ozeri <oro@il.ibm.com>
cache/WriteAroundObjectDispatch.cc
crypto/BlockCrypto.cc
crypto/CryptoContextPool.cc
- crypto/CryptoImageDispatch.cc
crypto/CryptoObjectDispatch.cc
crypto/FormatRequest.cc
crypto/LoadRequest.cc
#include "librbd/exclusive_lock/AutomaticPolicy.h"
#include "librbd/exclusive_lock/StandardPolicy.h"
#include "librbd/crypto/EncryptionFormat.h"
+#include "librbd/crypto/CryptoInterface.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/AsyncOperation.h"
#include "librbd/io/ImageDispatcher.h"
return new Journal<ImageCtx>(*this);
}
+ uint64_t ImageCtx::get_data_offset() const {
+ if (encryption_format != nullptr) {
+ return encryption_format->get_crypto()->get_data_offset();
+ }
+ return 0;
+ }
+
void ImageCtx::set_image_name(const std::string &image_name) {
// update the name so rename can be invoked repeatedly
std::shared_lock owner_locker{owner_lock};
ObjectMap<ImageCtx> *create_object_map(uint64_t snap_id);
Journal<ImageCtx> *create_journal();
+ uint64_t get_data_offset() const;
void set_image_name(const std::string &name);
void notify_update();
+++ /dev/null
-// -*- 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_to_physical(io::Extents& image_extents,
- io::ImageArea area) {
- switch (area) {
- case io::ImageArea::DATA:
- for (auto& [off, _] : image_extents) {
- off += 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
-} // namespace librbd
+++ /dev/null
-// -*- 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:
- static CryptoImageDispatch* create(uint64_t data_offset) {
- return new CryptoImageDispatch(data_offset);
- }
- 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<uint32_t>* 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,
- int op_flags, const ZTracer::Trace &parent_trace,
- uint64_t tid, std::atomic<uint32_t>* 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, const ZTracer::Trace &parent_trace,
- uint64_t tid, std::atomic<uint32_t>* 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,
- int op_flags, const ZTracer::Trace &parent_trace,
- uint64_t tid, std::atomic<uint32_t>* 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,
- int op_flags, const ZTracer::Trace &parent_trace,
- uint64_t tid, std::atomic<uint32_t>* 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<uint32_t>* 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<uint32_t>* image_dispatch_flags,
- io::DispatchResult* dispatch_result, Context** on_finish,
- Context* on_dispatched) override {
- return false;
- }
-
- bool invalidate_cache(Context* on_finish) override {
- return false;
- }
-
- // 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;
-
-};
-
-} // namespace crypto
-} // namespace librbd
-
-#endif // CEPH_LIBRBD_CRYPTO_CRYPTO_IMAGE_DISPATCH_H
#include "common/dout.h"
#include "common/errno.h"
#include "librbd/Utils.h"
-#include "librbd/crypto/CryptoImageDispatch.h"
#include "librbd/crypto/CryptoObjectDispatch.h"
#include "librbd/crypto/EncryptionFormat.h"
#include "librbd/io/ImageDispatcherInterface.h"
if (r < 0) {
lderr(m_image_ctx->cct) << "failed to shut down object dispatch: "
<< cpp_strerror(r) << dendl;
- finish(r);
- return;
}
- shut_down_image_dispatch();
-}
-
-template <typename I>
-void ShutDownCryptoRequest<I>::shut_down_image_dispatch() {
- if (!m_image_ctx->io_image_dispatcher->exists(
- io::IMAGE_DISPATCH_LAYER_CRYPTO)) {
- finish(0);
- return;
- }
-
- auto ctx = create_context_callback<
- ShutDownCryptoRequest<I>,
- &ShutDownCryptoRequest<I>::handle_shut_down_image_dispatch>(this);
- m_image_ctx->io_image_dispatcher->shut_down_dispatch(
- io::IMAGE_DISPATCH_LAYER_CRYPTO, ctx);
-}
-
-template <typename I>
-void ShutDownCryptoRequest<I>::handle_shut_down_image_dispatch(int r) {
- ldout(m_image_ctx->cct, 20) << "r=" << r << dendl;
-
- if (r < 0) {
- lderr(m_image_ctx->cct) << "failed to shut down image dispatch: "
- << cpp_strerror(r) << dendl;
- }
finish(r);
}
void send();
void shut_down_object_dispatch();
void handle_shut_down_object_dispatch(int r);
- void shut_down_image_dispatch();
- void handle_shut_down_image_dispatch(int r);
void finish(int r);
private:
#include "common/errno.h"
#include "librbd/ImageCtx.h"
#include "librbd/crypto/BlockCrypto.h"
-#include "librbd/crypto/CryptoImageDispatch.h"
#include "librbd/crypto/CryptoInterface.h"
#include "librbd/crypto/CryptoObjectDispatch.h"
#include "librbd/crypto/EncryptionFormat.h"
auto crypto = encryption_format->get_crypto();
auto object_dispatch = CryptoObjectDispatch<I>::create(image_ctx, crypto);
- auto image_dispatch = CryptoImageDispatch::create(crypto->get_data_offset());
image_ctx->io_object_dispatcher->register_dispatch(object_dispatch);
- image_ctx->io_image_dispatcher->register_dispatch(image_dispatch);
image_ctx->encryption_format = std::move(encryption_format);
}
#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"
m_write_block_dispatch->wait_on_writes_unblocked(on_unblocked);
}
-template <typename I>
-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};
- 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>
bool ImageDispatcher<I>::send_dispatch(
ImageDispatchInterface* image_dispatch,
void unblock_writes() override;
void wait_on_writes_unblocked(Context *on_unblocked) override;
- void remap_to_physical(Extents& image_extents, ImageArea area) override;
- ImageArea remap_to_logical(Extents& image_extents) override;
-
protected:
bool send_dispatch(
ImageDispatchInterface* image_dispatch,
virtual void wait_on_writes_unblocked(Context *on_unblocked) = 0;
virtual void invalidate_cache(Context* on_finish) = 0;
-
- virtual void remap_to_physical(Extents& image_extents, ImageArea area) = 0;
- virtual ImageArea remap_to_logical(Extents& image_extents) = 0;
};
} // namespace io
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
};
void area_to_object_extents(I* image_ctx, uint64_t offset, uint64_t length,
ImageArea area, uint64_t buffer_offset,
striper::LightweightObjectExtents* object_extents) {
- Extents extents = {{offset, length}};
- image_ctx->io_image_dispatcher->remap_to_physical(extents, area);
- for (auto [off, len] : extents) {
- Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, off, len, 0,
- buffer_offset, object_extents);
- }
+ offset = area_to_raw_offset(*image_ctx, offset, area);
+ Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, offset, length,
+ 0, buffer_offset, object_extents);
}
template <typename I>
Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no, off,
len, extents);
}
- auto area = image_ctx->io_image_dispatcher->remap_to_logical(extents);
+
+ auto area = ImageArea::DATA;
+ uint64_t data_offset = image_ctx->get_data_offset();
+ bool saw_data = false;
+ bool saw_crypto_header = false;
+ for (auto& [off, _] : extents) {
+ if (off >= data_offset) {
+ off -= data_offset;
+ saw_data = true;
+ } else {
+ saw_crypto_header = true;
+ }
+ }
+ if (saw_crypto_header) {
+ ceph_assert(!saw_data);
+ area = ImageArea::CRYPTO_HEADER;
+ }
+
return {std::move(extents), area};
}
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;
+ switch (area) {
+ case ImageArea::DATA:
+ return offset + image_ctx.get_data_offset();
+ case ImageArea::CRYPTO_HEADER:
+ // direct mapping
+ ceph_assert(image_ctx.get_data_offset() != 0);
+ return offset;
+ default:
+ ceph_abort();
+ }
}
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};
+ uint64_t data_offset = image_ctx.get_data_offset();
+ if (offset >= data_offset) {
+ return {offset - data_offset, ImageArea::DATA};
+ }
+ return {offset, ImageArea::CRYPTO_HEADER};
}
} // namespace util
mock_image_ctx->layout.object_size));
}
- 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_CALL(*mock_image_ctx, get_parent_overlap(_, _))
.WillOnce(WithArg<1>(Invoke([overlap](uint64_t *o) {
expect_get_object_size();
expect_get_parent_overlap(100 << 20);
- expect_remap_to_logical(11 * mock_image_ctx->layout.object_size,
- 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(100 << 20);
- expect_remap_to_logical(11 * mock_image_ctx->layout.object_size,
- 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;
- uint64_t base = 11 * mock_image_ctx->layout.object_size;
- expect_remap_to_logical(base, 4096);
- expect_remap_to_logical(base + 4096, 4096);
- expect_remap_to_logical(base + 8192, 4096);
- expect_remap_to_logical(base, 4096);
- expect_remap_to_logical(base + 4096, 8192);
- expect_remap_to_logical(base + 16384, 4096);
ASSERT_EQ(0, mock_crypto_object_dispatch->prepare_copyup(
11, &snapshot_sparse_bufferlist));
MockShutDownCryptoRequest* mock_shutdown_crypto_request;
MockEncryptionFormat* mock_encryption_format;
Context* shutdown_object_dispatch_context;
- Context* shutdown_image_dispatch_context;
void SetUp() override {
TestMockFixture::SetUp();
io::OBJECT_DISPATCH_LAYER_CRYPTO)).WillOnce(Return(exists));
}
- void expect_crypto_image_layer_exists_check(
- MockTestImageCtx* image_ctx, bool exists) {
- EXPECT_CALL(*image_ctx->io_image_dispatcher, exists(
- io::IMAGE_DISPATCH_LAYER_CRYPTO)).WillOnce(Return(exists));
- }
-
void expect_shutdown_crypto_object_dispatch(MockTestImageCtx* image_ctx) {
EXPECT_CALL(*image_ctx->io_object_dispatcher, shut_down_dispatch(
io::OBJECT_DISPATCH_LAYER_CRYPTO, _)).WillOnce(
shutdown_object_dispatch_context = ctx;
})));
}
-
- void expect_shutdown_crypto_image_dispatch(MockTestImageCtx* image_ctx) {
- EXPECT_CALL(*image_ctx->io_image_dispatcher, shut_down_dispatch(
- io::IMAGE_DISPATCH_LAYER_CRYPTO, _)).WillOnce(
- WithArgs<1>(Invoke([this](Context* ctx) {
- shutdown_image_dispatch_context = ctx;
- })));
- }
};
TEST_F(TestMockShutDownCryptoRequest, NoCryptoObjectDispatch) {
ASSERT_EQ(mock_encryption_format, mock_image_ctx->encryption_format.get());
}
-TEST_F(TestMockShutDownCryptoRequest, NoCryptoImageDispatch) {
- expect_crypto_object_layer_exists_check(mock_image_ctx, true);
- expect_shutdown_crypto_object_dispatch(mock_image_ctx);
- mock_shutdown_crypto_request->send();
- ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
- expect_crypto_image_layer_exists_check(mock_image_ctx, false);
- shutdown_object_dispatch_context->complete(0);
- ASSERT_EQ(0, finished_cond.wait());
- ASSERT_EQ(nullptr, mock_image_ctx->encryption_format.get());
-}
-
-TEST_F(TestMockShutDownCryptoRequest, FailShutdownImageDispatch) {
- expect_crypto_object_layer_exists_check(mock_image_ctx, true);
- expect_shutdown_crypto_object_dispatch(mock_image_ctx);
- mock_shutdown_crypto_request->send();
- ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
- expect_crypto_image_layer_exists_check(mock_image_ctx, true);
- expect_shutdown_crypto_image_dispatch(mock_image_ctx);
- shutdown_object_dispatch_context->complete(0);
- ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
- shutdown_image_dispatch_context->complete(-EIO);
- ASSERT_EQ(-EIO, finished_cond.wait());
- ASSERT_EQ(mock_encryption_format, mock_image_ctx->encryption_format.get());
-}
-
TEST_F(TestMockShutDownCryptoRequest, Success) {
expect_crypto_object_layer_exists_check(mock_image_ctx, true);
expect_shutdown_crypto_object_dispatch(mock_image_ctx);
mock_shutdown_crypto_request->send();
ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
- expect_crypto_image_layer_exists_check(mock_image_ctx, true);
- expect_shutdown_crypto_image_dispatch(mock_image_ctx);
shutdown_object_dispatch_context->complete(0);
- ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
- shutdown_image_dispatch_context->complete(0);
ASSERT_EQ(0, finished_cond.wait());
ASSERT_EQ(nullptr, mock_image_ctx->encryption_format.get());
}
expect_shutdown_crypto_object_dispatch(mock_image_ctx);
mock_shutdown_crypto_request->send();
ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
- expect_crypto_image_layer_exists_check(mock_image_ctx, true);
- expect_shutdown_crypto_image_dispatch(mock_image_ctx);
- shutdown_object_dispatch_context->complete(0);
- ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
expect_crypto_object_layer_exists_check(parent_image_ctx, true);
expect_shutdown_crypto_object_dispatch(parent_image_ctx);
- shutdown_image_dispatch_context->complete(0);
- ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
- expect_crypto_image_layer_exists_check(parent_image_ctx, true);
- expect_shutdown_crypto_image_dispatch(parent_image_ctx);
shutdown_object_dispatch_context->complete(0);
ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
mock_image_ctx->parent = nullptr;
- shutdown_image_dispatch_context->complete(0);
+ shutdown_object_dispatch_context->complete(0);
ASSERT_EQ(0, finished_cond.wait());
ASSERT_EQ(nullptr, mock_image_ctx->encryption_format.get());
ASSERT_EQ(nullptr, parent_image_ctx->encryption_format.get());
return std::make_shared<neorados::IOContext>(*get_data_io_context());
}
+uint64_t MockImageCtx::get_data_offset() const {
+ if (encryption_format != nullptr) {
+ return encryption_format->get_crypto()->get_data_offset();
+ }
+ return 0;
+}
+
} // namespace librbd
MOCK_METHOD0(rebuild_data_io_context, void());
IOContext get_data_io_context();
IOContext duplicate_data_io_context();
+ uint64_t get_data_offset() const;
static void set_timer_instance(MockSafeTimer *timer, ceph::mutex *timer_lock);
static void get_timer_instance(CephContext *cct, MockSafeTimer **timer,
MOCK_METHOD0(unblock_writes, void());
MOCK_METHOD1(wait_on_writes_unblocked, void(Context*));
-
- MOCK_METHOD2(remap_to_physical, void(Extents&, ImageArea));
- MOCK_METHOD1(remap_to_logical, ImageArea(Extents&));
};
} // namespace io