From: myoungwon oh Date: Wed, 11 Sep 2024 06:04:30 +0000 (+0000) Subject: crimson/os/seastore: fix data inconsistency during ool writes X-Git-Tag: v20.0.0~865^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=829c857b9e1be3a4133f088f63950e961ecce67e;p=ceph.git crimson/os/seastore: fix data inconsistency during ool writes In RBM, seastore issues ool writes with allocated address. If a transaction conflict occurs at this point, the allocated address is freed, allowing the address to be reused. However, data inconsistency can occur if seastore issues ool writes with freed address before the preceding ool write has not been complete. To fix this issue, this commit frees the allocated address after ool writes is don in the event of the transaction conflict after ool write is issued. Signed-off-by: Myoungwon Oh --- diff --git a/src/crimson/os/seastore/cache.cc b/src/crimson/os/seastore/cache.cc index cf8d3c0891d7f..5dcb7514ee1ab 100644 --- a/src/crimson/os/seastore/cache.cc +++ b/src/crimson/os/seastore/cache.cc @@ -990,8 +990,12 @@ void Cache::mark_transaction_conflicted( } efforts.mutate_delta_bytes += delta_stat.bytes; - for (auto &i: t.pre_alloc_list) { - epm.mark_space_free(i->get_paddr(), i->get_length()); + if (t.get_pending_ool()) { + t.get_pending_ool()->is_conflicted = true; + } else { + for (auto &i: t.pre_alloc_list) { + epm.mark_space_free(i->get_paddr(), i->get_length()); + } } auto& ool_stats = t.get_ool_write_stats(); diff --git a/src/crimson/os/seastore/extent_placement_manager.cc b/src/crimson/os/seastore/extent_placement_manager.cc index 34ac199eed8dd..0458fbfed7480 100644 --- a/src/crimson/os/seastore/extent_placement_manager.cc +++ b/src/crimson/os/seastore/extent_placement_manager.cc @@ -987,7 +987,19 @@ RandomBlockOolWriter::alloc_write_ool_extents( return alloc_write_iertr::now(); } return seastar::with_gate(write_guard, [this, &t, &extents] { - return do_write(t, extents); + seastar::lw_shared_ptr ptr = + seastar::make_lw_shared(); + ptr->pending_extents = t.get_pre_alloc_list(); + assert(!t.is_conflicted()); + t.set_pending_ool(ptr); + return do_write(t, extents + ).finally([this, ptr=ptr] { + if (ptr->is_conflicted) { + for (auto &e : ptr->pending_extents) { + rb_cleaner->mark_space_free(e->get_paddr(), e->get_length()); + } + } + }); }); } diff --git a/src/crimson/os/seastore/transaction.h b/src/crimson/os/seastore/transaction.h index 52515937a9e59..5d8ad00ba228b 100644 --- a/src/crimson/os/seastore/transaction.h +++ b/src/crimson/os/seastore/transaction.h @@ -80,6 +80,11 @@ struct rewrite_stats_t { } }; +struct rbm_pending_ool_t { + bool is_conflicted = false; + std::list pending_extents; +}; + /** * Transaction * @@ -554,6 +559,18 @@ public: return static_cast(*view); } + void set_pending_ool(seastar::lw_shared_ptr ptr) { + pending_ool = ptr; + } + + seastar::lw_shared_ptr get_pending_ool() { + return pending_ool; + } + + const auto& get_pre_alloc_list() { + return pre_alloc_list; + } + private: friend class Cache; friend Ref make_test_transaction(); @@ -650,6 +667,8 @@ private: const src_t src; transaction_id_t trans_id = TRANS_ID_NULL; + + seastar::lw_shared_ptr pending_ool; }; using TransactionRef = Transaction::Ref;