From: Jason Dillaman Date: Fri, 6 May 2016 01:30:18 +0000 (-0400) Subject: journal: prohibit journal entries larger than the soft object size X-Git-Tag: v10.2.1~18^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f1a2e6aeaa22233f13878d004cbe905a42bdc744;p=ceph.git journal: prohibit journal entries larger than the soft object size This avoids complications like a librbd write event of 128MB trying to fit within a 24MB journal object. Signed-off-by: Jason Dillaman (cherry picked from commit d5f307dec10429a1ffc042919b71ac25466a1b72) --- diff --git a/src/journal/Entry.cc b/src/journal/Entry.cc index af6c6997b15b..f88dea86358b 100644 --- a/src/journal/Entry.cc +++ b/src/journal/Entry.cc @@ -16,22 +16,27 @@ namespace journal { namespace { const uint32_t HEADER_FIXED_SIZE = 25; /// preamble, version, entry tid, tag id +const uint32_t REMAINDER_FIXED_SIZE = 8; /// data size, crc } // anonymous namespace +uint32_t Entry::get_fixed_size() { + return HEADER_FIXED_SIZE + REMAINDER_FIXED_SIZE; +} + void Entry::encode(bufferlist &bl) const { bufferlist data_bl; ::encode(preamble, data_bl); ::encode(static_cast(1), data_bl); ::encode(m_entry_tid, data_bl); ::encode(m_tag_tid, data_bl); - assert(HEADER_FIXED_SIZE == data_bl.length()); - ::encode(m_data, data_bl); uint32_t crc = data_bl.crc32c(0); + uint32_t bl_offset = bl.length(); bl.claim_append(data_bl); ::encode(crc, bl); + assert(get_fixed_size() + m_data.length() + bl_offset == bl.length()); } void Entry::decode(bufferlist::iterator &iter) { diff --git a/src/journal/Entry.h b/src/journal/Entry.h index 3d0a0d0e50e8..7867a19a3bfe 100644 --- a/src/journal/Entry.h +++ b/src/journal/Entry.h @@ -24,6 +24,8 @@ public: { } + static uint32_t get_fixed_size(); + inline uint64_t get_tag_tid() const { return m_tag_tid; } diff --git a/src/journal/JournalMetadata.h b/src/journal/JournalMetadata.h index d95f1ed7072b..c9e6d931bfc7 100644 --- a/src/journal/JournalMetadata.h +++ b/src/journal/JournalMetadata.h @@ -83,6 +83,9 @@ public: inline uint8_t get_order() const { return m_order; } + inline uint64_t get_object_size() const { + return 1 << m_order; + } inline uint8_t get_splay_width() const { return m_splay_width; } diff --git a/src/journal/JournalRecorder.cc b/src/journal/JournalRecorder.cc index b730b267a5cc..f78f0c82c497 100644 --- a/src/journal/JournalRecorder.cc +++ b/src/journal/JournalRecorder.cc @@ -71,6 +71,7 @@ JournalRecorder::~JournalRecorder() { Future JournalRecorder::append(uint64_t tag_tid, const bufferlist &payload_bl) { + Mutex::Locker locker(m_lock); uint64_t entry_tid = m_journal_metadata->allocate_entry_tid(tag_tid); @@ -87,6 +88,7 @@ Future JournalRecorder::append(uint64_t tag_tid, bufferlist entry_bl; ::encode(Entry(future->get_tag_tid(), future->get_entry_tid(), payload_bl), entry_bl); + assert(entry_bl.length() <= m_journal_metadata->get_object_size()); AppendBuffers append_buffers; append_buffers.push_back(std::make_pair(future, entry_bl)); diff --git a/src/journal/Journaler.cc b/src/journal/Journaler.cc index 0981db8e18da..2a02f60af3c5 100644 --- a/src/journal/Journaler.cc +++ b/src/journal/Journaler.cc @@ -349,6 +349,10 @@ void Journaler::stop_append(Context *on_safe) { m_recorder = NULL; } +uint64_t Journaler::get_max_append_size() const { + return m_metadata->get_object_size() - Entry::get_fixed_size(); +} + Future Journaler::append(uint64_t tag_tid, const bufferlist &payload_bl) { return m_recorder->append(tag_tid, payload_bl); } diff --git a/src/journal/Journaler.h b/src/journal/Journaler.h index 055b8bf353c4..f74f7ab9ab35 100644 --- a/src/journal/Journaler.h +++ b/src/journal/Journaler.h @@ -96,6 +96,7 @@ public: bool try_pop_front(ReplayEntry *replay_entry, uint64_t *tag_tid = nullptr); void stop_replay(); + uint64_t get_max_append_size() const; void start_append(int flush_interval, uint64_t flush_bytes, double flush_age); Future append(uint64_t tag_tid, const bufferlist &bl); void flush_append(Context *on_safe); diff --git a/src/test/journal/test_JournalRecorder.cc b/src/test/journal/test_JournalRecorder.cc index d384e7f7d938..149e63b11d41 100644 --- a/src/test/journal/test_JournalRecorder.cc +++ b/src/test/journal/test_JournalRecorder.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab #include "journal/JournalRecorder.h" +#include "journal/Entry.h" #include "journal/JournalMetadata.h" #include "test/journal/RadosTestFixture.h" #include @@ -58,7 +59,8 @@ TEST_F(TestJournalRecorder, AppendKnownOverflow) { journal::JournalRecorder *recorder = create_recorder(oid, metadata); - recorder->append(123, create_payload(std::string(1 << 12, '1'))); + recorder->append(123, create_payload(std::string(metadata->get_object_size() - + journal::Entry::get_fixed_size(), '1'))); journal::Future future2 = recorder->append(123, create_payload(std::string(1, '2'))); C_SaferCond cond; @@ -80,8 +82,9 @@ TEST_F(TestJournalRecorder, AppendDelayedOverflow) { journal::JournalRecorder *recorder1 = create_recorder(oid, metadata); journal::JournalRecorder *recorder2 = create_recorder(oid, metadata); - recorder1->append(123, create_payload(std::string(1, '1'))); - recorder2->append(234, create_payload(std::string(1 << 12, '2'))); + recorder1->append(234, create_payload(std::string(1, '1'))); + recorder2->append(123, create_payload(std::string(metadata->get_object_size() - + journal::Entry::get_fixed_size(), '2'))); journal::Future future = recorder2->append(123, create_payload(std::string(1, '3'))); diff --git a/src/test/librbd/test_mock_Journal.cc b/src/test/librbd/test_mock_Journal.cc index 9ebea8f3e707..70deac04199c 100644 --- a/src/test/librbd/test_mock_Journal.cc +++ b/src/test/librbd/test_mock_Journal.cc @@ -100,6 +100,7 @@ struct MockJournaler { MOCK_METHOD3(start_append, void(int flush_interval, uint64_t flush_bytes, double flush_age)); + MOCK_CONST_METHOD0(get_max_append_size, uint64_t()); MOCK_METHOD2(append, MockFutureProxy(uint64_t tag_id, const bufferlist &bl)); MOCK_METHOD1(flush, void(Context *on_safe)); @@ -185,6 +186,9 @@ struct MockJournalerProxy { flush_age); } + uint64_t get_max_append_size() const { + return MockJournaler::get_instance().get_max_append_size(); + } MockFutureProxy append(uint64_t tag_id, const bufferlist &bl) { return MockJournaler::get_instance().append(tag_id, bl); }