]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: initial plugin registry implementation
authorJason Dillaman <dillaman@redhat.com>
Wed, 20 May 2020 18:36:49 +0000 (14:36 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 20 May 2020 23:32:10 +0000 (19:32 -0400)
The plugin registry will attempt to dynamically load the specified
librbd plugins at image open time.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/common/options.cc
src/librbd/CMakeLists.txt
src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/PluginRegistry.cc [new file with mode: 0644]
src/librbd/PluginRegistry.h [new file with mode: 0644]
src/librbd/image/OpenRequest.cc
src/librbd/image/OpenRequest.h
src/librbd/plugin/Types.h [new file with mode: 0644]

index c39095bfde890961fac9641923650c4ff85bdc6c..99aad045c946dbbfbea8725678540b1b219d56c2 100644 (file)
@@ -7513,6 +7513,11 @@ static std::vector<Option> get_rbd_options() {
     .set_default(10)
     .set_min(1)
     .set_description("the number of quiesce notification attempts"),
+
+    Option("rbd_plugins", Option::TYPE_STR, Option::LEVEL_ADVANCED)
+    .set_default("")
+    .set_description("comma-delimited list of librbd plugins to enable"),
+
   });
 }
 
index 5deb68071bc9a797ceb191cd221c4d147eaba0c1..57823cdbf678c49f1c08a815f74f381c13fdc05d 100644 (file)
@@ -20,6 +20,7 @@ set(librbd_internal_srcs
   MirroringWatcher.cc
   ObjectMap.cc
   Operations.cc
+  PluginRegistry.cc
   TrashWatcher.cc
   Utils.cc
   Watcher.cc
@@ -166,6 +167,9 @@ set(librbd_internal_srcs
   watcher/RewatchRequest.cc
   ${CMAKE_SOURCE_DIR}/src/common/ContextCompletion.cc)
 
+add_custom_target(librbd_plugins)
+set(librbd_plugins_dir ${CEPH_INSTALL_PKGLIBDIR}/librbd)
+
 if(WITH_EVENTTRACE)
   list(APPEND librbd_internal_srcs ../common/EventTrace.cc)
 endif()
@@ -211,6 +215,7 @@ add_library(librbd ${CEPH_SHARED}
 if(WITH_LTTNG)
   add_dependencies(librbd librbd-tp)
 endif()
+add_dependencies(librbd librbd_plugins)
 
 target_link_libraries(librbd PRIVATE
   rbd_internal
index b1798c4680e3bcabcb375314da8c943ae52a0132..3c85fede4852c5a8fe8a2b0f22faccfff8aebc23 100644 (file)
@@ -21,7 +21,7 @@
 #include "librbd/LibrbdAdminSocketHook.h"
 #include "librbd/ObjectMap.h"
 #include "librbd/Operations.h"
-#include "librbd/operation/ResizeRequest.h"
+#include "librbd/PluginRegistry.h"
 #include "librbd/Types.h"
 #include "librbd/Utils.h"
 #include "librbd/exclusive_lock/AutomaticPolicy.h"
@@ -32,6 +32,7 @@
 #include "librbd/io/ObjectDispatcher.h"
 #include "librbd/io/QosImageDispatch.h"
 #include "librbd/journal/StandardPolicy.h"
+#include "librbd/operation/ResizeRequest.h"
 
 #include "osdc/Striper.h"
 #include <boost/bind.hpp>
@@ -123,6 +124,7 @@ public:
       operations(new Operations<>(*this)),
       exclusive_lock(nullptr), object_map(nullptr),
       op_work_queue(nullptr),
+      plugin_registry(new PluginRegistry<ImageCtx>(this)),
       external_callback_completions(32),
       event_socket_completions(32),
       asok_hook(nullptr),
@@ -179,6 +181,8 @@ public:
     delete exclusive_lock_policy;
     delete operations;
     delete state;
+
+    delete plugin_registry;
   }
 
   void ImageCtx::init() {
index ed47d43a5569024b5843ba59fd29fe9cb4a2f59f..d1c2ef135cd994e33b4bd2d97e6e1bb144c1f34e 100644 (file)
@@ -49,6 +49,7 @@ namespace librbd {
   class LibrbdAdminSocketHook;
   template <typename> class ObjectMap;
   template <typename> class Operations;
+  template <typename> class PluginRegistry;
 
   namespace cache {
   template <typename> class ImageCache;
@@ -185,6 +186,8 @@ namespace librbd {
 
     ContextWQ *op_work_queue;
 
+    PluginRegistry<ImageCtx>* plugin_registry;
+
     typedef boost::lockfree::queue<
       io::AioCompletion*,
       boost::lockfree::allocator<ceph::allocator<void>>> Completions;
diff --git a/src/librbd/PluginRegistry.cc b/src/librbd/PluginRegistry.cc
new file mode 100644 (file)
index 0000000..c600c86
--- /dev/null
@@ -0,0 +1,52 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/PluginRegistry.h"
+#include "include/Context.h"
+#include "common/dout.h"
+#include "librbd/ImageCtx.h"
+#include <boost/tokenizer.hpp>
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::PluginRegistry: " \
+                           << this << " " << __func__ << ": "
+
+namespace librbd {
+
+template <typename I>
+PluginRegistry<I>::PluginRegistry(I* image_ctx) : m_image_ctx(image_ctx) {
+}
+
+template <typename I>
+void PluginRegistry<I>::init(const std::string& plugins, Context* on_finish) {
+  auto cct = m_image_ctx->cct;
+  auto plugin_registry = cct->get_plugin_registry();
+
+  auto gather_ctx = new C_Gather(cct, on_finish);
+
+  boost::tokenizer<boost::escaped_list_separator<char>> tokenizer(plugins);
+  for (auto token : tokenizer) {
+    ldout(cct, 5) << "attempting to load plugin: " << token << dendl;
+
+    auto ctx = gather_ctx->new_sub();
+
+    auto plugin = dynamic_cast<plugin::Interface<I>*>(
+      plugin_registry->get_with_load("librbd", "librbd_" + token));
+    if (plugin == nullptr) {
+      lderr(cct) << "failed to load plugin: " << token << dendl;
+      ctx->complete(-ENOENT);
+      break;
+    }
+
+    m_plugin_hook_points.emplace_back();
+    auto hook_points = &m_plugin_hook_points.back();
+    plugin->init(m_image_ctx, hook_points, ctx);
+  }
+
+  gather_ctx->activate();
+}
+
+} // namespace librbd
+
+template class librbd::PluginRegistry<librbd::ImageCtx>;
diff --git a/src/librbd/PluginRegistry.h b/src/librbd/PluginRegistry.h
new file mode 100644 (file)
index 0000000..2e975f8
--- /dev/null
@@ -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_REGISTRY_H
+#define CEPH_LIBRBD_PLUGIN_REGISTRY_H
+
+#include "librbd/plugin/Types.h"
+#include <string>
+#include <list>
+
+struct Context;
+
+namespace librbd {
+
+struct ImageCtx;
+
+template <typename ImageCtxT>
+class PluginRegistry {
+public:
+  PluginRegistry(ImageCtxT* image_ctx);
+
+  void init(const std::string& plugins, Context* on_finish);
+
+private:
+  typedef std::list<plugin::HookPoints> PluginHookPoints;
+
+  ImageCtxT* m_image_ctx;
+  std::string m_plugins;
+
+  PluginHookPoints m_plugin_hook_points;
+
+};
+
+} // namespace librbd
+
+extern template class librbd::PluginRegistry<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_PLUGIN_REGISTRY_H
index 88d5d62e0e5ab27a981a4f7f5a6c4d3355067119..f9e7696ec2aac91d04df49de3559e244ad19ae77 100644 (file)
@@ -6,6 +6,7 @@
 #include "common/errno.h"
 #include "cls/rbd/cls_rbd_client.h"
 #include "librbd/ImageCtx.h"
+#include "librbd/PluginRegistry.h"
 #include "librbd/Utils.h"
 #include "librbd/cache/ObjectCacherObjectDispatch.h"
 #include "librbd/cache/WriteAroundObjectDispatch.h"
@@ -519,6 +520,35 @@ Context *OpenRequest<I>::handle_refresh(int *result) {
     return nullptr;
   }
 
+  send_init_plugin_registry();
+  return nullptr;
+}
+
+template <typename I>
+void OpenRequest<I>::send_init_plugin_registry() {
+  CephContext *cct = m_image_ctx->cct;
+
+  auto plugins = m_image_ctx->config.template get_val<std::string>(
+    "rbd_plugins");
+  ldout(cct, 10) << __func__ << ": plugins=" << plugins << dendl;
+
+  auto ctx = create_context_callback<
+    OpenRequest<I>, &OpenRequest<I>::handle_init_plugin_registry>(this);
+  m_image_ctx->plugin_registry->init(plugins, ctx);
+}
+
+template <typename I>
+Context* OpenRequest<I>::handle_init_plugin_registry(int *result) {
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << __func__ << ": r=" << *result << dendl;
+
+  if (*result < 0) {
+    lderr(cct) << "failed to initialize plugin registry: "
+               << cpp_strerror(*result) << dendl;
+    send_close_image(*result);
+    return nullptr;
+  }
+
   return send_parent_cache(result);
 }
 
index 460839bb3d8526ca62c533a483032278569d55aa..9241ef0b64d4ad2f9ef0a169151cd5de70ec5e14 100644 (file)
@@ -61,6 +61,9 @@ private:
    *            V2_GET_DATA_POOL --------------> REFRESH
    *                                                |
    *                                                v
+   *                                             INIT_PLUGIN_REGISTRY
+   *                                                |
+   *                                                v
    *                                             INIT_PARENT_CACHE(skip if
    *                                                |               disable)
    *                                                v
@@ -123,6 +126,9 @@ private:
   void send_refresh();
   Context *handle_refresh(int *result);
 
+  void send_init_plugin_registry();
+  Context* handle_init_plugin_registry(int *result);
+
   Context* send_parent_cache(int *result);
   Context* handle_parent_cache(int *result);
 
diff --git a/src/librbd/plugin/Types.h b/src/librbd/plugin/Types.h
new file mode 100644 (file)
index 0000000..73f4509
--- /dev/null
@@ -0,0 +1,31 @@
+// -*- 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 "common/PluginRegistry.h"
+
+struct CephContext;
+struct Context;
+
+namespace librbd {
+namespace plugin {
+
+struct HookPoints {
+  // TODO later commits will add support for exclusive-lock hook points
+};
+
+template <typename ImageCtxT>
+struct Interface : public ceph::Plugin {
+  Interface(CephContext* cct) : Plugin(cct) {
+  }
+
+  virtual void init(ImageCtxT* image_ctx, HookPoints* hook_points,
+                    Context* on_finish) = 0;
+};
+
+} // namespace plugin
+} // namespace librbd
+
+#endif // CEPH_LIBRBD_PLUGIN_TYPES_H