]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd/plugin: enable hook points for exclusive lock
authorlixiaoy1 <xiaoyan.li@intel.com>
Wed, 4 Nov 2020 14:21:15 +0000 (22:21 +0800)
committerlixiaoy1 <xiaoyan.li@intel.com>
Mon, 7 Dec 2020 09:22:31 +0000 (04:22 -0500)
Signed-off-by: Li, Xiaoyan <xiaoyan.li@intel.com>
13 files changed:
src/librbd/PluginRegistry.cc
src/librbd/PluginRegistry.h
src/librbd/exclusive_lock/PostAcquireRequest.cc
src/librbd/exclusive_lock/PostAcquireRequest.h
src/librbd/exclusive_lock/PreReleaseRequest.cc
src/librbd/exclusive_lock/PreReleaseRequest.h
src/librbd/plugin/ParentCache.cc
src/librbd/plugin/ParentCache.h
src/librbd/plugin/Types.h
src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc
src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc
src/test/librbd/mock/MockImageCtx.h
src/test/librbd/mock/MockPluginRegistry.h [new file with mode: 0644]

index a4dabb7d33ef09107a76c598729b05c55f95020b..6ddf0a414f8a932aa365d1e419b24bffe4131a48 100644 (file)
@@ -4,6 +4,7 @@
 #include "librbd/PluginRegistry.h"
 #include "include/Context.h"
 #include "common/dout.h"
+#include "librbd/cache/ImageWriteback.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/plugin/Api.h"
 #include <boost/tokenizer.hpp>
@@ -17,7 +18,8 @@ namespace librbd {
 
 template <typename I>
 PluginRegistry<I>::PluginRegistry(I* image_ctx)
-  : m_image_ctx(image_ctx), m_plugin_api(std::make_unique<plugin::Api<I>>()) {
+  : m_image_ctx(image_ctx), m_plugin_api(std::make_unique<plugin::Api<I>>()),
+    m_image_writeback(std::make_unique<cache::ImageWriteback<I>>(*image_ctx)) {
 }
 
 template <typename I>
@@ -45,14 +47,55 @@ void PluginRegistry<I>::init(const std::string& plugins, Context* on_finish) {
       break;
     }
 
-    m_plugin_hook_points.emplace_back();
-    auto hook_points = &m_plugin_hook_points.back();
-    plugin->init(m_image_ctx, *m_plugin_api, hook_points, ctx);
+    plugin->init(
+       m_image_ctx, *m_plugin_api, *m_image_writeback, m_plugin_hook_points, ctx);
   }
 
   gather_ctx->activate();
 }
 
+template <typename I>
+void PluginRegistry<I>::acquired_exclusive_lock(Context* on_finish) {
+  auto cct = m_image_ctx->cct;
+  ldout(cct, 20) << dendl;
+
+  auto gather_ctx = new C_Gather(cct, on_finish);
+
+  for (auto &hook : m_plugin_hook_points) {
+    auto ctx = gather_ctx->new_sub();
+    hook->acquired_exclusive_lock(ctx);
+  }
+  gather_ctx->activate();
+}
+
+template <typename I>
+void PluginRegistry<I>::prerelease_exclusive_lock(Context* on_finish) {
+  auto cct = m_image_ctx->cct;
+  ldout(cct, 20) << dendl;
+
+  auto gather_ctx = new C_Gather(cct, on_finish);
+
+  for (auto &hook : m_plugin_hook_points) {
+    auto ctx = gather_ctx->new_sub();
+    hook->prerelease_exclusive_lock(ctx);
+  }
+  gather_ctx->activate();
+}
+
+template <typename I>
+void PluginRegistry<I>::discard(Context* on_finish) {
+  auto cct = m_image_ctx->cct;
+  ldout(cct, 20) << dendl;
+
+  auto gather_ctx = new C_Gather(cct, on_finish);
+
+  for (auto &hook : m_plugin_hook_points) {
+    auto ctx = gather_ctx->new_sub();
+    hook->discard(ctx);
+  }
+  gather_ctx->activate();
+}
+
 } // namespace librbd
 
 template class librbd::PluginRegistry<librbd::ImageCtx>;
index ca343fdd814ee949135dabd475941283fdfd2a3c..92e183ce10a01ab8a322a0bdf9fcec2c6e15549d 100644 (file)
@@ -15,6 +15,10 @@ namespace librbd {
 
 struct ImageCtx;
 
+namespace cache {
+class ImageWritebackInterface;
+}
+
 namespace plugin { template <typename> struct Api; }
 
 template <typename ImageCtxT>
@@ -25,15 +29,18 @@ public:
 
   void init(const std::string& plugins, Context* on_finish);
 
-private:
-  typedef std::list<plugin::HookPoints> PluginHookPoints;
+  void acquired_exclusive_lock(Context* on_finish);
+  void prerelease_exclusive_lock(Context* on_finish);
+  void discard(Context* on_finish);
 
+private:
   ImageCtxT* m_image_ctx;
   std::unique_ptr<plugin::Api<ImageCtxT>> m_plugin_api;
+  std::unique_ptr<cache::ImageWritebackInterface> m_image_writeback;
 
   std::string m_plugins;
 
-  PluginHookPoints m_plugin_hook_points;
+  plugin::PluginHookPoints m_plugin_hook_points;
 
 };
 
index d858e317a1b7f730e5355fff9f946dd06744f6bc..51267c1cfcc6769d0c21648dd880e6641fb22fb4 100644 (file)
@@ -17,6 +17,7 @@
 #include "librbd/Utils.h"
 #include "librbd/image/RefreshRequest.h"
 #include "librbd/journal/Policy.h"
+#include "librbd/PluginRegistry.h"
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
@@ -115,7 +116,7 @@ void PostAcquireRequest<I>::send_open_journal() {
   }
   if (!journal_enabled) {
     apply();
-    send_open_image_cache();
+    send_process_plugin_acquire_lock();
     return;
   }
 
@@ -173,9 +174,60 @@ void PostAcquireRequest<I>::handle_allocate_journal_tag(int r) {
     return;
   }
 
+  send_process_plugin_acquire_lock();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::send_process_plugin_acquire_lock() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << dendl;
+
+  using klass = PostAcquireRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_process_plugin_acquire_lock>(this);
+  m_image_ctx.plugin_registry->acquired_exclusive_lock(ctx);
+}
+
+template <typename I>
+void PostAcquireRequest<I>::handle_process_plugin_acquire_lock(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << "r=" << r << dendl;
+
+  save_result(r);
+  if (r < 0) {
+    lderr(cct) << "failed to process plugins: " << cpp_strerror(r)
+               << dendl;
+    send_process_plugin_release_lock();
+    return;
+  }
+
   send_open_image_cache();
 }
 
+template <typename I>
+void PostAcquireRequest<I>::send_process_plugin_release_lock() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << dendl;
+
+  using klass = PostAcquireRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_process_plugin_release_lock>(this);
+  m_image_ctx.plugin_registry->prerelease_exclusive_lock(ctx);
+}
+
+template <typename I>
+void PostAcquireRequest<I>::handle_process_plugin_release_lock(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << "r=" << r << dendl;
+
+  save_result(r);
+  if (r < 0) {
+    lderr(cct) << "failed to release plugins: " << cpp_strerror(r)
+               << dendl;
+  }
+  send_close_journal();
+}
+
 template <typename I>
 void PostAcquireRequest<I>::send_open_image_cache() {
   CephContext *cct = m_image_ctx.cct;
@@ -199,7 +251,7 @@ void PostAcquireRequest<I>::handle_open_image_cache(int r) {
   if (r < 0) {
     lderr(cct) << "failed to open image cache: " << cpp_strerror(r)
                << dendl;
-    send_close_journal();
+    send_process_plugin_release_lock();
     return;
   }
 
index f908634263211506e5182ab737309a0034aeaf01..56532838bed193a18ecfe9b14620254a09d480c6 100644 (file)
@@ -49,10 +49,17 @@ private:
    *      |            *    *
    *      |            *    *
    *      v            *    *
-   *  OPEN_IMAGE_CACHE *    *
+   *  PROCESS_PLUGIN_ACQUIRE*
+   *      |            *    *
+   *      |            *    *
+   *      v            *    *
+   *  OPEN_IMAGE_CACHE      *
    *      |         *  *    *
    *      |         *  *    *
    *      |         v  v    v
+   *      |         PROCESS_PLUGIN_RELEASE
+   *      |               |
+   *      |               v
    *      |         CLOSE_JOURNAL
    *      |               |
    *      |               v
@@ -95,12 +102,15 @@ private:
   void send_close_object_map();
   void handle_close_object_map(int r);
 
+  void send_process_plugin_acquire_lock();
+  void handle_process_plugin_acquire_lock(int r);
+
+  void send_process_plugin_release_lock();
+  void handle_process_plugin_release_lock(int r);
+
   void send_open_image_cache();
   void handle_open_image_cache(int r);
 
-  void send_close_image_cache();
-  void handle_close_image_cache(int r);
-
   void apply();
   void revert();
 
index 5d926c9059c738ba009805a84693469a4c31c196..3adc3b54a45b248bd65338186bf94f72e4086611 100644 (file)
@@ -17,6 +17,7 @@
 #include "librbd/io/ImageDispatcherInterface.h"
 #include "librbd/io/ObjectDispatcherInterface.h"
 #include "librbd/io/Types.h"
+#include "librbd/PluginRegistry.h"
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
@@ -142,7 +143,7 @@ void PreReleaseRequest<I>::handle_wait_for_ops(int r) {
 template <typename I>
 void PreReleaseRequest<I>::send_prepare_lock() {
   if (m_shutting_down) {
-    send_shut_down_image_cache();
+    send_process_plugin_release_lock();
     return;
   }
 
@@ -160,30 +161,29 @@ void PreReleaseRequest<I>::handle_prepare_lock(int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 10) << "r=" << r << dendl;
 
-  send_shut_down_image_cache();
+  send_process_plugin_release_lock();
 }
 
 template <typename I>
-void PreReleaseRequest<I>::send_shut_down_image_cache() {
+void PreReleaseRequest<I>::send_process_plugin_release_lock() {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 10) << dendl;
 
   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));
-  m_image_ctx.io_image_dispatcher->shut_down_dispatch(
-    io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, ctx);
+      &PreReleaseRequest<I>::handle_process_plugin_release_lock>(this));
+  m_image_ctx.plugin_registry->prerelease_exclusive_lock(ctx);
 }
 
 template <typename I>
-void PreReleaseRequest<I>::handle_shut_down_image_cache(int r) {
+void PreReleaseRequest<I>::handle_process_plugin_release_lock(int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 10) << "r=" << r << dendl;
 
   if (r < 0) {
-    lderr(cct) << "failed to shut down image cache: " << cpp_strerror(r)
-               << dendl;
+    lderr(cct) << "failed to handle plugins before releasing lock: "
+               << cpp_strerror(r) << dendl;
     m_image_dispatch->unset_require_lock(io::DIRECTION_BOTH);
     save_result(r);
     finish();
index 8156df3415fe8b636391a2e8eba62c3554a7f289..680cf3cb73fe599a499d9c2c3e25efe2e8aed50d 100644 (file)
@@ -49,6 +49,9 @@ private:
    * PREPARE_LOCK
    *    |
    *    v
+   * PROCESS_PLUGIN_RELEASE
+   *    |
+   *    v
    * SHUT_DOWN_IMAGE_CACHE
    *    |
    *    v
@@ -100,6 +103,9 @@ private:
   void send_prepare_lock();
   void handle_prepare_lock(int r);
 
+  void send_process_plugin_release_lock();
+  void handle_process_plugin_release_lock(int r);
+
   void send_shut_down_image_cache();
   void handle_shut_down_image_cache(int r);
 
index cdbe8ff9b3cda11e16db42afa24aa0b0a94c03cf..3eba430abcef81d316f6b55d6275cc4fde802032 100644 (file)
@@ -33,7 +33,9 @@ namespace librbd {
 namespace plugin {
 
 template <typename I>
-void ParentCache<I>::init(I* image_ctx, Api<I>& api, HookPoints* hook_points,
+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");
index 276170b258cbc23cf2ba048d74019a3ad4bfe9ae..1039efff9ae7ad19d0d130d749f80585f1159875 100644 (file)
@@ -19,7 +19,9 @@ public:
   ParentCache(CephContext* cct) : Interface<ImageCtxT>(cct) {
   }
 
-  void init(ImageCtxT* image_ctx, Api<ImageCtxT>& api, HookPoints* hook_points,
+  void init(ImageCtxT* image_ctx, Api<ImageCtxT>& api,
+            cache::ImageWritebackInterface& image_writeback,
+            PluginHookPoints& hook_points_list,
             Context* on_finish) override;
 
 private:
index af60f49ef63ed4af767ee250947fff150dfe3495..b66d754ac28cc47a08046fe8fadd640f1d8276e4 100644 (file)
@@ -5,9 +5,9 @@
 #define CEPH_LIBRBD_PLUGIN_TYPES_H
 
 #include "include/common_fwd.h"
+#include "include/Context.h"
 #include "common/PluginRegistry.h"
-
-struct Context;
+#include "librbd/cache/ImageWriteback.h"
 
 namespace librbd {
 namespace plugin {
@@ -15,16 +15,28 @@ namespace plugin {
 template <typename> struct Api;
 
 struct HookPoints {
-  // TODO later commits will add support for exclusive-lock hook points
+  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,
-                    HookPoints* hook_points, Context* on_finish) = 0;
+                   librbd::cache::ImageWritebackInterface& image_writeback,
+                    PluginHookPoints& hook_points_list, Context* on_finish) = 0;
 };
 
 } // namespace plugin
index 7335dfe6ae19c8f9f307791cd3158906a350d77a..0cb959d19140b4d9897bafc49a2d1d903fdc1c26 100644 (file)
@@ -202,10 +202,14 @@ public:
     EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
   }
 
-  void expect_init_image_cache(MockTestImageCtx &mock_image_ctx,
-                               MockInitRequest &mock_init_request, int r) {
-    EXPECT_CALL(mock_init_request, send())
-                  .WillOnce(FinishRequest(&mock_init_request, r, &mock_image_ctx));
+  void expect_acquired_exclusive_lock(MockTestImageCtx &mock_image_ctx, int r) {
+    EXPECT_CALL(*mock_image_ctx.plugin_registry, acquired_exclusive_lock(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_prerelease_exclusive_lock(MockTestImageCtx &mock_image_ctx, int r) {
+    EXPECT_CALL(*mock_image_ctx.plugin_registry, prerelease_exclusive_lock(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
   }
 
 };
@@ -239,6 +243,8 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, Success) {
   expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
   expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
 
+  expect_acquired_exclusive_lock(mock_image_ctx, 0);
+
   MockInitRequest mock_init_request;
   expect_init_image_cache(mock_image_ctx, mock_init_request, 0);
   C_SaferCond acquire_ctx;
@@ -271,6 +277,8 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessRefresh) {
                        mock_image_ctx.image_lock, false);
   expect_handle_prepare_lock_complete(mock_image_ctx);
 
+  expect_acquired_exclusive_lock(mock_image_ctx, 0);
+
   MockInitRequest mock_init_request;
   expect_init_image_cache(mock_image_ctx, mock_init_request, 0);
 
@@ -305,6 +313,8 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessJournalDisabled) {
                        mock_image_ctx.image_lock, false);
   expect_handle_prepare_lock_complete(mock_image_ctx);
 
+  expect_acquired_exclusive_lock(mock_image_ctx, 0);
+
   MockInitRequest mock_init_request;
   expect_init_image_cache(mock_image_ctx, mock_init_request, 0);
 
@@ -344,6 +354,8 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessObjectMapDisabled) {
   expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
   expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
 
+  expect_acquired_exclusive_lock(mock_image_ctx, 0);
+
   MockInitRequest mock_init_request;
   expect_init_image_cache(mock_image_ctx, mock_init_request, 0);
 
@@ -401,6 +413,8 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, RefreshLockDisabled) {
                        mock_image_ctx.image_lock, false);
   expect_handle_prepare_lock_complete(mock_image_ctx);
 
+  expect_acquired_exclusive_lock(mock_image_ctx, 0);
+
   MockInitRequest mock_init_request;
   expect_init_image_cache(mock_image_ctx, mock_init_request, 0);
 
@@ -521,6 +535,9 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, InitImageCacheError) {
   expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
   expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
 
+  expect_acquired_exclusive_lock(mock_image_ctx, -ENOENT);
+  expect_prerelease_exclusive_lock(mock_image_ctx, 0);
+
   MockInitRequest mock_init_request;
   expect_init_image_cache(mock_image_ctx, mock_init_request, -ENOENT);
 
@@ -593,6 +610,8 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, OpenObjectMapTooBig) {
   expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
   expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
 
+  expect_acquired_exclusive_lock(mock_image_ctx, 0);
+
   MockInitRequest mock_init_request;
   expect_init_image_cache(mock_image_ctx, mock_init_request, 0);
 
index a3f2e14e10e0d06c14df152f3b6bc9d1ed1db276..ceb45ca2e68b45c5b646c2419e2bb9b737deef03 100644 (file)
@@ -135,11 +135,9 @@ public:
                   .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
   }
 
-  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_prerelease_exclusive_lock(MockTestImageCtx &mock_image_ctx, int r) {
+    EXPECT_CALL(*mock_image_ctx.plugin_registry, prerelease_exclusive_lock(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
   }
 
   void expect_invalidate_cache(MockTestImageCtx &mock_image_ctx,
@@ -204,7 +202,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, Success) {
 
   expect_prepare_lock(mock_image_ctx);
 
-  expect_close_image_cache(mock_image_ctx, 0);
+  expect_prerelease_exclusive_lock(mock_image_ctx, 0);
 
   expect_invalidate_cache(mock_image_ctx, 0);
 
@@ -245,7 +243,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessJournalDisabled) {
   expect_cancel_op_requests(mock_image_ctx, 0);
   expect_prepare_lock(mock_image_ctx);
 
-  expect_close_image_cache(mock_image_ctx, 0);
+  expect_prerelease_exclusive_lock(mock_image_ctx, 0);
 
   expect_invalidate_cache(mock_image_ctx, 0);
 
@@ -281,7 +279,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessObjectMapDisabled) {
   InSequence seq;
   expect_cancel_op_requests(mock_image_ctx, 0);
 
-  expect_close_image_cache(mock_image_ctx, 0);
+  expect_prerelease_exclusive_lock(mock_image_ctx, 0);
 
   expect_invalidate_cache(mock_image_ctx, 0);
 
@@ -313,7 +311,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, Blocklisted) {
                           -EBLOCKLISTED);
   expect_prepare_lock(mock_image_ctx);
 
-  expect_close_image_cache(mock_image_ctx, 0);
+  expect_prerelease_exclusive_lock(mock_image_ctx, 0);
 
   expect_invalidate_cache(mock_image_ctx, -EBLOCKLISTED);
 
@@ -356,7 +354,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, Disabled) {
 
   expect_prepare_lock(mock_image_ctx);
 
-  expect_close_image_cache(mock_image_ctx, 0);
+  expect_prerelease_exclusive_lock(mock_image_ctx, 0);
 
   expect_invalidate_cache(mock_image_ctx, 0);
 
index 1e176bd21ef68811ff54e771d8dc72b19fa379de..429a58410e986ec1cf5757f42b87af3c9bdfa417 100644 (file)
@@ -12,6 +12,7 @@
 #include "test/librbd/mock/MockJournal.h"
 #include "test/librbd/mock/MockObjectMap.h"
 #include "test/librbd/mock/MockOperations.h"
+#include "test/librbd/mock/MockPluginRegistry.h"
 #include "test/librbd/mock/MockReadahead.h"
 #include "test/librbd/mock/io/MockImageDispatcher.h"
 #include "test/librbd/mock/io/MockObjectDispatcher.h"
@@ -86,6 +87,7 @@ struct MockImageCtx {
       io_image_dispatcher(new io::MockImageDispatcher()),
       io_object_dispatcher(new io::MockObjectDispatcher()),
       op_work_queue(new MockContextWQ()),
+      plugin_registry(new MockPluginRegistry()),
       readahead_max_bytes(image_ctx.readahead_max_bytes),
       event_socket(image_ctx.event_socket),
       parent(NULL), operations(new MockOperations()),
@@ -126,6 +128,7 @@ struct MockImageCtx {
     delete operations;
     delete image_watcher;
     delete op_work_queue;
+    delete plugin_registry;
     delete io_image_dispatcher;
     delete io_object_dispatcher;
   }
@@ -294,6 +297,8 @@ struct MockImageCtx {
   io::MockObjectDispatcher *io_object_dispatcher;
   MockContextWQ *op_work_queue;
 
+  MockPluginRegistry* plugin_registry;
+
   MockReadahead readahead;
   uint64_t readahead_max_bytes;
 
diff --git a/src/test/librbd/mock/MockPluginRegistry.h b/src/test/librbd/mock/MockPluginRegistry.h
new file mode 100644 (file)
index 0000000..8854a74
--- /dev/null
@@ -0,0 +1,21 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_TEST_LIBRBD_MOCK_PLUGIN_REGISTRY_H
+#define CEPH_TEST_LIBRBD_MOCK_PLUGIN_REGISTRY_H
+
+#include <gmock/gmock.h>
+
+class Context;
+
+namespace librbd {
+
+struct MockPluginRegistry{
+  MOCK_METHOD2(init, void(const std::string&, Context*));
+  MOCK_METHOD1(acquired_exclusive_lock, void(Context*));
+  MOCK_METHOD1(prerelease_exclusive_lock, void(Context*));
+};
+
+} // namespace librbd
+
+#endif // CEPH_TEST_LIBRBD_MOCK_PLUGIN_REGISTRY_H