]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd/cache/pwl/ssd/WriteLog: don't crash on split log entries
authorIlya Dryomov <idryomov@gmail.com>
Thu, 29 Apr 2021 13:03:46 +0000 (15:03 +0200)
committerDeepika Upadhyay <dupadhya@redhat.com>
Tue, 2 Nov 2021 11:50:08 +0000 (17:20 +0530)
write_log_entries() will split a log entry at the end of the log, the
remainder is written to the beginning at DATA_RING_BUFFER_OFFSET.  On
the read side aio_read_data_block() doesn't handle this case and just
crashes.  Unless the workload in use is <= 4K, the image is rendered
unusable sooner or later.

trivial fix: formating changes
Fixes: https://tracker.ceph.com/issues/50589
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
(cherry picked from commit 155ee28d98b832e5414aa594094c86cb6bfee45e)

src/librbd/cache/pwl/ssd/WriteLog.cc
src/librbd/cache/pwl/ssd/WriteLog.h

index edca766cd1bfd17726d5d3ef3d4fc7d8e0e80c55..bd19701f0fa59ee72d5c9e1001208aa7c6600eb9 100644 (file)
@@ -953,20 +953,8 @@ int WriteLog<I>::update_pool_root_sync(
 }
 
 template <typename I>
-void WriteLog<I>::pre_io_check(WriteLogCacheEntry *log_entry,
-                               uint64_t &length) {
-  assert(log_entry->is_write() || log_entry->is_writesame());
-  ceph_assert(log_entry->write_data_pos <= pool_size);
-
-  length = log_entry->is_write() ? log_entry->write_bytes :
-                                   log_entry->ws_datalen;
-  length = round_up_to(length, MIN_WRITE_ALLOC_SSD_SIZE);
-  ceph_assert(length != 0 && log_entry->write_data_pos + length <= pool_size);
-}
-
-template <typename I>
-void WriteLog<I>::aio_read_data_block(
-  WriteLogCacheEntry *log_entry, bufferlist *bl, Context *ctx) {
+void WriteLog<I>::aio_read_data_block(WriteLogCacheEntry *log_entry,
+                                      bufferlist *bl, Context *ctx) {
   std::vector<WriteLogCacheEntry*> log_entries {log_entry};
   std::vector<bufferlist *> bls {bl};
   aio_read_data_block(log_entries, bls, ctx);
@@ -997,12 +985,32 @@ void WriteLog<I>::aio_read_data_block(
   for (unsigned int i = 0; i < log_entries.size(); i++) {
     auto log_entry = log_entries[i];
 
-    uint64_t length;
-    pre_io_check(log_entry, length);
-    ldout(cct, 20) << "Read at " << log_entry->write_data_pos
-                   << ", length " << length << dendl;
-
-    bdev->aio_read(log_entry->write_data_pos, length, bls[i], &aio->ioc);
+    ceph_assert(log_entry->is_write() || log_entry->is_writesame());
+    uint64_t len = log_entry->is_write() ? log_entry->write_bytes :
+                                           log_entry->ws_datalen;
+    uint64_t align_len = round_up_to(len, MIN_WRITE_ALLOC_SSD_SIZE);
+
+    ldout(cct, 20) << "entry i=" << i << " " << log_entry->write_data_pos
+                   << "~" << len << dendl;
+    ceph_assert(log_entry->write_data_pos <= pool_root.pool_size);
+    ceph_assert(align_len != 0);
+    if (log_entry->write_data_pos + align_len > pool_root.pool_size) {
+      // spans boundary, need to split
+      uint64_t len1 = pool_root.pool_size - log_entry->write_data_pos;
+      uint64_t len2 = align_len - len1;
+
+      ldout(cct, 20) << "read " << log_entry->write_data_pos << "~"
+                     << align_len << " spans boundary, split into "
+                     << log_entry->write_data_pos << "~" << len1
+                     << " and " << DATA_RING_BUFFER_OFFSET << "~"
+                     << len2 << dendl;
+      bdev->aio_read(log_entry->write_data_pos, len1, bls[i], &aio->ioc);
+      bdev->aio_read(DATA_RING_BUFFER_OFFSET, len2, bls[i], &aio->ioc);
+    } else {
+      ldout(cct, 20) << "read " << log_entry->write_data_pos << "~"
+                     << align_len << dendl;
+      bdev->aio_read(log_entry->write_data_pos, align_len, bls[i], &aio->ioc);
+    }
   }
   bdev->aio_submit(&aio->ioc);
 }
index 2202aa609c6289208511da36923783c71c208fb5..fa07bca2666b3d0a1bc2878817b742b90eacd526 100644 (file)
@@ -134,7 +134,6 @@ private:
   int update_pool_root_sync(std::shared_ptr<pwl::WriteLogPoolRoot> root);
   void update_pool_root(std::shared_ptr<WriteLogPoolRoot> root,
                                           AioTransContext *aio);
-  void pre_io_check(WriteLogCacheEntry *log_entry, uint64_t &length);
   void aio_read_data_block(WriteLogCacheEntry *log_entry, bufferlist *bl,
                            Context *ctx);
   void aio_read_data_block(std::vector<WriteLogCacheEntry*> &log_entries,