]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tests: verify proper handling of librbd replay of IO journal events
authorJason Dillaman <dillaman@redhat.com>
Thu, 23 Jul 2015 17:56:59 +0000 (13:56 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 13 Nov 2015 04:27:07 +0000 (23:27 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/Makefile-client.am
src/test/librbd/test_JournalReplay.cc [new file with mode: 0644]
src/test/librbd/test_main.cc

index cc96eaa8e430a3d491ed5640610a8dd58778efec..4a1c8003ffd61aa0b832e4f364f409b07172cff6 100644 (file)
@@ -344,6 +344,7 @@ librbd_test_la_SOURCES = \
        test/librbd/test_librbd.cc \
        test/librbd/test_ImageWatcher.cc \
        test/librbd/test_internal.cc \
+       test/librbd/test_JournalReplay.cc \
        test/librbd/test_ObjectMap.cc
 librbd_test_la_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 noinst_LTLIBRARIES += librbd_test.la
diff --git a/src/test/librbd/test_JournalReplay.cc b/src/test/librbd/test_JournalReplay.cc
new file mode 100644 (file)
index 0000000..c6d6347
--- /dev/null
@@ -0,0 +1,209 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/librbd/test_fixture.h"
+#include "test/librbd/test_support.h"
+#include "librbd/AioCompletion.h"
+#include "librbd/AioImageRequest.h"
+#include "librbd/AioImageRequestWQ.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ImageWatcher.h"
+#include "librbd/Journal.h"
+#include "librbd/JournalTypes.h"
+
+void register_test_journal_replay() {
+}
+
+class TestJournalReplay : public TestFixture {
+public:
+
+  struct Listener : public librbd::ImageWatcher::Listener{
+    Mutex lock;
+    Cond cond;
+
+    Listener() : lock("TestJournalReplay::Listener::lock") {
+    }
+    virtual bool handle_requested_lock() {
+      return true;
+    }
+    virtual void handle_releasing_lock() {
+    }
+    virtual void handle_lock_updated(
+        librbd::ImageWatcher::LockUpdateState state) {
+      Mutex::Locker locker(lock);
+      cond.Signal();
+    }
+  };
+
+  void wait_for_lock_owner(librbd::ImageCtx *ictx) {
+    Listener listener;
+    ictx->image_watcher->register_listener(&listener);
+    {
+      Mutex::Locker listener_locker(listener.lock);
+      RWLock::RLocker owner_locker(ictx->owner_lock);
+      while (!ictx->image_watcher->is_lock_owner()) {
+        ictx->owner_lock.put_read();
+        listener.cond.Wait(listener.lock);
+        ictx->owner_lock.get_read();
+      }
+    }
+    ictx->image_watcher->unregister_listener(&listener);
+  }
+};
+
+TEST_F(TestJournalReplay, AioDiscardEvent) {
+  REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+  // write to the image w/o using the journal
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ictx->features &= ~RBD_FEATURE_JOURNALING;
+  ASSERT_EQ(0, ictx->close_journal(true));
+
+  std::string payload(4096, '1');
+  librbd::AioCompletion *aio_comp = new librbd::AioCompletion();
+  ictx->aio_work_queue->aio_write(aio_comp, 0, payload.size(), payload.c_str(),
+                                  0);
+  ASSERT_EQ(0, aio_comp->wait_for_complete());
+  aio_comp->release();
+
+  aio_comp = new librbd::AioCompletion();
+  ictx->aio_work_queue->aio_flush(aio_comp);
+  ASSERT_EQ(0, aio_comp->wait_for_complete());
+  aio_comp->release();
+
+  std::string read_payload(4096, '\0');
+  aio_comp = new librbd::AioCompletion();
+  ictx->aio_work_queue->aio_read(aio_comp, 0, read_payload.size(),
+                                 &read_payload[0], NULL, 0);
+  ASSERT_EQ(0, aio_comp->wait_for_complete());
+  aio_comp->release();
+  ASSERT_EQ(payload, read_payload);
+  close_image(ictx);
+
+  // inject a discard operation into the journal
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  {
+    RWLock::WLocker owner_locker(ictx->owner_lock);
+    ictx->image_watcher->request_lock();
+  }
+  wait_for_lock_owner(ictx);
+
+  ictx->journal->open();
+  ASSERT_TRUE(ictx->journal->wait_for_journal_ready());
+
+  librbd::journal::EventEntry event_entry(
+    librbd::journal::AioDiscardEvent(0, payload.size()));
+  librbd::Journal::AioObjectRequests requests;
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ictx->journal->append_event(NULL, event_entry, requests, 0, 0, true);
+  }
+  ASSERT_EQ(0, ictx->journal->close());
+
+  // re-open the journal so that it replays the new entry
+  ictx->journal->open();
+  ASSERT_TRUE(ictx->journal->wait_for_journal_ready());
+
+  aio_comp = new librbd::AioCompletion();
+  ictx->aio_work_queue->aio_read(aio_comp, 0, read_payload.size(),
+                                 &read_payload[0], NULL, 0);
+  ASSERT_EQ(0, aio_comp->wait_for_complete());
+  aio_comp->release();
+  ASSERT_EQ(std::string(read_payload.size(), '\0'), read_payload);
+}
+
+TEST_F(TestJournalReplay, AioWriteEvent) {
+  REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+  // inject a write operation into the journal
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  {
+    RWLock::WLocker owner_locker(ictx->owner_lock);
+    ictx->image_watcher->request_lock();
+  }
+  wait_for_lock_owner(ictx);
+
+  ictx->journal->open();
+  ASSERT_TRUE(ictx->journal->wait_for_journal_ready());
+
+  std::string payload(4096, '1');
+  bufferlist payload_bl;
+  payload_bl.append(payload);
+  librbd::journal::EventEntry event_entry(
+    librbd::journal::AioWriteEvent(0, payload.size(), payload_bl));
+  librbd::Journal::AioObjectRequests requests;
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ictx->journal->append_event(NULL, event_entry, requests, 0, 0, true);
+  }
+  ASSERT_EQ(0, ictx->journal->close());
+
+  // re-open the journal so that it replays the new entry
+  ictx->journal->open();
+  ASSERT_TRUE(ictx->journal->wait_for_journal_ready());
+
+  std::string read_payload(4096, '\0');
+  librbd::AioCompletion *aio_comp = new librbd::AioCompletion();
+  ictx->aio_work_queue->aio_read(aio_comp, 0, read_payload.size(),
+                                 &read_payload[0], NULL, 0);
+  ASSERT_EQ(0, aio_comp->wait_for_complete());
+  aio_comp->release();
+  ASSERT_EQ(payload, read_payload);
+}
+
+TEST_F(TestJournalReplay, AioFlushEvent) {
+  REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+  // inject a flush operation into the journal
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  {
+    RWLock::WLocker owner_locker(ictx->owner_lock);
+    ictx->image_watcher->request_lock();
+  }
+  wait_for_lock_owner(ictx);
+
+  ictx->journal->open();
+  ASSERT_TRUE(ictx->journal->wait_for_journal_ready());
+
+  librbd::journal::AioFlushEvent aio_flush_event;
+  librbd::journal::EventEntry event_entry(aio_flush_event);
+  librbd::Journal::AioObjectRequests requests;
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    ictx->journal->append_event(NULL, event_entry, requests, 0, 0, true);
+  }
+  ASSERT_EQ(0, ictx->journal->close());
+
+  // start an AIO write op
+  librbd::Journal *journal = ictx->journal;
+  ictx->journal = NULL;
+
+  std::string payload(m_image_size, '1');
+  librbd::AioCompletion *aio_comp = new librbd::AioCompletion();
+  {
+    RWLock::RLocker owner_lock(ictx->owner_lock);
+    librbd::AioImageRequest::aio_write(ictx, aio_comp, 0, payload.size(),
+                                       payload.c_str(), 0);
+  }
+  ictx->journal = journal;
+
+  // re-open the journal so that it replays the new entry
+  ictx->journal->open();
+  ASSERT_TRUE(ictx->journal->wait_for_journal_ready());
+
+  ASSERT_TRUE(aio_comp->is_complete());
+  ASSERT_EQ(0, aio_comp->wait_for_complete());
+  aio_comp->release();
+
+  std::string read_payload(m_image_size, '\0');
+  aio_comp = new librbd::AioCompletion();
+  ictx->aio_work_queue->aio_read(aio_comp, 0, read_payload.size(),
+                                 &read_payload[0], NULL, 0);
+  ASSERT_EQ(0, aio_comp->wait_for_complete());
+  aio_comp->release();
+  ASSERT_EQ(payload, read_payload);
+}
+
index e71a5aff4ba83dbb32eea58c1f5121977b598b82..e1c0d4e01c7c0df26bb27b29d4e65e9dfd3d0f40 100644 (file)
@@ -12,6 +12,7 @@ extern void register_test_librbd();
 #ifdef TEST_LIBRBD_INTERNALS
 extern void register_test_image_watcher();
 extern void register_test_internal();
+extern void register_test_journal_replay();
 extern void register_test_object_map();
 #endif // TEST_LIBRBD_INTERNALS
 
@@ -21,6 +22,7 @@ int main(int argc, char **argv)
 #ifdef TEST_LIBRBD_INTERNALS
   register_test_image_watcher();
   register_test_internal();
+  register_test_journal_replay();
   register_test_object_map();
 #endif // TEST_LIBRBD_INTERNALS