]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tests: updated test cases for librbd journal tag allocation
authorJason Dillaman <dillaman@redhat.com>
Fri, 26 Feb 2016 17:33:32 +0000 (12:33 -0500)
committerJason Dillaman <dillaman@redhat.com>
Tue, 8 Mar 2016 14:03:44 +0000 (09:03 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc
src/test/librbd/journal/test_Replay.cc
src/test/librbd/mock/MockJournal.h
src/test/librbd/test_mock_Journal.cc

index 60b4c5a5e6a4dd2b2f803d409bf898afc2a2e00d..363a022c0d1fe90957be8bb0a16d1728f73e5557 100644 (file)
@@ -80,6 +80,22 @@ public:
                   .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
   }
 
+  void expect_close_journal(MockImageCtx &mock_image_ctx,
+                            MockJournal &mock_journal) {
+    EXPECT_CALL(mock_journal, close(_))
+                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_is_journal_tag_owner(MockJournal &mock_journal, bool owner) {
+    EXPECT_CALL(mock_journal, is_tag_owner()).WillOnce(Return(owner));
+  }
+
+  void expect_allocate_journal_tag(MockImageCtx &mock_image_ctx,
+                                   MockJournal &mock_journal, int r) {
+    EXPECT_CALL(mock_journal, allocate_tag("", _))
+                  .WillOnce(WithArg<1>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
+  }
+
   void expect_get_lock_info(MockImageCtx &mock_image_ctx, int r,
                             const entity_name_t &locker_entity,
                             const std::string &locker_address,
@@ -171,6 +187,8 @@ TEST_F(TestMockExclusiveLockAcquireRequest, Success) {
   expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
   expect_create_journal(mock_image_ctx, &mock_journal);
   expect_open_journal(mock_image_ctx, mock_journal, 0);
+  expect_is_journal_tag_owner(mock_journal, true);
+  expect_allocate_journal_tag(mock_image_ctx, mock_journal, 0);
 
   C_SaferCond acquire_ctx;
   C_SaferCond ctx;
@@ -231,6 +249,8 @@ TEST_F(TestMockExclusiveLockAcquireRequest, SuccessObjectMapDisabled) {
   expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
   expect_create_journal(mock_image_ctx, &mock_journal);
   expect_open_journal(mock_image_ctx, mock_journal, 0);
+  expect_is_journal_tag_owner(mock_journal, true);
+  expect_allocate_journal_tag(mock_image_ctx, mock_journal, 0);
 
   C_SaferCond acquire_ctx;
   C_SaferCond ctx;
@@ -264,6 +284,7 @@ TEST_F(TestMockExclusiveLockAcquireRequest, JournalError) {
   expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
   expect_create_journal(mock_image_ctx, mock_journal);
   expect_open_journal(mock_image_ctx, *mock_journal, -EINVAL);
+  expect_close_journal(mock_image_ctx, *mock_journal);
   expect_close_object_map(mock_image_ctx, *mock_object_map);
 
   C_SaferCond acquire_ctx;
@@ -275,6 +296,77 @@ TEST_F(TestMockExclusiveLockAcquireRequest, JournalError) {
   ASSERT_EQ(-EINVAL, ctx.wait());
 }
 
+TEST_F(TestMockExclusiveLockAcquireRequest, NotJournalTagOwner) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_flush_notifies(mock_image_ctx);
+  expect_lock(mock_image_ctx, 0);
+
+  MockObjectMap *mock_object_map = new MockObjectMap();
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_create_object_map(mock_image_ctx, mock_object_map);
+  expect_open_object_map(mock_image_ctx, *mock_object_map);
+
+  MockJournal *mock_journal = new MockJournal();
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
+  expect_create_journal(mock_image_ctx, mock_journal);
+  expect_open_journal(mock_image_ctx, *mock_journal, 0);
+  expect_is_journal_tag_owner(*mock_journal, false);
+  expect_close_journal(mock_image_ctx, *mock_journal);
+  expect_close_object_map(mock_image_ctx, *mock_object_map);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
+                                                       TEST_COOKIE,
+                                                       &acquire_ctx, &ctx);
+  req->send();
+  ASSERT_EQ(-EPERM, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockAcquireRequest, AllocateJournalTagError) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_flush_notifies(mock_image_ctx);
+  expect_lock(mock_image_ctx, 0);
+
+  MockObjectMap *mock_object_map = new MockObjectMap();
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_create_object_map(mock_image_ctx, mock_object_map);
+  expect_open_object_map(mock_image_ctx, *mock_object_map);
+
+  MockJournal *mock_journal = new MockJournal();
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
+  expect_create_journal(mock_image_ctx, mock_journal);
+  expect_open_journal(mock_image_ctx, *mock_journal, 0);
+  expect_is_journal_tag_owner(*mock_journal, true);
+  expect_allocate_journal_tag(mock_image_ctx, *mock_journal, -ESTALE);
+  expect_close_journal(mock_image_ctx, *mock_journal);
+  expect_close_object_map(mock_image_ctx, *mock_object_map);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
+                                                       TEST_COOKIE,
+                                                       &acquire_ctx, &ctx);
+  req->send();
+  ASSERT_EQ(-ESTALE, ctx.wait());
+}
+
 TEST_F(TestMockExclusiveLockAcquireRequest, LockBusy) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
 
index 7e048a04e55b5b71bc38a2356989750412469751..49fd479a2501b899999491b093238ff6bc0c6ceb 100644 (file)
@@ -44,7 +44,8 @@ public:
     }
   }
 
-  void get_journal_commit_position(librbd::ImageCtx *ictx, int64_t *tid)
+  void get_journal_commit_position(librbd::ImageCtx *ictx, int64_t *tag,
+                                   int64_t *entry)
   {
     const std::string client_id = "";
     std::string journal_id = ictx->id;
@@ -69,19 +70,16 @@ public:
        break;
       }
     }
-    if (c == registered_clients.end()) {
-      *tid = -1;
-      return;
+    if (c == registered_clients.end() ||
+        c->commit_position.object_positions.empty()) {
+      *tag = 0;
+      *entry = -1;
+    } else {
+      const cls::journal::ObjectPosition &object_position =
+        *c->commit_position.object_positions.begin();
+      *tag = object_position.tag_tid;
+      *entry = object_position.entry_tid;
     }
-    cls::journal::ObjectPositions object_positions =
-       c->commit_position.object_positions;
-    cls::journal::ObjectPositions::const_iterator p;
-    for (p = object_positions.begin(); p != object_positions.end(); p++) {
-      if (p->tag_tid == 0) {
-       break;
-      }
-    }
-    *tid = p == object_positions.end() ? -1 : p->entry_tid;
 
     C_SaferCond open_cond;
     ictx->journal = new librbd::Journal<>(*ictx);
@@ -123,8 +121,9 @@ TEST_F(TestJournalReplay, AioDiscardEvent) {
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject a discard operation into the journal
   inject_into_journal(ictx,
@@ -142,9 +141,11 @@ TEST_F(TestJournalReplay, AioDiscardEvent) {
   ASSERT_EQ(std::string(read_payload.size(), '\0'), read_payload);
 
   // check the commit position is properly updated
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 1);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(0, current_entry);
 
   // replay several envents and check the commit position
   inject_into_journal(ictx,
@@ -153,8 +154,9 @@ TEST_F(TestJournalReplay, AioDiscardEvent) {
                       librbd::journal::AioDiscardEvent(0, payload.size()));
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 3);
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 2, current_tag);
+  ASSERT_EQ(1, current_entry);
 
   // verify lock ordering constraints
   aio_comp = new librbd::AioCompletion();
@@ -171,8 +173,9 @@ TEST_F(TestJournalReplay, AioWriteEvent) {
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject a write operation into the journal
   std::string payload(4096, '1');
@@ -194,9 +197,11 @@ TEST_F(TestJournalReplay, AioWriteEvent) {
   ASSERT_EQ(payload, read_payload);
 
   // check the commit position is properly updated
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 1);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(0, current_entry);
 
   // replay several events and check the commit position
   inject_into_journal(ictx,
@@ -205,8 +210,9 @@ TEST_F(TestJournalReplay, AioWriteEvent) {
       librbd::journal::AioWriteEvent(0, payload.size(), payload_bl));
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 3);
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 2, current_tag);
+  ASSERT_EQ(1, current_entry);
 
   // verify lock ordering constraints
   aio_comp = new librbd::AioCompletion();
@@ -225,8 +231,9 @@ TEST_F(TestJournalReplay, AioFlushEvent) {
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject a flush operation into the journal
   inject_into_journal(ictx, librbd::journal::AioFlushEvent());
@@ -261,17 +268,20 @@ TEST_F(TestJournalReplay, AioFlushEvent) {
   ASSERT_EQ(payload, read_payload);
 
   // check the commit position is properly updated
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 1);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(0, current_entry);
 
   // replay several events and check the commit position
   inject_into_journal(ictx, librbd::journal::AioFlushEvent());
   inject_into_journal(ictx, librbd::journal::AioFlushEvent());
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 3);
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 2, current_tag);
+  ASSERT_EQ(1, current_entry);
 
   // verify lock ordering constraints
   aio_comp = new librbd::AioCompletion();
@@ -289,8 +299,9 @@ TEST_F(TestJournalReplay, SnapCreate) {
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   inject_into_journal(ictx, librbd::journal::SnapCreateEvent(1, "snap"));
@@ -300,9 +311,11 @@ TEST_F(TestJournalReplay, SnapCreate) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(1, current_entry);
 
   {
     RWLock::RLocker snap_locker(ictx->snap_lock);
@@ -324,8 +337,9 @@ TEST_F(TestJournalReplay, SnapProtect) {
   ASSERT_EQ(0, ictx->operations->snap_create("snap"));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   inject_into_journal(ictx, librbd::journal::SnapProtectEvent(1, "snap"));
@@ -335,9 +349,11 @@ TEST_F(TestJournalReplay, SnapProtect) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag, current_tag);
+  ASSERT_EQ(initial_entry + 2, current_entry);
 
   bool is_protected;
   ASSERT_EQ(0, librbd::snap_is_protected(ictx, "snap", &is_protected));
@@ -366,8 +382,9 @@ TEST_F(TestJournalReplay, SnapUnprotect) {
   ASSERT_EQ(0, ictx->operations->snap_protect("snap"));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   inject_into_journal(ictx, librbd::journal::SnapUnprotectEvent(1, "snap"));
@@ -377,9 +394,11 @@ TEST_F(TestJournalReplay, SnapUnprotect) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag, current_tag);
+  ASSERT_EQ(initial_entry + 2, current_entry);
 
   bool is_protected;
   ASSERT_EQ(0, librbd::snap_is_protected(ictx, "snap", &is_protected));
@@ -408,8 +427,9 @@ TEST_F(TestJournalReplay, SnapRename) {
   }
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   inject_into_journal(ictx, librbd::journal::SnapRenameEvent(1, snap_id, "snap2"));
@@ -419,9 +439,11 @@ TEST_F(TestJournalReplay, SnapRename) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag, current_tag);
+  ASSERT_EQ(initial_entry + 2, current_entry);
 
   {
     RWLock::RLocker snap_locker(ictx->snap_lock);
@@ -444,8 +466,9 @@ TEST_F(TestJournalReplay, SnapRollback) {
   ASSERT_EQ(0, ictx->operations->snap_create("snap"));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   inject_into_journal(ictx, librbd::journal::SnapRollbackEvent(1, "snap"));
@@ -455,9 +478,11 @@ TEST_F(TestJournalReplay, SnapRollback) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag, current_tag);
+  ASSERT_EQ(initial_entry + 2, current_entry);
 
   // verify lock ordering constraints
   librbd::NoOpProgressContext no_op_progress;
@@ -475,8 +500,9 @@ TEST_F(TestJournalReplay, SnapRemove) {
   ASSERT_EQ(0, ictx->operations->snap_create("snap"));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   inject_into_journal(ictx, librbd::journal::SnapRemoveEvent(1, "snap"));
@@ -486,9 +512,11 @@ TEST_F(TestJournalReplay, SnapRemove) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag, current_tag);
+  ASSERT_EQ(initial_entry + 2, current_entry);
 
   {
     RWLock::RLocker snap_locker(ictx->snap_lock);
@@ -510,8 +538,9 @@ TEST_F(TestJournalReplay, Rename) {
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   std::string new_image_name(get_temp_image_name());
@@ -522,9 +551,11 @@ TEST_F(TestJournalReplay, Rename) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(1, current_entry);
 
   // verify lock ordering constraints
   librbd::RBD rbd;
@@ -540,8 +571,9 @@ TEST_F(TestJournalReplay, Resize) {
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   inject_into_journal(ictx, librbd::journal::ResizeEvent(1, 16));
@@ -551,9 +583,11 @@ TEST_F(TestJournalReplay, Resize) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(1, current_entry);
 
   // verify lock ordering constraints
   librbd::NoOpProgressContext no_op_progress;
@@ -578,8 +612,9 @@ TEST_F(TestJournalReplay, Flatten) {
   ASSERT_EQ(0, when_acquired_lock(ictx2));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx2, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx2, &initial_tag, &initial_entry);
 
   // inject snapshot ops into journal
   inject_into_journal(ictx2, librbd::journal::FlattenEvent(1));
@@ -589,9 +624,11 @@ TEST_F(TestJournalReplay, Flatten) {
   ASSERT_EQ(0, open_image(clone_name, &ictx2));
   ASSERT_EQ(0, when_acquired_lock(ictx2));
 
-  int64_t current;
-  get_journal_commit_position(ictx2, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx2, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(1, current_entry);
   ASSERT_EQ(0, ictx->operations->snap_unprotect("snap"));
 
   // verify lock ordering constraints
@@ -607,8 +644,9 @@ TEST_F(TestJournalReplay, ObjectPosition) {
   ASSERT_EQ(0, when_acquired_lock(ictx));
 
   // get current commit position
-  int64_t initial;
-  get_journal_commit_position(ictx, &initial);
+  int64_t initial_tag;
+  int64_t initial_entry;
+  get_journal_commit_position(ictx, &initial_tag, &initial_entry);
 
   std::string payload(4096, '1');
   librbd::AioCompletion *aio_comp = new librbd::AioCompletion();
@@ -623,9 +661,11 @@ TEST_F(TestJournalReplay, ObjectPosition) {
   aio_comp->release();
 
   // check the commit position updated
-  int64_t current;
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 2);
+  int64_t current_tag;
+  int64_t current_entry;
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(1, current_entry);
 
   // write again
 
@@ -641,6 +681,7 @@ TEST_F(TestJournalReplay, ObjectPosition) {
   aio_comp->release();
 
   // check the commit position updated
-  get_journal_commit_position(ictx, &current);
-  ASSERT_EQ(current, initial + 4);
+  get_journal_commit_position(ictx, &current_tag, &current_entry);
+  ASSERT_EQ(initial_tag + 1, current_tag);
+  ASSERT_EQ(3, current_entry);
 }
index 9fe3518506004d50a4c93dfe39f79b42d69eb371..1393399d5557cef96aa5f77cbe9fc8ce00d04904 100644 (file)
@@ -16,6 +16,9 @@ struct MockJournal {
 
   MOCK_METHOD1(wait_for_journal_ready, void(Context *));
 
+  MOCK_CONST_METHOD0(is_tag_owner, bool());
+  MOCK_METHOD2(allocate_tag, void(const std::string &, Context *));
+
   MOCK_METHOD1(open, void(Context *));
   MOCK_METHOD1(close, void(Context *));
 
index 5c506199d570dab81bc06e7f160de148d4c8da03..dea29efb0f65964bd0ffa540d30c33116425c3a5 100644 (file)
@@ -7,6 +7,7 @@
 #include "common/Cond.h"
 #include "common/Mutex.h"
 #include "cls/journal/cls_journal_types.h"
+#include "journal/Journaler.h"
 #include "librbd/Journal.h"
 #include "librbd/Utils.h"
 #include "librbd/journal/Replay.h"
@@ -87,6 +88,9 @@ struct MockJournaler {
   MOCK_METHOD1(init, void(Context*));
   MOCK_METHOD1(flush_commit_position, void(Context*));
 
+  MOCK_METHOD2(get_cached_client, int(const std::string&, cls::journal::Client*));
+  MOCK_METHOD3(get_tags, void(uint64_t, journal::Journaler::Tags*, Context*));
+
   MOCK_METHOD1(start_replay, void(::journal::ReplayHandler *replay_handler));
   MOCK_METHOD1(try_pop_front, bool(MockReplayEntryProxy *replay_entry));
   MOCK_METHOD0(stop_replay, void());
@@ -134,6 +138,16 @@ struct MockJournalerProxy {
     MockJournaler::get_instance().init(on_finish);
   }
 
+  int get_cached_client(const std::string& client_id,
+                        cls::journal::Client* client) {
+    return MockJournaler::get_instance().get_cached_client(client_id, client);
+  }
+
+  void get_tags(uint64_t tag_class, journal::Journaler::Tags *tags,
+                Context *on_finish) {
+    MockJournaler::get_instance().get_tags(tag_class, tags, on_finish);
+  }
+
   void flush_commit_position(Context *on_finish) {
     MockJournaler::get_instance().flush_commit_position(on_finish);
   }
@@ -308,7 +322,36 @@ public:
   void expect_init_journaler(::journal::MockJournaler &mock_journaler, int r) {
     EXPECT_CALL(mock_journaler, init(_))
                   .WillOnce(CompleteContext(r, NULL));
+  }
+
+  void expect_get_journaler_cached_client(::journal::MockJournaler &mock_journaler, int r) {
+
+    journal::ImageClientMeta image_client_meta;
+    image_client_meta.tag_class = 0;
+
+    journal::ClientData client_data;
+    client_data.client_meta = image_client_meta;
+
+    cls::journal::Client client;
+    ::encode(client_data, client.data);
+
+    EXPECT_CALL(mock_journaler, get_cached_client("", _))
+                  .WillOnce(DoAll(SetArgPointee<1>(client),
+                                  Return(r)));
+  }
+
+  void expect_get_journaler_tags(MockImageCtx &mock_image_ctx,
+                                 ::journal::MockJournaler &mock_journaler,
+                                 int r) {
+    journal::TagData tag_data;
+
+    bufferlist tag_data_bl;
+    ::encode(tag_data, tag_data_bl);
 
+    ::journal::Journaler::Tags tags = {{0, 0, {}}, {1, 0, tag_data_bl}};
+    EXPECT_CALL(mock_journaler, get_tags(0, _, _))
+                  .WillOnce(DoAll(SetArgPointee<1>(tags),
+                                  WithArg<2>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue))));
   }
 
   void expect_start_replay(MockJournalImageCtx &mock_image_ctx,
@@ -442,6 +485,8 @@ public:
     InSequence seq;
     expect_construct_journaler(mock_journaler);
     expect_init_journaler(mock_journaler, 0);
+    expect_get_journaler_cached_client(mock_journaler, 0);
+    expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
     expect_start_replay(
       mock_image_ctx, mock_journaler, {
         std::bind(&invoke_replay_complete, _1, 0)
@@ -485,6 +530,8 @@ TEST_F(TestMockJournal, StateTransitions) {
   ::journal::MockJournaler mock_journaler;
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_ready, _1),
@@ -533,6 +580,45 @@ TEST_F(TestMockJournal, InitError) {
   ASSERT_EQ(-EINVAL, when_open(mock_journal));
 }
 
+TEST_F(TestMockJournal, GetCachedClientError) {
+  REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+  MockJournal mock_journal(mock_image_ctx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+
+  ::journal::MockJournaler mock_journaler;
+  expect_construct_journaler(mock_journaler);
+  expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, -ENOENT);
+  ASSERT_EQ(-ENOENT, when_open(mock_journal));
+}
+
+TEST_F(TestMockJournal, GetTagsError) {
+  REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+  MockJournal mock_journal(mock_image_ctx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+
+  ::journal::MockJournaler mock_journaler;
+  expect_construct_journaler(mock_journaler);
+  expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, -EBADMSG);
+  ASSERT_EQ(-EBADMSG, when_open(mock_journal));
+}
+
 TEST_F(TestMockJournal, ReplayCompleteError) {
   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
 
@@ -548,6 +634,8 @@ TEST_F(TestMockJournal, ReplayCompleteError) {
   ::journal::MockJournaler mock_journaler;
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_complete, _1, -EINVAL)
@@ -560,6 +648,8 @@ TEST_F(TestMockJournal, ReplayCompleteError) {
   // replay failure should result in replay-restart
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_complete, _1, 0)
@@ -589,6 +679,8 @@ TEST_F(TestMockJournal, FlushReplayError) {
   ::journal::MockJournaler mock_journaler;
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_ready, _1),
@@ -606,6 +698,8 @@ TEST_F(TestMockJournal, FlushReplayError) {
   // replay flush failure should result in replay-restart
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_complete, _1, 0)
@@ -635,6 +729,8 @@ TEST_F(TestMockJournal, StopError) {
   ::journal::MockJournaler mock_journaler;
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_complete, _1, 0)
@@ -664,6 +760,8 @@ TEST_F(TestMockJournal, ReplayOnDiskPreFlushError) {
   ::journal::MockJournaler mock_journaler;
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
 
   ::journal::ReplayHandler *replay_handler = nullptr;
   expect_start_replay(
@@ -688,6 +786,8 @@ TEST_F(TestMockJournal, ReplayOnDiskPreFlushError) {
   // replay write-to-disk failure should result in replay-restart
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_complete, _1, 0)
@@ -738,6 +838,8 @@ TEST_F(TestMockJournal, ReplayOnDiskPostFlushError) {
   ::journal::MockJournaler mock_journaler;
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_ready, _1),
@@ -759,6 +861,8 @@ TEST_F(TestMockJournal, ReplayOnDiskPostFlushError) {
   // replay write-to-disk failure should result in replay-restart
   expect_construct_journaler(mock_journaler);
   expect_init_journaler(mock_journaler, 0);
+  expect_get_journaler_cached_client(mock_journaler, 0);
+  expect_get_journaler_tags(mock_image_ctx, mock_journaler, 0);
   expect_start_replay(
     mock_image_ctx, mock_journaler, {
       std::bind(&invoke_replay_complete, _1, 0)