From: Xuehan Xu Date: Mon, 6 Nov 2023 10:34:28 +0000 (+0800) Subject: test/crimson/seastore: add unittest cases for scattered allocation X-Git-Tag: v19.1.0~354^2~3 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=63b87f70ce98d5ce1db73b85115ae038dc9a9a58;p=ceph.git test/crimson/seastore: add unittest cases for scattered allocation Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/common/errorator.h b/src/crimson/common/errorator.h index 656af5813560f..ebc5a95bb3e6e 100644 --- a/src/crimson/common/errorator.h +++ b/src/crimson/common/errorator.h @@ -11,6 +11,8 @@ #include "crimson/common/utility.h" #include "include/ceph_assert.h" +class transaction_manager_test_t; + namespace crimson::interruptible { template @@ -528,6 +530,7 @@ private: protected: using base_t::get_exception; + friend class ::transaction_manager_test_t; public: using errorator_type = ::crimson::errorator; using promise_type = seastar::promise; @@ -708,6 +711,9 @@ private: auto unsafe_get0() { return seastar::future::get0(); } + void unsafe_wait() { + seastar::future::wait(); + } template _future finally(FuncT &&func) { diff --git a/src/crimson/os/seastore/async_cleaner.h b/src/crimson/os/seastore/async_cleaner.h index 8f69d742d7416..1c94745d820c2 100644 --- a/src/crimson/os/seastore/async_cleaner.h +++ b/src/crimson/os/seastore/async_cleaner.h @@ -1156,6 +1156,10 @@ public: virtual std::size_t get_reclaim_size_per_cycle() const = 0; +#ifdef UNIT_TESTS_BUILT + virtual void prefill_fragmented_devices() {} +#endif + // test only virtual bool check_usage() = 0; @@ -1677,6 +1681,17 @@ public: return 0; } +#ifdef UNIT_TESTS_BUILT + void prefill_fragmented_devices() final { + LOG_PREFIX(RBMCleaner::prefill_fragmented_devices); + SUBDEBUG(seastore_cleaner, ""); + auto rbs = rb_group->get_rb_managers(); + for (auto p : rbs) { + p->prefill_fragmented_device(); + } + } +#endif + RandomBlockManager* get_rbm(paddr_t paddr) { auto rbs = rb_group->get_rb_managers(); for (auto p : rbs) { diff --git a/src/crimson/os/seastore/extent_placement_manager.h b/src/crimson/os/seastore/extent_placement_manager.h index b1a4de2ef457a..6a71a4ca98645 100644 --- a/src/crimson/os/seastore/extent_placement_manager.h +++ b/src/crimson/os/seastore/extent_placement_manager.h @@ -48,6 +48,10 @@ public: virtual bool can_inplace_rewrite(Transaction& t, CachedExtentRef extent) = 0; + +#ifdef UNIT_TESTS_BUILT + virtual void prefill_fragmented_devices() {} +#endif }; using ExtentOolWriterRef = std::unique_ptr; @@ -152,6 +156,13 @@ public: return crimson::os::seastore::can_inplace_rewrite(extent->get_type()); } +#ifdef UNIT_TESTS_BUILT + void prefill_fragmented_devices() final { + LOG_PREFIX(RandomBlockOolWriter::prefill_fragmented_devices); + SUBDEBUG(seastore_epm, ""); + return rb_cleaner->prefill_fragmented_devices(); + } +#endif private: alloc_write_iertr::future<> do_write( Transaction& t, @@ -377,6 +388,16 @@ public: return allocs; } +#ifdef UNIT_TESTS_BUILT + void prefill_fragmented_devices() { + LOG_PREFIX(ExtentPlacementManager::prefill_fragmented_devices); + SUBDEBUG(seastore_epm, ""); + for (auto &writer : writer_refs) { + writer->prefill_fragmented_devices(); + } + } +#endif + /** * dispatch_result_t * diff --git a/src/crimson/os/seastore/random_block_manager.h b/src/crimson/os/seastore/random_block_manager.h index f0e0f018bd103..fc45af3b2f559 100644 --- a/src/crimson/os/seastore/random_block_manager.h +++ b/src/crimson/os/seastore/random_block_manager.h @@ -149,6 +149,9 @@ public: virtual rbm_extent_state_t get_extent_state(paddr_t addr, size_t size) = 0; virtual size_t get_journal_size() const = 0; virtual ~RandomBlockManager() {} +#ifdef UNIT_TESTS_BUILT + virtual void prefill_fragmented_device() = 0; +#endif }; using RandomBlockManagerRef = std::unique_ptr; diff --git a/src/crimson/os/seastore/random_block_manager/block_rb_manager.cc b/src/crimson/os/seastore/random_block_manager/block_rb_manager.cc index cca520a9bfea3..715aafbc8a8e9 100644 --- a/src/crimson/os/seastore/random_block_manager/block_rb_manager.cc +++ b/src/crimson/os/seastore/random_block_manager/block_rb_manager.cc @@ -182,6 +182,25 @@ BlockRBManager::write_ertr::future<> BlockRBManager::write( std::move(bptr)); } +#ifdef UNIT_TESTS_BUILT +void BlockRBManager::prefill_fragmented_device() +{ + LOG_PREFIX(BlockRBManager::prefill_fragmented_device); + // the first 2 blocks must be allocated to lba root + // and backref root during mkfs + for (size_t block = get_block_size() * 2; + block <= get_size() - get_block_size() * 2; + block += get_block_size() * 2) { + DEBUG("marking {}~{} used", + get_start_rbm_addr() + block, + get_block_size()); + allocator->mark_extent_used( + get_start_rbm_addr() + block, + get_block_size()); + } +} +#endif + std::ostream &operator<<(std::ostream &out, const rbm_metadata_header_t &header) { out << " rbm_metadata_header_t(size=" << header.size diff --git a/src/crimson/os/seastore/random_block_manager/block_rb_manager.h b/src/crimson/os/seastore/random_block_manager/block_rb_manager.h index 14d2a28a31460..bc33710eee020 100644 --- a/src/crimson/os/seastore/random_block_manager/block_rb_manager.h +++ b/src/crimson/os/seastore/random_block_manager/block_rb_manager.h @@ -127,6 +127,10 @@ public: return device->get_journal_size(); } +#ifdef UNIT_TESTS_BUILT + void prefill_fragmented_device() final; +#endif + private: /* * this contains the number of bitmap blocks, free blocks and diff --git a/src/test/crimson/seastore/test_transaction_manager.cc b/src/test/crimson/seastore/test_transaction_manager.cc index 378644dafa840..869eae716cd6e 100644 --- a/src/test/crimson/seastore/test_transaction_manager.cc +++ b/src/test/crimson/seastore/test_transaction_manager.cc @@ -398,6 +398,40 @@ struct transaction_manager_test_t : return extent; } + std::vector alloc_extents( + test_transaction_t &t, + laddr_t hint, + extent_len_t len, + char contents) { + auto extents = with_trans_intr(*(t.t), [&](auto& trans) { + return tm->alloc_data_extents(trans, hint, len); + }).unsafe_get0(); + size_t length = 0; + for (auto &extent : extents) { + extent->set_contents(contents); + length += extent->get_length(); + EXPECT_FALSE(test_mappings.contains(extent->get_laddr(), t.mapping_delta)); + test_mappings.alloced(hint, *extent, t.mapping_delta); + } + EXPECT_EQ(len, length); + return extents; + } + + void alloc_extents_deemed_fail( + test_transaction_t &t, + laddr_t hint, + extent_len_t len, + char contents) + { + std::cout << __func__ << std::endl; + auto fut = with_trans_intr(*(t.t), [&](auto& trans) { + return tm->alloc_data_extents(trans, hint, len); + }); + fut.unsafe_wait(); + assert(fut.failed()); + (void)fut.get_exception(); + } + TestBlockRef alloc_extent( test_transaction_t &t, laddr_t hint, @@ -1675,6 +1709,30 @@ struct tm_multi_tier_device_test_t : tm_multi_tier_device_test_t() : transaction_manager_test_t(1, 2) {} }; +struct tm_random_block_device_test_t : + public transaction_manager_test_t { + + tm_random_block_device_test_t() : transaction_manager_test_t(1, 0) {} +}; + +TEST_P(tm_random_block_device_test_t, scatter_allocation) +{ + run_async([this] { + constexpr laddr_t ADDR = 0xFF * 4096; + epm->prefill_fragmented_devices(); + auto t = create_transaction(); + for (int i = 0; i < 1991; i++) { + auto extents = alloc_extents(t, ADDR + i * 16384, 16384, 'a'); + std::cout << "num of extents: " << extents.size() << std::endl; + } + alloc_extents_deemed_fail(t, ADDR + 1991 * 16384, 16384, 'a'); + check_mappings(t); + check(); + submit_transaction(std::move(t)); + check(); + }); +} + TEST_P(tm_single_device_test_t, basic) { constexpr laddr_t SIZE = 4096; @@ -2133,3 +2191,11 @@ INSTANTIATE_TEST_SUITE_P( "segmented" ) ); + +INSTANTIATE_TEST_SUITE_P( + transaction_manager_test, + tm_random_block_device_test_t, + ::testing::Values ( + "circularbounded" + ) +);