]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
journal: prohibit journal entries larger than the soft object size
authorJason Dillaman <dillaman@redhat.com>
Fri, 6 May 2016 01:30:18 +0000 (21:30 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 10 May 2016 17:29:35 +0000 (13:29 -0400)
This avoids complications like a librbd write event of 128MB trying
to fit within a 24MB journal object.

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

src/journal/Entry.cc
src/journal/Entry.h
src/journal/JournalMetadata.h
src/journal/JournalRecorder.cc
src/journal/Journaler.cc
src/journal/Journaler.h
src/test/journal/test_JournalRecorder.cc
src/test/librbd/test_mock_Journal.cc

index af6c6997b15bec4dee2b96af8919a301c5de4bc3..f88dea86358baf7a693fba1e0e44a7dd1efe7035 100644 (file)
@@ -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<uint8_t>(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) {
index 3d0a0d0e50e81be93b27a39a3c76a3333c01ce8a..7867a19a3bfe65863782b65200c28c7e3fbd7675 100644 (file)
@@ -24,6 +24,8 @@ public:
   {
   }
 
+  static uint32_t get_fixed_size();
+
   inline uint64_t get_tag_tid() const {
     return m_tag_tid;
   }
index d95f1ed7072b36633164aef01a4ffa5874132cb6..c9e6d931bfc760d7c6195c620977bba8f3307ec5 100644 (file)
@@ -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;
   }
index b730b267a5ccd994550fa64d387baec569e8a300..f78f0c82c497c02d2ffbfb24b4fe30bbe9986d7e 100644 (file)
@@ -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));
index 0981db8e18da664f560314be1537d16d268d5387..2a02f60af3c56448d053e98d51a87543851517a5 100644 (file)
@@ -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);
 }
index 055b8bf353c4f16761116cc09612a313759c8d5c..f74f7ab9ab35a455dba7624c4a898bbf36b65dc9 100644 (file)
@@ -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);
index d384e7f7d938dda800a7a823381e578b6f6088b4..149e63b11d41ffc1c6cc8a101f695f7288c7d2c8 100644 (file)
@@ -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 <limits>
@@ -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')));
 
index 9ebea8f3e7079e9b86da48a57cc3f837b1a785e6..70deac04199ccaa36e67ff230948b9db98459c4a 100644 (file)
@@ -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);
   }