diff options
Diffstat (limited to 'src/librbd/plugin')
-rw-r--r-- | src/librbd/plugin/Api.cc | 92 | ||||
-rw-r--r-- | src/librbd/plugin/Api.h | 84 | ||||
-rw-r--r-- | src/librbd/plugin/ParentCache.cc | 81 | ||||
-rw-r--r-- | src/librbd/plugin/ParentCache.h | 38 | ||||
-rw-r--r-- | src/librbd/plugin/Types.h | 45 | ||||
-rw-r--r-- | src/librbd/plugin/WriteLogImageCache.cc | 104 | ||||
-rw-r--r-- | src/librbd/plugin/WriteLogImageCache.h | 53 |
7 files changed, 497 insertions, 0 deletions
diff --git a/src/librbd/plugin/Api.cc b/src/librbd/plugin/Api.cc new file mode 100644 index 000000000..67303be3f --- /dev/null +++ b/src/librbd/plugin/Api.cc @@ -0,0 +1,92 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "common/Timer.h" +#include "librbd/plugin/Api.h" +#include "librbd/ImageCtx.h" +#include "librbd/io/AioCompletion.h" +#include "librbd/io/Utils.h" +#include "librbd/Operations.h" +#include "librbd/Utils.h" + +namespace librbd { +namespace plugin { + +template <typename I> +void Api<I>::read_parent( + I *image_ctx, uint64_t object_no, io::ReadExtents* extents, + librados::snap_t snap_id, const ZTracer::Trace &trace, + Context* on_finish) { + io::util::read_parent<I>(image_ctx, object_no, extents, snap_id, trace, + on_finish); +} + +template <typename I> +void Api<I>::execute_image_metadata_set( + I *image_ctx, const std::string &key, + const std::string &value, Context *on_finish) { + ImageCtx* ictx = util::get_image_ctx(image_ctx); + ictx->operations->execute_metadata_set(key, value, on_finish); +} + +template <typename I> +void Api<I>::execute_image_metadata_remove( + I *image_ctx, const std::string &key, Context *on_finish) { + ImageCtx* ictx = util::get_image_ctx(image_ctx); + ictx->operations->execute_metadata_remove(key, on_finish); +} + +template <typename I> +void Api<I>::get_image_timer_instance( + CephContext *cct, SafeTimer **timer, ceph::mutex **timer_lock) { + ImageCtx::get_timer_instance(cct, timer, timer_lock); +} + +template <typename I> +bool Api<I>::test_image_features(I *image_ctx, uint64_t features) { + return image_ctx->test_features(features); +} + +template <typename I> +void Api<I>::update_aio_comp(io::AioCompletion* aio_comp, + uint32_t request_count, + io::ReadResult &read_result, + io::Extents &image_extents) { + aio_comp->set_request_count(request_count); + aio_comp->read_result = std::move(read_result); + aio_comp->read_result.set_image_extents(image_extents); + start_in_flight_io(aio_comp); +} + +template <typename I> +void Api<I>::update_aio_comp( + io::AioCompletion* aio_comp, uint32_t request_count) { + aio_comp->set_request_count(request_count); + start_in_flight_io(aio_comp); +} + +template <typename I> +io::ReadResult::C_ImageReadRequest* Api<I>::create_image_read_request( + io::AioCompletion* aio_comp, uint64_t buffer_offset, + const Extents& image_extents) { + return new io::ReadResult::C_ImageReadRequest( + aio_comp, buffer_offset, image_extents); +} + +template <typename I> +io::C_AioRequest* Api<I>::create_aio_request(io::AioCompletion* aio_comp) { + io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp); + return req_comp; +} + +template <typename I> +void Api<I>::start_in_flight_io(io::AioCompletion* aio_comp) { + if (!aio_comp->async_op.started()) { + aio_comp->start_op(); + } +} + +} // namespace plugin +} // namespace librbd + +template class librbd::plugin::Api<librbd::ImageCtx>; diff --git a/src/librbd/plugin/Api.h b/src/librbd/plugin/Api.h new file mode 100644 index 000000000..04f77e5c3 --- /dev/null +++ b/src/librbd/plugin/Api.h @@ -0,0 +1,84 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_PLUGIN_API_H +#define CEPH_LIBRBD_PLUGIN_API_H + +#include "common/Timer.h" +#include "common/ceph_mutex.h" +#include "include/common_fwd.h" +#include "include/int_types.h" +#include "include/rados/librados.hpp" +#include "librbd/io/Types.h" +#include "librbd/io/ReadResult.h" + +namespace ZTracer { struct Trace; } + +namespace librbd { + +namespace io { +class AioCompletion; +class C_AioRequest; +} + +struct ImageCtx; + +namespace plugin { + +template <typename ImageCtxT> +struct Api { + using Extents = librbd::io::Extents; + + Api() {} + virtual ~Api() {} + + virtual void read_parent( + ImageCtxT *image_ctx, uint64_t object_no, io::ReadExtents* extents, + librados::snap_t snap_id, const ZTracer::Trace &trace, + Context* on_finish); + + virtual void execute_image_metadata_set( + ImageCtxT *image_ctx, + const std::string &key, + const std::string &value, + Context *on_finish); + + virtual void execute_image_metadata_remove( + ImageCtxT *image_ctx, + const std::string &key, + Context *on_finish); + + virtual void get_image_timer_instance( + CephContext *cct, SafeTimer **timer, + ceph::mutex **timer_lock); + + virtual bool test_image_features( + ImageCtxT *image_ctx, + uint64_t features); + + virtual void update_aio_comp( + io::AioCompletion* aio_comp, + uint32_t request_count, + io::ReadResult& read_result, + io::Extents &image_extents); + + virtual void update_aio_comp( + io::AioCompletion* aio_comp, + uint32_t request_count); + + virtual io::ReadResult::C_ImageReadRequest* create_image_read_request( + io::AioCompletion* aio_comp, uint64_t buffer_offset, + const Extents& image_extents); + + virtual io::C_AioRequest* create_aio_request(io::AioCompletion* aio_comp); + +private: + void start_in_flight_io(io::AioCompletion* aio_comp); +}; + +} // namespace plugin +} // namespace librbd + +extern template class librbd::plugin::Api<librbd::ImageCtx>; + +#endif // CEPH_LIBRBD_PLUGIN_API_H diff --git a/src/librbd/plugin/ParentCache.cc b/src/librbd/plugin/ParentCache.cc new file mode 100644 index 000000000..3eba430ab --- /dev/null +++ b/src/librbd/plugin/ParentCache.cc @@ -0,0 +1,81 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/plugin/ParentCache.h" +#include "ceph_ver.h" +#include "common/dout.h" +#include "common/errno.h" +#include "common/PluginRegistry.h" +#include "librbd/ImageCtx.h" +#include "librbd/cache/ParentCacheObjectDispatch.h" + +extern "C" { + +const char *__ceph_plugin_version() { + return CEPH_GIT_NICE_VER; +} + +int __ceph_plugin_init(CephContext *cct, const std::string& type, + const std::string& name) { + auto plugin_registry = cct->get_plugin_registry(); + return plugin_registry->add( + type, name, new librbd::plugin::ParentCache<librbd::ImageCtx>(cct)); +} + +} // extern "C" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::plugin::ParentCache: " \ + << this << " " << __func__ << ": " + +namespace librbd { +namespace plugin { + +template <typename I> +void ParentCache<I>::init(I* image_ctx, Api<I>& api, + cache::ImageWritebackInterface& image_writeback, + PluginHookPoints& hook_points_list, + Context* on_finish) { + bool parent_cache_enabled = image_ctx->config.template get_val<bool>( + "rbd_parent_cache_enabled"); + if (image_ctx->child == nullptr || !parent_cache_enabled || + !image_ctx->data_ctx.is_valid()) { + on_finish->complete(0); + return; + } + + auto cct = image_ctx->cct; + ldout(cct, 5) << dendl; + + auto parent_cache = cache::ParentCacheObjectDispatch<I>::create( + image_ctx, api); + on_finish = new LambdaContext([this, on_finish, parent_cache](int r) { + if (r < 0) { + // the object dispatcher will handle cleanup if successfully initialized + delete parent_cache; + } + + handle_init_parent_cache(r, on_finish); + }); + parent_cache->init(on_finish); +} + +template <typename I> +void ParentCache<I>::handle_init_parent_cache(int r, Context* on_finish) { + ldout(cct, 5) << "r=" << r << dendl; + + if (r < 0) { + lderr(cct) << "Failed to initialize parent cache object dispatch layer: " + << cpp_strerror(r) << dendl; + on_finish->complete(r); + return; + } + + on_finish->complete(0); +} + +} // namespace plugin +} // namespace librbd + +template class librbd::plugin::ParentCache<librbd::ImageCtx>; diff --git a/src/librbd/plugin/ParentCache.h b/src/librbd/plugin/ParentCache.h new file mode 100644 index 000000000..1039efff9 --- /dev/null +++ b/src/librbd/plugin/ParentCache.h @@ -0,0 +1,38 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_PLUGIN_PARENT_CACHE_H +#define CEPH_LIBRBD_PLUGIN_PARENT_CACHE_H + +#include "librbd/plugin/Types.h" +#include "include/Context.h" + +namespace librbd { + +struct ImageCtx; + +namespace plugin { + +template <typename ImageCtxT> +class ParentCache : public Interface<ImageCtxT> { +public: + ParentCache(CephContext* cct) : Interface<ImageCtxT>(cct) { + } + + void init(ImageCtxT* image_ctx, Api<ImageCtxT>& api, + cache::ImageWritebackInterface& image_writeback, + PluginHookPoints& hook_points_list, + Context* on_finish) override; + +private: + void handle_init_parent_cache(int r, Context* on_finish); + using ceph::Plugin::cct; + +}; + +} // namespace plugin +} // namespace librbd + +extern template class librbd::plugin::ParentCache<librbd::ImageCtx>; + +#endif // CEPH_LIBRBD_PLUGIN_PARENT_CACHE_H diff --git a/src/librbd/plugin/Types.h b/src/librbd/plugin/Types.h new file mode 100644 index 000000000..b66d754ac --- /dev/null +++ b/src/librbd/plugin/Types.h @@ -0,0 +1,45 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_PLUGIN_TYPES_H +#define CEPH_LIBRBD_PLUGIN_TYPES_H + +#include "include/common_fwd.h" +#include "include/Context.h" +#include "common/PluginRegistry.h" +#include "librbd/cache/ImageWriteback.h" + +namespace librbd { +namespace plugin { + +template <typename> struct Api; + +struct HookPoints { + virtual ~HookPoints() { + } + virtual void acquired_exclusive_lock(Context* on_finish) = 0; + virtual void prerelease_exclusive_lock(Context* on_finish) = 0; + virtual void discard(Context* on_finish) { + on_finish->complete(0); + } +}; + +typedef std::list<std::unique_ptr<HookPoints>> PluginHookPoints; + +template <typename ImageCtxT> +struct Interface : public ceph::Plugin { + Interface(CephContext* cct) : Plugin(cct) { + } + + virtual ~Interface() { + } + + virtual void init(ImageCtxT* image_ctx, Api<ImageCtxT>& api, + librbd::cache::ImageWritebackInterface& image_writeback, + PluginHookPoints& hook_points_list, Context* on_finish) = 0; +}; + +} // namespace plugin +} // namespace librbd + +#endif // CEPH_LIBRBD_PLUGIN_TYPES_H diff --git a/src/librbd/plugin/WriteLogImageCache.cc b/src/librbd/plugin/WriteLogImageCache.cc new file mode 100644 index 000000000..308bb6a00 --- /dev/null +++ b/src/librbd/plugin/WriteLogImageCache.cc @@ -0,0 +1,104 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "ceph_ver.h" +#include "common/dout.h" +#include "common/errno.h" +#include "common/PluginRegistry.h" +#include "librbd/ImageCtx.h" +#include "librbd/cache/WriteLogImageDispatch.h" +#include "librbd/cache/ImageWriteback.h" +#include "librbd/cache/Utils.h" +#include "librbd/cache/pwl/DiscardRequest.h" +#include "librbd/cache/pwl/InitRequest.h" +#include "librbd/io/ImageDispatcherInterface.h" +#include "librbd/plugin/WriteLogImageCache.h" + +extern "C" { + +const char *__ceph_plugin_version() { + return CEPH_GIT_NICE_VER; +} + +int __ceph_plugin_init(CephContext *cct, const std::string& type, + const std::string& name) { + auto plugin_registry = cct->get_plugin_registry(); + return plugin_registry->add( + type, name, new librbd::plugin::WriteLogImageCache<librbd::ImageCtx>(cct)); +} + +} // extern "C" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::plugin::WriteLogImageCache: " \ + << this << " " << __func__ << ": " + +namespace librbd { +namespace plugin { + +template <typename I> +void WriteLogImageCache<I>::init(I* image_ctx, Api<I>& api, + cache::ImageWritebackInterface& image_writeback, + PluginHookPoints& hook_points_list, + Context* on_finish) { + bool pwl_enabled = librbd::cache::util::is_pwl_enabled(*image_ctx); + if (!pwl_enabled || !image_ctx->data_ctx.is_valid()) { + on_finish->complete(0); + return; + } + + auto cct = image_ctx->cct; + ldout(cct, 5) << dendl; + + auto hook_points = std::make_unique<WriteLogImageCache::HookPoints>( + image_ctx, image_writeback, api); + hook_points_list.emplace_back(std::move(hook_points)); + + on_finish->complete(0); +} + +template <typename I> +WriteLogImageCache<I>::~WriteLogImageCache() { +} + +template <typename I> +WriteLogImageCache<I>::HookPoints::HookPoints( + I* image_ctx, cache::ImageWritebackInterface& image_writeback, + plugin::Api<I>& plugin_api) + : m_image_ctx(image_ctx), m_image_writeback(image_writeback), + m_plugin_api(plugin_api) +{ +} + +template <typename I> +WriteLogImageCache<I>::HookPoints::~HookPoints() { +} + +template <typename I> +void WriteLogImageCache<I>::HookPoints::acquired_exclusive_lock( + Context* on_finish) { + cache::pwl::InitRequest<I> *req = cache::pwl::InitRequest<I>::create( + *m_image_ctx, m_image_writeback, m_plugin_api, on_finish); + req->send(); +} + +template <typename I> +void WriteLogImageCache<I>::HookPoints::prerelease_exclusive_lock( + Context* on_finish) { + m_image_ctx->io_image_dispatcher->shut_down_dispatch( + io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, on_finish); +} + +template <typename I> +void WriteLogImageCache<I>::HookPoints::discard( + Context* on_finish) { + cache::pwl::DiscardRequest<I> *req = cache::pwl::DiscardRequest<I>::create( + *m_image_ctx, m_plugin_api, on_finish); + req->send(); +} + +} // namespace plugin +} // namespace librbd + +template class librbd::plugin::WriteLogImageCache<librbd::ImageCtx>; diff --git a/src/librbd/plugin/WriteLogImageCache.h b/src/librbd/plugin/WriteLogImageCache.h new file mode 100644 index 000000000..2ceb87ec6 --- /dev/null +++ b/src/librbd/plugin/WriteLogImageCache.h @@ -0,0 +1,53 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_PLUGIN_WRITELOG_IMAGE_CACHE_H +#define CEPH_LIBRBD_PLUGIN_WRITELOG_IMAGE_CACHE_H + +#include "librbd/plugin/Types.h" +#include "include/Context.h" + +namespace librbd { + +struct ImageCtx; + +namespace plugin { + +template <typename ImageCtxT> +class WriteLogImageCache : public Interface<ImageCtxT> { +public: + WriteLogImageCache(CephContext* cct) : Interface<ImageCtxT>(cct) { + } + + ~WriteLogImageCache() override; + + void init(ImageCtxT* image_ctx, Api<ImageCtxT>& api, + cache::ImageWritebackInterface& image_writeback, + PluginHookPoints& hook_points_list, + Context* on_finish) override; + + class HookPoints : public plugin::HookPoints { + public: + HookPoints(ImageCtxT* image_ctx, + cache::ImageWritebackInterface& image_writeback, + plugin::Api<ImageCtxT>& plugin_api); + ~HookPoints() override; + + void acquired_exclusive_lock(Context* on_finish) override; + void prerelease_exclusive_lock(Context* on_finish) override; + void discard(Context* on_finish) override; + + private: + ImageCtxT* m_image_ctx; + cache::ImageWritebackInterface& m_image_writeback; + plugin::Api<ImageCtxT>& m_plugin_api; + }; + +}; + +} // namespace plugin +} // namespace librbd + +extern template class librbd::plugin::WriteLogImageCache<librbd::ImageCtx>; + +#endif // CEPH_LIBRBD_PLUGIN_WRITELOG_IMAGE_CACHE_H |