This is a preparation work to make ReplicatedWriteLog as a plugin.
Signed-off-by: Li, Xiaoyan <xiaoyan.li@intel.com>
cache/pwl/Types.cc
cache/pwl/ReplicatedWriteLog.cc
cache/pwl/AbstractWriteLog.cc
+ cache/pwl/ImageDispatch.cc
cache/WriteLogCache.cc)
endif()
template <typename> class PluginRegistry;
namespace asio { struct ContextWQ; }
- namespace cache { template <typename> class ImageCache; }
namespace exclusive_lock { struct Policy; }
namespace io {
class AioCompletion;
file_layout_t layout;
- cache::ImageCache<ImageCtx> *image_cache = nullptr;
-
Readahead readahead;
std::atomic<uint64_t> total_bytes_read = {0};
#include "librbd/ImageCtx.h"
#include "librbd/Utils.h"
#include "librbd/io/AioCompletion.h"
+#include "librbd/io/ImageDispatchSpec.h"
#include "librbd/io/ImageRequest.h"
#include "librbd/io/ReadResult.h"
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_READ);
- io::ImageReadRequest<> req(*image_ctx, aio_comp, std::move(image_extents),
- io::ReadResult{bl},
- image_ctx->get_data_io_context(), fadvise_flags,
- 0, {});
- req.set_bypass_image_cache();
- req.send();
+ ZTracer::Trace trace;
+ auto req = io::ImageDispatchSpec::create_read(
+ *image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp,
+ std::move(image_extents), io::ReadResult{bl},
+ image_ctx->get_data_io_context(),
+ fadvise_flags, 0, trace);
+ req->send();
}
template <typename I>
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_WRITE);
- io::ImageWriteRequest<> req(*image_ctx, aio_comp, std::move(image_extents),
- std::move(bl), image_ctx->get_data_io_context(),
- fadvise_flags, {});
- req.set_bypass_image_cache();
- req.send();
+ ZTracer::Trace trace;
+ auto req = io::ImageDispatchSpec::create_write(
+ *image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp,
+ std::move(image_extents), std::move(bl),
+ image_ctx->get_data_io_context(), fadvise_flags, trace);
+ req->send();
}
template <typename I>
void ImageWriteback<I>::aio_discard(uint64_t offset, uint64_t length,
- uint32_t discard_granularity_bytes,
+ uint32_t discard_granularity_bytes,
Context *on_finish) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << "offset=" << offset << ", "
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_DISCARD);
- io::ImageDiscardRequest<> req(*image_ctx, aio_comp, {{offset, length}},
- discard_granularity_bytes,
- image_ctx->get_data_io_context(), {});
- req.set_bypass_image_cache();
- req.send();
+ ZTracer::Trace trace;
+ auto req = io::ImageDispatchSpec::create_discard(
+ *image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp, offset,
+ length, discard_granularity_bytes,
+ image_ctx->get_data_io_context(), trace);
+ req->send();
}
template <typename I>
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_FLUSH);
- io::ImageFlushRequest<> req(*image_ctx, aio_comp, flush_source,
- {});
- req.set_bypass_image_cache();
- req.send();
+
+ ZTracer::Trace trace;
+ auto req = io::ImageDispatchSpec::create_flush(
+ *image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp,
+ flush_source, trace);
+ req->send();
}
template <typename I>
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_WRITESAME);
- io::ImageWriteSameRequest<> req(*image_ctx, aio_comp, {{offset, length}},
- std::move(bl),
- image_ctx->get_data_io_context(),
- fadvise_flags, {});
- req.set_bypass_image_cache();
- req.send();
+ ZTracer::Trace trace;
+ auto req = io::ImageDispatchSpec::create_write_same(
+ *image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp, offset,
+ length, std::move(bl), image_ctx->get_data_io_context(),
+ fadvise_flags, trace);
+ req->send();
}
template <typename I>
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_COMPARE_AND_WRITE);
- io::ImageCompareAndWriteRequest<> req(*image_ctx, aio_comp,
- std::move(image_extents),
- std::move(cmp_bl), std::move(bl),
- mismatch_offset,
- image_ctx->get_data_io_context(),
- fadvise_flags, {});
- req.set_bypass_image_cache();
- req.send();
+ ZTracer::Trace trace;
+ auto req = io::ImageDispatchSpec::create_compare_and_write(
+ *image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp,
+ std::move(image_extents), std::move(cmp_bl), std::move(bl),
+ mismatch_offset, image_ctx->get_data_io_context(),
+ fadvise_flags, trace);
+ req->send();
}
} // namespace cache
using namespace librbd::cache::pwl;
-typedef WriteLogCache<ImageCtx>::Extent Extent;
-typedef WriteLogCache<ImageCtx>::Extents Extents;
-
template <typename I>
WriteLogCache<I>::WriteLogCache(I &image_ctx, librbd::cache::pwl::ImageCacheState<I>* cache_state) {
m_write_log = new librbd::cache::pwl::ReplicatedWriteLog<I>(image_ctx, cache_state);
} // namespace librbd
template class librbd::cache::WriteLogCache<librbd::ImageCtx>;
-template class librbd::cache::ImageCache<librbd::ImageCtx>;
#define CEPH_LIBRBD_CACHE_WRITE_LOG_CACHE
#include "librbd/cache/ImageCache.h"
+#include "librbd/io/Types.h"
namespace librbd {
}
template <typename ImageCtxT>
-class WriteLogCache : public ImageCache<ImageCtxT> {
+class WriteLogCache {
public:
- using typename ImageCache<ImageCtxT>::Extent;
- using typename ImageCache<ImageCtxT>::Extents;
+ typedef io::Extent Extent;
+ typedef io::Extents Extents;
WriteLogCache(ImageCtxT &image_ctx, librbd::cache::pwl::ImageCacheState<ImageCtxT>* cache_state);
~WriteLogCache();
/// client AIO methods
void aio_read(Extents&& image_extents, ceph::bufferlist *bl,
- int fadvise_flags, Context *on_finish) override;
+ int fadvise_flags, Context *on_finish) ;
void aio_write(Extents&& image_extents, ceph::bufferlist&& bl,
- int fadvise_flags, Context *on_finish) override;
+ int fadvise_flags, Context *on_finish) ;
void aio_discard(uint64_t offset, uint64_t length,
uint32_t discard_granularity_bytes,
- Context *on_finish) override;
- void aio_flush(io::FlushSource flush_source, Context *on_finish) override;
+ Context *on_finish) ;
+ void aio_flush(io::FlushSource flush_source, Context *on_finish) ;
void aio_writesame(uint64_t offset, uint64_t length,
ceph::bufferlist&& bl,
- int fadvise_flags, Context *on_finish) override;
+ int fadvise_flags, Context *on_finish) ;
void aio_compare_and_write(Extents&& image_extents,
ceph::bufferlist&& cmp_bl, ceph::bufferlist&& bl,
uint64_t *mismatch_offset,int fadvise_flags,
- Context *on_finish) override;
+ Context *on_finish) ;
/// internal state methods
- void init(Context *on_finish) override;
- void shut_down(Context *on_finish) override;
- void invalidate(Context *on_finish) override;
- void flush(Context *on_finish) override;
+ void init(Context *on_finish) ;
+ void shut_down(Context *on_finish) ;
+ void invalidate(Context *on_finish) ;
+ void flush(Context *on_finish) ;
librbd::cache::pwl::AbstractWriteLog<ImageCtxT> *m_write_log;
};
});
ctx = new LambdaContext(
[this, ctx](int r) {
+ ldout(m_image_ctx.cct, 6) << "image cache cleaned" << dendl;
Context *next_ctx = override_ctx(r, ctx);
bool periodic_stats_enabled = m_periodic_stats_enabled;
m_periodic_stats_enabled = false;
ctx = new LambdaContext(
[this, ctx, invalidate](int r) {
Context *next_ctx = ctx;
+ ldout(m_image_ctx.cct, 6) << "flush_dirty_entries finished" << dendl;
if (r < 0) {
/* Override on_finish status with this error */
next_ctx = new LambdaContext([r, ctx](int _r) {
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "common/dout.h"
+#include "librbd/cache/pwl/ImageDispatch.h"
+#include "librbd/cache/pwl/ShutdownRequest.h"
+#include "librbd/cache/WriteLogCache.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/io/AioCompletion.h"
+#include "librbd/io/Utils.h"
+
+#define dout_subsys ceph_subsys_rbd_pwl
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::cache::pwl::ImageDispatch: " << this << " " \
+ << __func__ << ": "
+
+namespace librbd {
+namespace cache {
+namespace pwl{
+
+namespace {
+
+void start_in_flight_io(io::AioCompletion* aio_comp) {
+ if (!aio_comp->async_op.started()) {
+ aio_comp->start_op();
+ }
+}
+
+} // anonymous namespace
+
+template <typename I>
+void ImageDispatch<I>::shut_down(Context* on_finish) {
+ ceph_assert(m_image_cache != nullptr);
+
+ Context* ctx = new LambdaContext(
+ [this, on_finish](int r) {
+ m_image_cache = nullptr;
+ on_finish->complete(r);
+ });
+
+ cache::pwl::ShutdownRequest<I> *req = cache::pwl::ShutdownRequest<I>::create(
+ *m_image_ctx, m_image_cache, ctx);
+ req->send();
+}
+
+template <typename I>
+bool ImageDispatch<I>::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) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << "image_extents=" << image_extents << dendl;
+
+ *dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+ if (preprocess_length(aio_comp, image_extents)) {
+ return true;
+ }
+
+ start_in_flight_io(aio_comp);
+
+ aio_comp->set_request_count(1);
+ aio_comp->read_result = std::move(read_result);
+ uint64_t length = io::util::extents_length(image_extents);
+ aio_comp->read_result.set_clip_length(length);
+
+ auto *req_comp = new io::ReadResult::C_ImageReadRequest(
+ aio_comp, image_extents);
+
+ m_image_cache->aio_read(std::move(image_extents),
+ &req_comp->bl, op_flags,
+ req_comp);
+ return true;
+}
+
+template <typename I>
+bool ImageDispatch<I>::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) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << "image_extents=" << image_extents << dendl;
+
+ *dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+ if (preprocess_length(aio_comp, image_extents)) {
+ return true;
+ }
+
+ start_in_flight_io(aio_comp);
+
+ aio_comp->set_request_count(1);
+ io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
+ m_image_cache->aio_write(std::move(image_extents),
+ std::move(bl), op_flags, req_comp);
+ return true;
+}
+
+template <typename I>
+bool ImageDispatch<I>::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) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << "image_extents=" << image_extents << dendl;
+
+ *dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+ if (preprocess_length(aio_comp, image_extents)) {
+ return true;
+ }
+
+ start_in_flight_io(aio_comp);
+
+ aio_comp->set_request_count(image_extents.size());
+ for (auto &extent : image_extents) {
+ io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
+ m_image_cache->aio_discard(extent.first, extent.second,
+ discard_granularity_bytes,
+ req_comp);
+ }
+ return true;
+}
+
+template <typename I>
+bool ImageDispatch<I>::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) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << "image_extents=" << image_extents << dendl;
+
+ *dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+ if (preprocess_length(aio_comp, image_extents)) {
+ return true;
+ }
+
+ start_in_flight_io(aio_comp);
+
+ aio_comp->set_request_count(image_extents.size());
+ for (auto &extent : image_extents) {
+ io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
+ m_image_cache->aio_writesame(extent.first, extent.second,
+ std::move(bl), op_flags,
+ req_comp);
+ }
+ return true;
+}
+
+template <typename I>
+bool ImageDispatch<I>::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) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << "image_extents=" << image_extents << dendl;
+
+ *dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+ if (preprocess_length(aio_comp, image_extents)) {
+ return true;
+ }
+
+ start_in_flight_io(aio_comp);
+
+ aio_comp->set_request_count(1);
+ io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
+ m_image_cache->aio_compare_and_write(
+ std::move(image_extents), std::move(cmp_bl), std::move(bl),
+ mismatch_offset, op_flags, req_comp);
+ return true;
+}
+
+template <typename I>
+bool ImageDispatch<I>::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) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << "tid=" << tid << dendl;
+
+ start_in_flight_io(aio_comp);
+
+ *dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+
+ aio_comp->set_request_count(1);
+ io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
+ m_image_cache->aio_flush(flush_source, req_comp);
+
+ return true;
+}
+
+template <typename I>
+bool ImageDispatch<I>::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) {
+ ceph_abort();
+}
+
+
+template <typename I>
+bool ImageDispatch<I>::preprocess_length(
+ io::AioCompletion* aio_comp, io::Extents &image_extents) const {
+ auto total_bytes = io::util::extents_length(image_extents);
+ if (total_bytes == 0) {
+ aio_comp->set_request_count(0);
+ return true;
+ }
+ return false;
+}
+
+} // namespace pwl
+} // namespace io
+} // namespace librbd
+
+template class librbd::cache::pwl::ImageDispatch<librbd::ImageCtx>;
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_PWL_IMAGE_DISPATCH_H
+#define CEPH_LIBRBD_PWL_IMAGE_DISPATCH_H
+
+#include "librbd/io/ImageDispatchInterface.h"
+#include "include/int_types.h"
+#include "include/buffer.h"
+#include "common/zipkin_trace.h"
+#include "librbd/io/ReadResult.h"
+#include "librbd/io/Types.h"
+
+struct Context;
+
+namespace librbd {
+
+struct ImageCtx;
+
+namespace cache {
+
+template<typename>
+class WriteLogCache;
+
+namespace pwl {
+
+template <typename ImageCtxT>
+class ImageDispatch : public io::ImageDispatchInterface {
+public:
+ ImageDispatch(ImageCtxT* image_ctx,
+ WriteLogCache<ImageCtx> *image_cache) :
+ m_image_ctx(image_ctx), m_image_cache(image_cache) {
+ }
+
+ io::ImageDispatchLayer get_dispatch_layer() const override {
+ return io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE;
+ }
+
+ void shut_down(Context* on_finish) override;
+
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+
+private:
+ ImageCtxT* m_image_ctx;
+ cache::WriteLogCache<ImageCtx> *m_image_cache;
+
+ bool preprocess_length(
+ io::AioCompletion* aio_comp, io::Extents &image_extents) const;
+};
+
+} // namespace pwl
+} // namespace cache
+} // namespace librbd
+
+extern template class librbd::cache::pwl::ImageDispatch<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_PWL_IMAGE_DISPATCH_H
// vim: ts=8 sw=2 smarttab
#include "librbd/cache/pwl/InitRequest.h"
+#include "librbd/io/ImageDispatcher.h"
#include "librbd/Utils.h"
#include "common/dout.h"
#include "common/errno.h"
#if defined(WITH_RBD_RWL)
#include "librbd/cache/pwl/ImageCacheState.h"
+#include "librbd/cache/pwl/ImageDispatch.h"
#include "librbd/cache/WriteLogCache.h"
#endif // WITH_RBD_RWL
auto cache_type = cache_state->get_image_cache_type();
switch(cache_type) {
case cache::IMAGE_CACHE_TYPE_RWL:
- m_image_ctx.image_cache =
+ m_image_cache =
new librbd::cache::WriteLogCache<I>(m_image_ctx,
cache_state);
break;
using klass = InitRequest<I>;
Context *ctx = create_context_callback<klass, &klass::handle_init_image_cache>(
this);
- m_image_ctx.image_cache->init(ctx);
+ m_image_cache->init(ctx);
}
template <typename I>
if (r < 0) {
lderr(cct) << "failed to init image cache: " << cpp_strerror(r)
<< dendl;
- delete m_image_ctx.image_cache;
- m_image_ctx.image_cache = nullptr;
+ delete m_image_cache;
+ m_image_cache = nullptr;
save_result(r);
finish();
return;
lderr(cct) << "failed to set feature bit: " << cpp_strerror(r)
<< dendl;
save_result(r);
- } else if (m_image_ctx.discard_granularity_bytes) {
+
+ shutdown_image_cache();
+ }
+
+ if (m_image_ctx.discard_granularity_bytes) {
ldout(cct, 1) << "RWL image cache is enabled and "
<< "set discard_granularity_bytes = 0." << dendl;
m_image_ctx.discard_granularity_bytes = 0;
}
+
+ // Register RWL dispatch
+ auto image_dispatch = new cache::pwl::ImageDispatch<I>(&m_image_ctx, m_image_cache);
+
+ m_image_ctx.io_image_dispatcher->register_dispatch(image_dispatch);
+
+ finish();
+}
+
+template <typename I>
+void InitRequest<I>::shutdown_image_cache() {
+ CephContext *cct = m_image_ctx.cct;
+ ldout(cct, 10) << dendl;
+
+ using klass = InitRequest<I>;
+ Context *ctx = create_context_callback<klass, &klass::handle_shutdown_image_cache>(
+ this);
+ m_image_cache->shut_down(ctx);
+}
+
+template <typename I>
+void InitRequest<I>::handle_shutdown_image_cache(int r) {
+ CephContext *cct = m_image_ctx.cct;
+ ldout(cct, 10) << dendl;
+
+ if (r < 0) {
+ lderr(cct) << "failed to close image cache: " << cpp_strerror(r)
+ << dendl;
+ }
+ delete m_image_cache;
+ m_image_cache = nullptr;
+
finish();
}
class ImageCtx;
+namespace io { class ImageDispatchInterface; }
+
namespace cache {
+
+template<typename>
+class WriteLogCache;
+
namespace pwl {
template<typename>
* INIT_IMAGE_CACHE
* |
* v
- * SET_FEATURE_BIT
- * |
- * v
- * <finish>
+ * SET_FEATURE_BIT * * * > CLOSE_IMAGE_CACHE
+ * | |
+ * v |
+ * <finish> <-------------------/
*
* @endverbatim
*/
InitRequest(ImageCtxT &image_ctx, Context *on_finish);
ImageCtxT &m_image_ctx;
+ cache::WriteLogCache<ImageCtx> *m_image_cache;
Context *m_on_finish;
int m_error_result;
void set_feature_bit();
void handle_set_feature_bit(int r);
+ void shutdown_image_cache();
+ void handle_shutdown_image_cache(int r);
+
void finish();
void save_result(int result) {
// vim: ts=8 sw=2 smarttab
#include "librbd/cache/pwl/ShutdownRequest.h"
+#include "librbd/cache/WriteLogCache.h"
#include "librbd/ImageCtx.h"
#include "librbd/Utils.h"
#include "common/dout.h"
#include "common/errno.h"
#include "librbd/Operations.h"
#include "librbd/asio/ContextWQ.h"
-#include "librbd/cache/ImageCache.h"
#include "librbd/cache/Types.h"
using librbd::util::create_context_callback;
template <typename I>
-ShutdownRequest<I>* ShutdownRequest<I>::create(I &image_ctx,
- Context *on_finish) {
- return new ShutdownRequest(image_ctx, on_finish);
+ShutdownRequest<I>* ShutdownRequest<I>::create(
+ I &image_ctx,
+ cache::WriteLogCache<ImageCtx> *image_cache,
+ Context *on_finish) {
+ return new ShutdownRequest(image_ctx, image_cache, on_finish);
}
template <typename I>
-ShutdownRequest<I>::ShutdownRequest(I &image_ctx, Context *on_finish)
+ShutdownRequest<I>::ShutdownRequest(
+ I &image_ctx,
+ cache::WriteLogCache<ImageCtx> *image_cache,
+ Context *on_finish)
: m_image_ctx(image_ctx),
+ m_image_cache(image_cache),
m_on_finish(create_async_context_callback(image_ctx, on_finish)),
m_error_result(0) {
}
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << dendl;
- if (m_image_ctx.image_cache == nullptr) {
+ if (m_image_cache == nullptr) {
finish();
return;
}
Context *ctx = create_context_callback<klass, &klass::handle_shutdown_image_cache>(
this);
- m_image_ctx.image_cache->shut_down(ctx);
+ m_image_cache->shut_down(ctx);
}
template <typename I>
finish();
return;
} else {
- delete m_image_ctx.image_cache;
- m_image_ctx.image_cache = nullptr;
+ delete m_image_cache;
+ m_image_cache = nullptr;
}
send_remove_feature_bit();
}
class ImageCtx;
namespace cache {
+
+template<typename>
+class WriteLogCache;
+
namespace pwl {
template<typename>
template <typename ImageCtxT = ImageCtx>
class ShutdownRequest {
public:
- static ShutdownRequest* create(ImageCtxT &image_ctx, Context *on_finish);
+ static ShutdownRequest* create(
+ ImageCtxT &image_ctx,
+ cache::WriteLogCache<ImageCtx> *image_cache,
+ Context *on_finish);
void send();
* @endverbatim
*/
- ShutdownRequest(ImageCtxT &image_ctx, Context *on_finish);
+ ShutdownRequest(ImageCtxT &image_ctx,
+ cache::WriteLogCache<ImageCtx> *image_cache,
+ Context *on_finish);
ImageCtxT &m_image_ctx;
+ cache::WriteLogCache<ImageCtx> *m_image_cache;
Context *m_on_finish;
int m_error_result;
#include "common/errno.h"
#include "include/stringify.h"
#include "librbd/cache/pwl/InitRequest.h"
-#include "librbd/cache/pwl/ShutdownRequest.h"
#include "librbd/ExclusiveLock.h"
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
if (r < 0) {
lderr(cct) << "failed to open image cache: " << cpp_strerror(r)
<< dendl;
- send_close_image_cache();
+ send_close_journal();
return;
}
finish();
}
-template <typename I>
-void PostAcquireRequest<I>::send_close_image_cache() {
- if (m_image_ctx.image_cache == nullptr) {
- send_close_journal();
- }
-
- using klass = PostAcquireRequest<I>;
- Context *ctx = create_context_callback<klass, &klass::handle_close_image_cache>(
- this);
- cache::pwl::ShutdownRequest<I> *req = cache::pwl::ShutdownRequest<I>::create(
- m_image_ctx, ctx);
- req->send();
-}
-
-template <typename I>
-void PostAcquireRequest<I>::handle_close_image_cache(int r) {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 10) << "r=" << r << dendl;
-
- save_result(r);
- if (r < 0) {
- lderr(cct) << "failed to close image_cache: " << cpp_strerror(r) << dendl;
- }
-
- send_close_journal();
-}
-
template <typename I>
void PostAcquireRequest<I>::send_close_journal() {
if (m_journal == nullptr) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << dendl;
- /* Shut down existing image cache whether the feature bit is on or not */
- if (!m_image_ctx.image_cache) {
- send_invalidate_cache();
- return;
- }
std::shared_lock owner_lock{m_image_ctx.owner_lock};
Context *ctx = create_async_context_callback(m_image_ctx, create_context_callback<
PreReleaseRequest<I>,
&PreReleaseRequest<I>::handle_shut_down_image_cache>(this));
- cache::pwl::ShutdownRequest<I> *req = cache::pwl::ShutdownRequest<I>::create(
- m_image_ctx, ctx);
- req->send();
+ m_image_ctx.io_image_dispatcher->shut_down_dispatch(
+ io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, ctx);
}
template <typename I>
{
std::unique_lock locker{m_lock};
auto it = m_dispatches.find(dispatch_layer);
- ceph_assert(it != m_dispatches.end());
+ if (it == m_dispatches.end()) {
+ on_finish->complete(0);
+ return;
+ }
dispatch_meta = it->second;
m_dispatches.erase(it);
#include "librbd/Types.h"
#include "librbd/Utils.h"
#include "librbd/asio/ContextWQ.h"
-#include "librbd/cache/ImageCache.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/AsyncOperation.h"
#include "librbd/io/ObjectDispatchInterface.h"
ldout(cct, 20) << get_request_type() << ": ictx=" << &image_ctx << ", "
<< "completion=" << aio_comp << dendl;
- if (m_bypass_image_cache || m_image_ctx.image_cache == nullptr) {
- update_timestamp();
- send_request();
- } else {
- send_image_cache_request();
- }
+ update_timestamp();
+ send_request();
}
template <typename I>
image_ctx.perfcounter->inc(l_librbd_rd_bytes, buffer_ofs);
}
-template <typename I>
-void ImageReadRequest<I>::send_image_cache_request() {
- I &image_ctx = this->m_image_ctx;
- ceph_assert(image_ctx.image_cache != nullptr);
-
- AioCompletion *aio_comp = this->m_aio_comp;
- aio_comp->set_request_count(1);
-
- auto *req_comp = new io::ReadResult::C_ImageReadRequest(
- aio_comp, this->m_image_extents);
- image_ctx.image_cache->aio_read(std::move(this->m_image_extents),
- &req_comp->bl, m_op_flags,
- req_comp);
-}
-
template <typename I>
void AbstractImageWriteRequest<I>::send_request() {
I &image_ctx = this->m_image_ctx;
return tid;
}
-template <typename I>
-void ImageWriteRequest<I>::send_image_cache_request() {
- I &image_ctx = this->m_image_ctx;
- ceph_assert(image_ctx.image_cache != nullptr);
-
- AioCompletion *aio_comp = this->m_aio_comp;
- aio_comp->set_request_count(1);
- C_AioRequest *req_comp = new C_AioRequest(aio_comp);
- image_ctx.image_cache->aio_write(std::move(this->m_image_extents),
- std::move(m_bl), m_op_flags, req_comp);
-}
-
template <typename I>
ObjectDispatchSpec *ImageWriteRequest<I>::create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
return tid;
}
-template <typename I>
-void ImageDiscardRequest<I>::send_image_cache_request() {
- I &image_ctx = this->m_image_ctx;
- ceph_assert(image_ctx.image_cache != nullptr);
-
- AioCompletion *aio_comp = this->m_aio_comp;
- aio_comp->set_request_count(this->m_image_extents.size());
- for (auto &extent : this->m_image_extents) {
- C_AioRequest *req_comp = new C_AioRequest(aio_comp);
- image_ctx.image_cache->aio_discard(extent.first, extent.second,
- this->m_discard_granularity_bytes,
- req_comp);
- }
-}
-
template <typename I>
ObjectDispatchSpec *ImageDiscardRequest<I>::create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
}
}
-template <typename I>
-void ImageFlushRequest<I>::send_image_cache_request() {
- I &image_ctx = this->m_image_ctx;
- ceph_assert(image_ctx.image_cache != nullptr);
-
- AioCompletion *aio_comp = this->m_aio_comp;
- aio_comp->set_request_count(1);
- C_AioRequest *req_comp = new C_AioRequest(aio_comp);
- image_ctx.image_cache->aio_flush(m_flush_source, req_comp);
-}
-
template <typename I>
uint64_t ImageWriteSameRequest<I>::append_journal_event(bool synchronous) {
I &image_ctx = this->m_image_ctx;
return tid;
}
-template <typename I>
-void ImageWriteSameRequest<I>::send_image_cache_request() {
- I &image_ctx = this->m_image_ctx;
- ceph_assert(image_ctx.image_cache != nullptr);
-
- AioCompletion *aio_comp = this->m_aio_comp;
- aio_comp->set_request_count(this->m_image_extents.size());
- for (auto &extent : this->m_image_extents) {
- C_AioRequest *req_comp = new C_AioRequest(aio_comp);
- image_ctx.image_cache->aio_writesame(extent.first, extent.second,
- std::move(m_data_bl), m_op_flags,
- req_comp);
- }
-}
-
template <typename I>
ObjectDispatchSpec *ImageWriteSameRequest<I>::create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
}
}
-template <typename I>
-void ImageCompareAndWriteRequest<I>::send_image_cache_request() {
- I &image_ctx = this->m_image_ctx;
- ceph_assert(image_ctx.image_cache != nullptr);
-
- AioCompletion *aio_comp = this->m_aio_comp;
- aio_comp->set_request_count(1);
- C_AioRequest *req_comp = new C_AioRequest(aio_comp);
- image_ctx.image_cache->aio_compare_and_write(
- std::move(this->m_image_extents), std::move(m_cmp_bl), std::move(m_bl),
- m_mismatch_offset, m_op_flags, req_comp);
-}
-
template <typename I>
ObjectDispatchSpec *ImageCompareAndWriteRequest<I>::create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
void send();
- void set_bypass_image_cache() {
- m_bypass_image_cache = true;
- }
-
inline const ZTracer::Trace &get_trace() const {
return m_trace;
}
Extents m_image_extents;
IOContext m_io_context;
ZTracer::Trace m_trace;
- bool m_bypass_image_cache = false;
ImageRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp,
Extents &&image_extents, IOContext io_context,
virtual void update_timestamp();
virtual void send_request() = 0;
- virtual void send_image_cache_request() = 0;
virtual aio_type_t get_aio_type() const = 0;
virtual const char *get_request_type() const = 0;
protected:
void send_request() override;
- void send_image_cache_request() override;
aio_type_t get_aio_type() const override {
return AIO_TYPE_READ;
void assemble_extent(const LightweightObjectExtent &object_extent,
bufferlist *bl);
- void send_image_cache_request() override;
-
-
ObjectDispatchSpec *create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
uint64_t journal_tid, bool single_extent, Context *on_finish) override;
return "aio_discard";
}
- void send_image_cache_request() override;
-
ObjectDispatchSpec *create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
uint64_t journal_tid, bool single_extent, Context *on_finish) override;
void update_timestamp() override {
}
void send_request() override;
- void send_image_cache_request() override;
aio_type_t get_aio_type() const override {
return AIO_TYPE_FLUSH;
return "aio_writesame";
}
- void send_image_cache_request() override;
-
ObjectDispatchSpec *create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
uint64_t journal_tid, bool single_extent, Context *on_finish) override;
}
protected:
- void send_image_cache_request() override;
-
void assemble_extent(const LightweightObjectExtent &object_extent,
bufferlist *bl);
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librados_test_stub/MockTestMemRadosClient.h"
#include "librbd/cache/pwl/InitRequest.h"
-#include "librbd/cache/pwl/ShutdownRequest.h"
#include "librbd/exclusive_lock/PostAcquireRequest.h"
#include "librbd/image/RefreshRequest.h"
InitRequest<librbd::MockTestImageCtx> *InitRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-template<>
-struct ShutdownRequest<librbd::MockTestImageCtx> {
- static ShutdownRequest *s_instance;
- Context *on_finish = nullptr;
-
- static ShutdownRequest *create(librbd::MockTestImageCtx &image_ctx,
- Context *on_finish) {
- ceph_assert(s_instance != nullptr);
- s_instance->on_finish = on_finish;
- return s_instance;
- }
-
- ShutdownRequest() {
- s_instance = this;
- }
- MOCK_METHOD0(send, void());
-};
-
-ShutdownRequest<librbd::MockTestImageCtx> *ShutdownRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-
} // namespace pwl
} // namespace cache
} // namespace librbd
typedef PostAcquireRequest<MockTestImageCtx> MockPostAcquireRequest;
typedef librbd::image::RefreshRequest<MockTestImageCtx> MockRefreshRequest;
typedef librbd::cache::pwl::InitRequest<MockTestImageCtx> MockInitRequest;
- typedef librbd::cache::pwl::ShutdownRequest<MockTestImageCtx> MockShutdownRequest;
void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features,
bool enabled) {
.WillOnce(FinishRequest(&mock_init_request, r, &mock_image_ctx));
}
- void expect_close_image_cache(MockTestImageCtx &mock_image_ctx,
- MockShutdownRequest &mock_shutdown_request, int r) {
- EXPECT_CALL(mock_shutdown_request, send())
- .WillOnce(FinishRequest(&mock_shutdown_request, r, &mock_image_ctx));
- }
-
};
TEST_F(TestMockExclusiveLockPostAcquireRequest, Success) {
MockInitRequest mock_init_request;
expect_init_image_cache(mock_image_ctx, mock_init_request, -ENOENT);
- cache::MockImageCache mock_image_cache;
- mock_image_ctx.image_cache = &mock_image_cache;
- MockShutdownRequest mock_shutdown_request;
- expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
-
expect_close_journal(mock_image_ctx, mock_journal);
expect_close_object_map(mock_image_ctx, mock_object_map);
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
-#include "librbd/cache/pwl/ShutdownRequest.h"
#include "test/librbd/test_mock_fixture.h"
#include "test/librbd/test_support.h"
#include "test/librbd/mock/cache/MockImageCache.h"
} // namespace exclusive_lock
-namespace cache {
-namespace pwl {
-template<>
-struct ShutdownRequest<librbd::MockTestImageCtx> {
- static ShutdownRequest *s_instance;
- Context *on_finish = nullptr;
-
- static ShutdownRequest *create(librbd::MockTestImageCtx &image_ctx,
- Context *on_finish) {
- ceph_assert(s_instance != nullptr);
- s_instance->on_finish = on_finish;
- return s_instance;
- }
-
- ShutdownRequest() {
- s_instance = this;
- }
- MOCK_METHOD0(send, void());
-};
-
-ShutdownRequest<librbd::MockTestImageCtx> *ShutdownRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-
-} // namespace pwl
-} // namespace cache
-
namespace util {
inline ImageCtx* get_image_ctx(MockTestImageCtx* image_ctx) {
public:
typedef ImageDispatch<MockTestImageCtx> MockImageDispatch;
typedef PreReleaseRequest<MockTestImageCtx> MockPreReleaseRequest;
- typedef librbd::cache::pwl::ShutdownRequest<MockTestImageCtx> MockShutdownRequest;
void expect_complete_context(MockContext &mock_context, int r) {
EXPECT_CALL(mock_context, complete(r));
.WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
}
- void expect_close_image_cache(MockTestImageCtx &mock_image_ctx,
- MockShutdownRequest &mock_shutdown_req, int r) {
- EXPECT_CALL(mock_shutdown_req, send())
- .WillOnce(FinishRequest(&mock_shutdown_req, r, &mock_image_ctx));
+ void expect_close_image_cache(MockTestImageCtx &mock_image_ctx, int r) {
+ EXPECT_CALL(*mock_image_ctx.io_image_dispatcher,
+ shut_down_dispatch(io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, _))
+ .WillOnce(WithArg<1>(
+ CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue)));
}
void expect_invalidate_cache(MockTestImageCtx &mock_image_ctx,
expect_prepare_lock(mock_image_ctx);
- cache::MockImageCache mock_image_cache;
- mock_image_ctx.image_cache = &mock_image_cache;
- MockShutdownRequest mock_shutdown_request;
- expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
+ expect_close_image_cache(mock_image_ctx, 0);
expect_invalidate_cache(mock_image_ctx, 0);
expect_cancel_op_requests(mock_image_ctx, 0);
expect_prepare_lock(mock_image_ctx);
- cache::MockImageCache mock_image_cache;
- mock_image_ctx.image_cache = &mock_image_cache;
- MockShutdownRequest mock_shutdown_request;
- expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
+ expect_close_image_cache(mock_image_ctx, 0);
expect_invalidate_cache(mock_image_ctx, 0);
InSequence seq;
expect_cancel_op_requests(mock_image_ctx, 0);
- cache::MockImageCache mock_image_cache;
- mock_image_ctx.image_cache = &mock_image_cache;
- MockShutdownRequest mock_shutdown_request;
- expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
+ expect_close_image_cache(mock_image_ctx, 0);
expect_invalidate_cache(mock_image_ctx, 0);
-EBLOCKLISTED);
expect_prepare_lock(mock_image_ctx);
- cache::MockImageCache mock_image_cache;
- mock_image_ctx.image_cache = &mock_image_cache;
- MockShutdownRequest mock_shutdown_request;
- expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
+ expect_close_image_cache(mock_image_ctx, 0);
expect_invalidate_cache(mock_image_ctx, -EBLOCKLISTED);
namespace librbd {
-namespace cache { class MockImageCache; }
namespace operation {
template <typename> class ResizeRequest;
}
io::MockObjectDispatcher *io_object_dispatcher;
MockContextWQ *op_work_queue;
- cache::MockImageCache *image_cache = nullptr;
-
MockReadahead readahead;
uint64_t readahead_max_bytes;