.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"),
+
});
}
MirroringWatcher.cc
ObjectMap.cc
Operations.cc
+ PluginRegistry.cc
TrashWatcher.cc
Utils.cc
Watcher.cc
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()
if(WITH_LTTNG)
add_dependencies(librbd librbd-tp)
endif()
+add_dependencies(librbd librbd_plugins)
target_link_libraries(librbd PRIVATE
rbd_internal
#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"
#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>
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),
delete exclusive_lock_policy;
delete operations;
delete state;
+
+ delete plugin_registry;
}
void ImageCtx::init() {
class LibrbdAdminSocketHook;
template <typename> class ObjectMap;
template <typename> class Operations;
+ template <typename> class PluginRegistry;
namespace cache {
template <typename> class ImageCache;
ContextWQ *op_work_queue;
+ PluginRegistry<ImageCtx>* plugin_registry;
+
typedef boost::lockfree::queue<
io::AioCompletion*,
boost::lockfree::allocator<ceph::allocator<void>>> Completions;
--- /dev/null
+// -*- 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>;
--- /dev/null
+// -*- 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
#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"
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);
}
* V2_GET_DATA_POOL --------------> REFRESH
* |
* v
+ * INIT_PLUGIN_REGISTRY
+ * |
+ * v
* INIT_PARENT_CACHE(skip if
* | disable)
* v
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);
--- /dev/null
+// -*- 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