From 8240be8f324b244061b17bb2c1676b192a12dca2 Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Tue, 13 Sep 2022 15:50:35 +0800 Subject: [PATCH] crimson/os/seastore/cached_extent: record transaction id in pending CachedExtents Signed-off-by: Xuehan Xu --- src/crimson/os/seastore/cache.cc | 9 +++- src/crimson/os/seastore/cache.h | 14 +++-- src/crimson/os/seastore/cached_extent.h | 54 +++++++++++++++++-- src/crimson/os/seastore/logging.h | 6 ++- src/crimson/os/seastore/seastore_types.h | 3 ++ src/crimson/os/seastore/transaction.h | 16 ++++-- src/crimson/os/seastore/transaction_manager.h | 3 +- 7 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/crimson/os/seastore/cache.cc b/src/crimson/os/seastore/cache.cc index 86c3730fd8b4d..65c0f8ef5fe40 100644 --- a/src/crimson/os/seastore/cache.cc +++ b/src/crimson/os/seastore/cache.cc @@ -98,7 +98,8 @@ Cache::retire_extent_ret Cache::retire_extent_addr( ext->init(CachedExtent::extent_state_t::CLEAN, addr, PLACEMENT_HINT_NULL, - NULL_GENERATION); + NULL_GENERATION, + TRANS_ID_NULL); DEBUGT("retire {}~{} as placeholder, add extent -- {}", t, addr, length, *ext); const auto t_src = t.get_src(); @@ -1012,6 +1013,7 @@ CachedExtentRef Cache::duplicate_for_write( } auto ret = i->duplicate_for_write(); + ret->pending_for_transaction = t.get_trans_id(); ret->prior_instance = i; // duplicate_for_write won't occur after ool write finished assert(!i->prior_poffset); @@ -1448,6 +1450,7 @@ void Cache::complete_commit( i->set_paddr(final_block_start.add_relative(i->get_paddr())); } i->last_committed_crc = i->get_crc32c(); + i->pending_for_transaction = TRANS_ID_NULL; i->on_initial_write(); i->state = CachedExtent::extent_state_t::CLEAN; @@ -1489,6 +1492,7 @@ void Cache::complete_commit( assert(i->is_exist_mutation_pending() || i->prior_instance); i->on_delta_write(final_block_start); + i->pending_for_transaction = TRANS_ID_NULL; i->prior_instance = CachedExtentRef(); i->state = CachedExtent::extent_state_t::DIRTY; assert(i->version > 0); @@ -1593,7 +1597,8 @@ void Cache::init() root->init(CachedExtent::extent_state_t::CLEAN, P_ADDR_ROOT, PLACEMENT_HINT_NULL, - NULL_GENERATION); + NULL_GENERATION, + TRANS_ID_NULL); INFO("init root -- {}", *root); extents.insert(*root); } diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h index 253836276675d..3b73594157f8b 100644 --- a/src/crimson/os/seastore/cache.h +++ b/src/crimson/os/seastore/cache.h @@ -205,7 +205,8 @@ public: last_commit, [this](Transaction& t) { return on_transaction_destruct(t); - } + }, + ++next_id ); SUBDEBUGT(seastore_t, "created name={}, source={}, is_weak={}", *ret, name, src, is_weak); @@ -284,7 +285,8 @@ public: ret->init(CachedExtent::extent_state_t::CLEAN_PENDING, offset, PLACEMENT_HINT_NULL, - NULL_GENERATION); + NULL_GENERATION, + TRANS_ID_NULL); SUBDEBUG(seastore_cache, "{} {}~{} is absent, add extent and reading ... -- {}", T::TYPE, offset, length, *ret); @@ -303,7 +305,8 @@ public: ret->init(CachedExtent::extent_state_t::CLEAN_PENDING, offset, PLACEMENT_HINT_NULL, - NULL_GENERATION); + NULL_GENERATION, + TRANS_ID_NULL); SUBDEBUG(seastore_cache, "{} {}~{} is absent(placeholder), reading ... -- {}", T::TYPE, offset, length, *ret); @@ -648,7 +651,8 @@ public: ret->init(CachedExtent::extent_state_t::INITIAL_WRITE_PENDING, result.paddr, hint, - result.gen); + result.gen, + t.get_trans_id()); t.add_fresh_extent(ret); SUBDEBUGT(seastore_cache, "allocated {} {}B extent at {}, hint={}, gen={} -- {}", @@ -990,6 +994,8 @@ private: // FIXME: This is specific to the segmented implementation std::vector segment_providers_by_device_id; + transaction_id_t next_id = 0; + /** * dirty * diff --git a/src/crimson/os/seastore/cached_extent.h b/src/crimson/os/seastore/cached_extent.h index 5ccafc5fa1961..7f76c26145302 100644 --- a/src/crimson/os/seastore/cached_extent.h +++ b/src/crimson/os/seastore/cached_extent.h @@ -76,9 +76,55 @@ using read_set_t = std::set< read_set_item_t, typename read_set_item_t::cmp_t>; +struct trans_spec_view_t { + // if the extent is pending, contains the id of the owning transaction; + // TRANS_ID_NULL otherwise + transaction_id_t pending_for_transaction = TRANS_ID_NULL; + + struct cmp_t { + bool operator()( + const trans_spec_view_t &lhs, + const trans_spec_view_t &rhs) const + { + return lhs.pending_for_transaction < rhs.pending_for_transaction; + } + bool operator()( + const transaction_id_t &lhs, + const trans_spec_view_t &rhs) const + { + return lhs < rhs.pending_for_transaction; + } + bool operator()( + const trans_spec_view_t &lhs, + const transaction_id_t &rhs) const + { + return lhs.pending_for_transaction < rhs; + } + }; + + using trans_view_hook_t = + boost::intrusive::set_member_hook< + boost::intrusive::link_mode< + boost::intrusive::auto_unlink>>; + trans_view_hook_t trans_view_hook; + + using trans_view_member_options = + boost::intrusive::member_hook< + trans_spec_view_t, + trans_view_hook_t, + &trans_spec_view_t::trans_view_hook>; + using trans_view_set_t = boost::intrusive::set< + trans_spec_view_t, + trans_view_member_options, + boost::intrusive::constant_time_size, + boost::intrusive::compare>; +}; + class ExtentIndex; -class CachedExtent : public boost::intrusive_ref_counter< - CachedExtent, boost::thread_unsafe_counter> { +class CachedExtent + : public boost::intrusive_ref_counter< + CachedExtent, boost::thread_unsafe_counter>, + public trans_spec_view_t { enum class extent_state_t : uint8_t { INITIAL_WRITE_PENDING, // In Transaction::write_set and fresh_block_list MUTATION_PENDING, // In Transaction::write_set and mutated_block_list @@ -117,12 +163,14 @@ public: void init(extent_state_t _state, paddr_t paddr, placement_hint_t hint, - rewrite_gen_t gen) { + rewrite_gen_t gen, + transaction_id_t trans_id) { assert(gen == NULL_GENERATION || is_rewrite_generation(gen)); state = _state; set_paddr(paddr); user_hint = hint; rewrite_generation = gen; + pending_for_transaction = trans_id; } void set_modify_time(sea_time_point t) { diff --git a/src/crimson/os/seastore/logging.h b/src/crimson/os/seastore/logging.h index ec9b7df5ed181..3f12ee72cfed7 100644 --- a/src/crimson/os/seastore/logging.h +++ b/src/crimson/os/seastore/logging.h @@ -8,9 +8,11 @@ #include "crimson/common/log.h" #define LOGT(level_, MSG, t, ...) \ - LOCAL_LOGGER.log(level_, "{} {}: " MSG, (void*)&t, FNAME , ##__VA_ARGS__) + LOCAL_LOGGER.log(level_, "{} trans.{} {}: " MSG, (void*)&t, \ + (t).get_trans_id(), FNAME , ##__VA_ARGS__) #define SUBLOGT(subname_, level_, MSG, t, ...) \ - LOGGER(subname_).log(level_, "{} {}: " MSG, (void*)&t, FNAME , ##__VA_ARGS__) + LOGGER(subname_).log(level_, "{} trans.{} {}: " MSG, (void*)&t, \ + (t).get_trans_id(), FNAME , ##__VA_ARGS__) #define TRACET(...) LOGT(seastar::log_level::trace, __VA_ARGS__) #define SUBTRACET(subname_, ...) SUBLOGT(subname_, seastar::log_level::trace, __VA_ARGS__) diff --git a/src/crimson/os/seastore/seastore_types.h b/src/crimson/os/seastore/seastore_types.h index 99d17472eb3c9..a1efc729b96fa 100644 --- a/src/crimson/os/seastore/seastore_types.h +++ b/src/crimson/os/seastore/seastore_types.h @@ -24,6 +24,9 @@ namespace crimson::os::seastore { /* using a special xattr key "omap_header" to store omap header */ const std::string OMAP_HEADER_XATTR_KEY = "omap_header"; +using transaction_id_t = uint64_t; +constexpr transaction_id_t TRANS_ID_NULL = 0; + /* * Note: NULL value is usually the default and max value. */ diff --git a/src/crimson/os/seastore/transaction.h b/src/crimson/os/seastore/transaction.h index 8899e105cefc5..e7eef11427a81 100644 --- a/src/crimson/os/seastore/transaction.h +++ b/src/crimson/os/seastore/transaction.h @@ -337,11 +337,13 @@ public: bool weak, src_t src, journal_seq_t initiated_after, - on_destruct_func_t&& f + on_destruct_func_t&& f, + transaction_id_t trans_id ) : weak(weak), handle(std::move(handle)), on_destruct(std::move(f)), - src(src) + src(src), + trans_id(trans_id) {} void invalidate_clear_write_set() { @@ -468,6 +470,10 @@ public: return existing_block_stats; } + transaction_id_t get_trans_id() const { + return trans_id; + } + private: friend class Cache; friend Ref make_test_transaction(); @@ -553,17 +559,21 @@ private: on_destruct_func_t on_destruct; const src_t src; + + transaction_id_t trans_id = TRANS_ID_NULL; }; using TransactionRef = Transaction::Ref; /// Should only be used with dummy staged-fltree node extent manager inline TransactionRef make_test_transaction() { + static transaction_id_t next_id = 0; return std::make_unique( get_dummy_ordering_handle(), false, Transaction::src_t::MUTATE, JOURNAL_SEQ_NULL, - [](Transaction&) {} + [](Transaction&) {}, + ++next_id ); } diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 47dcfc7129446..6cb18c560fab4 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -371,7 +371,8 @@ public: ext->init(CachedExtent::extent_state_t::EXIST_CLEAN, existing_paddr, PLACEMENT_HINT_NULL, - NULL_GENERATION); + NULL_GENERATION, + t.get_trans_id()); t.add_fresh_extent(ext); -- 2.39.5