]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: optionally skip object map creation upon snapshot
authorJason Dillaman <dillaman@redhat.com>
Fri, 29 Apr 2016 20:43:07 +0000 (16:43 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 10 May 2016 17:43:46 +0000 (13:43 -0400)
This feature is used by rbd-mirror during image bootstrap since
it will directly create an empty object map.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit db16240c79be7e28d65edac2088352b9b146da5f)

src/librbd/ImageWatcher.cc
src/librbd/Operations.cc
src/librbd/Operations.h
src/librbd/journal/Replay.cc
src/librbd/operation/SnapshotCreateRequest.cc
src/librbd/operation/SnapshotCreateRequest.h
src/test/librbd/journal/test_mock_Replay.cc
src/test/librbd/mock/MockOperations.h
src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc
src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc
src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc

index b48974e9925f13ff53e35732d58a7809f6ccac5b..d3d4e701a736ee92c2c7e7192c62b337910e34b2 100644 (file)
@@ -714,7 +714,7 @@ bool ImageWatcher::handle_payload(const SnapCreatePayload &payload,
 
     m_image_ctx.operations->execute_snap_create(payload.snap_name.c_str(),
                                                 new C_ResponseMessage(ack_ctx),
-                                                0);
+                                                0, false);
     return false;
   }
   return true;
index 620b0bf6cee105b47fc5b7cb1cbe81fa15ef1546..c523b912680d3d2a36a2139dbb57207edad72fdd 100644 (file)
@@ -596,7 +596,8 @@ void Operations<I>::snap_create(const char *snap_name, Context *on_finish) {
 
   C_InvokeAsyncRequest<I> *req = new C_InvokeAsyncRequest<I>(
     m_image_ctx, "snap_create", true,
-    boost::bind(&Operations<I>::execute_snap_create, this, snap_name, _1, 0),
+    boost::bind(&Operations<I>::execute_snap_create, this, snap_name, _1, 0,
+                false),
     boost::bind(&ImageWatcher::notify_snap_create, m_image_ctx.image_watcher,
                 snap_name, _1),
     {-EEXIST}, on_finish);
@@ -606,7 +607,8 @@ void Operations<I>::snap_create(const char *snap_name, Context *on_finish) {
 template <typename I>
 void Operations<I>::execute_snap_create(const char *snap_name,
                                         Context *on_finish,
-                                        uint64_t journal_op_tid) {
+                                        uint64_t journal_op_tid,
+                                        bool skip_object_map) {
   assert(m_image_ctx.owner_lock.is_locked());
   assert(m_image_ctx.exclusive_lock == nullptr ||
          m_image_ctx.exclusive_lock->is_lock_owner());
@@ -618,7 +620,7 @@ void Operations<I>::execute_snap_create(const char *snap_name,
   operation::SnapshotCreateRequest<I> *req =
     new operation::SnapshotCreateRequest<I>(
       m_image_ctx, new C_NotifyUpdate<I>(m_image_ctx, on_finish), snap_name,
-      journal_op_tid);
+      journal_op_tid, skip_object_map);
   req->send();
 }
 
index a32116a0156616a03f5e37a3d5b9028e7d8f7b98..95af4dcf1e96369c1b4c5f046d368c4c9abb2e1b 100644 (file)
@@ -38,7 +38,7 @@ public:
   int snap_create(const char *snap_name);
   void snap_create(const char *snap_name, Context *on_finish);
   void execute_snap_create(const char *snap_name, Context *on_finish,
-                           uint64_t journal_op_tid);
+                           uint64_t journal_op_tid, bool skip_object_map);
 
   int snap_rollback(const char *snap_name, ProgressContext& prog_ctx);
   void execute_snap_rollback(const char *snap_name, ProgressContext& prog_ctx,
index efe534c7fcdbf620fba94ac719c4d06240f7fb06..c6c4f55b602f1a25e0ab6c4e1391ff37c3462fc8 100644 (file)
@@ -41,7 +41,7 @@ struct ExecuteOp : public Context {
   void execute(const journal::SnapCreateEvent &_) {
     image_ctx.operations->execute_snap_create(event.snap_name.c_str(),
                                               on_op_complete,
-                                              event.op_tid);
+                                              event.op_tid, false);
   }
 
   void execute(const journal::SnapRemoveEvent &_) {
index e4a1fc31e166a5bb9fbfdd737f5b7c0ab10d843c..cb92c6cac7646b0c53f95079eea61a9ebb51a087 100644 (file)
@@ -62,9 +62,10 @@ template <typename I>
 SnapshotCreateRequest<I>::SnapshotCreateRequest(I &image_ctx,
                                                 Context *on_finish,
                                                 const std::string &snap_name,
-                                                uint64_t journal_op_tid)
+                                                uint64_t journal_op_tid,
+                                                bool skip_object_map)
   : Request<I>(image_ctx, on_finish, journal_op_tid), m_snap_name(snap_name),
-    m_ret_val(0), m_snap_id(CEPH_NOSNAP) {
+    m_skip_object_map(skip_object_map), m_ret_val(0), m_snap_id(CEPH_NOSNAP) {
 }
 
 template <typename I>
@@ -247,7 +248,7 @@ Context *SnapshotCreateRequest<I>::send_create_object_map() {
   update_snap_context();
 
   image_ctx.snap_lock.get_read();
-  if (image_ctx.object_map == nullptr) {
+  if (image_ctx.object_map == nullptr || m_skip_object_map) {
     image_ctx.snap_lock.put_read();
 
     finalize(0);
index 6b5268189629f325ff4ae85a66a37288af3054ab..35f8b53d60abc2894cd6c2fc26079b8349c473e5 100644 (file)
@@ -60,7 +60,8 @@ public:
    * (if enabled) and bubble the originating error code back to the client.
    */
   SnapshotCreateRequest(ImageCtxT &image_ctx, Context *on_finish,
-                       const std::string &snap_name, uint64_t journal_op_tid);
+                       const std::string &snap_name, uint64_t journal_op_tid,
+                        bool skip_object_map);
 
 protected:
   virtual void send_op();
@@ -76,6 +77,7 @@ protected:
 
 private:
   std::string m_snap_name;
+  bool m_skip_object_map;
 
   int m_ret_val;
 
index 2fc4344334775e424de8dce90022223b496e81bf..f4145e1f6b1b15374e0d5d7df20221a3ee36ab79 100644 (file)
@@ -147,7 +147,7 @@ public:
                           Context **on_finish, const char *snap_name,
                           uint64_t op_tid) {
     EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(CStrEq(snap_name), _,
-                                                                op_tid))
+                                                                op_tid, false))
                   .WillOnce(DoAll(SaveArg<1>(on_finish),
                                   NotifyInvoke(&m_invoke_lock, &m_invoke_cond)));
   }
index c92578a36f1ad2337774664704434576dfcb6b73..5bbd9b364968e6eccd05bbce4165b33b0f956ac9 100644 (file)
@@ -22,9 +22,10 @@ struct MockOperations {
                                     Context *on_finish,
                                     uint64_t journal_op_tid));
   MOCK_METHOD2(snap_create, void(const char *snap_name, Context *on_finish));
-  MOCK_METHOD3(execute_snap_create, void(const char *snap_name,
+  MOCK_METHOD4(execute_snap_create, void(const char *snap_name,
                                          Context *on_finish,
-                                         uint64_t journal_op_tid));
+                                         uint64_t journal_op_tid,
+                                         bool skip_object_map));
   MOCK_METHOD2(snap_remove, void(const char *snap_name, Context *on_finish));
   MOCK_METHOD2(execute_snap_remove, void(const char *snap_name,
                                          Context *on_finish));
index 8cc5fda42cfa873b921bb7b12f4a6ba152752cca..1b94b7e1f9f1bf4edc8153c97cdd77f7652a7540 100644 (file)
@@ -138,7 +138,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, Success) {
 
   C_SaferCond cond_ctx;
   MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
-    mock_image_ctx, &cond_ctx, "snap1", 0);
+    mock_image_ctx, &cond_ctx, "snap1", 0, false);
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     req->send();
@@ -167,7 +167,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, AllocateSnapIdError) {
 
   C_SaferCond cond_ctx;
   MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
-    mock_image_ctx, &cond_ctx, "snap1", 0);
+    mock_image_ctx, &cond_ctx, "snap1", 0, false);
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     req->send();
@@ -205,7 +205,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, CreateSnapStale) {
 
   C_SaferCond cond_ctx;
   MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
-    mock_image_ctx, &cond_ctx, "snap1", 0);
+    mock_image_ctx, &cond_ctx, "snap1", 0, false);
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     req->send();
@@ -235,7 +235,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, CreateSnapError) {
 
   C_SaferCond cond_ctx;
   MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
-    mock_image_ctx, &cond_ctx, "snap1", 0);
+    mock_image_ctx, &cond_ctx, "snap1", 0, false);
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     req->send();
@@ -265,7 +265,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, ReleaseSnapIdError) {
 
   C_SaferCond cond_ctx;
   MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
-    mock_image_ctx, &cond_ctx, "snap1", 0);
+    mock_image_ctx, &cond_ctx, "snap1", 0, false);
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     req->send();
@@ -273,5 +273,41 @@ TEST_F(TestMockOperationSnapshotCreateRequest, ReleaseSnapIdError) {
   ASSERT_EQ(-EINVAL, cond_ctx.wait());
 }
 
+TEST_F(TestMockOperationSnapshotCreateRequest, SkipObjectMap) {
+  REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+
+  MockExclusiveLock mock_exclusive_lock;
+  if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
+    mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
+  }
+
+  MockObjectMap mock_object_map;
+  mock_image_ctx.object_map = &mock_object_map;
+
+  expect_verify_lock_ownership(mock_image_ctx);
+  expect_op_work_queue(mock_image_ctx);
+
+  ::testing::InSequence seq;
+  expect_block_writes(mock_image_ctx);
+  expect_allocate_snap_id(mock_image_ctx, 0);
+  expect_snap_create(mock_image_ctx, 0);
+  expect_update_snap_context(mock_image_ctx);
+  expect_unblock_writes(mock_image_ctx);
+
+  C_SaferCond cond_ctx;
+  MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
+    mock_image_ctx, &cond_ctx, "snap1", 0, true);
+  {
+    RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
+    req->send();
+  }
+  ASSERT_EQ(0, cond_ctx.wait());
+}
+
 } // namespace operation
 } // namespace librbd
index f8778212053b888f80189879d18e93d4f0644f5c..5d8d78d991f3996b595da78d26db20cbe5c71d10 100644 (file)
@@ -49,7 +49,7 @@ public:
 
   void expect_snap_create(librbd::MockImageCtx &mock_image_ctx,
                           const std::string &snap_name, uint64_t snap_id, int r) {
-    EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(StrEq(snap_name), _, 0))
+    EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(StrEq(snap_name), _, 0, true))
                   .WillOnce(DoAll(InvokeWithoutArgs([&mock_image_ctx, snap_id, snap_name]() {
                                     inject_snap(mock_image_ctx, snap_id, snap_name);
                                   }),
index 7b5ce250cb936745986dd1b1495ef8886f3cfc16..ec69dffb8b82ec41f39cf9afe13848abf193aea5 100644 (file)
@@ -130,7 +130,7 @@ void SnapshotCreateRequest<I>::send_snap_create() {
       this);
   RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
   m_local_image_ctx->operations->execute_snap_create(m_snap_name.c_str(), ctx,
-                                                     0U);
+                                                     0U, true);
 }
 
 template <typename I>