]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore: set ExtentPlacementManager::allocated_to before rolling segments 43492/head
authorXuehan Xu <xxhdx1985126@gmail.com>
Tue, 12 Oct 2021 01:55:21 +0000 (09:55 +0800)
committerXuehan Xu <xxhdx1985126@gmail.com>
Tue, 12 Oct 2021 04:43:22 +0000 (12:43 +0800)
There are circumstances in which a transaction that are supposed to roll the current segment
is invalidated after it finished writing and before it rolls the segment. If we don't set
ExtentPlacementManager::allocated_to in this situation, another transaction can try to write
to the old "allocated_to" position, which would cause an invalid write error

Fixes: https://tracker.ceph.com/issues/52894
Signed-off-by: Xuehan Xu <xxhdx1985126@gmail.com>
src/crimson/os/seastore/extent_placement_manager.cc
src/crimson/os/seastore/extent_placement_manager.h

index 48a89ea273ae93ff6f5858c4582d03f99938997d..f3670f3c2eab2bbdae18de5ba2561a91f99c1d34 100644 (file)
@@ -69,9 +69,10 @@ SegmentedAllocator::Writer::finish_write(
 SegmentedAllocator::Writer::write_iertr::future<>
 SegmentedAllocator::Writer::_write(
   Transaction& t,
-  ool_record_t& record,
-  const record_size_t& record_size)
+  ool_record_t& record)
 {
+  record_size_t record_size = record.get_encoded_record_length();
+  allocated_to += record_size.mdlength + record_size.dlength;
   bufferlist bl = record.encode(
       record_size,
       current_segment->segment->get_segment_id(),
@@ -165,9 +166,8 @@ SegmentedAllocator::Writer::write(
                   num_extents,
                   current_segment->segment->get_segment_id(),
                   allocated_to);
-                auto rsize = record.get_encoded_record_length();
                 return (num_extents ?
-                        _write(t, record, rsize) :
+                        _write(t, record) :
                         write_iertr::now()
                 ).si_then([this]() mutable {
                   return roll_segment(false);
@@ -179,7 +179,6 @@ SegmentedAllocator::Writer::write(
               add_extent_to_write(record, extent);
               it = extents.erase(it);
             }
-            record_size_t rsize = record.get_encoded_record_length();
 
             DEBUGT(
               "writing {} extents to segment {} at {}",
@@ -187,8 +186,7 @@ SegmentedAllocator::Writer::write(
               record.get_num_extents(),
               current_segment->segment->get_segment_id(),
               allocated_to);
-            allocated_to += rsize.mdlength + rsize.dlength;
-            return _write(t, record, rsize);
+            return _write(t, record);
           }
         ).si_then([]()
           -> write_iertr::future<seastar::stop_iteration> {
index d9a15ea5577a8e5e0c997a0ffbf0b009b44e7186..690d817c2ed31881786c5a5a61d026b7eec62790 100644 (file)
@@ -217,8 +217,7 @@ class SegmentedAllocator : public ExtentAllocator {
 
     write_iertr::future<> _write(
       Transaction& t,
-      ool_record_t& record,
-      const record_size_t& record_size);
+      ool_record_t& record);
 
     using roll_segment_ertr = crimson::errorator<
       crimson::ct_error::input_output_error>;