]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/crimson/seastore/onode_tree/test_fltree_onode_manager.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / crimson / seastore / onode_tree / test_fltree_onode_manager.cc
CommitLineData
20effc67
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
2// vim: ts=8 sw=2 smarttab
3
4#include <boost/range/combine.hpp>
5
6#include "test/crimson/gtest_seastar.h"
7
8#include "test/crimson/seastore/transaction_manager_test_state.h"
9
10#include "crimson/os/seastore/onode_manager/staged-fltree/fltree_onode_manager.h"
11#include "crimson/os/seastore/onode_manager/staged-fltree/tree_utils.h"
12
13using namespace crimson;
14using namespace crimson::os;
15using namespace crimson::os::seastore;
16using namespace crimson::os::seastore::onode;
17using CTransaction = ceph::os::Transaction;
18using namespace std;
19
20namespace {
21 [[maybe_unused]] seastar::logger& logger() {
22 return crimson::get_logger(ceph_subsys_test);
23 }
24}
25
26struct onode_item_t {
27 uint32_t size;
28 uint64_t id;
1e59de90 29 uint64_t block_size;
20effc67
TL
30 uint32_t cnt_modify = 0;
31
32 void initialize(Transaction& t, Onode& value) const {
33 auto& layout = value.get_mutable_layout(t);
34 layout.size = size;
1e59de90
TL
35 layout.omap_root.update(omap_root_t(id, cnt_modify,
36 value.get_metadata_hint(block_size)));
20effc67
TL
37 validate(value);
38 }
39
40 void validate(Onode& value) const {
41 auto& layout = value.get_layout();
42 ceph_assert(laddr_t(layout.size) == laddr_t{size});
1e59de90
TL
43 ceph_assert(layout.omap_root.get(value.get_metadata_hint(block_size)).addr == id);
44 ceph_assert(layout.omap_root.get(value.get_metadata_hint(block_size)).depth == cnt_modify);
20effc67
TL
45 }
46
47 void modify(Transaction& t, Onode& value) {
48 validate(value);
49 ++cnt_modify;
50 initialize(t, value);
51 }
52
1e59de90 53 static onode_item_t create(std::size_t size, std::size_t id, uint64_t block_size) {
20effc67 54 ceph_assert(size <= std::numeric_limits<uint32_t>::max());
1e59de90 55 return {(uint32_t)size, id, block_size};
20effc67
TL
56 }
57};
58
59struct fltree_onode_manager_test_t
60 : public seastar_test_suite_t, TMTestState {
61 using iterator_t = typename KVPool<onode_item_t>::iterator_t;
62
63 FLTreeOnodeManagerRef manager;
64
65 seastar::future<> set_up_fut() final {
66 return tm_setup();
67 }
68
69 seastar::future<> tear_down_fut() final {
70 return tm_teardown();
71 }
72
1e59de90
TL
73 virtual seastar::future<> _init() final {
74 return TMTestState::_init().then([this] {
75 manager.reset(new FLTreeOnodeManager(*tm));
76 });
20effc67
TL
77 }
78
1e59de90 79 virtual seastar::future<> _destroy() final {
20effc67 80 manager.reset();
1e59de90 81 return TMTestState::_destroy();
20effc67
TL
82 }
83
84 virtual FuturizedStore::mkfs_ertr::future<> _mkfs() final {
85 return TMTestState::_mkfs(
86 ).safe_then([this] {
1e59de90
TL
87 return restart_fut();
88 }).safe_then([this] {
89 return repeat_eagain([this] {
90 return seastar::do_with(
91 create_mutate_transaction(),
92 [this](auto &ref_t)
93 {
94 return with_trans_intr(*ref_t, [&](auto &t) {
95 return manager->mkfs(t
96 ).si_then([this, &t] {
97 return submit_transaction_fut2(t);
98 });
99 });
100 });
101 });
102 }).handle_error(
103 crimson::ct_error::assert_all{"Invalid error in _mkfs"}
104 );
20effc67
TL
105 }
106
107 template <typename F>
108 void with_transaction(F&& f) {
109 auto t = create_mutate_transaction();
110 std::invoke(f, *t);
111 submit_transaction(std::move(t));
20effc67
TL
112 }
113
114 template <typename F>
115 void with_onode_write(iterator_t& it, F&& f) {
116 with_transaction([this, &it, f=std::move(f)] (auto& t) {
117 auto p_kv = *it;
118 auto onode = with_trans_intr(t, [&](auto &t) {
119 return manager->get_or_create_onode(t, p_kv->key);
120 }).unsafe_get0();
121 std::invoke(f, t, *onode, p_kv->value);
122 with_trans_intr(t, [&](auto &t) {
123 return manager->write_dirty(t, {onode});
124 }).unsafe_get0();
125 });
126 }
127
128 void validate_onode(iterator_t& it) {
129 with_transaction([this, &it] (auto& t) {
130 auto p_kv = *it;
131 auto onode = with_trans_intr(t, [&](auto &t) {
132 return manager->get_onode(t, p_kv->key);
133 }).unsafe_get0();
134 p_kv->value.validate(*onode);
135 });
136 }
137
138 void validate_erased(iterator_t& it) {
139 with_transaction([this, &it] (auto& t) {
140 auto p_kv = *it;
141 auto exist = with_trans_intr(t, [&](auto &t) {
142 return manager->contains_onode(t, p_kv->key);
143 }).unsafe_get0();
144 ceph_assert(exist == false);
145 });
146 }
147
148 template <typename F>
149 void with_onodes_process(
150 const iterator_t& start, const iterator_t& end, F&& f) {
151 std::vector<ghobject_t> oids;
152 std::vector<onode_item_t*> items;
153 auto it = start;
154 while(it != end) {
155 auto p_kv = *it;
156 oids.emplace_back(p_kv->key);
157 items.emplace_back(&p_kv->value);
158 ++it;
159 }
160 with_transaction([&oids, &items, f=std::move(f)] (auto& t) mutable {
161 std::invoke(f, t, oids, items);
162 });
163 }
164
165 template <typename F>
166 void with_onodes_write(
167 const iterator_t& start, const iterator_t& end, F&& f) {
168 with_onodes_process(start, end,
169 [this, f=std::move(f)] (auto& t, auto& oids, auto& items) {
170 auto onodes = with_trans_intr(t, [&](auto &t) {
171 return manager->get_or_create_onodes(t, oids);
172 }).unsafe_get0();
173 for (auto tup : boost::combine(onodes, items)) {
174 OnodeRef onode;
175 onode_item_t* p_item;
176 boost::tie(onode, p_item) = tup;
177 std::invoke(f, t, *onode, *p_item);
178 }
179 with_trans_intr(t, [&](auto &t) {
180 return manager->write_dirty(t, onodes);
181 }).unsafe_get0();
182 });
183 }
184
185 void validate_onodes(
186 const iterator_t& start, const iterator_t& end) {
187 with_onodes_process(start, end,
188 [this] (auto& t, auto& oids, auto& items) {
189 for (auto tup : boost::combine(oids, items)) {
190 ghobject_t oid;
191 onode_item_t* p_item;
192 boost::tie(oid, p_item) = tup;
193 auto onode = with_trans_intr(t, [&](auto &t) {
194 return manager->get_onode(t, oid);
195 }).unsafe_get0();
196 p_item->validate(*onode);
197 }
198 });
199 }
200
201 void validate_erased(
202 const iterator_t& start, const iterator_t& end) {
203 with_onodes_process(start, end,
204 [this] (auto& t, auto& oids, auto& items) {
205 for (auto& oid : oids) {
206 auto exist = with_trans_intr(t, [&](auto &t) {
207 return manager->contains_onode(t, oid);
208 }).unsafe_get0();
209 ceph_assert(exist == false);
210 }
211 });
212 }
213
214 static constexpr uint64_t LIST_LIMIT = 10;
215 void validate_list_onodes(KVPool<onode_item_t>& pool) {
216 with_onodes_process(pool.begin(), pool.end(),
217 [this] (auto& t, auto& oids, auto& items) {
218 std::vector<ghobject_t> listed_oids;
219 auto start = ghobject_t();
220 auto end = ghobject_t::get_max();
221 assert(start < end);
222 assert(start < oids[0]);
223 assert(oids[0] < end);
224 while (start != end) {
225 auto [list_ret, list_end] = with_trans_intr(t, [&](auto &t) {
226 return manager->list_onodes(t, start, end, LIST_LIMIT);
227 }).unsafe_get0();
228 listed_oids.insert(listed_oids.end(), list_ret.begin(), list_ret.end());
229 start = list_end;
230 }
231 ceph_assert(oids.size() == listed_oids.size());
232 });
233 }
234
235 fltree_onode_manager_test_t() {}
236};
237
238TEST_F(fltree_onode_manager_test_t, 1_single)
239{
240 run_async([this] {
1e59de90
TL
241 uint64_t block_size = tm->get_block_size();
242 auto pool = KVPool<onode_item_t>::create_range({0, 1}, {128, 256}, block_size);
20effc67
TL
243 auto iter = pool.begin();
244 with_onode_write(iter, [](auto& t, auto& onode, auto& item) {
245 item.initialize(t, onode);
246 });
247 validate_onode(iter);
248
249 with_onode_write(iter, [](auto& t, auto& onode, auto& item) {
250 item.modify(t, onode);
251 });
252 validate_onode(iter);
253
254 validate_list_onodes(pool);
255
256 with_onode_write(iter, [this](auto& t, auto& onode, auto& item) {
257 OnodeRef onode_ref = &onode;
258 with_trans_intr(t, [&](auto &t) {
259 return manager->erase_onode(t, onode_ref);
260 }).unsafe_get0();
261 });
262 validate_erased(iter);
263 });
264}
265
266TEST_F(fltree_onode_manager_test_t, 2_synthetic)
267{
268 run_async([this] {
1e59de90 269 uint64_t block_size = tm->get_block_size();
20effc67 270 auto pool = KVPool<onode_item_t>::create_range(
1e59de90 271 {0, 100}, {32, 64, 128, 256, 512}, block_size);
20effc67
TL
272 auto start = pool.begin();
273 auto end = pool.end();
274 with_onodes_write(start, end,
275 [](auto& t, auto& onode, auto& item) {
276 item.initialize(t, onode);
277 });
278 validate_onodes(start, end);
279
280 validate_list_onodes(pool);
281
282 auto rd_start = pool.random_begin();
283 auto rd_end = rd_start + 50;
284 with_onodes_write(rd_start, rd_end,
285 [](auto& t, auto& onode, auto& item) {
286 item.modify(t, onode);
287 });
288 validate_onodes(start, end);
289
290 pool.shuffle();
291 rd_start = pool.random_begin();
292 rd_end = rd_start + 50;
293 with_onodes_write(rd_start, rd_end,
294 [](auto& t, auto& onode, auto& item) {
295 item.modify(t, onode);
296 });
297 validate_onodes(start, end);
298
299 pool.shuffle();
300 rd_start = pool.random_begin();
301 rd_end = rd_start + 50;
302 with_onodes_write(rd_start, rd_end,
303 [this](auto& t, auto& onode, auto& item) {
304 OnodeRef onode_ref = &onode;
305 with_trans_intr(t, [&](auto &t) {
306 return manager->erase_onode(t, onode_ref);
307 }).unsafe_get0();
308 });
309 validate_erased(rd_start, rd_end);
310 pool.erase_from_random(rd_start, rd_end);
311 start = pool.begin();
312 end = pool.end();
313 validate_onodes(start, end);
314
315 validate_list_onodes(pool);
316 });
317}