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 <oro@il.ibm.com>
cache/WriteAroundObjectDispatch.cc
crypto/BlockCrypto.cc
crypto/CryptoContextPool.cc
+ crypto/CryptoImageDispatch.cc
crypto/CryptoObjectDispatch.cc
crypto/openssl/DataCryptor.cc
deep_copy/ImageCopyRequest.cc
#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"
// reverse map this object extent onto the parent
vector<pair<uint64_t,uint64_t> > 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
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) {
--- /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_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
--- /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:
+ 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, IOContext io_context, 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, IOContext io_context,
+ 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, IOContext io_context, 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,
+ IOContext io_context, 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;
+ }
+
+ 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
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;
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);
#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
template <typename I>
void ObjectCopyRequest<I>::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;
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 << ", "
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);
#include "librbd/io/ObjectDispatcherInterface.h"
#include "librbd/io/ObjectRequest.h"
#include "librbd/io/ReadResult.h"
+#include "librbd/io/Utils.h"
#include <boost/lambda/bind.hpp>
#include <boost/lambda/construct.hpp>
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 <typename I>
auto comp = AioCompletion::create_and_start<
CopyupRequest<I>,
&CopyupRequest<I>::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
ldout(cct, 20) << "flatten=" << m_flatten << dendl;
- auto ctx = util::create_context_callback<
+ auto ctx = librbd::util::create_context_callback<
CopyupRequest<I>, &CopyupRequest<I>::handle_deep_copy>(this);
auto req = deep_copy::ObjectCopyRequest<I>::create(
m_image_ctx->parent, m_image_ctx, 0, 0,
boost::lambda::bind(boost::lambda::new_ptr<C_UpdateObjectMap<I>>(),
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<I>, &CopyupRequest<I>::handle_update_object_maps>(this);
auto throttle = new AsyncObjectThrottle<I>(
nullptr, *m_image_ctx, context_factory, ctx, nullptr, 0, m_snap_ids.size());
return false;
}
std::vector<std::pair<uint64_t, uint64_t>> 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;
// 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);
Context* on_dispatched) = 0;
virtual bool invalidate_cache(Context* on_finish) = 0;
+
+ virtual void remap_extents(Extents&& image_extents,
+ ImageExtentsMapType type) {}
+
};
} // namespace io
m_write_block_dispatch->wait_on_writes_unblocked(on_unblocked);
}
+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(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 <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_extents(Extents&& image_extents,
+ ImageExtentsMapType type) 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_extents(Extents&& image_extents,
+ ImageExtentsMapType type) = 0;
};
} // namespace io
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];
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,
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;
}
template <typename I>
void AbstractImageWriteRequest<I>::send_request() {
I &image_ctx = this->m_image_ctx;
- CephContext *cct = image_ctx.cct;
bool journaling = false;
}
// 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;
}
}
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);
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) {
// 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) {
// 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;
// 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(
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
};
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,
#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"
// 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;
return true;
}
+template <typename I>
+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 <typename I>
+void extent_to_file(I* image_ctx, uint64_t object_no, uint64_t offset,
+ uint64_t length,
+ 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(
+ std::move(extents), IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL);
+}
+
+template <typename I>
+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
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<std::pair<uint64_t, uint64_t> >& extents);
+template uint64_t librbd::io::util::get_file_offset(
+ librbd::ImageCtx *image_ctx, uint64_t object_no, uint64_t offset);
+
template <typename ImageCtxT = librbd::ImageCtx>
bool trigger_copyup(ImageCtxT *image_ctx, uint64_t object_no,
IOContext io_context, Context* on_finish);
+
+template <typename ImageCtxT = librbd::ImageCtx>
+void file_to_extents(ImageCtxT *image_ctx, uint64_t offset, uint64_t length,
+ uint64_t buffer_offset,
+ striper::LightweightObjectExtents* object_extents);
+
+template <typename ImageCtxT = librbd::ImageCtx>
+void extent_to_file(ImageCtxT *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 get_file_offset(ImageCtxT *image_ctx, uint64_t object_no,
+ uint64_t offset);
} // namespace util
} // namespace io
#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
(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);
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 {
#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"
}
} // 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<std::pair<uint64_t, uint64_t> >& extents) {
+ Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no,
+ offset, length, extents);
+}
+
+} // namespace util
+} // namespace io
+
} // namespace librbd
// template definitions
#include "librbd/io/ImageDispatchSpec.h"
#include "librbd/io/ObjectRequest.h"
#include "librbd/io/ReadResult.h"
+#include "librbd/io/Utils.h"
namespace librbd {
namespace {
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<std::pair<uint64_t, uint64_t> >& extents) {
+ Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no,
+ offset, length, extents);
+}
+
+} // namespace util
+
template <>
struct ObjectRequest<librbd::MockTestImageCtx> {
static void add_write_hint(librbd::MockTestImageCtx&,
#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 {
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<std::pair<uint64_t, uint64_t> >& 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;
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<std::pair<uint64_t, uint64_t> >& extents) {
+ Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no,
+ offset, length, extents);
+}
+
namespace {
struct Mock {
MOCK_METHOD0(unblock_writes, void());
MOCK_METHOD1(wait_on_writes_unblocked, void(Context*));
+
+ MOCK_METHOD2(remap_extents, void(Extents&&, ImageExtentsMapType));
};
} // namespace io