From: Yingxin Cheng Date: Mon, 8 Aug 2022 01:49:35 +0000 (+0800) Subject: crimson/os/seastore: introduce JournalTrimmer X-Git-Tag: v18.0.0~287^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F47489%2Fhead;p=ceph.git crimson/os/seastore: introduce JournalTrimmer Signed-off-by: Myoungwon Oh Signed-off-by: Yingxin Cheng --- diff --git a/src/crimson/os/seastore/async_cleaner.h b/src/crimson/os/seastore/async_cleaner.h index 963efe3a8055..528e569c1b25 100644 --- a/src/crimson/os/seastore/async_cleaner.h +++ b/src/crimson/os/seastore/async_cleaner.h @@ -267,9 +267,9 @@ private: std::ostream &operator<<(std::ostream &, const segments_info_t &); /** - * Callback interface for managing available segments + * Callback interface for journal trimming */ -class SegmentProvider { +class JournalTrimmer { public: // get the committed journal head virtual journal_seq_t get_journal_head() const = 0; @@ -292,6 +292,14 @@ public: virtual void update_journal_tails( journal_seq_t dirty_tail, journal_seq_t alloc_tail) = 0; + virtual ~JournalTrimmer() {} +}; + +/** + * Callback interface for managing available segments + */ +class SegmentProvider { +public: virtual const segment_info_t& get_seg_info(segment_id_t id) const = 0; virtual segment_id_t allocate_segment( @@ -519,7 +527,7 @@ public: }; -class AsyncCleaner : public SegmentProvider { +class AsyncCleaner : public SegmentProvider, public JournalTrimmer { public: /// Config struct config_t { diff --git a/src/crimson/os/seastore/extent_placement_manager.cc b/src/crimson/os/seastore/extent_placement_manager.cc index 78c707bb713e..9518fdc78974 100644 --- a/src/crimson/os/seastore/extent_placement_manager.cc +++ b/src/crimson/os/seastore/extent_placement_manager.cc @@ -14,7 +14,7 @@ SegmentedOolWriter::SegmentedOolWriter( reclaim_gen_t gen, SegmentProvider& sp, SegmentSeqAllocator &ssa) - : segment_allocator(segment_type_t::OOL, category, gen, sp, ssa), + : segment_allocator(nullptr, category, gen, sp, ssa), record_submitter(crimson::common::get_conf( "seastore_journal_iodepth_limit"), crimson::common::get_conf( diff --git a/src/crimson/os/seastore/journal.cc b/src/crimson/os/seastore/journal.cc index 1f219724d768..d4714cf3f961 100644 --- a/src/crimson/os/seastore/journal.cc +++ b/src/crimson/os/seastore/journal.cc @@ -7,16 +7,19 @@ namespace crimson::os::seastore::journal { -JournalRef make_segmented(SegmentProvider &provider) +JournalRef make_segmented( + SegmentProvider &provider, + JournalTrimmer &trimmer) { - return std::make_unique(provider); + return std::make_unique(provider, trimmer); } JournalRef make_circularbounded( + JournalTrimmer &trimmer, crimson::os::seastore::random_block_device::RBMDevice* device, std::string path) { - return std::make_unique(device, path); + return std::make_unique(trimmer, device, path); } } diff --git a/src/crimson/os/seastore/journal.h b/src/crimson/os/seastore/journal.h index c2e537008f27..71eac4c00338 100644 --- a/src/crimson/os/seastore/journal.h +++ b/src/crimson/os/seastore/journal.h @@ -17,6 +17,7 @@ class RBMDevice; class SegmentManagerGroup; class SegmentProvider; +class JournalTrimmer; enum class journal_type_t { SEGMENT_JOURNAL = 0, @@ -25,6 +26,7 @@ enum class journal_type_t { class Journal { public: + virtual JournalTrimmer &get_trimmer() = 0; /** * initializes journal for mkfs writes -- must run prior to calls * to submit_record. @@ -108,9 +110,12 @@ using JournalRef = std::unique_ptr; namespace journal { -JournalRef make_segmented(SegmentProvider &provider); +JournalRef make_segmented( + SegmentProvider &provider, + JournalTrimmer &trimmer); JournalRef make_circularbounded( + JournalTrimmer &trimmer, crimson::os::seastore::random_block_device::RBMDevice* device, std::string path); diff --git a/src/crimson/os/seastore/journal/circular_bounded_journal.cc b/src/crimson/os/seastore/journal/circular_bounded_journal.cc index d7ff795f0076..2bc4672319bd 100644 --- a/src/crimson/os/seastore/journal/circular_bounded_journal.cc +++ b/src/crimson/os/seastore/journal/circular_bounded_journal.cc @@ -5,6 +5,7 @@ #include "crimson/common/errorator-loop.h" #include "include/intarith.h" +#include "crimson/os/seastore/async_cleaner.h" #include "crimson/os/seastore/journal/circular_bounded_journal.h" #include "crimson/os/seastore/logging.h" @@ -24,9 +25,11 @@ std::ostream &operator<<(std::ostream &out, << ")"; } -CircularBoundedJournal::CircularBoundedJournal(RBMDevice* device, +CircularBoundedJournal::CircularBoundedJournal( + JournalTrimmer &trimmer, + RBMDevice* device, const std::string &path) - : device(device), path(path) {} + : trimmer(trimmer), device(device), path(path) {} CircularBoundedJournal::mkfs_ret CircularBoundedJournal::mkfs(const mkfs_config_t& config) @@ -236,6 +239,7 @@ CircularBoundedJournal::submit_record_ret CircularBoundedJournal::submit_record( paddr, write_result }; + trimmer.set_journal_head(write_result.start_seq); return submit_result; }); } diff --git a/src/crimson/os/seastore/journal/circular_bounded_journal.h b/src/crimson/os/seastore/journal/circular_bounded_journal.h index 4a310806a95f..c41d75405f0c 100644 --- a/src/crimson/os/seastore/journal/circular_bounded_journal.h +++ b/src/crimson/os/seastore/journal/circular_bounded_journal.h @@ -20,7 +20,6 @@ #include "crimson/os/seastore/random_block_manager/rbm_device.h" #include - namespace crimson::os::seastore::journal { constexpr rbm_abs_addr CBJOURNAL_START_ADDRESS = 0; @@ -77,9 +76,14 @@ public: } }; - CircularBoundedJournal(RBMDevice* device, const std::string &path); + CircularBoundedJournal( + JournalTrimmer &trimmer, RBMDevice* device, const std::string &path); ~CircularBoundedJournal() {} + JournalTrimmer &get_trimmer() final { + return trimmer; + } + open_for_mkfs_ret open_for_mkfs() final; open_for_mount_ret open_for_mount() final; @@ -280,6 +284,7 @@ public: private: cbj_header_t header; + JournalTrimmer &trimmer; RBMDevice* device; std::string path; WritePipeline *write_pipeline = nullptr; diff --git a/src/crimson/os/seastore/journal/segment_allocator.cc b/src/crimson/os/seastore/journal/segment_allocator.cc index b8b193ae39e6..f97dd6a181ac 100644 --- a/src/crimson/os/seastore/journal/segment_allocator.cc +++ b/src/crimson/os/seastore/journal/segment_allocator.cc @@ -13,20 +13,22 @@ SET_SUBSYS(seastore_journal); namespace crimson::os::seastore::journal { SegmentAllocator::SegmentAllocator( - segment_type_t type, + JournalTrimmer *trimmer, data_category_t category, reclaim_gen_t gen, SegmentProvider &sp, SegmentSeqAllocator &ssa) : print_name{fmt::format("{}_G{}", category, gen)}, - type{type}, + type{trimmer == nullptr ? + segment_type_t::OOL : + segment_type_t::JOURNAL}, category{category}, gen{gen}, segment_provider{sp}, sm_group{*sp.get_segment_manager_group()}, - segment_seq_allocator(ssa) + segment_seq_allocator(ssa), + trimmer{trimmer} { - ceph_assert(type != segment_type_t::NULL_SEG); reset(); } @@ -57,8 +59,8 @@ SegmentAllocator::do_open(bool is_mkfs) journal_seq_t dirty_tail; journal_seq_t alloc_tail; if (type == segment_type_t::JOURNAL) { - dirty_tail = segment_provider.get_dirty_tail(); - alloc_tail = segment_provider.get_alloc_tail(); + dirty_tail = trimmer->get_dirty_tail(); + alloc_tail = trimmer->get_alloc_tail(); if (is_mkfs) { ceph_assert(dirty_tail == JOURNAL_SEQ_NULL); ceph_assert(alloc_tail == JOURNAL_SEQ_NULL); diff --git a/src/crimson/os/seastore/journal/segment_allocator.h b/src/crimson/os/seastore/journal/segment_allocator.h index a664b42e78f5..3355f18418f8 100644 --- a/src/crimson/os/seastore/journal/segment_allocator.h +++ b/src/crimson/os/seastore/journal/segment_allocator.h @@ -16,6 +16,7 @@ namespace crimson::os::seastore { class SegmentProvider; + class JournalTrimmer; } namespace crimson::os::seastore::journal { @@ -30,7 +31,7 @@ class SegmentAllocator { crimson::ct_error::input_output_error>; public: - SegmentAllocator(segment_type_t type, + SegmentAllocator(JournalTrimmer *trimmer, data_category_t category, reclaim_gen_t gen, SegmentProvider &sp, @@ -128,7 +129,7 @@ class SegmentAllocator { seastore_off_t written_to; SegmentSeqAllocator &segment_seq_allocator; segment_nonce_t current_segment_nonce; - //3. journal tail written to both segment_header_t and segment_tail_t + JournalTrimmer *trimmer; }; /** diff --git a/src/crimson/os/seastore/journal/segmented_journal.cc b/src/crimson/os/seastore/journal/segmented_journal.cc index 19008138df4b..12fc3b86d946 100644 --- a/src/crimson/os/seastore/journal/segmented_journal.cc +++ b/src/crimson/os/seastore/journal/segmented_journal.cc @@ -27,11 +27,11 @@ SET_SUBSYS(seastore_journal); namespace crimson::os::seastore::journal { SegmentedJournal::SegmentedJournal( - SegmentProvider &segment_provider) - : segment_provider(segment_provider), - segment_seq_allocator( + SegmentProvider &segment_provider, + JournalTrimmer &trimmer) + : segment_seq_allocator( new SegmentSeqAllocator(segment_type_t::JOURNAL)), - journal_segment_allocator(segment_type_t::JOURNAL, + journal_segment_allocator(&trimmer, data_category_t::METADATA, 0, // generation segment_provider, @@ -45,7 +45,8 @@ SegmentedJournal::SegmentedJournal( crimson::common::get_conf( "seastore_journal_batch_preferred_fullness"), journal_segment_allocator), - sm_group(*segment_provider.get_segment_manager_group()) + sm_group(*segment_provider.get_segment_manager_group()), + trimmer{trimmer} { } @@ -105,9 +106,9 @@ SegmentedJournal::prep_replay_segments( return scan_last_segment(last_segment_id, last_header ).safe_then([this, FNAME, segments=std::move(segments)] { INFO("dirty_tail={}, alloc_tail={}", - segment_provider.get_dirty_tail(), - segment_provider.get_alloc_tail()); - auto journal_tail = segment_provider.get_journal_tail(); + trimmer.get_dirty_tail(), + trimmer.get_alloc_tail()); + auto journal_tail = trimmer.get_journal_tail(); auto journal_tail_paddr = journal_tail.offset; ceph_assert(journal_tail != JOURNAL_SEQ_NULL); ceph_assert(journal_tail_paddr != P_ADDR_NULL); @@ -152,7 +153,7 @@ SegmentedJournal::scan_last_segment( { LOG_PREFIX(SegmentedJournal::scan_last_segment); assert(segment_id == segment_header.physical_segment_id); - segment_provider.update_journal_tails( + trimmer.update_journal_tails( segment_header.dirty_tail, segment_header.alloc_tail); auto seq = journal_seq_t{ segment_header.segment_seq, @@ -203,7 +204,7 @@ SegmentedJournal::scan_last_segment( DEBUG("got {}, at {}", tail_delta, start_seq); ceph_assert(tail_delta.dirty_tail != JOURNAL_SEQ_NULL); ceph_assert(tail_delta.alloc_tail != JOURNAL_SEQ_NULL); - segment_provider.update_journal_tails( + trimmer.update_journal_tails( tail_delta.dirty_tail, tail_delta.alloc_tail); } } @@ -287,8 +288,8 @@ SegmentedJournal::replay_segment( return handler( locator, delta, - segment_provider.get_dirty_tail(), - segment_provider.get_alloc_tail(), + trimmer.get_dirty_tail(), + trimmer.get_alloc_tail(), modify_time ).safe_then([&stats, delta_type=delta.type](bool is_applied) { if (is_applied) { diff --git a/src/crimson/os/seastore/journal/segmented_journal.h b/src/crimson/os/seastore/journal/segmented_journal.h index cc5e489393df..ba4b0cd5fb9d 100644 --- a/src/crimson/os/seastore/journal/segmented_journal.h +++ b/src/crimson/os/seastore/journal/segmented_journal.h @@ -24,9 +24,15 @@ namespace crimson::os::seastore::journal { */ class SegmentedJournal : public Journal { public: - SegmentedJournal(SegmentProvider &segment_provider); + SegmentedJournal( + SegmentProvider &segment_provider, + JournalTrimmer &trimmer); ~SegmentedJournal() {} + JournalTrimmer &get_trimmer() final { + return trimmer; + } + open_for_mkfs_ret open_for_mkfs() final; open_for_mount_ret open_for_mount() final; @@ -55,11 +61,11 @@ private: OrderingHandle &handle ); - SegmentProvider& segment_provider; SegmentSeqAllocatorRef segment_seq_allocator; SegmentAllocator journal_segment_allocator; RecordSubmitter record_submitter; SegmentManagerGroup &sm_group; + JournalTrimmer &trimmer; WritePipeline* write_pipeline = nullptr; /// return ordered vector of segments to replay diff --git a/src/crimson/os/seastore/transaction_manager.cc b/src/crimson/os/seastore/transaction_manager.cc index 52623def9ed3..5172838673c8 100644 --- a/src/crimson/os/seastore/transaction_manager.cc +++ b/src/crimson/os/seastore/transaction_manager.cc @@ -49,8 +49,8 @@ TransactionManager::mkfs_ertr::future<> TransactionManager::mkfs() ).safe_then([this] { return journal->open_for_mkfs(); }).safe_then([this](auto start_seq) { - async_cleaner->update_journal_tails(start_seq, start_seq); - async_cleaner->set_journal_head(start_seq); + journal->get_trimmer().update_journal_tails(start_seq, start_seq); + journal->get_trimmer().set_journal_head(start_seq); return epm->open(); }).safe_then([this, FNAME]() { return with_transaction_intr( @@ -109,7 +109,7 @@ TransactionManager::mount_ertr::future<> TransactionManager::mount() }).safe_then([this] { return journal->open_for_mount(); }).safe_then([this](auto start_seq) { - async_cleaner->set_journal_head(start_seq); + journal->get_trimmer().set_journal_head(start_seq); return with_transaction_weak( "mount", [this](auto &t) @@ -337,8 +337,8 @@ TransactionManager::submit_transaction_direct( auto record = cache->prepare_record( tref, - async_cleaner->get_journal_head(), - async_cleaner->get_dirty_tail()); + journal->get_trimmer().get_journal_head(), + journal->get_trimmer().get_dirty_tail()); tref.get_handle().maybe_release_collection_lock(); @@ -347,7 +347,7 @@ TransactionManager::submit_transaction_direct( ).safe_then([this, FNAME, &tref](auto submit_result) mutable { SUBDEBUGT(seastore_t, "committed with {}", tref, submit_result); auto start_seq = submit_result.write_result.start_seq; - async_cleaner->set_journal_head(start_seq); + journal->get_trimmer().set_journal_head(start_seq); cache->complete_commit( tref, submit_result.record_block_base, @@ -389,7 +389,7 @@ TransactionManager::submit_transaction_direct( lba_manager->complete_transaction(tref, lba_to_clear, lba_to_link); backref_manager->complete_transaction(tref, backref_to_clear, backref_to_link); - async_cleaner->update_journal_tails( + journal->get_trimmer().update_journal_tails( cache->get_oldest_dirty_from().value_or(start_seq), cache->get_oldest_backref_dirty_from().value_or(start_seq)); return tref.get_handle().complete(); @@ -664,10 +664,11 @@ TransactionManagerRef make_transaction_manager( auto p_device_type = primary_device->get_device_type(); JournalRef journal; if (p_device_type == device_type_t::SEGMENTED) { - journal = journal::make_segmented(*async_cleaner); + journal = journal::make_segmented(*async_cleaner, *async_cleaner); } else { ceph_assert(p_device_type == device_type_t::RANDOM_BLOCK); journal = journal::make_circularbounded( + *async_cleaner, static_cast(primary_device), ""); async_cleaner->set_disable_trim(true); diff --git a/src/test/crimson/seastore/test_btree_lba_manager.cc b/src/test/crimson/seastore/test_btree_lba_manager.cc index 92719d83aa27..adc3ce504c63 100644 --- a/src/test/crimson/seastore/test_btree_lba_manager.cc +++ b/src/test/crimson/seastore/test_btree_lba_manager.cc @@ -25,7 +25,7 @@ using namespace crimson::os::seastore::lba_manager; using namespace crimson::os::seastore::lba_manager::btree; struct btree_test_base : - public seastar_test_suite_t, SegmentProvider { + public seastar_test_suite_t, SegmentProvider, JournalTrimmer { segment_manager::EphemeralSegmentManagerRef segment_manager; SegmentManagerGroupRef sms; @@ -49,7 +49,7 @@ struct btree_test_base : btree_test_base() = default; /* - * SegmentProvider interfaces + * JournalTrimmer interfaces */ journal_seq_t get_journal_head() const final { return dummy_tail; } @@ -61,6 +61,9 @@ struct btree_test_base : void update_journal_tails(journal_seq_t, journal_seq_t) final {} + /* + * SegmentProvider interfaces + */ const segment_info_t& get_seg_info(segment_id_t id) const final { tmp_info = {}; tmp_info.seq = segment_seqs.at(id); @@ -114,7 +117,7 @@ struct btree_test_base : segment_manager::get_ephemeral_device_config(0, 1)); }).safe_then([this] { sms.reset(new SegmentManagerGroup()); - journal = journal::make_segmented(*this); + journal = journal::make_segmented(*this, *this); epm.reset(new ExtentPlacementManager()); cache.reset(new Cache(*epm)); diff --git a/src/test/crimson/seastore/test_cbjournal.cc b/src/test/crimson/seastore/test_cbjournal.cc index d7ed72eae327..309118fa37d7 100644 --- a/src/test/crimson/seastore/test_cbjournal.cc +++ b/src/test/crimson/seastore/test_cbjournal.cc @@ -6,11 +6,12 @@ #include #include "crimson/common/log.h" -#include "crimson/os/seastore/seastore_types.h" +#include "crimson/os/seastore/async_cleaner.h" #include "crimson/os/seastore/journal.h" #include "crimson/os/seastore/journal/circular_bounded_journal.h" #include "crimson/os/seastore/random_block_manager.h" #include "crimson/os/seastore/random_block_manager/rbm_device.h" +#include "crimson/os/seastore/seastore_types.h" #include "test/crimson/seastore/transaction_manager_test_state.h" using namespace crimson; @@ -119,7 +120,7 @@ struct entry_validator_t { } }; -struct cbjournal_test_t : public seastar_test_suite_t +struct cbjournal_test_t : public seastar_test_suite_t, JournalTrimmer { std::vector entries; std::unique_ptr cbj; @@ -132,7 +133,7 @@ struct cbjournal_test_t : public seastar_test_suite_t cbjournal_test_t() { device = new random_block_device::TestMemory(CBTEST_DEFAULT_TEST_SIZE + CBTEST_DEFAULT_BLOCK_SIZE); - cbj.reset(new CircularBoundedJournal(device, std::string())); + cbj.reset(new CircularBoundedJournal(*this, device, std::string())); device_id_t d_id = 1 << (std::numeric_limits::digits - 1); config.block_size = CBTEST_DEFAULT_BLOCK_SIZE; config.total_size = CBTEST_DEFAULT_TEST_SIZE; @@ -141,6 +142,27 @@ struct cbjournal_test_t : public seastar_test_suite_t cbj->set_write_pipeline(&pipeline); } + /* + * JournalTrimmer interfaces + */ + journal_seq_t get_journal_head() const { + return JOURNAL_SEQ_NULL; + } + + journal_seq_t get_dirty_tail() const final { + return JOURNAL_SEQ_NULL; + } + + journal_seq_t get_alloc_tail() const final { + return JOURNAL_SEQ_NULL; + } + + void set_journal_head(journal_seq_t head) final {} + + void update_journal_tails( + journal_seq_t dirty_tail, + journal_seq_t alloc_tail) final {} + seastar::future<> set_up_fut() final { return seastar::now(); } diff --git a/src/test/crimson/seastore/test_seastore_journal.cc b/src/test/crimson/seastore/test_seastore_journal.cc index 0b6f7870c8f6..ac190c78102b 100644 --- a/src/test/crimson/seastore/test_seastore_journal.cc +++ b/src/test/crimson/seastore/test_seastore_journal.cc @@ -63,7 +63,7 @@ struct record_validator_t { } }; -struct journal_test_t : seastar_test_suite_t, SegmentProvider { +struct journal_test_t : seastar_test_suite_t, SegmentProvider, JournalTrimmer { segment_manager::EphemeralSegmentManagerRef segment_manager; WritePipeline pipeline; JournalRef journal; @@ -88,7 +88,7 @@ struct journal_test_t : seastar_test_suite_t, SegmentProvider { journal_test_t() = default; /* - * SegmentProvider interfaces + * JournalTrimmer interfaces */ journal_seq_t get_journal_head() const final { return dummy_tail; } @@ -100,6 +100,9 @@ struct journal_test_t : seastar_test_suite_t, SegmentProvider { void update_journal_tails(journal_seq_t, journal_seq_t) final {} + /* + * SegmentProvider interfaces + */ const segment_info_t& get_seg_info(segment_id_t id) const final { tmp_info = {}; tmp_info.seq = segment_seqs.at(id); @@ -140,7 +143,7 @@ struct journal_test_t : seastar_test_suite_t, SegmentProvider { block_size = segment_manager->get_block_size(); sms.reset(new SegmentManagerGroup()); next = segment_id_t(segment_manager->get_device_id(), 0); - journal = journal::make_segmented(*this); + journal = journal::make_segmented(*this, *this); journal->set_write_pipeline(&pipeline); sms->add_segment_manager(segment_manager.get()); return journal->open_for_mkfs(); @@ -169,7 +172,7 @@ struct journal_test_t : seastar_test_suite_t, SegmentProvider { auto replay(T &&f) { return journal->close( ).safe_then([this, f=std::move(f)]() mutable { - journal = journal::make_segmented(*this); + journal = journal::make_segmented(*this, *this); journal->set_write_pipeline(&pipeline); return journal->replay(std::forward(std::move(f))); }).safe_then([this] {