From 683c0274a900560afa7ecf4da5a8f213be810f4c Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Mon, 16 Oct 2023 16:22:31 +0800 Subject: [PATCH] test/crimson/seastore: add unittests for clone/remap/read_pin Signed-off-by: Xuehan Xu --- .../seastore/test_transaction_manager.cc | 145 ++++++++++++++++-- 1 file changed, 133 insertions(+), 12 deletions(-) diff --git a/src/test/crimson/seastore/test_transaction_manager.cc b/src/test/crimson/seastore/test_transaction_manager.cc index 1148884a0c193..914eea9bbbfdd 100644 --- a/src/test/crimson/seastore/test_transaction_manager.cc +++ b/src/test/crimson/seastore/test_transaction_manager.cc @@ -239,12 +239,15 @@ struct transaction_manager_test_t : void check_hint( laddr_t hint, + laddr_t intermediate_hint, laddr_t addr, extent_len_t len, delta_t &delta) const { delta_overlay_t overlay(*this, delta); - auto iter = overlay.lower_bound(hint); - laddr_t last = hint; + auto real_hint = intermediate_hint == L_ADDR_NULL + ? hint : intermediate_hint; + auto iter = overlay.lower_bound(real_hint); + laddr_t last = real_hint; while (true) { if (iter == overlay.end() || iter->first > addr) { EXPECT_EQ(addr, last); @@ -286,8 +289,18 @@ struct transaction_manager_test_t : test_extent_record_t{extent.get_desc(), 1}; } - void alloced(laddr_t hint, TestBlock &extent, delta_t &delta) const { - check_hint(hint, extent.get_laddr(), extent.get_length(), delta); + void alloced( + laddr_t hint, + TestBlock &extent, + delta_t &delta, + laddr_t intermediate_hint = L_ADDR_NULL) const + { + check_hint( + hint, + intermediate_hint, + extent.get_laddr(), + extent.get_length(), + delta); insert(extent, delta); } @@ -413,6 +426,25 @@ struct transaction_manager_test_t : check_mappings(t); } + TestBlockRef read_pin( + test_transaction_t &t, + LBAMappingRef pin) { + auto addr = pin->is_indirect() + ? pin->get_intermediate_base() + : pin->get_key(); + auto len = pin->is_indirect() + ? pin->get_intermediate_length() + : pin->get_length(); + ceph_assert(test_mappings.contains(addr, t.mapping_delta)); + ceph_assert(test_mappings.get(addr, t.mapping_delta).desc.len == len); + + auto ext = with_trans_intr(*(t.t), [&](auto& trans) { + return tm->read_pin(trans, std::move(pin)); + }).unsafe_get0(); + EXPECT_EQ(addr, ext->get_laddr()); + return ext; + } + TestBlockRef get_extent( test_transaction_t &t, laddr_t addr, @@ -484,7 +516,9 @@ struct transaction_manager_test_t : LBAMappingRef &&pin) { using ertr = with_trans_ertr; using ret = ertr::future; + bool indirect = pin->is_indirect(); auto addr = pin->get_key(); + auto im_addr = indirect ? pin->get_intermediate_base() : L_ADDR_NULL; auto ext = with_trans_intr(*(t.t), [&](auto& trans) { return tm->read_pin(trans, std::move(pin)); }).safe_then([](auto ext) -> ret { @@ -498,7 +532,11 @@ struct transaction_manager_test_t : } ).get0(); if (ext) { - EXPECT_EQ(addr, ext->get_laddr()); + if (indirect) { + EXPECT_EQ(im_addr, ext->get_laddr()); + } else { + EXPECT_EQ(addr, ext->get_laddr()); + } } if (t.t->is_conflicted()) { return nullptr; @@ -544,6 +582,20 @@ struct transaction_manager_test_t : return pin; } + LBAMappingRef clone_pin( + test_transaction_t &t, + laddr_t offset, + const LBAMapping &mapping) { + auto pin = with_trans_intr(*(t.t), [&](auto &trans) { + return tm->clone_pin(trans, offset, mapping); + }).unsafe_get0(); + EXPECT_EQ(offset, pin->get_key()); + EXPECT_EQ(mapping.get_key(), pin->get_intermediate_key()); + EXPECT_EQ(mapping.get_key(), pin->get_intermediate_base()); + test_mappings.inc_ref(pin->get_intermediate_key(), t.mapping_delta); + return pin; + } + LBAMappingRef try_get_pin( test_transaction_t &t, laddr_t offset) { @@ -597,7 +649,7 @@ struct transaction_manager_test_t : for (const auto &i: overlay) { logger().debug("check_mappings: {}->{}", i.first, i.second); auto ext = get_extent(t, i.first, i.second.desc.len); - EXPECT_EQ(i.second, ext->get_desc()); + assert(i.second == ext->get_desc()); } with_trans_intr( *t.t, @@ -992,6 +1044,9 @@ struct transaction_manager_test_t : return nullptr; } auto o_laddr = opin->get_key(); + auto data_laddr = opin->is_indirect() + ? opin->get_intermediate_base() + : o_laddr; auto pin = with_trans_intr(*(t.t), [&](auto& trans) { return tm->remap_pin( trans, std::move(opin), std::array{ @@ -1006,16 +1061,24 @@ struct transaction_manager_test_t : if (t.t->is_conflicted()) { return nullptr; } - test_mappings.dec_ref(o_laddr, t.mapping_delta); - EXPECT_FALSE(test_mappings.contains(o_laddr, t.mapping_delta)); + if (opin->is_indirect()) { + test_mappings.inc_ref(data_laddr, t.mapping_delta); + } else { + test_mappings.dec_ref(data_laddr, t.mapping_delta); + EXPECT_FALSE(test_mappings.contains(data_laddr, t.mapping_delta)); + } EXPECT_TRUE(pin); EXPECT_EQ(pin->get_length(), new_len); EXPECT_EQ(pin->get_key(), o_laddr + new_offset); auto extent = try_read_pin(t, pin->duplicate()); if (extent) { - test_mappings.alloced(pin->get_key(), *extent, t.mapping_delta); - EXPECT_TRUE(extent->is_exist_clean()); + if (!pin->is_indirect()) { + test_mappings.alloced(pin->get_key(), *extent, t.mapping_delta); + EXPECT_TRUE(extent->is_exist_clean()); + } else { + EXPECT_TRUE(extent->is_stable()); + } } else { ceph_assert(t.t->is_conflicted()); return nullptr; @@ -1220,7 +1283,7 @@ struct transaction_manager_test_t : ASSERT_TRUE(pin2); auto pin3 = remap_pin(t, std::move(pin2), 0, 4 << 10); ASSERT_TRUE(pin3); - auto lext = get_extent(t, pin3->get_key(), pin3->get_length()); + auto lext = read_pin(t, std::move(pin3)); EXPECT_EQ('l', lext->get_bptr().c_str()[0]); auto mlext = mutate_extent(t, lext); ASSERT_TRUE(mlext->is_exist_mutation_pending()); @@ -1233,7 +1296,7 @@ struct transaction_manager_test_t : ASSERT_TRUE(pin5); auto pin6 = remap_pin(t, std::move(pin5), 4 << 10, 4 << 10); ASSERT_TRUE(pin6); - auto rext = get_extent(t, pin6->get_key(), pin6->get_length()); + auto rext = read_pin(t, std::move(pin6)); EXPECT_EQ('r', rext->get_bptr().c_str()[0]); auto mrext = mutate_extent(t, rext); ASSERT_TRUE(mrext->is_exist_mutation_pending()); @@ -1247,6 +1310,59 @@ struct transaction_manager_test_t : }); } + void test_clone_and_remap_pin() { + run_async([this] { + constexpr size_t l_offset = 32 << 10; + constexpr size_t l_len = 32 << 10; + constexpr size_t r_offset = 64 << 10; + constexpr size_t r_len = 32 << 10; + constexpr size_t l_clone_offset = 96 << 10; + constexpr size_t r_clone_offset = 128 << 10; + { + auto t = create_transaction(); + auto lext = alloc_extent(t, l_offset, l_len); + lext->set_contents('l', 0, 16 << 10); + test_mappings.update(l_offset, lext->get_desc(), t.mapping_delta); + auto rext = alloc_extent(t, r_offset, r_len); + rext->set_contents('r', 16 << 10, 16 << 10); + test_mappings.update(r_offset, rext->get_desc(), t.mapping_delta); + submit_transaction(std::move(t)); + } + { + auto t = create_transaction(); + auto lpin = get_pin(t, l_offset); + auto rpin = get_pin(t, r_offset); + auto l_clone_pin = clone_pin(t, l_clone_offset, *lpin); + auto r_clone_pin = clone_pin(t, r_clone_offset, *rpin); + //split left + auto pin1 = remap_pin(t, std::move(l_clone_pin), 0, 16 << 10); + ASSERT_TRUE(pin1); + auto pin2 = remap_pin(t, std::move(pin1), 0, 8 << 10); + ASSERT_TRUE(pin2); + auto pin3 = remap_pin(t, std::move(pin2), 0, 4 << 10); + ASSERT_TRUE(pin3); + auto lext = read_pin(t, std::move(pin3)); + EXPECT_EQ('l', lext->get_bptr().c_str()[0]); + + //split right + auto pin4 = remap_pin(t, std::move(r_clone_pin), 16 << 10, 16 << 10); + ASSERT_TRUE(pin4); + auto pin5 = remap_pin(t, std::move(pin4), 8 << 10, 8 << 10); + ASSERT_TRUE(pin5); + auto pin6 = remap_pin(t, std::move(pin5), 4 << 10, 4 << 10); + ASSERT_TRUE(pin6); + auto int_offset = pin6->get_intermediate_offset(); + auto rext = read_pin(t, std::move(pin6)); + EXPECT_EQ('r', rext->get_bptr().c_str()[int_offset]); + + submit_transaction(std::move(t)); + check(); + } + replay(); + check(); + }); + } + void test_overwrite_pin() { run_async([this] { constexpr size_t m_offset = 8 << 10; @@ -1954,6 +2070,11 @@ TEST_P(tm_single_device_test_t, test_remap_pin) test_remap_pin(); } +TEST_P(tm_single_device_test_t, test_clone_and_remap_pin) +{ + test_clone_and_remap_pin(); +} + TEST_P(tm_single_device_test_t, test_overwrite_pin) { test_overwrite_pin(); -- 2.39.5