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/onode.h"
8 #include "crimson/os/seastore/object_data_handler.h"
10 using namespace crimson
;
11 using namespace crimson::os
;
12 using namespace crimson::os::seastore
;
14 #define MAX_OBJECT_SIZE (16<<20)
15 #define DEFAULT_OBJECT_DATA_RESERVATION (16<<20)
16 #define DEFAULT_OBJECT_METADATA_RESERVATION (16<<20)
19 [[maybe_unused
]] seastar::logger
& logger() {
20 return crimson::get_logger(ceph_subsys_test
);
24 class TestOnode final
: public Onode
{
25 onode_layout_t layout
;
29 TestOnode(uint32_t ddr
, uint32_t dmr
) : Onode(ddr
, dmr
) {}
30 const onode_layout_t
&get_layout() const final
{
33 onode_layout_t
&get_mutable_layout(Transaction
&t
) final
{
37 bool is_dirty() const { return dirty
; }
38 laddr_t
get_hint() const final
{return L_ADDR_MIN
; }
39 ~TestOnode() final
= default;
42 struct object_data_handler_test_t
:
43 public seastar_test_suite_t
,
47 bufferptr known_contents
;
48 extent_len_t size
= 0;
50 object_data_handler_test_t() {}
52 void write(Transaction
&t
, objaddr_t offset
, extent_len_t len
, char fill
) {
53 ceph_assert(offset
+ len
<= known_contents
.length());
54 size
= std::max
<extent_len_t
>(size
, offset
+ len
);
56 known_contents
.c_str() + offset
,
65 with_trans_intr(t
, [&](auto &t
) {
66 return ObjectDataHandler(MAX_OBJECT_SIZE
).write(
67 ObjectDataHandler::context_t
{
76 void write(objaddr_t offset
, extent_len_t len
, char fill
) {
77 auto t
= create_mutate_transaction();
78 write(*t
, offset
, len
, fill
);
79 return submit_transaction(std::move(t
));
82 void truncate(Transaction
&t
, objaddr_t offset
) {
85 known_contents
.c_str() + offset
,
88 with_trans_intr(t
, [&](auto &t
) {
89 return ObjectDataHandler(MAX_OBJECT_SIZE
).truncate(
90 ObjectDataHandler::context_t
{
100 void truncate(objaddr_t offset
) {
101 auto t
= create_mutate_transaction();
102 truncate(*t
, offset
);
103 return submit_transaction(std::move(t
));
106 void read(Transaction
&t
, objaddr_t offset
, extent_len_t len
) {
107 bufferlist bl
= with_trans_intr(t
, [&](auto &t
) {
108 return ObjectDataHandler(MAX_OBJECT_SIZE
).read(
109 ObjectDataHandler::context_t
{
123 EXPECT_EQ(bl
.length(), known
.length());
124 EXPECT_EQ(bl
, known
);
126 void read(objaddr_t offset
, extent_len_t len
) {
127 auto t
= create_read_transaction();
128 read(*t
, offset
, len
);
130 void read_near(objaddr_t offset
, extent_len_t len
, extent_len_t fuzz
) {
131 auto fuzzes
= std::vector
<int32_t>{-1 * (int32_t)fuzz
, 0, (int32_t)fuzz
};
132 for (auto left_fuzz
: fuzzes
) {
133 for (auto right_fuzz
: fuzzes
) {
134 read(offset
+ left_fuzz
, len
- left_fuzz
+ right_fuzz
);
139 seastar::future
<> set_up_fut() final
{
140 onode
= new TestOnode(
141 DEFAULT_OBJECT_DATA_RESERVATION
,
142 DEFAULT_OBJECT_METADATA_RESERVATION
);
143 known_contents
= buffer::create(4<<20 /* 4MB */);
144 memset(known_contents
.c_str(), 0, known_contents
.length());
149 seastar::future
<> tear_down_fut() final
{
152 return tm_teardown();
156 TEST_F(object_data_handler_test_t
, single_write
)
159 write(1<<20, 8<<10, 'c');
161 read_near(1<<20, 8<<10, 1);
162 read_near(1<<20, 8<<10, 512);
166 TEST_F(object_data_handler_test_t
, multi_write
)
169 write((1<<20) - (4<<10), 4<<10, 'a');
170 write(1<<20, 4<<10, 'b');
171 write((1<<20) + (4<<10), 4<<10, 'c');
173 read_near(1<<20, 4<<10, 1);
174 read_near(1<<20, 4<<10, 512);
176 read_near((1<<20)-(4<<10), 12<<10, 1);
177 read_near((1<<20)-(4<<10), 12<<10, 512);
181 TEST_F(object_data_handler_test_t
, write_hole
)
184 write((1<<20) - (4<<10), 4<<10, 'a');
186 write((1<<20) + (4<<10), 4<<10, 'c');
188 read_near(1<<20, 4<<10, 1);
189 read_near(1<<20, 4<<10, 512);
191 read_near((1<<20)-(4<<10), 12<<10, 1);
192 read_near((1<<20)-(4<<10), 12<<10, 512);
196 TEST_F(object_data_handler_test_t
, overwrite_single
)
199 write((1<<20), 4<<10, 'a');
200 write((1<<20), 4<<10, 'c');
202 read_near(1<<20, 4<<10, 1);
203 read_near(1<<20, 4<<10, 512);
207 TEST_F(object_data_handler_test_t
, overwrite_double
)
210 write((1<<20), 4<<10, 'a');
211 write((1<<20)+(4<<10), 4<<10, 'c');
212 write((1<<20), 8<<10, 'b');
214 read_near(1<<20, 8<<10, 1);
215 read_near(1<<20, 8<<10, 512);
217 read_near(1<<20, 4<<10, 1);
218 read_near(1<<20, 4<<10, 512);
220 read_near((1<<20) + (4<<10), 4<<10, 1);
221 read_near((1<<20) + (4<<10), 4<<10, 512);
225 TEST_F(object_data_handler_test_t
, overwrite_partial
)
228 write((1<<20), 12<<10, 'a');
229 read_near(1<<20, 12<<10, 1);
231 write((1<<20)+(8<<10), 4<<10, 'b');
232 read_near(1<<20, 12<<10, 1);
234 write((1<<20)+(4<<10), 4<<10, 'c');
235 read_near(1<<20, 12<<10, 1);
237 write((1<<20), 4<<10, 'd');
239 read_near(1<<20, 12<<10, 1);
240 read_near(1<<20, 12<<10, 512);
242 read_near(1<<20, 4<<10, 1);
243 read_near(1<<20, 4<<10, 512);
245 read_near((1<<20) + (4<<10), 4<<10, 1);
246 read_near((1<<20) + (4<<10), 4<<10, 512);
250 TEST_F(object_data_handler_test_t
, unaligned_write
)
253 objaddr_t base
= 1<<20;
254 write(base
, (4<<10)+(1<<10), 'a');
255 read_near(base
-(4<<10), 12<<10, 512);
257 base
= (1<<20) + (64<<10);
258 write(base
+(1<<10), (4<<10)+(1<<10), 'b');
259 read_near(base
-(4<<10), 12<<10, 512);
261 base
= (1<<20) + (128<<10);
262 write(base
-(1<<10), (4<<10)+(2<<20), 'c');
263 read_near(base
-(4<<10), 12<<10, 512);
267 TEST_F(object_data_handler_test_t
, unaligned_overwrite
)
270 objaddr_t base
= 1<<20;
271 write(base
, (128<<10) + (16<<10), 'x');
273 write(base
, (4<<10)+(1<<10), 'a');
274 read_near(base
-(4<<10), 12<<10, 2<<10);
276 base
= (1<<20) + (64<<10);
277 write(base
+(1<<10), (4<<10)+(1<<10), 'b');
278 read_near(base
-(4<<10), 12<<10, 2<<10);
280 base
= (1<<20) + (128<<10);
281 write(base
-(1<<10), (4<<10)+(2<<20), 'c');
282 read_near(base
-(4<<10), 12<<10, 2<<10);
284 read(base
, (128<<10) + (16<<10));
288 TEST_F(object_data_handler_test_t
, truncate
)
291 objaddr_t base
= 1<<20;
292 write(base
, 8<<10, 'a');
293 write(base
+(8<<10), 8<<10, 'b');
294 write(base
+(16<<10), 8<<10, 'c');
296 truncate(base
+ (32<<10));
299 truncate(base
+ (24<<10));
302 truncate(base
+ (12<<10));
305 truncate(base
- (12<<10));