1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/crimson/gtest_seastar.h"
5 #include "test/crimson/seastore/transaction_manager_test_state.h"
7 #include "crimson/os/seastore/cache.h"
8 #include "crimson/os/seastore/transaction_manager.h"
9 #include "crimson/os/seastore/segment_manager.h"
10 #include "crimson/os/seastore/extentmap_manager.h"
12 #include "test/crimson/seastore/test_block.h"
14 using namespace crimson
;
15 using namespace crimson::os
;
16 using namespace crimson::os::seastore
;
19 [[maybe_unused
]] seastar::logger
& logger() {
20 return crimson::get_logger(ceph_subsys_test
);
25 struct extentmap_manager_test_t
:
26 public seastar_test_suite_t
,
29 ExtentMapManagerRef extmap_manager
;
31 extentmap_manager_test_t() {}
33 seastar::future
<> set_up_fut() final
{
34 return tm_setup().then([this] {
35 extmap_manager
= extentmap_manager::create_extentmap_manager(*tm
);
36 return seastar::now();
40 seastar::future
<> tear_down_fut() final
{
41 return tm_teardown().then([this] {
42 extmap_manager
.reset();
43 return seastar::now();
47 using test_extmap_t
= std::map
<uint32_t, lext_map_val_t
>;
48 test_extmap_t test_ext_mappings
;
50 extent_mapping_t
insert_extent(
51 extmap_root_t
&extmap_root
,
55 auto extent
= extmap_manager
->add_lextent(extmap_root
, t
, lo
, val
).unsafe_get0();
56 EXPECT_EQ(lo
, extent
.logical_offset
);
57 EXPECT_EQ(val
.laddr
, extent
.laddr
);
58 EXPECT_EQ(val
.length
, extent
.length
);
59 test_ext_mappings
.emplace(extent
.logical_offset
,
60 lext_map_val_t
{extent
.laddr
, extent
.length
});
64 extent_map_list_t
find_extent(
65 extmap_root_t
&extmap_root
,
69 auto extent
= extmap_manager
->find_lextent(extmap_root
, t
, lo
, len
).unsafe_get0();
70 EXPECT_EQ(lo
, extent
.front().logical_offset
);
71 EXPECT_EQ(len
, extent
.front().length
);
75 extent_map_list_t
findno_extent(
76 extmap_root_t
&extmap_root
,
80 auto extent
= extmap_manager
->find_lextent(extmap_root
, t
, lo
, len
).unsafe_get0();
81 EXPECT_EQ(extent
.empty(), true);
86 extmap_root_t
&extmap_root
,
89 lext_map_val_t val
) {
90 auto ret
= extmap_manager
->rm_lextent(extmap_root
, t
, lo
, val
).unsafe_get0();
92 test_ext_mappings
.erase(lo
);
95 void check_mappings(extmap_root_t
&extmap_root
, Transaction
&t
) {
96 for (const auto& [lo
, ext
]: test_ext_mappings
){
97 const auto ext_list
= find_extent(extmap_root
, t
, lo
, ext
.length
);
98 ASSERT_EQ(ext_list
.size(), 1);
99 const auto& ext_map
= ext_list
.front();
100 EXPECT_EQ(ext
.laddr
, ext_map
.laddr
);
101 EXPECT_EQ(ext
.length
, ext_map
.length
);
105 void check_mappings(extmap_root_t
&extmap_root
) {
106 auto t
= tm
->create_transaction();
107 check_mappings(extmap_root
, *t
);
111 logger().debug("{}: begin", __func__
);
113 extmap_manager
= extentmap_manager::create_extentmap_manager(*tm
);
114 logger().debug("{}: end", __func__
);
120 TEST_F(extentmap_manager_test_t
, basic
)
123 extmap_root_t
extmap_root(0, L_ADDR_NULL
);
125 auto t
= tm
->create_transaction();
126 extmap_root
= extmap_manager
->initialize_extmap(*t
).unsafe_get0();
127 tm
->submit_transaction(std::move(t
)).unsafe_get();
131 uint32_t lo
= 0x1 * len
;
133 auto t
= tm
->create_transaction();
134 logger().debug("first transaction");
135 [[maybe_unused
]] auto addref
= insert_extent(extmap_root
, *t
, lo
, {lo
, len
});
136 [[maybe_unused
]] auto seekref
= find_extent(extmap_root
, *t
, lo
, len
);
137 tm
->submit_transaction(std::move(t
)).unsafe_get();
140 auto t
= tm
->create_transaction();
141 logger().debug("second transaction");
142 auto seekref
= find_extent(extmap_root
, *t
, lo
, len
);
143 rm_extent(extmap_root
, *t
, lo
, {seekref
.front().laddr
, len
});
144 [[maybe_unused
]] auto seekref2
= findno_extent(extmap_root
, *t
, lo
, len
);
145 tm
->submit_transaction(std::move(t
)).unsafe_get();
148 auto t
= tm
->create_transaction();
149 logger().debug("third transaction");
150 [[maybe_unused
]] auto seekref
= findno_extent(extmap_root
, *t
, lo
, len
);
151 tm
->submit_transaction(std::move(t
)).unsafe_get();
156 TEST_F(extentmap_manager_test_t
, force_leafnode_split
)
159 extmap_root_t
extmap_root(0, L_ADDR_NULL
);
161 auto t
= tm
->create_transaction();
162 extmap_root
= extmap_manager
->initialize_extmap(*t
).unsafe_get0();
163 tm
->submit_transaction(std::move(t
)).unsafe_get();
167 for (unsigned i
= 0; i
< 40; i
++) {
168 auto t
= tm
->create_transaction();
169 logger().debug("opened transaction");
170 for (unsigned j
= 0; j
< 10; ++j
) {
171 [[maybe_unused
]] auto addref
= insert_extent(extmap_root
, *t
, lo
, {lo
, len
});
173 if ((i
% 20 == 0) && (j
== 5)) {
174 check_mappings(extmap_root
, *t
);
177 logger().debug("force split submit transaction i = {}", i
);
178 tm
->submit_transaction(std::move(t
)).unsafe_get();
179 check_mappings(extmap_root
);
185 TEST_F(extentmap_manager_test_t
, force_leafnode_split_merge
)
188 extmap_root_t
extmap_root(0, L_ADDR_NULL
);
190 auto t
= tm
->create_transaction();
191 extmap_root
= extmap_manager
->initialize_extmap(*t
).unsafe_get0();
192 tm
->submit_transaction(std::move(t
)).unsafe_get();
196 for (unsigned i
= 0; i
< 80; i
++) {
197 auto t
= tm
->create_transaction();
198 logger().debug("opened split_merge transaction");
199 for (unsigned j
= 0; j
< 5; ++j
) {
200 [[maybe_unused
]] auto addref
= insert_extent(extmap_root
, *t
, lo
, {lo
, len
});
202 if ((i
% 10 == 0) && (j
== 3)) {
203 check_mappings(extmap_root
, *t
);
206 logger().debug("submitting transaction");
207 tm
->submit_transaction(std::move(t
)).unsafe_get();
209 check_mappings(extmap_root
);
212 auto t
= tm
->create_transaction();
214 for (auto iter
= test_ext_mappings
.begin(); iter
!= test_ext_mappings
.end();) {
215 auto [lo
, ext
] = *iter
;
218 rm_extent(extmap_root
, *t
, lo
, ext
);
223 logger().debug("submitting transaction i= {}", i
);
224 tm
->submit_transaction(std::move(t
)).unsafe_get();
225 t
= tm
->create_transaction();
228 logger().debug("check_mappings i= {}", i
);
229 check_mappings(extmap_root
, *t
);
230 check_mappings(extmap_root
);
233 logger().debug("finally submitting transaction ");
234 tm
->submit_transaction(std::move(t
)).unsafe_get();
238 TEST_F(extentmap_manager_test_t
, force_leafnode_split_merge_replay
)
241 extmap_root_t
extmap_root(0, L_ADDR_NULL
);
243 auto t
= tm
->create_transaction();
244 extmap_root
= extmap_manager
->initialize_extmap(*t
).unsafe_get0();
245 tm
->submit_transaction(std::move(t
)).unsafe_get();
250 for (unsigned i
= 0; i
< 50; i
++) {
251 auto t
= tm
->create_transaction();
252 logger().debug("opened split_merge transaction");
253 for (unsigned j
= 0; j
< 5; ++j
) {
254 [[maybe_unused
]] auto addref
= insert_extent(extmap_root
, *t
, lo
, {lo
, len
});
257 logger().debug("submitting transaction");
258 tm
->submit_transaction(std::move(t
)).unsafe_get();
261 auto t
= tm
->create_transaction();
263 for (auto iter
= test_ext_mappings
.begin(); iter
!= test_ext_mappings
.end();) {
264 auto [lo
, ext
] = *iter
;
266 rm_extent(extmap_root
, *t
, lo
, ext
);
270 logger().debug("submitting transaction i= {}", i
);
271 tm
->submit_transaction(std::move(t
)).unsafe_get();
272 t
= tm
->create_transaction();
275 check_mappings(extmap_root
);
278 logger().debug("finally submitting transaction ");
279 tm
->submit_transaction(std::move(t
)).unsafe_get();
281 check_mappings(extmap_root
);