]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/crimson/seastore/test_object_data_handler.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / test / crimson / seastore / test_object_data_handler.cc
CommitLineData
20effc67
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/onode.h"
8#include "crimson/os/seastore/object_data_handler.h"
9
10using namespace crimson;
11using namespace crimson::os;
12using namespace crimson::os::seastore;
13
14#define MAX_OBJECT_SIZE (16<<20)
15#define DEFAULT_OBJECT_DATA_RESERVATION (16<<20)
16#define DEFAULT_OBJECT_METADATA_RESERVATION (16<<20)
17
18namespace {
19 [[maybe_unused]] seastar::logger& logger() {
20 return crimson::get_logger(ceph_subsys_test);
21 }
22}
23
24class TestOnode final : public Onode {
25 onode_layout_t layout;
26 bool dirty = false;
27
28public:
29 TestOnode(uint32_t ddr, uint32_t dmr) : Onode(ddr, dmr) {}
30 const onode_layout_t &get_layout() const final {
31 return layout;
32 }
33 onode_layout_t &get_mutable_layout(Transaction &t) final {
34 dirty = true;
35 return layout;
36 }
aee94f69
TL
37 bool is_alive() const {
38 return true;
39 }
20effc67
TL
40 bool is_dirty() const { return dirty; }
41 laddr_t get_hint() const final {return L_ADDR_MIN; }
42 ~TestOnode() final = default;
43};
44
45struct object_data_handler_test_t:
46 public seastar_test_suite_t,
47 TMTestState {
48 OnodeRef onode;
49
50 bufferptr known_contents;
51 extent_len_t size = 0;
52
53 object_data_handler_test_t() {}
54
55 void write(Transaction &t, objaddr_t offset, extent_len_t len, char fill) {
56 ceph_assert(offset + len <= known_contents.length());
57 size = std::max<extent_len_t>(size, offset + len);
58 memset(
59 known_contents.c_str() + offset,
60 fill,
61 len);
62 bufferlist bl;
63 bl.append(
64 bufferptr(
65 known_contents,
66 offset,
67 len));
68 with_trans_intr(t, [&](auto &t) {
69 return ObjectDataHandler(MAX_OBJECT_SIZE).write(
70 ObjectDataHandler::context_t{
71 *tm,
72 t,
73 *onode,
74 },
75 offset,
76 bl);
77 }).unsafe_get0();
78 }
79 void write(objaddr_t offset, extent_len_t len, char fill) {
80 auto t = create_mutate_transaction();
81 write(*t, offset, len, fill);
82 return submit_transaction(std::move(t));
83 }
84
85 void truncate(Transaction &t, objaddr_t offset) {
86 if (size > offset) {
87 memset(
88 known_contents.c_str() + offset,
89 0,
90 size - offset);
91 with_trans_intr(t, [&](auto &t) {
92 return ObjectDataHandler(MAX_OBJECT_SIZE).truncate(
93 ObjectDataHandler::context_t{
94 *tm,
95 t,
96 *onode
97 },
98 offset);
99 }).unsafe_get0();
100 }
101 size = offset;
102 }
103 void truncate(objaddr_t offset) {
104 auto t = create_mutate_transaction();
105 truncate(*t, offset);
106 return submit_transaction(std::move(t));
107 }
108
109 void read(Transaction &t, objaddr_t offset, extent_len_t len) {
110 bufferlist bl = with_trans_intr(t, [&](auto &t) {
111 return ObjectDataHandler(MAX_OBJECT_SIZE).read(
112 ObjectDataHandler::context_t{
113 *tm,
114 t,
115 *onode
116 },
117 offset,
118 len);
119 }).unsafe_get0();
120 bufferlist known;
121 known.append(
122 bufferptr(
123 known_contents,
124 offset,
125 len));
126 EXPECT_EQ(bl.length(), known.length());
127 EXPECT_EQ(bl, known);
128 }
129 void read(objaddr_t offset, extent_len_t len) {
130 auto t = create_read_transaction();
131 read(*t, offset, len);
132 }
133 void read_near(objaddr_t offset, extent_len_t len, extent_len_t fuzz) {
134 auto fuzzes = std::vector<int32_t>{-1 * (int32_t)fuzz, 0, (int32_t)fuzz};
135 for (auto left_fuzz : fuzzes) {
136 for (auto right_fuzz : fuzzes) {
137 read(offset + left_fuzz, len - left_fuzz + right_fuzz);
138 }
139 }
140 }
1e59de90
TL
141 std::list<LBAMappingRef> get_mappings(objaddr_t offset, extent_len_t length) {
142 auto t = create_mutate_transaction();
143 auto ret = with_trans_intr(*t, [&](auto &t) {
144 return tm->get_pins(t, offset, length);
145 }).unsafe_get0();
146 return ret;
147 }
20effc67
TL
148
149 seastar::future<> set_up_fut() final {
150 onode = new TestOnode(
151 DEFAULT_OBJECT_DATA_RESERVATION,
152 DEFAULT_OBJECT_METADATA_RESERVATION);
153 known_contents = buffer::create(4<<20 /* 4MB */);
154 memset(known_contents.c_str(), 0, known_contents.length());
155 size = 0;
156 return tm_setup();
157 }
158
159 seastar::future<> tear_down_fut() final {
160 onode.reset();
161 size = 0;
162 return tm_teardown();
163 }
164};
165
aee94f69 166TEST_P(object_data_handler_test_t, single_write)
20effc67
TL
167{
168 run_async([this] {
169 write(1<<20, 8<<10, 'c');
170
171 read_near(1<<20, 8<<10, 1);
172 read_near(1<<20, 8<<10, 512);
173 });
174}
175
aee94f69 176TEST_P(object_data_handler_test_t, multi_write)
20effc67
TL
177{
178 run_async([this] {
179 write((1<<20) - (4<<10), 4<<10, 'a');
180 write(1<<20, 4<<10, 'b');
181 write((1<<20) + (4<<10), 4<<10, 'c');
182
183 read_near(1<<20, 4<<10, 1);
184 read_near(1<<20, 4<<10, 512);
185
186 read_near((1<<20)-(4<<10), 12<<10, 1);
187 read_near((1<<20)-(4<<10), 12<<10, 512);
188 });
189}
190
aee94f69 191TEST_P(object_data_handler_test_t, write_hole)
20effc67
TL
192{
193 run_async([this] {
194 write((1<<20) - (4<<10), 4<<10, 'a');
195 // hole at 1<<20
196 write((1<<20) + (4<<10), 4<<10, 'c');
197
198 read_near(1<<20, 4<<10, 1);
199 read_near(1<<20, 4<<10, 512);
200
201 read_near((1<<20)-(4<<10), 12<<10, 1);
202 read_near((1<<20)-(4<<10), 12<<10, 512);
203 });
204}
205
aee94f69 206TEST_P(object_data_handler_test_t, overwrite_single)
20effc67
TL
207{
208 run_async([this] {
209 write((1<<20), 4<<10, 'a');
210 write((1<<20), 4<<10, 'c');
211
212 read_near(1<<20, 4<<10, 1);
213 read_near(1<<20, 4<<10, 512);
214 });
215}
216
aee94f69 217TEST_P(object_data_handler_test_t, overwrite_double)
20effc67
TL
218{
219 run_async([this] {
220 write((1<<20), 4<<10, 'a');
221 write((1<<20)+(4<<10), 4<<10, 'c');
222 write((1<<20), 8<<10, 'b');
223
224 read_near(1<<20, 8<<10, 1);
225 read_near(1<<20, 8<<10, 512);
226
227 read_near(1<<20, 4<<10, 1);
228 read_near(1<<20, 4<<10, 512);
229
230 read_near((1<<20) + (4<<10), 4<<10, 1);
231 read_near((1<<20) + (4<<10), 4<<10, 512);
232 });
233}
234
aee94f69 235TEST_P(object_data_handler_test_t, overwrite_partial)
20effc67
TL
236{
237 run_async([this] {
238 write((1<<20), 12<<10, 'a');
239 read_near(1<<20, 12<<10, 1);
240
241 write((1<<20)+(8<<10), 4<<10, 'b');
242 read_near(1<<20, 12<<10, 1);
243
244 write((1<<20)+(4<<10), 4<<10, 'c');
245 read_near(1<<20, 12<<10, 1);
246
247 write((1<<20), 4<<10, 'd');
248
249 read_near(1<<20, 12<<10, 1);
250 read_near(1<<20, 12<<10, 512);
251
252 read_near(1<<20, 4<<10, 1);
253 read_near(1<<20, 4<<10, 512);
254
255 read_near((1<<20) + (4<<10), 4<<10, 1);
256 read_near((1<<20) + (4<<10), 4<<10, 512);
257 });
258}
259
aee94f69 260TEST_P(object_data_handler_test_t, unaligned_write)
20effc67
TL
261{
262 run_async([this] {
263 objaddr_t base = 1<<20;
264 write(base, (4<<10)+(1<<10), 'a');
265 read_near(base-(4<<10), 12<<10, 512);
266
267 base = (1<<20) + (64<<10);
268 write(base+(1<<10), (4<<10)+(1<<10), 'b');
269 read_near(base-(4<<10), 12<<10, 512);
270
271 base = (1<<20) + (128<<10);
272 write(base-(1<<10), (4<<10)+(2<<20), 'c');
273 read_near(base-(4<<10), 12<<10, 512);
274 });
275}
276
aee94f69 277TEST_P(object_data_handler_test_t, unaligned_overwrite)
20effc67
TL
278{
279 run_async([this] {
280 objaddr_t base = 1<<20;
281 write(base, (128<<10) + (16<<10), 'x');
282
283 write(base, (4<<10)+(1<<10), 'a');
284 read_near(base-(4<<10), 12<<10, 2<<10);
285
286 base = (1<<20) + (64<<10);
287 write(base+(1<<10), (4<<10)+(1<<10), 'b');
288 read_near(base-(4<<10), 12<<10, 2<<10);
289
290 base = (1<<20) + (128<<10);
291 write(base-(1<<10), (4<<10)+(2<<20), 'c');
292 read_near(base-(4<<10), 12<<10, 2<<10);
293
294 read(base, (128<<10) + (16<<10));
295 });
296}
297
aee94f69 298TEST_P(object_data_handler_test_t, truncate)
20effc67
TL
299{
300 run_async([this] {
301 objaddr_t base = 1<<20;
302 write(base, 8<<10, 'a');
303 write(base+(8<<10), 8<<10, 'b');
304 write(base+(16<<10), 8<<10, 'c');
305
306 truncate(base + (32<<10));
307 read(base, 64<<10);
308
309 truncate(base + (24<<10));
310 read(base, 64<<10);
311
312 truncate(base + (12<<10));
313 read(base, 64<<10);
314
315 truncate(base - (12<<10));
316 read(base, 64<<10);
317 });
318}
1e59de90 319
aee94f69 320TEST_P(object_data_handler_test_t, no_split) {
1e59de90
TL
321 run_async([this] {
322 write(0, 8<<10, 'x');
323 write(0, 8<<10, 'a');
324
325 auto pins = get_mappings(0, 8<<10);
326 EXPECT_EQ(pins.size(), 1);
327
328 read(0, 8<<10);
329 });
330}
331
aee94f69 332TEST_P(object_data_handler_test_t, split_left) {
1e59de90
TL
333 run_async([this] {
334 write(0, 128<<10, 'x');
335
336 write(64<<10, 60<<10, 'a');
337
338 auto pins = get_mappings(0, 128<<10);
339 EXPECT_EQ(pins.size(), 2);
340
341 size_t res[2] = {0, 64<<10};
342 auto base = pins.front()->get_key();
343 int i = 0;
344 for (auto &pin : pins) {
345 EXPECT_EQ(pin->get_key() - base, res[i]);
346 i++;
347 }
348 read(0, 128<<10);
349 });
350}
351
aee94f69 352TEST_P(object_data_handler_test_t, split_right) {
1e59de90
TL
353 run_async([this] {
354 write(0, 128<<10, 'x');
355 write(4<<10, 60<<10, 'a');
356
357 auto pins = get_mappings(0, 128<<10);
358 EXPECT_EQ(pins.size(), 2);
359
360 size_t res[2] = {0, 64<<10};
361 auto base = pins.front()->get_key();
362 int i = 0;
363 for (auto &pin : pins) {
364 EXPECT_EQ(pin->get_key() - base, res[i]);
365 i++;
366 }
367 read(0, 128<<10);
368 });
369}
aee94f69 370TEST_P(object_data_handler_test_t, split_left_right) {
1e59de90
TL
371 run_async([this] {
372 write(0, 128<<10, 'x');
373 write(48<<10, 32<<10, 'a');
374
375 auto pins = get_mappings(0, 128<<10);
376 EXPECT_EQ(pins.size(), 3);
377
378 size_t res[3] = {0, 48<<10, 80<<10};
379 auto base = pins.front()->get_key();
380 int i = 0;
381 for (auto &pin : pins) {
382 EXPECT_EQ(pin->get_key() - base, res[i]);
383 i++;
384 }
385 });
386}
aee94f69 387TEST_P(object_data_handler_test_t, multiple_split) {
1e59de90
TL
388 run_async([this] {
389 write(0, 128<<10, 'x');
390
391 auto t = create_mutate_transaction();
392 // normal split
393 write(*t, 120<<10, 4<<10, 'a');
394 // not aligned right
395 write(*t, 4<<10, 5<<10, 'b');
396 // split right extent of last split result
397 write(*t, 32<<10, 4<<10, 'c');
398 // non aligned overwrite
399 write(*t, 13<<10, 4<<10, 'd');
400
401 write(*t, 64<<10, 32<<10, 'e');
402 // not split right
403 write(*t, 60<<10, 8<<10, 'f');
404
405 submit_transaction(std::move(t));
406
407 auto pins = get_mappings(0, 128<<10);
408 EXPECT_EQ(pins.size(), 10);
409
410 size_t res[10] = {0, 4<<10, 12<<10, 20<<10, 32<<10,
411 36<<10, 60<<10, 96<<10, 120<<10, 124<<10};
412 auto base = pins.front()->get_key();
413 int i = 0;
414 for (auto &pin : pins) {
415 EXPECT_EQ(pin->get_key() - base, res[i]);
416 i++;
417 }
418 read(0, 128<<10);
419 });
420}
aee94f69
TL
421
422INSTANTIATE_TEST_SUITE_P(
423 object_data_handler_test,
424 object_data_handler_test_t,
425 ::testing::Values (
426 "segmented",
427 "circularbounded"
428 )
429);
430
431