From: Jason Dillaman Date: Thu, 23 Jul 2015 17:56:59 +0000 (-0400) Subject: tests: verify proper handling of librbd replay of IO journal events X-Git-Tag: v10.0.1~52^2~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c67a85e23566e2905109716da4bfdd30a030c010;p=ceph.git tests: verify proper handling of librbd replay of IO journal events Signed-off-by: Jason Dillaman --- diff --git a/src/test/Makefile-client.am b/src/test/Makefile-client.am index cc96eaa8e430..4a1c8003ffd6 100644 --- a/src/test/Makefile-client.am +++ b/src/test/Makefile-client.am @@ -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 index 000000000000..c6d634789a42 --- /dev/null +++ b/src/test/librbd/test_JournalReplay.cc @@ -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); +} + diff --git a/src/test/librbd/test_main.cc b/src/test/librbd/test_main.cc index e71a5aff4ba8..e1c0d4e01c7c 100644 --- a/src/test/librbd/test_main.cc +++ b/src/test/librbd/test_main.cc @@ -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