summaryrefslogtreecommitdiffstats
path: root/src/librbd/plugin
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/librbd/plugin/Api.cc92
-rw-r--r--src/librbd/plugin/Api.h84
-rw-r--r--src/librbd/plugin/ParentCache.cc81
-rw-r--r--src/librbd/plugin/ParentCache.h38
-rw-r--r--src/librbd/plugin/Types.h45
-rw-r--r--src/librbd/plugin/WriteLogImageCache.cc104
-rw-r--r--src/librbd/plugin/WriteLogImageCache.h53
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