]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "test/crimson/gtest_seastar.h" | |
5 | #include "test/crimson/seastore/transaction_manager_test_state.h" | |
6 | ||
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" | |
11 | ||
12 | #include "test/crimson/seastore/test_block.h" | |
13 | ||
14 | using namespace crimson; | |
15 | using namespace crimson::os; | |
16 | using namespace crimson::os::seastore; | |
17 | ||
18 | namespace { | |
19 | [[maybe_unused]] seastar::logger& logger() { | |
20 | return crimson::get_logger(ceph_subsys_test); | |
21 | } | |
22 | } | |
23 | ||
24 | ||
25 | struct extentmap_manager_test_t : | |
26 | public seastar_test_suite_t, | |
27 | TMTestState { | |
28 | ||
29 | ExtentMapManagerRef extmap_manager; | |
30 | ||
31 | extentmap_manager_test_t() {} | |
32 | ||
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(); | |
37 | }); | |
38 | } | |
39 | ||
40 | seastar::future<> tear_down_fut() final { | |
41 | return tm_teardown().then([this] { | |
42 | extmap_manager.reset(); | |
43 | return seastar::now(); | |
44 | }); | |
45 | } | |
46 | ||
47 | using test_extmap_t = std::map<uint32_t, lext_map_val_t>; | |
48 | test_extmap_t test_ext_mappings; | |
49 | ||
50 | extent_mapping_t insert_extent( | |
51 | extmap_root_t &extmap_root, | |
52 | Transaction &t, | |
53 | uint32_t lo, | |
54 | lext_map_val_t val) { | |
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}); | |
61 | return extent; | |
62 | } | |
63 | ||
64 | extent_map_list_t find_extent( | |
65 | extmap_root_t &extmap_root, | |
66 | Transaction &t, | |
67 | uint32_t lo, | |
68 | uint32_t len) { | |
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); | |
72 | return extent; | |
73 | } | |
74 | ||
75 | extent_map_list_t findno_extent( | |
76 | extmap_root_t &extmap_root, | |
77 | Transaction &t, | |
78 | uint32_t lo, | |
79 | uint32_t len) { | |
80 | auto extent = extmap_manager->find_lextent(extmap_root, t, lo, len).unsafe_get0(); | |
81 | EXPECT_EQ(extent.empty(), true); | |
82 | return extent; | |
83 | } | |
84 | ||
85 | void rm_extent( | |
86 | extmap_root_t &extmap_root, | |
87 | Transaction &t, | |
88 | uint32_t lo, | |
89 | lext_map_val_t val ) { | |
90 | auto ret = extmap_manager->rm_lextent(extmap_root, t, lo, val).unsafe_get0(); | |
91 | EXPECT_TRUE(ret); | |
92 | test_ext_mappings.erase(lo); | |
93 | } | |
94 | ||
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); | |
102 | } | |
103 | } | |
104 | ||
105 | void check_mappings(extmap_root_t &extmap_root) { | |
106 | auto t = tm->create_transaction(); | |
107 | check_mappings(extmap_root, *t); | |
108 | } | |
109 | ||
110 | void replay() { | |
111 | logger().debug("{}: begin", __func__); | |
112 | restart(); | |
113 | extmap_manager = extentmap_manager::create_extentmap_manager(*tm); | |
114 | logger().debug("{}: end", __func__); | |
115 | } | |
116 | ||
117 | ||
118 | }; | |
119 | ||
120 | TEST_F(extentmap_manager_test_t, basic) | |
121 | { | |
122 | run_async([this] { | |
123 | extmap_root_t extmap_root(0, L_ADDR_NULL); | |
124 | { | |
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(); | |
128 | } | |
129 | ||
130 | uint32_t len = 4096; | |
131 | uint32_t lo = 0x1 * len; | |
132 | { | |
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(); | |
138 | } | |
139 | { | |
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(); | |
146 | } | |
147 | { | |
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(); | |
152 | } | |
153 | }); | |
154 | } | |
155 | ||
156 | TEST_F(extentmap_manager_test_t, force_leafnode_split) | |
157 | { | |
158 | run_async([this] { | |
159 | extmap_root_t extmap_root(0, L_ADDR_NULL); | |
160 | { | |
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(); | |
164 | } | |
165 | uint32_t len = 4096; | |
166 | uint32_t lo = 0; | |
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}); | |
172 | lo += len; | |
173 | if ((i % 20 == 0) && (j == 5)) { | |
174 | check_mappings(extmap_root, *t); | |
175 | } | |
176 | } | |
177 | logger().debug("force split submit transaction i = {}", i); | |
178 | tm->submit_transaction(std::move(t)).unsafe_get(); | |
179 | check_mappings(extmap_root); | |
180 | } | |
181 | }); | |
182 | ||
183 | } | |
184 | ||
185 | TEST_F(extentmap_manager_test_t, force_leafnode_split_merge) | |
186 | { | |
187 | run_async([this] { | |
188 | extmap_root_t extmap_root(0, L_ADDR_NULL); | |
189 | { | |
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(); | |
193 | } | |
194 | uint32_t len = 4096; | |
195 | uint32_t lo = 0; | |
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}); | |
201 | lo += len; | |
202 | if ((i % 10 == 0) && (j == 3)) { | |
203 | check_mappings(extmap_root, *t); | |
204 | } | |
205 | } | |
206 | logger().debug("submitting transaction"); | |
207 | tm->submit_transaction(std::move(t)).unsafe_get(); | |
208 | if (i % 50 == 0) { | |
209 | check_mappings(extmap_root); | |
210 | } | |
211 | } | |
212 | auto t = tm->create_transaction(); | |
213 | int i = 0; | |
214 | for (auto iter = test_ext_mappings.begin(); iter != test_ext_mappings.end();) { | |
215 | auto [lo, ext] = *iter; | |
216 | ++iter; | |
217 | if (i % 3 != 0) { | |
218 | rm_extent(extmap_root, *t, lo, ext); | |
219 | } | |
220 | i++; | |
221 | ||
222 | if (i % 10 == 0) { | |
223 | logger().debug("submitting transaction i= {}", i); | |
224 | tm->submit_transaction(std::move(t)).unsafe_get(); | |
225 | t = tm->create_transaction(); | |
226 | } | |
227 | if (i % 100 == 0) { | |
228 | logger().debug("check_mappings i= {}", i); | |
229 | check_mappings(extmap_root, *t); | |
230 | check_mappings(extmap_root); | |
231 | } | |
232 | } | |
233 | logger().debug("finally submitting transaction "); | |
234 | tm->submit_transaction(std::move(t)).unsafe_get(); | |
235 | }); | |
236 | } | |
237 | ||
238 | TEST_F(extentmap_manager_test_t, force_leafnode_split_merge_replay) | |
239 | { | |
240 | run_async([this] { | |
241 | extmap_root_t extmap_root(0, L_ADDR_NULL); | |
242 | { | |
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(); | |
246 | replay(); | |
247 | } | |
248 | uint32_t len = 4096; | |
249 | uint32_t lo = 0; | |
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}); | |
255 | lo += len; | |
256 | } | |
257 | logger().debug("submitting transaction"); | |
258 | tm->submit_transaction(std::move(t)).unsafe_get(); | |
259 | } | |
260 | replay(); | |
261 | auto t = tm->create_transaction(); | |
262 | int i = 0; | |
263 | for (auto iter = test_ext_mappings.begin(); iter != test_ext_mappings.end();) { | |
264 | auto [lo, ext] = *iter; | |
265 | ++iter; | |
266 | rm_extent(extmap_root, *t, lo, ext); | |
267 | i++; | |
268 | ||
269 | if (i % 10 == 0) { | |
270 | logger().debug("submitting transaction i= {}", i); | |
271 | tm->submit_transaction(std::move(t)).unsafe_get(); | |
272 | t = tm->create_transaction(); | |
273 | } | |
274 | if (i% 100 == 0){ | |
275 | check_mappings(extmap_root); | |
276 | } | |
277 | } | |
278 | logger().debug("finally submitting transaction "); | |
279 | tm->submit_transaction(std::move(t)).unsafe_get(); | |
280 | replay(); | |
281 | check_mappings(extmap_root); | |
282 | }); | |
283 | } |