1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "include/types.h"
5 #include "os/bluestore/bluestore_types.h"
6 #include "gtest/gtest.h"
7 #include "include/stringify.h"
8 #include "common/ceph_time.h"
9 #include "os/bluestore/BlueStore.h"
10 #include "common/ceph_argparse.h"
11 #include "global/global_init.h"
12 #include "global/global_context.h"
17 #define STRINGIFY(x) _STR(x)
19 TEST(bluestore
, sizeof) {
20 #define P(t) cout << STRINGIFY(t) << "\t" << sizeof(t) << std::endl
24 P(BlueStore::SharedBlob
);
25 P(BlueStore::ExtentMap
);
26 P(BlueStore::extent_map_t
);
27 P(BlueStore::blob_map_t
);
28 P(BlueStore::BufferSpace
);
33 P(bluestore_shared_blob_t
);
34 P(bluestore_extent_ref_map_t
);
35 P(bluestore_extent_ref_map_t::record_t
);
36 P(bluestore_blob_use_tracker_t
);
38 P(BlueStore::SharedBlobRef
);
39 P(boost::intrusive::set_base_hook
<>);
40 P(boost::intrusive::unordered_set_base_hook
<>);
43 cout
<< "map<uint64_t,uint64_t>\t" << sizeof(map
<uint64_t,uint64_t>) << std::endl
;
44 cout
<< "map<char,char>\t" << sizeof(map
<char,char>) << std::endl
;
47 TEST(bluestore_extent_ref_map_t
, add
)
49 bluestore_extent_ref_map_t m
;
51 ASSERT_EQ(1u, m
.ref_map
.size());
52 cout
<< m
<< std::endl
;
54 cout
<< m
<< std::endl
;
55 ASSERT_EQ(1u, m
.ref_map
.size());
56 ASSERT_EQ(20u, m
.ref_map
[10].length
);
57 ASSERT_EQ(1u, m
.ref_map
[10].refs
);
59 cout
<< m
<< std::endl
;
60 ASSERT_EQ(2u, m
.ref_map
.size());
62 cout
<< m
<< std::endl
;
63 ASSERT_EQ(1u, m
.ref_map
.size());
65 cout
<< m
<< std::endl
;
66 ASSERT_EQ(1u, m
.ref_map
.size());
68 cout
<< m
<< std::endl
;
69 ASSERT_EQ(1u, m
.ref_map
.size());
72 TEST(bluestore_extent_ref_map_t
, get
)
74 bluestore_extent_ref_map_t m
;
76 cout
<< m
<< std::endl
;
78 cout
<< m
<< std::endl
;
79 ASSERT_EQ(3u, m
.ref_map
.size());
80 ASSERT_EQ(10u, m
.ref_map
[0].length
);
81 ASSERT_EQ(1u, m
.ref_map
[0].refs
);
82 ASSERT_EQ(10u, m
.ref_map
[10].length
);
83 ASSERT_EQ(2u, m
.ref_map
[10].refs
);
84 ASSERT_EQ(10u, m
.ref_map
[20].length
);
85 ASSERT_EQ(1u, m
.ref_map
[20].refs
);
87 cout
<< m
<< std::endl
;
88 ASSERT_EQ(3u, m
.ref_map
.size());
89 ASSERT_EQ(15u, m
.ref_map
[10].length
);
90 ASSERT_EQ(2u, m
.ref_map
[10].refs
);
91 ASSERT_EQ(5u, m
.ref_map
[25].length
);
92 ASSERT_EQ(1u, m
.ref_map
[25].refs
);
94 cout
<< m
<< std::endl
;
95 ASSERT_EQ(4u, m
.ref_map
.size());
96 ASSERT_EQ(5u, m
.ref_map
[0].length
);
97 ASSERT_EQ(1u, m
.ref_map
[0].refs
);
98 ASSERT_EQ(5u, m
.ref_map
[5].length
);
99 ASSERT_EQ(2u, m
.ref_map
[5].refs
);
100 ASSERT_EQ(15u, m
.ref_map
[10].length
);
101 ASSERT_EQ(3u, m
.ref_map
[10].refs
);
102 ASSERT_EQ(5u, m
.ref_map
[25].length
);
103 ASSERT_EQ(1u, m
.ref_map
[25].refs
);
105 cout
<< m
<< std::endl
;
106 ASSERT_EQ(5u, m
.ref_map
.size());
107 ASSERT_EQ(5u, m
.ref_map
[0].length
);
108 ASSERT_EQ(1u, m
.ref_map
[0].refs
);
109 ASSERT_EQ(5u, m
.ref_map
[5].length
);
110 ASSERT_EQ(2u, m
.ref_map
[5].refs
);
111 ASSERT_EQ(15u, m
.ref_map
[10].length
);
112 ASSERT_EQ(3u, m
.ref_map
[10].refs
);
113 ASSERT_EQ(3u, m
.ref_map
[25].length
);
114 ASSERT_EQ(2u, m
.ref_map
[25].refs
);
115 ASSERT_EQ(2u, m
.ref_map
[28].length
);
116 ASSERT_EQ(1u, m
.ref_map
[28].refs
);
119 TEST(bluestore_extent_ref_map_t
, put
)
121 bluestore_extent_ref_map_t m
;
125 cout
<< m
<< " " << r
<< std::endl
;
126 ASSERT_EQ(0u, m
.ref_map
.size());
127 ASSERT_EQ(1u, r
.size());
128 ASSERT_EQ(10u, r
[0].offset
);
129 ASSERT_EQ(30u, r
[0].length
);
134 cout
<< m
<< " " << r
<< std::endl
;
135 ASSERT_EQ(1u, m
.ref_map
.size());
136 ASSERT_EQ(10u, m
.ref_map
[20].length
);
137 ASSERT_EQ(1u, m
.ref_map
[20].refs
);
138 ASSERT_EQ(2u, r
.size());
139 ASSERT_EQ(10u, r
[0].offset
);
140 ASSERT_EQ(10u, r
[0].length
);
141 ASSERT_EQ(30u, r
[1].offset
);
142 ASSERT_EQ(10u, r
[1].length
);
147 cout
<< m
<< " " << r
<< std::endl
;
148 ASSERT_EQ(2u, m
.ref_map
.size());
149 ASSERT_EQ(5u, m
.ref_map
[30].length
);
150 ASSERT_EQ(1u, m
.ref_map
[30].refs
);
151 ASSERT_EQ(5u, m
.ref_map
[35].length
);
152 ASSERT_EQ(2u, m
.ref_map
[35].refs
);
153 ASSERT_EQ(1u, r
.size());
154 ASSERT_EQ(20u, r
[0].offset
);
155 ASSERT_EQ(10u, r
[0].length
);
158 cout
<< m
<< " " << r
<< std::endl
;
159 ASSERT_EQ(3u, m
.ref_map
.size());
160 ASSERT_EQ(3u, m
.ref_map
[30].length
);
161 ASSERT_EQ(1u, m
.ref_map
[30].refs
);
162 ASSERT_EQ(3u, m
.ref_map
[35].length
);
163 ASSERT_EQ(1u, m
.ref_map
[35].refs
);
164 ASSERT_EQ(2u, m
.ref_map
[38].length
);
165 ASSERT_EQ(2u, m
.ref_map
[38].refs
);
166 ASSERT_EQ(1u, r
.size());
167 ASSERT_EQ(33u, r
[0].offset
);
168 ASSERT_EQ(2u, r
[0].length
);
171 TEST(bluestore_extent_ref_map_t
, contains
)
173 bluestore_extent_ref_map_t m
;
175 ASSERT_TRUE(m
.contains(10, 30));
176 ASSERT_TRUE(m
.contains(10, 10));
177 ASSERT_TRUE(m
.contains(30, 10));
178 ASSERT_FALSE(m
.contains(0, 10));
179 ASSERT_FALSE(m
.contains(0, 20));
180 ASSERT_FALSE(m
.contains(0, 100));
181 ASSERT_FALSE(m
.contains(40, 10));
182 ASSERT_FALSE(m
.contains(30, 11));
185 ASSERT_TRUE(m
.contains(30, 11));
186 ASSERT_TRUE(m
.contains(30, 20));
187 ASSERT_TRUE(m
.contains(10, 40));
188 ASSERT_FALSE(m
.contains(0, 50));
189 ASSERT_FALSE(m
.contains(40, 20));
191 ASSERT_TRUE(m
.contains(60, 10));
192 ASSERT_TRUE(m
.contains(40, 10));
193 ASSERT_FALSE(m
.contains(40, 11));
194 ASSERT_FALSE(m
.contains(40, 20));
195 ASSERT_FALSE(m
.contains(40, 30));
196 ASSERT_FALSE(m
.contains(40, 3000));
197 ASSERT_FALSE(m
.contains(4000, 30));
200 TEST(bluestore_extent_ref_map_t
, intersects
)
202 bluestore_extent_ref_map_t m
;
204 ASSERT_TRUE(m
.intersects(10, 30));
205 ASSERT_TRUE(m
.intersects(0, 11));
206 ASSERT_TRUE(m
.intersects(10, 40));
207 ASSERT_TRUE(m
.intersects(15, 40));
208 ASSERT_FALSE(m
.intersects(0, 10));
209 ASSERT_FALSE(m
.intersects(0, 5));
210 ASSERT_FALSE(m
.intersects(40, 20));
211 ASSERT_FALSE(m
.intersects(41, 20));
214 ASSERT_TRUE(m
.intersects(0, 100));
215 ASSERT_TRUE(m
.intersects(10, 35));
216 ASSERT_TRUE(m
.intersects(45, 10));
217 ASSERT_FALSE(m
.intersects(50, 5));
219 ASSERT_TRUE(m
.intersects(45, 10));
220 ASSERT_TRUE(m
.intersects(55, 10));
221 ASSERT_TRUE(m
.intersects(50, 11));
222 ASSERT_FALSE(m
.intersects(50, 10));
223 ASSERT_FALSE(m
.intersects(51, 9));
224 ASSERT_FALSE(m
.intersects(55, 1));
227 TEST(bluestore_blob_t
, calc_csum
)
230 bl
.append("asdfghjkqwertyuizxcvbnm,");
232 bl2
.append("xxxxXXXXyyyyYYYYzzzzZZZZ");
234 f
.substr_of(bl
, 0, 8);
236 m
.substr_of(bl
, 8, 8);
238 e
.substr_of(bl
, 16, 8);
240 n
.append("12345678");
242 for (unsigned csum_type
= Checksummer::CSUM_NONE
+ 1;
243 csum_type
< Checksummer::CSUM_MAX
;
245 cout
<< "csum_type " << Checksummer::get_csum_type_string(csum_type
)
251 ASSERT_EQ(0, b
.verify_csum(0, bl
, &bad_off
, &bad_csum
));
252 ASSERT_EQ(-1, bad_off
);
254 b
.init_csum(csum_type
, 3, 24);
255 cout
<< " value size " << b
.get_csum_value_size() << std::endl
;
257 ASSERT_EQ(0, b
.verify_csum(0, bl
, &bad_off
, &bad_csum
));
258 ASSERT_EQ(-1, bad_off
);
259 ASSERT_EQ(-1, b
.verify_csum(0, bl2
, &bad_off
, &bad_csum
));
260 ASSERT_EQ(0, bad_off
);
262 ASSERT_EQ(0, b
.verify_csum(0, f
, &bad_off
, &bad_csum
));
263 ASSERT_EQ(-1, bad_off
);
264 ASSERT_EQ(-1, b
.verify_csum(8, f
, &bad_off
, &bad_csum
));
265 ASSERT_EQ(8, bad_off
);
266 ASSERT_EQ(-1, b
.verify_csum(16, f
, &bad_off
, &bad_csum
));
267 ASSERT_EQ(16, bad_off
);
269 ASSERT_EQ(-1, b
.verify_csum(0, m
, &bad_off
, &bad_csum
));
270 ASSERT_EQ(0, bad_off
);
271 ASSERT_EQ(0, b
.verify_csum(8, m
, &bad_off
, &bad_csum
));
272 ASSERT_EQ(-1, bad_off
);
273 ASSERT_EQ(-1, b
.verify_csum(16, m
, &bad_off
, &bad_csum
));
274 ASSERT_EQ(16, bad_off
);
276 ASSERT_EQ(-1, b
.verify_csum(0, e
, &bad_off
, &bad_csum
));
277 ASSERT_EQ(0, bad_off
);
278 ASSERT_EQ(-1, b
.verify_csum(8, e
, &bad_off
, &bad_csum
));
279 ASSERT_EQ(8, bad_off
);
280 ASSERT_EQ(0, b
.verify_csum(16, e
, &bad_off
, &bad_csum
));
281 ASSERT_EQ(-1, bad_off
);
284 ASSERT_EQ(0, b
.verify_csum(0, f
, &bad_off
, &bad_csum
));
285 ASSERT_EQ(-1, bad_off
);
286 ASSERT_EQ(0, b
.verify_csum(8, n
, &bad_off
, &bad_csum
));
287 ASSERT_EQ(-1, bad_off
);
288 ASSERT_EQ(0, b
.verify_csum(16, e
, &bad_off
, &bad_csum
));
289 ASSERT_EQ(-1, bad_off
);
290 ASSERT_EQ(-1, b
.verify_csum(0, bl
, &bad_off
, &bad_csum
));
291 ASSERT_EQ(8, bad_off
);
295 TEST(bluestore_blob_t
, csum_bench
)
298 bufferptr
bp(10485760);
299 for (char *a
= bp
.c_str(); a
< bp
.c_str() + bp
.length(); ++a
)
300 *a
= (unsigned long)a
& 0xff;
303 for (unsigned csum_type
= 1;
304 csum_type
< Checksummer::CSUM_MAX
;
307 b
.init_csum(csum_type
, 12, bl
.length());
308 ceph::mono_clock::time_point start
= ceph::mono_clock::now();
309 for (int i
= 0; i
<count
; ++i
) {
312 ceph::mono_clock::time_point end
= ceph::mono_clock::now();
313 auto dur
= std::chrono::duration_cast
<std::chrono::nanoseconds
>(end
- start
);
314 double mbsec
= (double)count
* (double)bl
.length() / 1000000.0 / (double)dur
.count() * 1000000000.0;
315 cout
<< "csum_type " << Checksummer::get_csum_type_string(csum_type
)
316 << ", " << dur
<< " seconds, "
317 << mbsec
<< " MB/sec" << std::endl
;
324 BlueStore
store(g_ceph_context
, "", 4096);
325 BlueStore::Cache
*cache
= BlueStore::Cache::create(
326 g_ceph_context
, "lru", NULL
);
327 BlueStore::Collection
coll(&store
, cache
, coll_t());
329 b
.shared_blob
= new BlueStore::SharedBlob(nullptr);
330 b
.shared_blob
->get(); // hack to avoid dtor from running
331 b
.dirty_blob().allocated_test(bluestore_pextent_t(0x40715000, 0x2000));
332 b
.dirty_blob().allocated_test(
333 bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
, 0x8000));
334 b
.dirty_blob().allocated_test(bluestore_pextent_t(0x4071f000, 0x5000));
335 b
.get_ref(&coll
, 0, 0x1200);
336 b
.get_ref(&coll
, 0xae00, 0x4200);
337 ASSERT_EQ(0x5400u
, b
.get_referenced_bytes());
338 cout
<< b
<< std::endl
;
341 ASSERT_FALSE(b
.put_ref(&coll
, 0, 0x1200, &r
));
342 ASSERT_EQ(0x4200u
, b
.get_referenced_bytes());
343 cout
<< " r " << r
<< std::endl
;
344 cout
<< b
<< std::endl
;
347 ASSERT_TRUE(b
.put_ref(&coll
, 0xae00, 0x4200, &r
));
348 ASSERT_EQ(0u, b
.get_referenced_bytes());
349 cout
<< " r " << r
<< std::endl
;
350 cout
<< b
<< std::endl
;
354 BlueStore
store(g_ceph_context
, "", 8192);
355 BlueStore::Cache
*cache
= BlueStore::Cache::create(
356 g_ceph_context
, "lru", NULL
);
357 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, cache
, coll_t()));
361 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
362 B
.shared_blob
->get(); // hack to avoid dtor from running
363 bluestore_blob_t
& b
= B
.dirty_blob();
365 b
.allocated_test(bluestore_pextent_t(0, mas
* 2));
366 B
.get_ref(coll
.get(), 0, mas
*2);
367 ASSERT_EQ(mas
* 2, B
.get_referenced_bytes());
368 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
369 ASSERT_TRUE(B
.put_ref(coll
.get(), 0, mas
*2, &r
));
370 ASSERT_EQ(0u, B
.get_referenced_bytes());
371 cout
<< "r " << r
<< " " << b
<< std::endl
;
372 ASSERT_EQ(1u, r
.size());
373 ASSERT_EQ(0u, r
[0].offset
);
374 ASSERT_EQ(mas
*2, r
[0].length
);
375 ASSERT_FALSE(b
.is_allocated(0, mas
*2));
376 ASSERT_FALSE(b
.is_allocated(0, mas
));
377 ASSERT_FALSE(b
.is_allocated(mas
, 0));
378 ASSERT_FALSE(b
.get_extents()[0].is_valid());
379 ASSERT_EQ(mas
*2, b
.get_extents()[0].length
);
383 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
384 B
.shared_blob
->get(); // hack to avoid dtor from running
385 bluestore_blob_t
& b
= B
.dirty_blob();
387 b
.allocated_test(bluestore_pextent_t(123, mas
* 2));
388 B
.get_ref(coll
.get(), 0, mas
*2);
389 ASSERT_EQ(mas
* 2, B
.get_referenced_bytes());
390 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, mas
, &r
));
391 ASSERT_EQ(mas
, B
.get_referenced_bytes());
392 cout
<< "r " << r
<< " " << b
<< std::endl
;
393 ASSERT_EQ(0u, r
.size());
394 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
395 ASSERT_TRUE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
396 ASSERT_EQ(0u, B
.get_referenced_bytes());
397 ASSERT_EQ(0u, B
.get_referenced_bytes());
398 cout
<< "r " << r
<< " " << b
<< std::endl
;
399 ASSERT_EQ(1u, r
.size());
400 ASSERT_EQ(123u, r
[0].offset
);
401 ASSERT_EQ(mas
*2, r
[0].length
);
402 ASSERT_FALSE(b
.is_allocated(0, mas
*2));
403 ASSERT_FALSE(b
.get_extents()[0].is_valid());
404 ASSERT_EQ(mas
*2, b
.get_extents()[0].length
);
408 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
409 B
.shared_blob
->get(); // hack to avoid dtor from running
410 bluestore_blob_t
& b
= B
.dirty_blob();
412 b
.allocated_test(bluestore_pextent_t(1, mas
));
413 b
.allocated_test(bluestore_pextent_t(2, mas
));
414 b
.allocated_test(bluestore_pextent_t(3, mas
));
415 b
.allocated_test(bluestore_pextent_t(4, mas
));
416 B
.get_ref(coll
.get(), 0, mas
*4);
417 ASSERT_EQ(mas
* 4, B
.get_referenced_bytes());
418 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
419 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
420 cout
<< "r " << r
<< " " << b
<< std::endl
;
421 ASSERT_EQ(0u, r
.size());
422 ASSERT_TRUE(b
.is_allocated(0, mas
*4));
423 ASSERT_TRUE(b
.is_allocated(mas
, mas
));
424 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
, &r
));
425 ASSERT_EQ(mas
* 2, B
.get_referenced_bytes());
426 cout
<< "r " << r
<< " " << b
<< std::endl
;
427 ASSERT_EQ(0u, r
.size());
428 ASSERT_TRUE(b
.is_allocated(mas
*2, mas
));
429 ASSERT_TRUE(b
.is_allocated(0, mas
*4));
430 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*3, mas
, &r
));
431 ASSERT_EQ(mas
, B
.get_referenced_bytes());
432 cout
<< "r " << r
<< " " << b
<< std::endl
;
433 ASSERT_EQ(2u, r
.size());
434 ASSERT_EQ(3u, r
[0].offset
);
435 ASSERT_EQ(mas
, r
[0].length
);
436 ASSERT_EQ(4u, r
[1].offset
);
437 ASSERT_EQ(mas
, r
[1].length
);
438 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
439 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*2));
440 ASSERT_TRUE(b
.get_extents()[0].is_valid());
441 ASSERT_TRUE(b
.get_extents()[1].is_valid());
442 ASSERT_FALSE(b
.get_extents()[2].is_valid());
443 ASSERT_EQ(3u, b
.get_extents().size());
447 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
448 B
.shared_blob
->get(); // hack to avoid dtor from running
449 bluestore_blob_t
& b
= B
.dirty_blob();
451 b
.allocated_test(bluestore_pextent_t(1, mas
));
452 b
.allocated_test(bluestore_pextent_t(2, mas
));
453 b
.allocated_test(bluestore_pextent_t(3, mas
));
454 b
.allocated_test(bluestore_pextent_t(4, mas
));
455 b
.allocated_test(bluestore_pextent_t(5, mas
));
456 b
.allocated_test(bluestore_pextent_t(6, mas
));
457 B
.get_ref(coll
.get(), 0, mas
*6);
458 ASSERT_EQ(mas
* 6, B
.get_referenced_bytes());
459 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
460 ASSERT_EQ(mas
* 5, B
.get_referenced_bytes());
461 cout
<< "r " << r
<< " " << b
<< std::endl
;
462 ASSERT_EQ(0u, r
.size());
463 ASSERT_TRUE(b
.is_allocated(0, mas
*6));
464 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
, &r
));
465 ASSERT_EQ(mas
* 4, B
.get_referenced_bytes());
466 cout
<< "r " << r
<< " " << b
<< std::endl
;
467 ASSERT_EQ(0u, r
.size());
468 ASSERT_TRUE(b
.is_allocated(0, mas
*6));
469 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*3, mas
, &r
));
470 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
471 cout
<< "r " << r
<< " " << b
<< std::endl
;
472 ASSERT_EQ(2u, r
.size());
473 ASSERT_EQ(3u, r
[0].offset
);
474 ASSERT_EQ(mas
, r
[0].length
);
475 ASSERT_EQ(4u, r
[1].offset
);
476 ASSERT_EQ(mas
, r
[1].length
);
477 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
478 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*2));
479 ASSERT_TRUE(b
.is_allocated(mas
*4, mas
*2));
480 ASSERT_EQ(5u, b
.get_extents().size());
481 ASSERT_TRUE(b
.get_extents()[0].is_valid());
482 ASSERT_TRUE(b
.get_extents()[1].is_valid());
483 ASSERT_FALSE(b
.get_extents()[2].is_valid());
484 ASSERT_TRUE(b
.get_extents()[3].is_valid());
485 ASSERT_TRUE(b
.get_extents()[4].is_valid());
489 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
490 B
.shared_blob
->get(); // hack to avoid dtor from running
491 bluestore_blob_t
& b
= B
.dirty_blob();
493 b
.allocated_test(bluestore_pextent_t(1, mas
* 6));
494 B
.get_ref(coll
.get(), 0, mas
*6);
495 ASSERT_EQ(mas
* 6, B
.get_referenced_bytes());
496 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
497 ASSERT_EQ(mas
* 5, B
.get_referenced_bytes());
498 cout
<< "r " << r
<< " " << b
<< std::endl
;
499 ASSERT_EQ(0u, r
.size());
500 ASSERT_TRUE(b
.is_allocated(0, mas
*6));
501 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
, &r
));
502 ASSERT_EQ(mas
* 4, B
.get_referenced_bytes());
503 cout
<< "r " << r
<< " " << b
<< std::endl
;
504 ASSERT_EQ(0u, r
.size());
505 ASSERT_TRUE(b
.is_allocated(0, mas
*6));
506 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*3, mas
, &r
));
507 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
508 cout
<< "r " << r
<< " " << b
<< std::endl
;
509 ASSERT_EQ(1u, r
.size());
510 ASSERT_EQ(0x2001u
, r
[0].offset
);
511 ASSERT_EQ(mas
*2, r
[0].length
);
512 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
513 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*2));
514 ASSERT_TRUE(b
.is_allocated(mas
*4, mas
*2));
515 ASSERT_EQ(3u, b
.get_extents().size());
516 ASSERT_TRUE(b
.get_extents()[0].is_valid());
517 ASSERT_FALSE(b
.get_extents()[1].is_valid());
518 ASSERT_TRUE(b
.get_extents()[2].is_valid());
522 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
523 B
.shared_blob
->get(); // hack to avoid dtor from running
524 bluestore_blob_t
& b
= B
.dirty_blob();
526 b
.allocated_test(bluestore_pextent_t(1, mas
* 4));
527 b
.allocated_test(bluestore_pextent_t(2, mas
* 4));
528 b
.allocated_test(bluestore_pextent_t(3, mas
* 4));
529 B
.get_ref(coll
.get(), 0, mas
*12);
530 ASSERT_EQ(mas
* 12, B
.get_referenced_bytes());
531 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
532 ASSERT_EQ(mas
* 11, B
.get_referenced_bytes());
533 cout
<< "r " << r
<< " " << b
<< std::endl
;
534 ASSERT_EQ(0u, r
.size());
535 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
536 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*9, mas
, &r
));
537 ASSERT_EQ(mas
* 10, B
.get_referenced_bytes());
538 cout
<< "r " << r
<< " " << b
<< std::endl
;
539 ASSERT_EQ(0u, r
.size());
540 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
541 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
*7, &r
));
542 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
543 cout
<< "r " << r
<< " " << b
<< std::endl
;
544 ASSERT_EQ(3u, r
.size());
545 ASSERT_EQ(0x2001u
, r
[0].offset
);
546 ASSERT_EQ(mas
*2, r
[0].length
);
547 ASSERT_EQ(0x2u
, r
[1].offset
);
548 ASSERT_EQ(mas
*4, r
[1].length
);
549 ASSERT_EQ(0x3u
, r
[2].offset
);
550 ASSERT_EQ(mas
*2, r
[2].length
);
551 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
552 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*8));
553 ASSERT_TRUE(b
.is_allocated(mas
*10, mas
*2));
554 ASSERT_EQ(3u, b
.get_extents().size());
555 ASSERT_TRUE(b
.get_extents()[0].is_valid());
556 ASSERT_FALSE(b
.get_extents()[1].is_valid());
557 ASSERT_TRUE(b
.get_extents()[2].is_valid());
561 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
562 B
.shared_blob
->get(); // hack to avoid dtor from running
563 bluestore_blob_t
& b
= B
.dirty_blob();
565 b
.allocated_test(bluestore_pextent_t(1, mas
* 4));
566 b
.allocated_test(bluestore_pextent_t(2, mas
* 4));
567 b
.allocated_test(bluestore_pextent_t(3, mas
* 4));
568 B
.get_ref(coll
.get(), 0, mas
*12);
569 ASSERT_EQ(mas
* 12, B
.get_referenced_bytes());
570 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
571 ASSERT_EQ(mas
* 11, B
.get_referenced_bytes());
572 cout
<< "r " << r
<< " " << b
<< std::endl
;
573 ASSERT_EQ(0u, r
.size());
574 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
575 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*9, mas
, &r
));
576 ASSERT_EQ(mas
* 10, B
.get_referenced_bytes());
577 cout
<< "r " << r
<< " " << b
<< std::endl
;
578 ASSERT_EQ(0u, r
.size());
579 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
580 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
*7, &r
));
581 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
582 cout
<< "r " << r
<< " " << b
<< std::endl
;
583 ASSERT_EQ(3u, r
.size());
584 ASSERT_EQ(0x2001u
, r
[0].offset
);
585 ASSERT_EQ(mas
*2, r
[0].length
);
586 ASSERT_EQ(0x2u
, r
[1].offset
);
587 ASSERT_EQ(mas
*4, r
[1].length
);
588 ASSERT_EQ(0x3u
, r
[2].offset
);
589 ASSERT_EQ(mas
*2, r
[2].length
);
590 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
591 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*8));
592 ASSERT_TRUE(b
.is_allocated(mas
*10, mas
*2));
593 ASSERT_EQ(3u, b
.get_extents().size());
594 ASSERT_TRUE(b
.get_extents()[0].is_valid());
595 ASSERT_FALSE(b
.get_extents()[1].is_valid());
596 ASSERT_TRUE(b
.get_extents()[2].is_valid());
597 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, mas
, &r
));
598 ASSERT_EQ(mas
* 2, B
.get_referenced_bytes());
599 cout
<< "r " << r
<< " " << b
<< std::endl
;
600 ASSERT_EQ(1u, r
.size());
601 ASSERT_EQ(0x1u
, r
[0].offset
);
602 ASSERT_EQ(mas
*2, r
[0].length
);
603 ASSERT_EQ(2u, b
.get_extents().size());
604 ASSERT_FALSE(b
.get_extents()[0].is_valid());
605 ASSERT_TRUE(b
.get_extents()[1].is_valid());
606 ASSERT_TRUE(B
.put_ref(coll
.get(), mas
*10, mas
*2, &r
));
607 ASSERT_EQ(mas
* 0, B
.get_referenced_bytes());
608 cout
<< "r " << r
<< " " << b
<< std::endl
;
609 ASSERT_EQ(1u, r
.size());
610 ASSERT_EQ(0x2003u
, r
[0].offset
);
611 ASSERT_EQ(mas
*2, r
[0].length
);
612 ASSERT_EQ(1u, b
.get_extents().size());
613 ASSERT_FALSE(b
.get_extents()[0].is_valid());
617 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
618 B
.shared_blob
->get(); // hack to avoid dtor from running
619 bluestore_blob_t
& b
= B
.dirty_blob();
621 b
.allocated_test(bluestore_pextent_t(1, mas
* 4));
622 b
.allocated_test(bluestore_pextent_t(2, mas
* 4));
623 b
.allocated_test(bluestore_pextent_t(3, mas
* 4));
624 B
.get_ref(coll
.get(), 0, mas
*12);
625 ASSERT_EQ(mas
* 12, B
.get_referenced_bytes());
626 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
627 ASSERT_EQ(mas
* 11, B
.get_referenced_bytes());
628 cout
<< "r " << r
<< " " << b
<< std::endl
;
629 ASSERT_EQ(0u, r
.size());
630 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
631 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*9, mas
, &r
));
632 ASSERT_EQ(mas
* 10, B
.get_referenced_bytes());
633 cout
<< "r " << r
<< " " << b
<< std::endl
;
634 ASSERT_EQ(0u, r
.size());
635 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
636 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
*7, &r
));
637 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
638 cout
<< "r " << r
<< " " << b
<< std::endl
;
639 ASSERT_EQ(3u, r
.size());
640 ASSERT_EQ(0x2001u
, r
[0].offset
);
641 ASSERT_EQ(mas
*2, r
[0].length
);
642 ASSERT_EQ(0x2u
, r
[1].offset
);
643 ASSERT_EQ(mas
*4, r
[1].length
);
644 ASSERT_EQ(0x3u
, r
[2].offset
);
645 ASSERT_EQ(mas
*2, r
[2].length
);
646 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
647 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*8));
648 ASSERT_TRUE(b
.is_allocated(mas
*10, mas
*2));
649 ASSERT_EQ(3u, b
.get_extents().size());
650 ASSERT_TRUE(b
.get_extents()[0].is_valid());
651 ASSERT_FALSE(b
.get_extents()[1].is_valid());
652 ASSERT_TRUE(b
.get_extents()[2].is_valid());
653 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*10, mas
*2, &r
));
654 ASSERT_EQ(mas
* 1, B
.get_referenced_bytes());
655 cout
<< "r " << r
<< " " << b
<< std::endl
;
656 ASSERT_EQ(1u, r
.size());
657 ASSERT_EQ(0x2003u
, r
[0].offset
);
658 ASSERT_EQ(mas
*2, r
[0].length
);
659 ASSERT_EQ(2u, b
.get_extents().size());
660 ASSERT_TRUE(b
.get_extents()[0].is_valid());
661 ASSERT_FALSE(b
.get_extents()[1].is_valid());
662 ASSERT_TRUE(B
.put_ref(coll
.get(), 0, mas
, &r
));
663 ASSERT_EQ(mas
* 0, B
.get_referenced_bytes());
664 cout
<< "r " << r
<< " " << b
<< std::endl
;
665 ASSERT_EQ(1u, r
.size());
666 ASSERT_EQ(0x1u
, r
[0].offset
);
667 ASSERT_EQ(mas
*2, r
[0].length
);
668 ASSERT_EQ(1u, b
.get_extents().size());
669 ASSERT_FALSE(b
.get_extents()[0].is_valid());
673 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
674 B
.shared_blob
->get(); // hack to avoid dtor from running
675 bluestore_blob_t
& b
= B
.dirty_blob();
677 b
.allocated_test(bluestore_pextent_t(1, mas
* 8));
678 B
.get_ref(coll
.get(), 0, mas
*8);
679 ASSERT_EQ(mas
* 8, B
.get_referenced_bytes());
680 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, mas
, &r
));
681 ASSERT_EQ(mas
* 7, B
.get_referenced_bytes());
682 cout
<< "r " << r
<< " " << b
<< std::endl
;
683 ASSERT_EQ(0u, r
.size());
684 ASSERT_TRUE(b
.is_allocated(0, mas
*8));
685 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*7, mas
, &r
));
686 ASSERT_EQ(mas
* 6, B
.get_referenced_bytes());
687 cout
<< "r " << r
<< " " << b
<< std::endl
;
688 ASSERT_EQ(0u, r
.size());
689 ASSERT_TRUE(b
.is_allocated(0, mas
*8));
690 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
, &r
));
691 ASSERT_EQ(mas
* 5, B
.get_referenced_bytes());
692 cout
<< "r " << r
<< " " << b
<< std::endl
;
693 ASSERT_EQ(0u, r
.size());
694 ASSERT_TRUE(b
.is_allocated(0, 8));
695 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*3, mas
*4, &r
));
696 ASSERT_EQ(mas
* 1, B
.get_referenced_bytes());
697 ASSERT_EQ(1u, r
.size());
698 ASSERT_EQ(0x2001u
, r
[0].offset
);
699 ASSERT_EQ(mas
*6, r
[0].length
);
700 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
701 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*6));
702 ASSERT_EQ(2u, b
.get_extents().size());
703 ASSERT_TRUE(b
.get_extents()[0].is_valid());
704 ASSERT_FALSE(b
.get_extents()[1].is_valid());
705 ASSERT_TRUE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
706 ASSERT_EQ(mas
* 0, B
.get_referenced_bytes());
707 cout
<< "r " << r
<< " " << b
<< std::endl
;
708 ASSERT_EQ(1u, r
.size());
709 ASSERT_EQ(0x1u
, r
[0].offset
);
710 ASSERT_EQ(mas
*2, r
[0].length
);
711 ASSERT_EQ(1u, b
.get_extents().size());
712 ASSERT_FALSE(b
.get_extents()[0].is_valid());
714 // verify csum chunk size if factored in properly
717 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
718 B
.shared_blob
->get(); // hack to avoid dtor from running
719 bluestore_blob_t
& b
= B
.dirty_blob();
721 b
.allocated_test(bluestore_pextent_t(0, mas
*4));
722 b
.init_csum(Checksummer::CSUM_CRC32C
, 14, mas
* 4);
723 B
.get_ref(coll
.get(), 0, mas
*4);
724 ASSERT_EQ(mas
* 4, B
.get_referenced_bytes());
725 ASSERT_TRUE(b
.is_allocated(0, mas
*4));
726 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, mas
*3, &r
));
727 ASSERT_EQ(mas
* 1, B
.get_referenced_bytes());
728 cout
<< "r " << r
<< " " << b
<< std::endl
;
729 ASSERT_EQ(0u, r
.size());
730 ASSERT_TRUE(b
.is_allocated(0, mas
*4));
731 ASSERT_TRUE(b
.get_extents()[0].is_valid());
732 ASSERT_EQ(mas
*4, b
.get_extents()[0].length
);
736 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
737 B
.shared_blob
->get(); // hack to avoid dtor from running
738 bluestore_blob_t
& b
= B
.dirty_blob();
739 b
.allocated_test(bluestore_pextent_t(0x40101000, 0x4000));
740 b
.allocated_test(bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
,
743 b
.allocated_test(bluestore_pextent_t(0x40118000, 0x7000));
744 B
.get_ref(coll
.get(), 0x0, 0x3800);
745 B
.get_ref(coll
.get(), 0x17c00, 0x6400);
746 ASSERT_EQ(0x3800u
+ 0x6400u
, B
.get_referenced_bytes());
747 b
.set_flag(bluestore_blob_t::FLAG_SHARED
);
748 b
.init_csum(Checksummer::CSUM_CRC32C
, 12, 0x1e000);
750 cout
<< "before: " << B
<< std::endl
;
752 ASSERT_FALSE(B
.put_ref(coll
.get(), 0x1800, 0x2000, &r
));
753 ASSERT_EQ(0x3800u
+ 0x6400u
- 0x2000u
, B
.get_referenced_bytes());
754 cout
<< "after: " << B
<< std::endl
;
755 cout
<< "r " << r
<< std::endl
;
759 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
760 B
.shared_blob
->get(); // hack to avoid dtor from running
761 bluestore_blob_t
& b
= B
.dirty_blob();
762 b
.allocated_test(bluestore_pextent_t(1, 0x5000));
763 b
.allocated_test(bluestore_pextent_t(2, 0x5000));
764 B
.get_ref(coll
.get(), 0x0, 0xa000);
765 ASSERT_EQ(0xa000u
, B
.get_referenced_bytes());
766 cout
<< "before: " << B
<< std::endl
;
768 ASSERT_FALSE(B
.put_ref(coll
.get(), 0x8000, 0x2000, &r
));
769 cout
<< "after: " << B
<< std::endl
;
770 cout
<< "r " << r
<< std::endl
;
771 ASSERT_EQ(0x8000u
, B
.get_referenced_bytes());
772 ASSERT_EQ(1u, r
.size());
773 ASSERT_EQ(0x3002u
, r
[0].offset
);
774 ASSERT_EQ(0x2000u
, r
[0].length
);
778 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
779 B
.shared_blob
->get(); // hack to avoid dtor from running
780 bluestore_blob_t
& b
= B
.dirty_blob();
781 b
.allocated_test(bluestore_pextent_t(1, 0x7000));
782 b
.allocated_test(bluestore_pextent_t(2, 0x7000));
783 B
.get_ref(coll
.get(), 0x0, 0xe000);
784 ASSERT_EQ(0xe000u
, B
.get_referenced_bytes());
785 cout
<< "before: " << B
<< std::endl
;
787 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, 0xb000, &r
));
788 ASSERT_EQ(0x3000u
, B
.get_referenced_bytes());
789 cout
<< "after: " << B
<< std::endl
;
790 cout
<< "r " << r
<< std::endl
;
791 ASSERT_EQ(0x3000u
, B
.get_referenced_bytes());
792 ASSERT_EQ(2u, r
.size());
793 ASSERT_EQ(1u, r
[0].offset
);
794 ASSERT_EQ(0x7000u
, r
[0].length
);
795 ASSERT_EQ(2u, r
[1].offset
);
796 ASSERT_EQ(0x3000u
, r
[1].length
); // we have 0x1000 bytes less due to
797 // alignment caused by min_alloc_size = 0x2000
800 BlueStore
store(g_ceph_context
, "", 0x4000);
801 BlueStore::Cache
*cache
= BlueStore::Cache::create(
802 g_ceph_context
, "lru", NULL
);
803 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, cache
, coll_t()));
805 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
806 B
.shared_blob
->get(); // hack to avoid dtor from running
807 bluestore_blob_t
& b
= B
.dirty_blob();
808 b
.allocated_test(bluestore_pextent_t(1, 0x5000));
809 b
.allocated_test(bluestore_pextent_t(2, 0x7000));
810 B
.get_ref(coll
.get(), 0x0, 0xc000);
811 ASSERT_EQ(0xc000u
, B
.get_referenced_bytes());
812 cout
<< "before: " << B
<< std::endl
;
814 ASSERT_FALSE(B
.put_ref(coll
.get(), 0x2000, 0xa000, &r
));
815 cout
<< "after: " << B
<< std::endl
;
816 cout
<< "r " << r
<< std::endl
;
817 ASSERT_EQ(0x2000u
, B
.get_referenced_bytes());
818 ASSERT_EQ(2u, r
.size());
819 ASSERT_EQ(0x4001u
, r
[0].offset
);
820 ASSERT_EQ(0x1000u
, r
[0].length
);
821 ASSERT_EQ(2u, r
[1].offset
);
822 ASSERT_EQ(0x7000u
, r
[1].length
);
823 ASSERT_EQ(1u, b
.get_extents()[0].offset
);
824 ASSERT_EQ(0x4000u
, b
.get_extents()[0].length
);
828 TEST(bluestore_blob_t
, can_split
)
831 a
.flags
= bluestore_blob_t::FLAG_MUTABLE
;
832 ASSERT_TRUE(a
.can_split());
833 a
.flags
= bluestore_blob_t::FLAG_SHARED
;
834 ASSERT_FALSE(a
.can_split());
835 a
.flags
= bluestore_blob_t::FLAG_COMPRESSED
;
836 ASSERT_FALSE(a
.can_split());
837 a
.flags
= bluestore_blob_t::FLAG_HAS_UNUSED
;
838 ASSERT_FALSE(a
.can_split());
841 TEST(bluestore_blob_t
, can_split_at
)
844 a
.flags
= bluestore_blob_t::FLAG_MUTABLE
;
845 a
.allocated_test(bluestore_pextent_t(0x10000, 0x2000));
846 a
.allocated_test(bluestore_pextent_t(0x20000, 0x2000));
847 ASSERT_TRUE(a
.can_split_at(0x1000));
848 ASSERT_TRUE(a
.can_split_at(0x1800));
849 a
.init_csum(Checksummer::CSUM_CRC32C
, 12, 0x4000);
850 ASSERT_TRUE(a
.can_split_at(0x1000));
851 ASSERT_TRUE(a
.can_split_at(0x2000));
852 ASSERT_TRUE(a
.can_split_at(0x3000));
853 ASSERT_FALSE(a
.can_split_at(0x2800));
856 TEST(bluestore_blob_t
, prune_tail
)
859 a
.flags
= bluestore_blob_t::FLAG_MUTABLE
;
860 a
.allocated_test(bluestore_pextent_t(0x10000, 0x2000));
861 a
.allocated_test(bluestore_pextent_t(0x20000, 0x2000));
862 ASSERT_FALSE(a
.can_prune_tail());
864 bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
, 0x2000));
865 ASSERT_TRUE(a
.can_prune_tail());
867 ASSERT_FALSE(a
.can_prune_tail());
868 ASSERT_EQ(2u, a
.get_extents().size());
869 ASSERT_EQ(0x4000u
, a
.get_logical_length());
872 bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
, 0x2000));
873 a
.init_csum(Checksummer::CSUM_CRC32C_8
, 12, 0x6000);
874 ASSERT_EQ(6u, a
.csum_data
.length());
875 ASSERT_TRUE(a
.can_prune_tail());
877 ASSERT_FALSE(a
.can_prune_tail());
878 ASSERT_EQ(2u, a
.get_extents().size());
879 ASSERT_EQ(0x4000u
, a
.get_logical_length());
880 ASSERT_EQ(4u, a
.csum_data
.length());
884 bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
, 0x2000));
885 ASSERT_FALSE(a
.can_prune_tail());
890 BlueStore
store(g_ceph_context
, "", 4096);
891 BlueStore::Cache
*cache
= BlueStore::Cache::create(
892 g_ceph_context
, "lru", NULL
);
893 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, cache
, coll_t()));
895 BlueStore::Blob L
, R
;
896 L
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
897 L
.shared_blob
->get(); // hack to avoid dtor from running
898 R
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
899 R
.shared_blob
->get(); // hack to avoid dtor from running
900 L
.dirty_blob().allocated_test(bluestore_pextent_t(0x2000, 0x2000));
901 L
.dirty_blob().init_csum(Checksummer::CSUM_CRC32C
, 12, 0x2000);
902 L
.get_ref(coll
.get(), 0, 0x2000);
903 L
.split(coll
.get(), 0x1000, &R
);
904 ASSERT_EQ(0x1000u
, L
.get_blob().get_logical_length());
905 ASSERT_EQ(4u, L
.get_blob().csum_data
.length());
906 ASSERT_EQ(1u, L
.get_blob().get_extents().size());
907 ASSERT_EQ(0x2000u
, L
.get_blob().get_extents().front().offset
);
908 ASSERT_EQ(0x1000u
, L
.get_blob().get_extents().front().length
);
909 ASSERT_EQ(0x1000u
, L
.get_referenced_bytes());
910 ASSERT_EQ(0x1000u
, R
.get_blob().get_logical_length());
911 ASSERT_EQ(4u, R
.get_blob().csum_data
.length());
912 ASSERT_EQ(1u, R
.get_blob().get_extents().size());
913 ASSERT_EQ(0x3000u
, R
.get_blob().get_extents().front().offset
);
914 ASSERT_EQ(0x1000u
, R
.get_blob().get_extents().front().length
);
915 ASSERT_EQ(0x1000u
, R
.get_referenced_bytes());
918 BlueStore::Blob L
, R
;
919 L
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
920 L
.shared_blob
->get(); // hack to avoid dtor from running
921 R
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
922 R
.shared_blob
->get(); // hack to avoid dtor from running
923 L
.dirty_blob().allocated_test(bluestore_pextent_t(0x2000, 0x1000));
924 L
.dirty_blob().allocated_test(bluestore_pextent_t(0x12000, 0x1000));
925 L
.dirty_blob().init_csum(Checksummer::CSUM_CRC32C
, 12, 0x2000);
926 L
.get_ref(coll
.get(), 0, 0x1000);
927 L
.get_ref(coll
.get(), 0x1000, 0x1000);
928 L
.split(coll
.get(), 0x1000, &R
);
929 ASSERT_EQ(0x1000u
, L
.get_blob().get_logical_length());
930 ASSERT_EQ(4u, L
.get_blob().csum_data
.length());
931 ASSERT_EQ(1u, L
.get_blob().get_extents().size());
932 ASSERT_EQ(0x2000u
, L
.get_blob().get_extents().front().offset
);
933 ASSERT_EQ(0x1000u
, L
.get_blob().get_extents().front().length
);
934 ASSERT_EQ(0x1000u
, L
.get_referenced_bytes());
935 ASSERT_EQ(0x1000u
, R
.get_blob().get_logical_length());
936 ASSERT_EQ(4u, R
.get_blob().csum_data
.length());
937 ASSERT_EQ(1u, R
.get_blob().get_extents().size());
938 ASSERT_EQ(0x12000u
, R
.get_blob().get_extents().front().offset
);
939 ASSERT_EQ(0x1000u
, R
.get_blob().get_extents().front().length
);
940 ASSERT_EQ(0x1000u
, R
.get_referenced_bytes());
944 TEST(Blob
, legacy_decode
)
946 BlueStore
store(g_ceph_context
, "", 4096);
947 BlueStore::Cache
*cache
= BlueStore::Cache::create(
948 g_ceph_context
, "lru", NULL
);
949 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, cache
, coll_t()));
954 B
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
955 B
.dirty_blob().allocated_test(bluestore_pextent_t(0x1, 0x2000));
956 B
.dirty_blob().init_csum(Checksummer::CSUM_CRC32C
, 12, 0x2000);
957 B
.get_ref(coll
.get(), 0, 0xff0);
958 B
.get_ref(coll
.get(), 0x1fff, 1);
960 bluestore_extent_ref_map_t fake_ref_map
;
961 fake_ref_map
.get(0, 0xff0);
962 fake_ref_map
.get(0x1fff, 1);
964 size_t bound
= 0, bound2
= 0;
971 fake_ref_map
.bound_encode(bound
);
980 auto app
= bl
.get_contiguous_appender(bound
);
981 auto app2
= bl2
.get_contiguous_appender(bound2
);
987 fake_ref_map
.encode(app
);
996 auto p
= bl
.front().begin_deep();
997 auto p2
= bl2
.front().begin_deep();
998 BlueStore::Blob Bres
, Bres2
;
999 Bres
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
1000 Bres2
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
1002 uint64_t sbid
, sbid2
;
1016 ASSERT_EQ(0xff0u
+ 1u, Bres
.get_blob_use_tracker().get_referenced_bytes());
1017 ASSERT_EQ(0xff0u
+ 1u, Bres2
.get_blob_use_tracker().get_referenced_bytes());
1018 ASSERT_TRUE(Bres
.get_blob_use_tracker().equal(Bres2
.get_blob_use_tracker()));
1021 TEST(ExtentMap
, find_lextent
)
1023 BlueStore
store(g_ceph_context
, "", 4096);
1024 BlueStore::LRUCache
cache(g_ceph_context
);
1025 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1026 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1027 BlueStore::ExtentMap
em(&onode
);
1028 BlueStore::BlobRef
br(new BlueStore::Blob
);
1029 br
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1031 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(0));
1032 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(100));
1034 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, br
));
1035 auto a
= em
.find(100);
1036 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(0));
1037 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(99));
1038 ASSERT_EQ(a
, em
.find_lextent(100));
1039 ASSERT_EQ(a
, em
.find_lextent(101));
1040 ASSERT_EQ(a
, em
.find_lextent(199));
1041 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(200));
1043 em
.extent_map
.insert(*new BlueStore::Extent(200, 0, 100, br
));
1044 auto b
= em
.find(200);
1045 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(0));
1046 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(99));
1047 ASSERT_EQ(a
, em
.find_lextent(100));
1048 ASSERT_EQ(a
, em
.find_lextent(101));
1049 ASSERT_EQ(a
, em
.find_lextent(199));
1050 ASSERT_EQ(b
, em
.find_lextent(200));
1051 ASSERT_EQ(b
, em
.find_lextent(299));
1052 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(300));
1054 em
.extent_map
.insert(*new BlueStore::Extent(400, 0, 100, br
));
1055 auto d
= em
.find(400);
1056 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(0));
1057 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(99));
1058 ASSERT_EQ(a
, em
.find_lextent(100));
1059 ASSERT_EQ(a
, em
.find_lextent(101));
1060 ASSERT_EQ(a
, em
.find_lextent(199));
1061 ASSERT_EQ(b
, em
.find_lextent(200));
1062 ASSERT_EQ(b
, em
.find_lextent(299));
1063 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(300));
1064 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(399));
1065 ASSERT_EQ(d
, em
.find_lextent(400));
1066 ASSERT_EQ(d
, em
.find_lextent(499));
1067 ASSERT_EQ(em
.extent_map
.end(), em
.find_lextent(500));
1070 TEST(ExtentMap
, seek_lextent
)
1072 BlueStore
store(g_ceph_context
, "", 4096);
1073 BlueStore::LRUCache
cache(g_ceph_context
);
1074 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1075 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1076 BlueStore::ExtentMap
em(&onode
);
1077 BlueStore::BlobRef
br(new BlueStore::Blob
);
1078 br
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1080 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(0));
1081 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(100));
1083 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, br
));
1084 auto a
= em
.find(100);
1085 ASSERT_EQ(a
, em
.seek_lextent(0));
1086 ASSERT_EQ(a
, em
.seek_lextent(99));
1087 ASSERT_EQ(a
, em
.seek_lextent(100));
1088 ASSERT_EQ(a
, em
.seek_lextent(101));
1089 ASSERT_EQ(a
, em
.seek_lextent(199));
1090 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(200));
1092 em
.extent_map
.insert(*new BlueStore::Extent(200, 0, 100, br
));
1093 auto b
= em
.find(200);
1094 ASSERT_EQ(a
, em
.seek_lextent(0));
1095 ASSERT_EQ(a
, em
.seek_lextent(99));
1096 ASSERT_EQ(a
, em
.seek_lextent(100));
1097 ASSERT_EQ(a
, em
.seek_lextent(101));
1098 ASSERT_EQ(a
, em
.seek_lextent(199));
1099 ASSERT_EQ(b
, em
.seek_lextent(200));
1100 ASSERT_EQ(b
, em
.seek_lextent(299));
1101 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(300));
1103 em
.extent_map
.insert(*new BlueStore::Extent(400, 0, 100, br
));
1104 auto d
= em
.find(400);
1105 ASSERT_EQ(a
, em
.seek_lextent(0));
1106 ASSERT_EQ(a
, em
.seek_lextent(99));
1107 ASSERT_EQ(a
, em
.seek_lextent(100));
1108 ASSERT_EQ(a
, em
.seek_lextent(101));
1109 ASSERT_EQ(a
, em
.seek_lextent(199));
1110 ASSERT_EQ(b
, em
.seek_lextent(200));
1111 ASSERT_EQ(b
, em
.seek_lextent(299));
1112 ASSERT_EQ(d
, em
.seek_lextent(300));
1113 ASSERT_EQ(d
, em
.seek_lextent(399));
1114 ASSERT_EQ(d
, em
.seek_lextent(400));
1115 ASSERT_EQ(d
, em
.seek_lextent(499));
1116 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(500));
1119 TEST(ExtentMap
, has_any_lextents
)
1121 BlueStore
store(g_ceph_context
, "", 4096);
1122 BlueStore::LRUCache
cache(g_ceph_context
);
1123 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1124 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1125 BlueStore::ExtentMap
em(&onode
);
1126 BlueStore::BlobRef
b(new BlueStore::Blob
);
1127 b
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1129 ASSERT_FALSE(em
.has_any_lextents(0, 0));
1130 ASSERT_FALSE(em
.has_any_lextents(0, 1000));
1131 ASSERT_FALSE(em
.has_any_lextents(1000, 1000));
1133 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, b
));
1134 ASSERT_FALSE(em
.has_any_lextents(0, 50));
1135 ASSERT_FALSE(em
.has_any_lextents(0, 100));
1136 ASSERT_FALSE(em
.has_any_lextents(50, 50));
1137 ASSERT_TRUE(em
.has_any_lextents(50, 51));
1138 ASSERT_TRUE(em
.has_any_lextents(50, 100051));
1139 ASSERT_TRUE(em
.has_any_lextents(100, 100));
1140 ASSERT_TRUE(em
.has_any_lextents(100, 1));
1141 ASSERT_TRUE(em
.has_any_lextents(199, 1));
1142 ASSERT_TRUE(em
.has_any_lextents(199, 2));
1143 ASSERT_FALSE(em
.has_any_lextents(200, 2));
1145 em
.extent_map
.insert(*new BlueStore::Extent(200, 0, 100, b
));
1146 ASSERT_TRUE(em
.has_any_lextents(199, 1));
1147 ASSERT_TRUE(em
.has_any_lextents(199, 2));
1148 ASSERT_TRUE(em
.has_any_lextents(200, 2));
1149 ASSERT_TRUE(em
.has_any_lextents(200, 200));
1150 ASSERT_TRUE(em
.has_any_lextents(299, 1));
1151 ASSERT_FALSE(em
.has_any_lextents(300, 1));
1153 em
.extent_map
.insert(*new BlueStore::Extent(400, 0, 100, b
));
1154 ASSERT_TRUE(em
.has_any_lextents(0, 10000));
1155 ASSERT_TRUE(em
.has_any_lextents(199, 1));
1156 ASSERT_FALSE(em
.has_any_lextents(300, 1));
1157 ASSERT_FALSE(em
.has_any_lextents(300, 100));
1158 ASSERT_FALSE(em
.has_any_lextents(399, 1));
1159 ASSERT_TRUE(em
.has_any_lextents(400, 1));
1160 ASSERT_TRUE(em
.has_any_lextents(400, 100));
1161 ASSERT_TRUE(em
.has_any_lextents(400, 1000));
1162 ASSERT_TRUE(em
.has_any_lextents(499, 1000));
1163 ASSERT_FALSE(em
.has_any_lextents(500, 1000));
1166 TEST(ExtentMap
, compress_extent_map
)
1168 BlueStore
store(g_ceph_context
, "", 4096);
1169 BlueStore::LRUCache
cache(g_ceph_context
);
1170 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1171 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1172 BlueStore::ExtentMap
em(&onode
);
1173 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1174 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1175 BlueStore::BlobRef
b3(new BlueStore::Blob
);
1176 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1177 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1178 b3
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1180 em
.extent_map
.insert(*new BlueStore::Extent(0, 0, 100, b1
));
1181 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, b2
));
1182 ASSERT_EQ(0, em
.compress_extent_map(0, 10000));
1183 ASSERT_EQ(2u, em
.extent_map
.size());
1185 em
.extent_map
.insert(*new BlueStore::Extent(200, 100, 100, b2
));
1186 em
.extent_map
.insert(*new BlueStore::Extent(300, 200, 100, b2
));
1187 ASSERT_EQ(0, em
.compress_extent_map(0, 0));
1188 ASSERT_EQ(0, em
.compress_extent_map(100000, 1000));
1189 ASSERT_EQ(2, em
.compress_extent_map(0, 100000));
1190 ASSERT_EQ(2u, em
.extent_map
.size());
1192 em
.extent_map
.erase(em
.find(100));
1193 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, b2
));
1194 em
.extent_map
.insert(*new BlueStore::Extent(200, 100, 100, b3
));
1195 em
.extent_map
.insert(*new BlueStore::Extent(300, 200, 100, b2
));
1196 ASSERT_EQ(0, em
.compress_extent_map(0, 1));
1197 ASSERT_EQ(0, em
.compress_extent_map(0, 100000));
1198 ASSERT_EQ(4u, em
.extent_map
.size());
1200 em
.extent_map
.insert(*new BlueStore::Extent(400, 300, 100, b2
));
1201 em
.extent_map
.insert(*new BlueStore::Extent(500, 500, 100, b2
));
1202 em
.extent_map
.insert(*new BlueStore::Extent(600, 600, 100, b2
));
1203 em
.extent_map
.insert(*new BlueStore::Extent(700, 0, 100, b1
));
1204 em
.extent_map
.insert(*new BlueStore::Extent(800, 0, 100, b3
));
1205 ASSERT_EQ(0, em
.compress_extent_map(0, 99));
1206 ASSERT_EQ(0, em
.compress_extent_map(800, 1000));
1207 ASSERT_EQ(2, em
.compress_extent_map(100, 500));
1208 ASSERT_EQ(7u, em
.extent_map
.size());
1209 em
.extent_map
.erase(em
.find(300));
1210 em
.extent_map
.erase(em
.find(500));
1211 em
.extent_map
.erase(em
.find(700));
1212 em
.extent_map
.insert(*new BlueStore::Extent(400, 300, 100, b2
));
1213 em
.extent_map
.insert(*new BlueStore::Extent(500, 400, 100, b2
));
1214 em
.extent_map
.insert(*new BlueStore::Extent(700, 500, 100, b2
));
1215 ASSERT_EQ(1, em
.compress_extent_map(0, 1000));
1216 ASSERT_EQ(6u, em
.extent_map
.size());
1219 TEST(GarbageCollector
, BasicTest
)
1221 BlueStore::LRUCache
cache(g_ceph_context
);
1222 BlueStore
store(g_ceph_context
, "", 4096);
1223 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1224 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1225 BlueStore::ExtentMap
em(&onode
);
1227 BlueStore::old_extent_map_t old_extents
;
1231 min_alloc_size = 4096
1232 original disposition
1233 extent1 <loffs = 100, boffs = 100, len = 10>
1234 -> blob1<compressed, len_on_disk=4096, logical_len=8192>
1235 extent2 <loffs = 200, boffs = 200, len = 10>
1236 -> blob2<raw, len_on_disk=4096, llen=4096>
1237 extent3 <loffs = 300, boffs = 300, len = 10>
1238 -> blob1<compressed, len_on_disk=4096, llen=8192>
1239 extent4 <loffs = 4096, boffs = 0, len = 10>
1240 -> blob3<raw, len_on_disk=4096, llen=4096>
1241 on write(300~100) resulted in
1242 extent1 <loffs = 100, boffs = 100, len = 10>
1243 -> blob1<compressed, len_on_disk=4096, logical_len=8192>
1244 extent2 <loffs = 200, boffs = 200, len = 10>
1245 -> blob2<raw, len_on_disk=4096, llen=4096>
1246 extent3 <loffs = 300, boffs = 300, len = 100>
1247 -> blob4<raw, len_on_disk=4096, llen=4096>
1248 extent4 <loffs = 4096, boffs = 0, len = 10>
1249 -> blob3<raw, len_on_disk=4096, llen=4096>
1252 BlueStore::GarbageCollector
gc(g_ceph_context
);
1254 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1255 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1256 BlueStore::BlobRef
b3(new BlueStore::Blob
);
1257 BlueStore::BlobRef
b4(new BlueStore::Blob
);
1258 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1259 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1260 b3
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1261 b4
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1262 b1
->dirty_blob().set_compressed(0x2000, 0x1000);
1263 b1
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x1000));
1264 b2
->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x1000));
1265 b3
->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x1000));
1266 b4
->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x1000));
1267 em
.extent_map
.insert(*new BlueStore::Extent(100, 100, 10, b1
));
1268 b1
->get_ref(coll
.get(), 100, 10);
1269 em
.extent_map
.insert(*new BlueStore::Extent(200, 200, 10, b2
));
1270 b2
->get_ref(coll
.get(), 200, 10);
1271 em
.extent_map
.insert(*new BlueStore::Extent(300, 300, 100, b4
));
1272 b4
->get_ref(coll
.get(), 300, 100);
1273 em
.extent_map
.insert(*new BlueStore::Extent(4096, 0, 10, b3
));
1274 b3
->get_ref(coll
.get(), 0, 10);
1276 old_extents
.push_back(*new BlueStore::OldExtent(300, 300, 10, b1
));
1278 saving
= gc
.estimate(300, 100, em
, old_extents
, 4096);
1279 ASSERT_EQ(saving
, 1);
1280 auto& to_collect
= gc
.get_extents_to_collect();
1281 ASSERT_EQ(to_collect
.size(), 1u);
1282 ASSERT_EQ(to_collect
[0], AllocExtent(100,10) );
1285 old_extents
.clear();
1288 original disposition
1289 min_alloc_size = 0x10000
1290 extent1 <loffs = 0, boffs = 0, len = 0x40000>
1291 -> blob1<compressed, len_on_disk=0x20000, logical_len=0x40000>
1292 Write 0x8000~37000 resulted in the following extent map prior to GC
1293 for the last write_small(0x30000~0xf000):
1295 extent1 <loffs = 0, boffs = 0, len = 0x8000>
1296 -> blob1<compressed, len_on_disk=0x20000, logical_len=0x40000>
1297 extent2 <loffs = 0x8000, boffs = 0x8000, len = 0x8000>
1298 -> blob2<raw, len_on_disk=0x10000, llen=0x10000>
1299 extent3 <loffs = 0x10000, boffs = 0, len = 0x20000>
1300 -> blob3<raw, len_on_disk=0x20000, llen=0x20000>
1301 extent4 <loffs = 0x30000, boffs = 0, len = 0xf000>
1302 -> blob4<raw, len_on_disk=0x10000, llen=0x10000>
1303 extent5 <loffs = 0x3f000, boffs = 0x3f000, len = 0x1000>
1304 -> blob1<compressed, len_on_disk=0x20000, llen=0x40000>
1307 BlueStore
store(g_ceph_context
, "", 0x10000);
1308 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1309 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1310 BlueStore::ExtentMap
em(&onode
);
1312 BlueStore::old_extent_map_t old_extents
;
1313 BlueStore::GarbageCollector
gc(g_ceph_context
);
1315 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1316 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1317 BlueStore::BlobRef
b3(new BlueStore::Blob
);
1318 BlueStore::BlobRef
b4(new BlueStore::Blob
);
1319 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1320 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1321 b3
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1322 b4
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1323 b1
->dirty_blob().set_compressed(0x40000, 0x20000);
1324 b1
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x20000));
1325 b2
->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x10000));
1326 b3
->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x20000));
1327 b4
->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x10000));
1329 em
.extent_map
.insert(*new BlueStore::Extent(0, 0, 0x8000, b1
));
1330 b1
->get_ref(coll
.get(), 0, 0x8000);
1331 em
.extent_map
.insert(
1332 *new BlueStore::Extent(0x8000, 0x8000, 0x8000, b2
)); // new extent
1333 b2
->get_ref(coll
.get(), 0x8000, 0x8000);
1334 em
.extent_map
.insert(
1335 *new BlueStore::Extent(0x10000, 0, 0x20000, b3
)); // new extent
1336 b3
->get_ref(coll
.get(), 0, 0x20000);
1337 em
.extent_map
.insert(
1338 *new BlueStore::Extent(0x30000, 0, 0xf000, b4
)); // new extent
1339 b4
->get_ref(coll
.get(), 0, 0xf000);
1340 em
.extent_map
.insert(*new BlueStore::Extent(0x3f000, 0x3f000, 0x1000, b1
));
1341 b1
->get_ref(coll
.get(), 0x3f000, 0x1000);
1343 old_extents
.push_back(*new BlueStore::OldExtent(0x8000, 0x8000, 0x8000, b1
));
1344 old_extents
.push_back(
1345 *new BlueStore::OldExtent(0x10000, 0x10000, 0x20000, b1
));
1346 old_extents
.push_back(*new BlueStore::OldExtent(0x30000, 0x30000, 0xf000, b1
));
1348 saving
= gc
.estimate(0x30000, 0xf000, em
, old_extents
, 0x10000);
1349 ASSERT_EQ(saving
, 2);
1350 auto& to_collect
= gc
.get_extents_to_collect();
1351 ASSERT_EQ(to_collect
.size(), 2u);
1352 ASSERT_TRUE(to_collect
[0] == AllocExtent(0x0,0x8000) ||
1353 to_collect
[1] == AllocExtent(0x0,0x8000));
1354 ASSERT_TRUE(to_collect
[0] == AllocExtent(0x3f000,0x1000) ||
1355 to_collect
[1] == AllocExtent(0x3f000,0x1000));
1358 old_extents
.clear();
1361 original disposition
1362 min_alloc_size = 0x1000
1363 extent1 <loffs = 0, boffs = 0, len = 0x4000>
1364 -> blob1<compressed, len_on_disk=0x2000, logical_len=0x4000>
1365 write 0x3000~4000 resulted in the following extent map
1366 (future feature - suppose we can compress incoming write prior to
1369 extent1 <loffs = 0, boffs = 0, len = 0x4000>
1370 -> blob1<compressed, len_on_disk=0x2000, logical_len=0x4000>
1371 extent2 <loffs = 0x3000, boffs = 0, len = 0x4000>
1372 -> blob2<compressed, len_on_disk=0x2000, llen=0x4000>
1375 BlueStore::GarbageCollector
gc(g_ceph_context
);
1377 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1378 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1379 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1380 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1381 b1
->dirty_blob().set_compressed(0x4000, 0x2000);
1382 b1
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x2000));
1383 b2
->dirty_blob().set_compressed(0x4000, 0x2000);
1384 b2
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x2000));
1386 em
.extent_map
.insert(*new BlueStore::Extent(0, 0, 0x3000, b1
));
1387 b1
->get_ref(coll
.get(), 0, 0x3000);
1388 em
.extent_map
.insert(
1389 *new BlueStore::Extent(0x3000, 0, 0x4000, b2
)); // new extent
1390 b2
->get_ref(coll
.get(), 0, 0x4000);
1392 old_extents
.push_back(*new BlueStore::OldExtent(0x3000, 0x3000, 0x1000, b1
));
1394 saving
= gc
.estimate(0x3000, 0x4000, em
, old_extents
, 0x1000);
1395 ASSERT_EQ(saving
, 0);
1396 auto& to_collect
= gc
.get_extents_to_collect();
1397 ASSERT_EQ(to_collect
.size(), 0u);
1399 old_extents
.clear();
1402 original disposition
1403 min_alloc_size = 0x10000
1404 extent0 <loffs = 0, boffs = 0, len = 0x20000>
1405 -> blob0<compressed, len_on_disk=0x10000, logical_len=0x20000>
1406 extent1 <loffs = 0x20000, boffs = 0, len = 0x20000>
1407 -> blob1<compressed, len_on_disk=0x10000, logical_len=0x20000>
1408 write 0x8000~37000 resulted in the following extent map prior
1409 to GC for the last write_small(0x30000~0xf000)
1411 extent0 <loffs = 0, boffs = 0, len = 0x8000>
1412 -> blob0<compressed, len_on_disk=0x10000, logical_len=0x20000>
1413 extent2 <loffs = 0x8000, boffs = 0x8000, len = 0x8000>
1414 -> blob2<raw, len_on_disk=0x10000, llen=0x10000>
1415 extent3 <loffs = 0x10000, boffs = 0, len = 0x20000>
1416 -> blob3<raw, len_on_disk=0x20000, llen=0x20000>
1417 extent4 <loffs = 0x30000, boffs = 0, len = 0xf000>
1418 -> blob4<raw, len_on_disk=0x1000, llen=0x1000>
1419 extent5 <loffs = 0x3f000, boffs = 0x1f000, len = 0x1000>
1420 -> blob1<compressed, len_on_disk=0x10000, llen=0x20000>
1423 BlueStore
store(g_ceph_context
, "", 0x10000);
1424 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1425 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1426 BlueStore::ExtentMap
em(&onode
);
1428 BlueStore::old_extent_map_t old_extents
;
1429 BlueStore::GarbageCollector
gc(g_ceph_context
);
1431 BlueStore::BlobRef
b0(new BlueStore::Blob
);
1432 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1433 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1434 BlueStore::BlobRef
b3(new BlueStore::Blob
);
1435 BlueStore::BlobRef
b4(new BlueStore::Blob
);
1436 b0
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1437 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1438 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1439 b3
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1440 b4
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1441 b0
->dirty_blob().set_compressed(0x2000, 0x1000);
1442 b0
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x10000));
1443 b1
->dirty_blob().set_compressed(0x20000, 0x10000);
1444 b1
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x10000));
1445 b2
->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x10000));
1446 b3
->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x20000));
1447 b4
->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x1000));
1449 em
.extent_map
.insert(*new BlueStore::Extent(0, 0, 0x8000, b0
));
1450 b0
->get_ref(coll
.get(), 0, 0x8000);
1451 em
.extent_map
.insert(
1452 *new BlueStore::Extent(0x8000, 0x8000, 0x8000, b2
)); // new extent
1453 b2
->get_ref(coll
.get(), 0x8000, 0x8000);
1454 em
.extent_map
.insert(
1455 *new BlueStore::Extent(0x10000, 0, 0x20000, b3
)); // new extent
1456 b3
->get_ref(coll
.get(), 0, 0x20000);
1457 em
.extent_map
.insert(
1458 *new BlueStore::Extent(0x30000, 0, 0xf000, b4
)); // new extent
1459 b4
->get_ref(coll
.get(), 0, 0xf000);
1460 em
.extent_map
.insert(*new BlueStore::Extent(0x3f000, 0x1f000, 0x1000, b1
));
1461 b1
->get_ref(coll
.get(), 0x1f000, 0x1000);
1463 old_extents
.push_back(*new BlueStore::OldExtent(0x8000, 0x8000, 0x8000, b0
));
1464 old_extents
.push_back(
1465 *new BlueStore::OldExtent(0x10000, 0x10000, 0x10000, b0
));
1466 old_extents
.push_back(
1467 *new BlueStore::OldExtent(0x20000, 0x00000, 0x1f000, b1
));
1469 saving
= gc
.estimate(0x30000, 0xf000, em
, old_extents
, 0x10000);
1470 ASSERT_EQ(saving
, 2);
1471 auto& to_collect
= gc
.get_extents_to_collect();
1472 ASSERT_EQ(to_collect
.size(), 2u);
1473 ASSERT_TRUE(to_collect
[0] == AllocExtent(0x0,0x8000) ||
1474 to_collect
[1] == AllocExtent(0x0,0x8000));
1475 ASSERT_TRUE(to_collect
[0] == AllocExtent(0x3f000,0x1000) ||
1476 to_collect
[1] == AllocExtent(0x3f000,0x1000));
1479 old_extents
.clear();
1483 int main(int argc
, char **argv
) {
1484 vector
<const char*> args
;
1485 argv_to_vec(argc
, (const char **)argv
, args
);
1487 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
1488 CODE_ENVIRONMENT_UTILITY
, 0);
1489 common_init_finish(g_ceph_context
);
1490 ::testing::InitGoogleTest(&argc
, argv
);
1491 return RUN_ALL_TESTS();