]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
test/crimson/seastore/test_btree_lba_manager: add test cases for conflict policy
authorZhang Song <zhangsong02@qianxin.com>
Tue, 27 May 2025 07:31:13 +0000 (15:31 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Sun, 24 May 2026 04:06:20 +0000 (12:06 +0800)
Signed-off-by: Zhang Song <zhangsong02@qianxin.com>
Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
src/test/crimson/seastore/test_btree_lba_manager.cc

index bd00384bb9e00e0d9e2ce11df6e62a60afb12f57..81ab5c78defd4f7535509df843af2d56d68c9a44 100644 (file)
@@ -543,7 +543,7 @@ struct btree_lba_manager_test : btree_test_base {
 
   auto alloc_mappings(
     test_transaction_t &t,
-    laddr_t addr,
+    laddr_hint_t hint,
     size_t len) {
     auto rets = with_trans_intr(
       *t.t,
@@ -557,11 +557,7 @@ struct btree_lba_manager_test : btree_test_base {
        return seastar::do_with(
          std::vector<LogicalChildNodeRef>(
            extents.begin(), extents.end()),
-         [this, &t, addr](auto &extents) {
-         laddr_hint_t hint;
-         hint.addr = addr;
-         hint.condition = laddr_conflict_condition_t::all_at_object_content;
-         hint.policy = laddr_conflict_policy_t::linear_search;
+         [this, &t, hint](auto &extents) {
          return lba_manager->alloc_extents(t, hint, std::move(extents), EXTENT_DEFAULT_REF_COUNT);
        });
       }).unsafe_get();
@@ -583,6 +579,18 @@ struct btree_lba_manager_test : btree_test_base {
     return rets;
   }
 
+  auto alloc_mappings(
+    test_transaction_t &t,
+    laddr_t addr,
+    size_t len) {
+    laddr_hint_t hint;
+    hint.addr = addr;
+    hint.condition = laddr_conflict_condition_t::all_at_object_content;
+    hint.policy = laddr_conflict_policy_t::linear_search;
+    hint.block_size = laddr_t::UNIT_SIZE;
+    return alloc_mappings(t, hint, len);
+  }
+
   auto decref_mapping(
     test_transaction_t &t,
     laddr_t addr) {
@@ -884,3 +892,277 @@ TEST_F(btree_lba_manager_test, split_merge_multi)
     check_mappings();
   });
 }
+
+TEST_F(btree_lba_manager_test, conflict_policy_global_linear)
+{
+  run_async([this] {
+    constexpr auto MAX = std::numeric_limits<uint64_t>::max();
+    auto t = create_transaction(false);
+
+    laddr_hint_t hint;
+    hint.addr = L_ADDR_MIN.with_object_content(MAX - 1);
+    hint.condition = laddr_conflict_condition_t::all_at_never;
+    hint.policy = laddr_conflict_policy_t::linear_search;
+    hint.block_size = laddr_t::UNIT_SIZE;
+
+    auto alloc = [&]() -> laddr_t {
+      std::vector<LBACursorRef> ret = alloc_mappings(t, hint, 4096);
+      assert(ret.size() == 1);
+      return ret.front()->get_key();
+    };
+
+    // 1 base
+    auto addr = alloc();
+    ASSERT_EQ(addr, hint.addr);
+
+    // 2 global end
+    hint.condition = laddr_conflict_condition_t::all_at_object_content;
+    addr = alloc();
+    ASSERT_EQ(addr, L_ADDR_MIN.with_object_content(MAX));
+
+    // 3 loop back
+    addr = alloc();
+    ASSERT_EQ(addr, L_ADDR_MIN);
+
+    submit_test_transaction(std::move(t));
+    check_mappings();
+  });
+}
+
+TEST_F(btree_lba_manager_test, conflict_policy_global_random)
+{
+  run_async([this] {
+    auto t = create_transaction(false);
+
+    laddr_hint_t hint = laddr_hint_t::create_global_md_hint();
+    hint.addr = L_ADDR_MIN;
+
+    std::set<laddr_t> addrs;
+    for (int i = 0; i < 128; i++) {
+      std::vector<LBACursorRef> ret = alloc_mappings(t, hint, 4096);
+      assert(ret.size() == 1);
+      auto addr = ret.front()->get_key();
+      ASSERT_EQ(addr.get_object_prefix(), L_ADDR_MIN.get_object_prefix());
+      auto p = addrs.insert(addr);
+      ASSERT_TRUE(p.second);
+    }
+
+    submit_test_transaction(std::move(t));
+    check_mappings();
+  });
+}
+
+TEST_F(btree_lba_manager_test, conflict_policy_object_data)
+{
+  run_async([this] {
+    auto t = create_transaction(false);
+    laddr_shard_t shard = 1;
+    laddr_pool_t pool = 1;
+    laddr_crush_hash_t crush = 1;
+
+    auto alloc = [&](laddr_hint_t hint) -> laddr_t {
+      auto ret = alloc_mappings(t, hint, 4096);
+      assert(ret.size() == 1);
+      return ret.front()->get_key();
+    };
+
+    auto hint = laddr_hint_t::create_fresh_object_data_hint(
+      shard, pool, crush, laddr_t::UNIT_SHIFT);
+    {
+      auto object_id = hint.addr.get_local_object_id();
+      if (object_id == LOCAL_OBJECT_ID_NULL) {
+       hint.addr.set_local_object_id(object_id - 1);
+      }
+      auto clone_id = hint.addr.get_local_clone_id();
+      if (clone_id == LOCAL_CLONE_ID_NULL) {
+       hint.addr.set_local_clone_id(clone_id - 1);
+      }
+    }
+
+    auto base_addr = alloc(hint);
+    auto object_id = base_addr.get_local_object_id();
+    auto clone_id = base_addr.get_local_clone_id();
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr;
+      // conflict with other object
+      hint.condition = laddr_conflict_condition_t::object_prefix_at_object_id;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_NE(object_id, addr.get_local_object_id());
+      ASSERT_EQ(clone_id, addr.get_local_clone_id());
+    }
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr.with_local_clone_id(clone_id + 1);
+      // conflict with other object, check prev
+      hint.condition = laddr_conflict_condition_t::object_prefix_at_object_id;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_NE(object_id, addr.get_local_object_id());
+      ASSERT_EQ(clone_id + 1, addr.get_local_clone_id());
+    }
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr.with_offset_by_blocks(rand());
+      hint.addr.set_metadata(true);
+      // allocating metadata for fresh clone conflicts with other clone, check prev
+      hint.condition = laddr_conflict_condition_t::clone_prefix_at_clone_id;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_EQ(object_id, addr.get_local_object_id());
+      ASSERT_NE(clone_id, addr.get_local_clone_id());
+    }
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr;
+      // conflict with other clone
+      hint.condition = laddr_conflict_condition_t::clone_prefix_at_clone_id;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_EQ(object_id, addr.get_local_object_id());
+      ASSERT_NE(clone_id, addr.get_local_clone_id());
+    }
+
+    submit_test_transaction(std::move(t));
+    check_mappings();
+  });
+}
+
+TEST_F(btree_lba_manager_test, conflict_policy_object_metadata)
+{
+  run_async([this] {
+    auto t = create_transaction(false);
+    laddr_shard_t shard = 1;
+    laddr_pool_t pool = 1;
+    laddr_crush_hash_t crush = 1;
+
+    auto alloc = [&](laddr_hint_t hint) -> laddr_t {
+      auto ret = alloc_mappings(t, hint, 4096);
+      assert(ret.size() == 1);
+      return ret.front()->get_key();
+    };
+
+    auto hint = laddr_hint_t::create_fresh_object_md_hint(
+      shard, pool, crush, laddr_t::UNIT_SIZE);
+    // set to max - 1 to test the linear_search policy
+    hint.addr.set_offset_by_blocks(
+      uint64_t(std::numeric_limits<uint32_t>::max() - 1));
+
+    auto base_addr = alloc(hint);
+    auto object_id = base_addr.get_local_object_id();
+    auto clone_id = base_addr.get_local_clone_id();
+    auto block_offset = base_addr.get_offset_bytes();
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr;
+      // conflict with other object
+      hint.condition = laddr_conflict_condition_t::object_prefix_at_object_id;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_NE(object_id, addr.get_local_object_id());
+      ASSERT_EQ(clone_id, addr.get_local_clone_id());
+      ASSERT_EQ(block_offset, addr.get_offset_bytes());
+    }
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr.with_offset_by_bytes(block_offset + laddr_t::UNIT_SIZE);
+      // conflict with other object, check prev
+      hint.condition = laddr_conflict_condition_t::object_prefix_at_object_id;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_NE(object_id, addr.get_local_object_id());
+      ASSERT_EQ(clone_id, addr.get_local_clone_id());
+      ASSERT_EQ(block_offset + laddr_t::UNIT_SIZE, addr.get_offset_bytes());
+    }
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr;
+      // conflict with other clone
+      hint.condition = laddr_conflict_condition_t::clone_prefix_at_clone_id;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_EQ(object_id, addr.get_local_object_id());
+      ASSERT_NE(clone_id, addr.get_local_clone_id());
+      ASSERT_EQ(block_offset, addr.get_offset_bytes());
+    }
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr.with_offset_by_bytes(block_offset + laddr_t::UNIT_SIZE);
+      // conflict with other clone, check prev
+      hint.condition = laddr_conflict_condition_t::clone_prefix_at_clone_id;
+      hint.policy = laddr_conflict_policy_t::gen_random;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_EQ(object_id, addr.get_local_object_id());
+      ASSERT_NE(clone_id, addr.get_local_clone_id());
+      ASSERT_EQ(block_offset + laddr_t::UNIT_SIZE, addr.get_offset_bytes());
+    }
+
+    {
+      laddr_hint_t hint;
+      hint.addr = base_addr;
+      // conflict with other extents
+      hint.condition = laddr_conflict_condition_t::all_at_object_content;
+      hint.policy = laddr_conflict_policy_t::linear_search;
+      hint.block_size = laddr_t::UNIT_SIZE;
+      auto addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_EQ(object_id, addr.get_local_object_id());
+      ASSERT_EQ(clone_id, addr.get_local_clone_id());
+      ASSERT_EQ(block_offset + laddr_t::UNIT_SIZE, addr.get_offset_bytes());
+
+      addr = alloc(hint);
+      ASSERT_EQ(base_addr.get_shard(), addr.get_shard());
+      ASSERT_EQ(base_addr.get_pool(), addr.get_pool());
+      ASSERT_EQ(base_addr.get_reversed_hash(), addr.get_reversed_hash());
+      ASSERT_EQ(object_id, addr.get_local_object_id());
+      ASSERT_EQ(clone_id, addr.get_local_clone_id());
+      ASSERT_EQ(0, addr.get_offset_bytes());
+    }
+
+    submit_test_transaction(std::move(t));
+    check_mappings();
+  });
+}