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
;
123 bool maybe_unshared
= false;
125 maybe_unshared
= true;
126 m
.put(10, 30, &r
, &maybe_unshared
);
127 cout
<< m
<< " " << r
<< " " << (int)maybe_unshared
<< std::endl
;
128 ASSERT_EQ(0u, m
.ref_map
.size());
129 ASSERT_EQ(1u, r
.size());
130 ASSERT_EQ(10u, r
[0].offset
);
131 ASSERT_EQ(30u, r
[0].length
);
132 ASSERT_TRUE(maybe_unshared
);
136 maybe_unshared
= true;
137 m
.put(10, 30, &r
, &maybe_unshared
);
138 cout
<< m
<< " " << r
<< " " << (int)maybe_unshared
<< std::endl
;
139 ASSERT_EQ(1u, m
.ref_map
.size());
140 ASSERT_EQ(10u, m
.ref_map
[20].length
);
141 ASSERT_EQ(1u, m
.ref_map
[20].refs
);
142 ASSERT_EQ(2u, r
.size());
143 ASSERT_EQ(10u, r
[0].offset
);
144 ASSERT_EQ(10u, r
[0].length
);
145 ASSERT_EQ(30u, r
[1].offset
);
146 ASSERT_EQ(10u, r
[1].length
);
147 ASSERT_TRUE(maybe_unshared
);
151 maybe_unshared
= true;
152 m
.put(20, 15, &r
, &maybe_unshared
);
153 cout
<< m
<< " " << r
<< " " << (int)maybe_unshared
<< std::endl
;
154 ASSERT_EQ(2u, m
.ref_map
.size());
155 ASSERT_EQ(5u, m
.ref_map
[30].length
);
156 ASSERT_EQ(1u, m
.ref_map
[30].refs
);
157 ASSERT_EQ(5u, m
.ref_map
[35].length
);
158 ASSERT_EQ(2u, m
.ref_map
[35].refs
);
159 ASSERT_EQ(1u, r
.size());
160 ASSERT_EQ(20u, r
[0].offset
);
161 ASSERT_EQ(10u, r
[0].length
);
162 ASSERT_FALSE(maybe_unshared
);
164 maybe_unshared
= true;
165 m
.put(33, 5, &r
, &maybe_unshared
);
166 cout
<< m
<< " " << r
<< " " << (int)maybe_unshared
<< std::endl
;
167 ASSERT_EQ(3u, m
.ref_map
.size());
168 ASSERT_EQ(3u, m
.ref_map
[30].length
);
169 ASSERT_EQ(1u, m
.ref_map
[30].refs
);
170 ASSERT_EQ(3u, m
.ref_map
[35].length
);
171 ASSERT_EQ(1u, m
.ref_map
[35].refs
);
172 ASSERT_EQ(2u, m
.ref_map
[38].length
);
173 ASSERT_EQ(2u, m
.ref_map
[38].refs
);
174 ASSERT_EQ(1u, r
.size());
175 ASSERT_EQ(33u, r
[0].offset
);
176 ASSERT_EQ(2u, r
[0].length
);
177 ASSERT_FALSE(maybe_unshared
);
179 maybe_unshared
= true;
180 m
.put(38, 2, &r
, &maybe_unshared
);
181 cout
<< m
<< " " << r
<< " " << (int)maybe_unshared
<< std::endl
;
182 ASSERT_TRUE(maybe_unshared
);
185 TEST(bluestore_extent_ref_map_t
, contains
)
187 bluestore_extent_ref_map_t m
;
189 ASSERT_TRUE(m
.contains(10, 30));
190 ASSERT_TRUE(m
.contains(10, 10));
191 ASSERT_TRUE(m
.contains(30, 10));
192 ASSERT_FALSE(m
.contains(0, 10));
193 ASSERT_FALSE(m
.contains(0, 20));
194 ASSERT_FALSE(m
.contains(0, 100));
195 ASSERT_FALSE(m
.contains(40, 10));
196 ASSERT_FALSE(m
.contains(30, 11));
199 ASSERT_TRUE(m
.contains(30, 11));
200 ASSERT_TRUE(m
.contains(30, 20));
201 ASSERT_TRUE(m
.contains(10, 40));
202 ASSERT_FALSE(m
.contains(0, 50));
203 ASSERT_FALSE(m
.contains(40, 20));
205 ASSERT_TRUE(m
.contains(60, 10));
206 ASSERT_TRUE(m
.contains(40, 10));
207 ASSERT_FALSE(m
.contains(40, 11));
208 ASSERT_FALSE(m
.contains(40, 20));
209 ASSERT_FALSE(m
.contains(40, 30));
210 ASSERT_FALSE(m
.contains(40, 3000));
211 ASSERT_FALSE(m
.contains(4000, 30));
214 TEST(bluestore_extent_ref_map_t
, intersects
)
216 bluestore_extent_ref_map_t m
;
218 ASSERT_TRUE(m
.intersects(10, 30));
219 ASSERT_TRUE(m
.intersects(0, 11));
220 ASSERT_TRUE(m
.intersects(10, 40));
221 ASSERT_TRUE(m
.intersects(15, 40));
222 ASSERT_FALSE(m
.intersects(0, 10));
223 ASSERT_FALSE(m
.intersects(0, 5));
224 ASSERT_FALSE(m
.intersects(40, 20));
225 ASSERT_FALSE(m
.intersects(41, 20));
228 ASSERT_TRUE(m
.intersects(0, 100));
229 ASSERT_TRUE(m
.intersects(10, 35));
230 ASSERT_TRUE(m
.intersects(45, 10));
231 ASSERT_FALSE(m
.intersects(50, 5));
233 ASSERT_TRUE(m
.intersects(45, 10));
234 ASSERT_TRUE(m
.intersects(55, 10));
235 ASSERT_TRUE(m
.intersects(50, 11));
236 ASSERT_FALSE(m
.intersects(50, 10));
237 ASSERT_FALSE(m
.intersects(51, 9));
238 ASSERT_FALSE(m
.intersects(55, 1));
241 TEST(bluestore_blob_t
, calc_csum
)
244 bl
.append("asdfghjkqwertyuizxcvbnm,");
246 bl2
.append("xxxxXXXXyyyyYYYYzzzzZZZZ");
248 f
.substr_of(bl
, 0, 8);
250 m
.substr_of(bl
, 8, 8);
252 e
.substr_of(bl
, 16, 8);
254 n
.append("12345678");
256 for (unsigned csum_type
= Checksummer::CSUM_NONE
+ 1;
257 csum_type
< Checksummer::CSUM_MAX
;
259 cout
<< "csum_type " << Checksummer::get_csum_type_string(csum_type
)
265 ASSERT_EQ(0, b
.verify_csum(0, bl
, &bad_off
, &bad_csum
));
266 ASSERT_EQ(-1, bad_off
);
268 b
.init_csum(csum_type
, 3, 24);
269 cout
<< " value size " << b
.get_csum_value_size() << std::endl
;
271 ASSERT_EQ(0, b
.verify_csum(0, bl
, &bad_off
, &bad_csum
));
272 ASSERT_EQ(-1, bad_off
);
273 ASSERT_EQ(-1, b
.verify_csum(0, bl2
, &bad_off
, &bad_csum
));
274 ASSERT_EQ(0, bad_off
);
276 ASSERT_EQ(0, b
.verify_csum(0, f
, &bad_off
, &bad_csum
));
277 ASSERT_EQ(-1, bad_off
);
278 ASSERT_EQ(-1, b
.verify_csum(8, f
, &bad_off
, &bad_csum
));
279 ASSERT_EQ(8, bad_off
);
280 ASSERT_EQ(-1, b
.verify_csum(16, f
, &bad_off
, &bad_csum
));
281 ASSERT_EQ(16, bad_off
);
283 ASSERT_EQ(-1, b
.verify_csum(0, m
, &bad_off
, &bad_csum
));
284 ASSERT_EQ(0, bad_off
);
285 ASSERT_EQ(0, b
.verify_csum(8, m
, &bad_off
, &bad_csum
));
286 ASSERT_EQ(-1, bad_off
);
287 ASSERT_EQ(-1, b
.verify_csum(16, m
, &bad_off
, &bad_csum
));
288 ASSERT_EQ(16, bad_off
);
290 ASSERT_EQ(-1, b
.verify_csum(0, e
, &bad_off
, &bad_csum
));
291 ASSERT_EQ(0, bad_off
);
292 ASSERT_EQ(-1, b
.verify_csum(8, e
, &bad_off
, &bad_csum
));
293 ASSERT_EQ(8, bad_off
);
294 ASSERT_EQ(0, b
.verify_csum(16, e
, &bad_off
, &bad_csum
));
295 ASSERT_EQ(-1, bad_off
);
298 ASSERT_EQ(0, b
.verify_csum(0, f
, &bad_off
, &bad_csum
));
299 ASSERT_EQ(-1, bad_off
);
300 ASSERT_EQ(0, b
.verify_csum(8, n
, &bad_off
, &bad_csum
));
301 ASSERT_EQ(-1, bad_off
);
302 ASSERT_EQ(0, b
.verify_csum(16, e
, &bad_off
, &bad_csum
));
303 ASSERT_EQ(-1, bad_off
);
304 ASSERT_EQ(-1, b
.verify_csum(0, bl
, &bad_off
, &bad_csum
));
305 ASSERT_EQ(8, bad_off
);
309 TEST(bluestore_blob_t
, csum_bench
)
312 bufferptr
bp(10485760);
313 for (char *a
= bp
.c_str(); a
< bp
.c_str() + bp
.length(); ++a
)
314 *a
= (unsigned long)a
& 0xff;
317 for (unsigned csum_type
= 1;
318 csum_type
< Checksummer::CSUM_MAX
;
321 b
.init_csum(csum_type
, 12, bl
.length());
322 ceph::mono_clock::time_point start
= ceph::mono_clock::now();
323 for (int i
= 0; i
<count
; ++i
) {
326 ceph::mono_clock::time_point end
= ceph::mono_clock::now();
327 auto dur
= std::chrono::duration_cast
<std::chrono::nanoseconds
>(end
- start
);
328 double mbsec
= (double)count
* (double)bl
.length() / 1000000.0 / (double)dur
.count() * 1000000000.0;
329 cout
<< "csum_type " << Checksummer::get_csum_type_string(csum_type
)
330 << ", " << dur
<< " seconds, "
331 << mbsec
<< " MB/sec" << std::endl
;
338 BlueStore
store(g_ceph_context
, "", 4096);
339 BlueStore::Cache
*cache
= BlueStore::Cache::create(
340 g_ceph_context
, "lru", NULL
);
341 BlueStore::Collection
coll(&store
, cache
, coll_t());
343 b
.shared_blob
= new BlueStore::SharedBlob(nullptr);
344 b
.shared_blob
->get(); // hack to avoid dtor from running
345 b
.dirty_blob().allocated_test(bluestore_pextent_t(0x40715000, 0x2000));
346 b
.dirty_blob().allocated_test(
347 bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
, 0x8000));
348 b
.dirty_blob().allocated_test(bluestore_pextent_t(0x4071f000, 0x5000));
349 b
.get_ref(&coll
, 0, 0x1200);
350 b
.get_ref(&coll
, 0xae00, 0x4200);
351 ASSERT_EQ(0x5400u
, b
.get_referenced_bytes());
352 cout
<< b
<< std::endl
;
355 ASSERT_FALSE(b
.put_ref(&coll
, 0, 0x1200, &r
));
356 ASSERT_EQ(0x4200u
, b
.get_referenced_bytes());
357 cout
<< " r " << r
<< std::endl
;
358 cout
<< b
<< std::endl
;
361 ASSERT_TRUE(b
.put_ref(&coll
, 0xae00, 0x4200, &r
));
362 ASSERT_EQ(0u, b
.get_referenced_bytes());
363 cout
<< " r " << r
<< std::endl
;
364 cout
<< b
<< std::endl
;
368 BlueStore
store(g_ceph_context
, "", 8192);
369 BlueStore::Cache
*cache
= BlueStore::Cache::create(
370 g_ceph_context
, "lru", NULL
);
371 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, cache
, coll_t()));
375 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
376 B
.shared_blob
->get(); // hack to avoid dtor from running
377 bluestore_blob_t
& b
= B
.dirty_blob();
379 b
.allocated_test(bluestore_pextent_t(0, mas
* 2));
380 B
.get_ref(coll
.get(), 0, mas
*2);
381 ASSERT_EQ(mas
* 2, B
.get_referenced_bytes());
382 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
383 ASSERT_TRUE(B
.put_ref(coll
.get(), 0, mas
*2, &r
));
384 ASSERT_EQ(0u, B
.get_referenced_bytes());
385 cout
<< "r " << r
<< " " << b
<< std::endl
;
386 ASSERT_EQ(1u, r
.size());
387 ASSERT_EQ(0u, r
[0].offset
);
388 ASSERT_EQ(mas
*2, r
[0].length
);
389 ASSERT_FALSE(b
.is_allocated(0, mas
*2));
390 ASSERT_FALSE(b
.is_allocated(0, mas
));
391 ASSERT_FALSE(b
.is_allocated(mas
, 0));
392 ASSERT_FALSE(b
.get_extents()[0].is_valid());
393 ASSERT_EQ(mas
*2, b
.get_extents()[0].length
);
397 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
398 B
.shared_blob
->get(); // hack to avoid dtor from running
399 bluestore_blob_t
& b
= B
.dirty_blob();
401 b
.allocated_test(bluestore_pextent_t(123, mas
* 2));
402 B
.get_ref(coll
.get(), 0, mas
*2);
403 ASSERT_EQ(mas
* 2, B
.get_referenced_bytes());
404 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, mas
, &r
));
405 ASSERT_EQ(mas
, B
.get_referenced_bytes());
406 cout
<< "r " << r
<< " " << b
<< std::endl
;
407 ASSERT_EQ(0u, r
.size());
408 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
409 ASSERT_TRUE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
410 ASSERT_EQ(0u, B
.get_referenced_bytes());
411 ASSERT_EQ(0u, B
.get_referenced_bytes());
412 cout
<< "r " << r
<< " " << b
<< std::endl
;
413 ASSERT_EQ(1u, r
.size());
414 ASSERT_EQ(123u, r
[0].offset
);
415 ASSERT_EQ(mas
*2, r
[0].length
);
416 ASSERT_FALSE(b
.is_allocated(0, mas
*2));
417 ASSERT_FALSE(b
.get_extents()[0].is_valid());
418 ASSERT_EQ(mas
*2, b
.get_extents()[0].length
);
422 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
423 B
.shared_blob
->get(); // hack to avoid dtor from running
424 bluestore_blob_t
& b
= B
.dirty_blob();
426 b
.allocated_test(bluestore_pextent_t(1, mas
));
427 b
.allocated_test(bluestore_pextent_t(2, mas
));
428 b
.allocated_test(bluestore_pextent_t(3, mas
));
429 b
.allocated_test(bluestore_pextent_t(4, mas
));
430 B
.get_ref(coll
.get(), 0, mas
*4);
431 ASSERT_EQ(mas
* 4, B
.get_referenced_bytes());
432 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
433 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
434 cout
<< "r " << r
<< " " << b
<< std::endl
;
435 ASSERT_EQ(0u, r
.size());
436 ASSERT_TRUE(b
.is_allocated(0, mas
*4));
437 ASSERT_TRUE(b
.is_allocated(mas
, mas
));
438 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
, &r
));
439 ASSERT_EQ(mas
* 2, B
.get_referenced_bytes());
440 cout
<< "r " << r
<< " " << b
<< std::endl
;
441 ASSERT_EQ(0u, r
.size());
442 ASSERT_TRUE(b
.is_allocated(mas
*2, mas
));
443 ASSERT_TRUE(b
.is_allocated(0, mas
*4));
444 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*3, mas
, &r
));
445 ASSERT_EQ(mas
, B
.get_referenced_bytes());
446 cout
<< "r " << r
<< " " << b
<< std::endl
;
447 ASSERT_EQ(2u, r
.size());
448 ASSERT_EQ(3u, r
[0].offset
);
449 ASSERT_EQ(mas
, r
[0].length
);
450 ASSERT_EQ(4u, r
[1].offset
);
451 ASSERT_EQ(mas
, r
[1].length
);
452 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
453 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*2));
454 ASSERT_TRUE(b
.get_extents()[0].is_valid());
455 ASSERT_TRUE(b
.get_extents()[1].is_valid());
456 ASSERT_FALSE(b
.get_extents()[2].is_valid());
457 ASSERT_EQ(3u, b
.get_extents().size());
461 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
462 B
.shared_blob
->get(); // hack to avoid dtor from running
463 bluestore_blob_t
& b
= B
.dirty_blob();
465 b
.allocated_test(bluestore_pextent_t(1, mas
));
466 b
.allocated_test(bluestore_pextent_t(2, mas
));
467 b
.allocated_test(bluestore_pextent_t(3, mas
));
468 b
.allocated_test(bluestore_pextent_t(4, mas
));
469 b
.allocated_test(bluestore_pextent_t(5, mas
));
470 b
.allocated_test(bluestore_pextent_t(6, mas
));
471 B
.get_ref(coll
.get(), 0, mas
*6);
472 ASSERT_EQ(mas
* 6, B
.get_referenced_bytes());
473 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
474 ASSERT_EQ(mas
* 5, B
.get_referenced_bytes());
475 cout
<< "r " << r
<< " " << b
<< std::endl
;
476 ASSERT_EQ(0u, r
.size());
477 ASSERT_TRUE(b
.is_allocated(0, mas
*6));
478 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
, &r
));
479 ASSERT_EQ(mas
* 4, B
.get_referenced_bytes());
480 cout
<< "r " << r
<< " " << b
<< std::endl
;
481 ASSERT_EQ(0u, r
.size());
482 ASSERT_TRUE(b
.is_allocated(0, mas
*6));
483 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*3, mas
, &r
));
484 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
485 cout
<< "r " << r
<< " " << b
<< std::endl
;
486 ASSERT_EQ(2u, r
.size());
487 ASSERT_EQ(3u, r
[0].offset
);
488 ASSERT_EQ(mas
, r
[0].length
);
489 ASSERT_EQ(4u, r
[1].offset
);
490 ASSERT_EQ(mas
, r
[1].length
);
491 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
492 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*2));
493 ASSERT_TRUE(b
.is_allocated(mas
*4, mas
*2));
494 ASSERT_EQ(5u, b
.get_extents().size());
495 ASSERT_TRUE(b
.get_extents()[0].is_valid());
496 ASSERT_TRUE(b
.get_extents()[1].is_valid());
497 ASSERT_FALSE(b
.get_extents()[2].is_valid());
498 ASSERT_TRUE(b
.get_extents()[3].is_valid());
499 ASSERT_TRUE(b
.get_extents()[4].is_valid());
503 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
504 B
.shared_blob
->get(); // hack to avoid dtor from running
505 bluestore_blob_t
& b
= B
.dirty_blob();
507 b
.allocated_test(bluestore_pextent_t(1, mas
* 6));
508 B
.get_ref(coll
.get(), 0, mas
*6);
509 ASSERT_EQ(mas
* 6, B
.get_referenced_bytes());
510 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
511 ASSERT_EQ(mas
* 5, B
.get_referenced_bytes());
512 cout
<< "r " << r
<< " " << b
<< std::endl
;
513 ASSERT_EQ(0u, r
.size());
514 ASSERT_TRUE(b
.is_allocated(0, mas
*6));
515 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
, &r
));
516 ASSERT_EQ(mas
* 4, B
.get_referenced_bytes());
517 cout
<< "r " << r
<< " " << b
<< std::endl
;
518 ASSERT_EQ(0u, r
.size());
519 ASSERT_TRUE(b
.is_allocated(0, mas
*6));
520 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*3, mas
, &r
));
521 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
522 cout
<< "r " << r
<< " " << b
<< std::endl
;
523 ASSERT_EQ(1u, r
.size());
524 ASSERT_EQ(0x2001u
, r
[0].offset
);
525 ASSERT_EQ(mas
*2, r
[0].length
);
526 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
527 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*2));
528 ASSERT_TRUE(b
.is_allocated(mas
*4, mas
*2));
529 ASSERT_EQ(3u, b
.get_extents().size());
530 ASSERT_TRUE(b
.get_extents()[0].is_valid());
531 ASSERT_FALSE(b
.get_extents()[1].is_valid());
532 ASSERT_TRUE(b
.get_extents()[2].is_valid());
536 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
537 B
.shared_blob
->get(); // hack to avoid dtor from running
538 bluestore_blob_t
& b
= B
.dirty_blob();
540 b
.allocated_test(bluestore_pextent_t(1, mas
* 4));
541 b
.allocated_test(bluestore_pextent_t(2, mas
* 4));
542 b
.allocated_test(bluestore_pextent_t(3, mas
* 4));
543 B
.get_ref(coll
.get(), 0, mas
*12);
544 ASSERT_EQ(mas
* 12, B
.get_referenced_bytes());
545 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
546 ASSERT_EQ(mas
* 11, B
.get_referenced_bytes());
547 cout
<< "r " << r
<< " " << b
<< std::endl
;
548 ASSERT_EQ(0u, r
.size());
549 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
550 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*9, mas
, &r
));
551 ASSERT_EQ(mas
* 10, B
.get_referenced_bytes());
552 cout
<< "r " << r
<< " " << b
<< std::endl
;
553 ASSERT_EQ(0u, r
.size());
554 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
555 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
*7, &r
));
556 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
557 cout
<< "r " << r
<< " " << b
<< std::endl
;
558 ASSERT_EQ(3u, r
.size());
559 ASSERT_EQ(0x2001u
, r
[0].offset
);
560 ASSERT_EQ(mas
*2, r
[0].length
);
561 ASSERT_EQ(0x2u
, r
[1].offset
);
562 ASSERT_EQ(mas
*4, r
[1].length
);
563 ASSERT_EQ(0x3u
, r
[2].offset
);
564 ASSERT_EQ(mas
*2, r
[2].length
);
565 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
566 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*8));
567 ASSERT_TRUE(b
.is_allocated(mas
*10, mas
*2));
568 ASSERT_EQ(3u, b
.get_extents().size());
569 ASSERT_TRUE(b
.get_extents()[0].is_valid());
570 ASSERT_FALSE(b
.get_extents()[1].is_valid());
571 ASSERT_TRUE(b
.get_extents()[2].is_valid());
575 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
576 B
.shared_blob
->get(); // hack to avoid dtor from running
577 bluestore_blob_t
& b
= B
.dirty_blob();
579 b
.allocated_test(bluestore_pextent_t(1, mas
* 4));
580 b
.allocated_test(bluestore_pextent_t(2, mas
* 4));
581 b
.allocated_test(bluestore_pextent_t(3, mas
* 4));
582 B
.get_ref(coll
.get(), 0, mas
*12);
583 ASSERT_EQ(mas
* 12, B
.get_referenced_bytes());
584 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
585 ASSERT_EQ(mas
* 11, B
.get_referenced_bytes());
586 cout
<< "r " << r
<< " " << b
<< std::endl
;
587 ASSERT_EQ(0u, r
.size());
588 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
589 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*9, mas
, &r
));
590 ASSERT_EQ(mas
* 10, B
.get_referenced_bytes());
591 cout
<< "r " << r
<< " " << b
<< std::endl
;
592 ASSERT_EQ(0u, r
.size());
593 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
594 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
*7, &r
));
595 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
596 cout
<< "r " << r
<< " " << b
<< std::endl
;
597 ASSERT_EQ(3u, r
.size());
598 ASSERT_EQ(0x2001u
, r
[0].offset
);
599 ASSERT_EQ(mas
*2, r
[0].length
);
600 ASSERT_EQ(0x2u
, r
[1].offset
);
601 ASSERT_EQ(mas
*4, r
[1].length
);
602 ASSERT_EQ(0x3u
, r
[2].offset
);
603 ASSERT_EQ(mas
*2, r
[2].length
);
604 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
605 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*8));
606 ASSERT_TRUE(b
.is_allocated(mas
*10, mas
*2));
607 ASSERT_EQ(3u, b
.get_extents().size());
608 ASSERT_TRUE(b
.get_extents()[0].is_valid());
609 ASSERT_FALSE(b
.get_extents()[1].is_valid());
610 ASSERT_TRUE(b
.get_extents()[2].is_valid());
611 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, mas
, &r
));
612 ASSERT_EQ(mas
* 2, B
.get_referenced_bytes());
613 cout
<< "r " << r
<< " " << b
<< std::endl
;
614 ASSERT_EQ(1u, r
.size());
615 ASSERT_EQ(0x1u
, r
[0].offset
);
616 ASSERT_EQ(mas
*2, r
[0].length
);
617 ASSERT_EQ(2u, b
.get_extents().size());
618 ASSERT_FALSE(b
.get_extents()[0].is_valid());
619 ASSERT_TRUE(b
.get_extents()[1].is_valid());
620 ASSERT_TRUE(B
.put_ref(coll
.get(), mas
*10, mas
*2, &r
));
621 ASSERT_EQ(mas
* 0, B
.get_referenced_bytes());
622 cout
<< "r " << r
<< " " << b
<< std::endl
;
623 ASSERT_EQ(1u, r
.size());
624 ASSERT_EQ(0x2003u
, r
[0].offset
);
625 ASSERT_EQ(mas
*2, r
[0].length
);
626 ASSERT_EQ(1u, b
.get_extents().size());
627 ASSERT_FALSE(b
.get_extents()[0].is_valid());
631 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
632 B
.shared_blob
->get(); // hack to avoid dtor from running
633 bluestore_blob_t
& b
= B
.dirty_blob();
635 b
.allocated_test(bluestore_pextent_t(1, mas
* 4));
636 b
.allocated_test(bluestore_pextent_t(2, mas
* 4));
637 b
.allocated_test(bluestore_pextent_t(3, mas
* 4));
638 B
.get_ref(coll
.get(), 0, mas
*12);
639 ASSERT_EQ(mas
* 12, B
.get_referenced_bytes());
640 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
641 ASSERT_EQ(mas
* 11, B
.get_referenced_bytes());
642 cout
<< "r " << r
<< " " << b
<< std::endl
;
643 ASSERT_EQ(0u, r
.size());
644 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
645 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*9, mas
, &r
));
646 ASSERT_EQ(mas
* 10, B
.get_referenced_bytes());
647 cout
<< "r " << r
<< " " << b
<< std::endl
;
648 ASSERT_EQ(0u, r
.size());
649 ASSERT_TRUE(b
.is_allocated(0, mas
*12));
650 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
*7, &r
));
651 ASSERT_EQ(mas
* 3, B
.get_referenced_bytes());
652 cout
<< "r " << r
<< " " << b
<< std::endl
;
653 ASSERT_EQ(3u, r
.size());
654 ASSERT_EQ(0x2001u
, r
[0].offset
);
655 ASSERT_EQ(mas
*2, r
[0].length
);
656 ASSERT_EQ(0x2u
, r
[1].offset
);
657 ASSERT_EQ(mas
*4, r
[1].length
);
658 ASSERT_EQ(0x3u
, r
[2].offset
);
659 ASSERT_EQ(mas
*2, r
[2].length
);
660 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
661 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*8));
662 ASSERT_TRUE(b
.is_allocated(mas
*10, mas
*2));
663 ASSERT_EQ(3u, b
.get_extents().size());
664 ASSERT_TRUE(b
.get_extents()[0].is_valid());
665 ASSERT_FALSE(b
.get_extents()[1].is_valid());
666 ASSERT_TRUE(b
.get_extents()[2].is_valid());
667 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*10, mas
*2, &r
));
668 ASSERT_EQ(mas
* 1, B
.get_referenced_bytes());
669 cout
<< "r " << r
<< " " << b
<< std::endl
;
670 ASSERT_EQ(1u, r
.size());
671 ASSERT_EQ(0x2003u
, r
[0].offset
);
672 ASSERT_EQ(mas
*2, r
[0].length
);
673 ASSERT_EQ(2u, b
.get_extents().size());
674 ASSERT_TRUE(b
.get_extents()[0].is_valid());
675 ASSERT_FALSE(b
.get_extents()[1].is_valid());
676 ASSERT_TRUE(B
.put_ref(coll
.get(), 0, mas
, &r
));
677 ASSERT_EQ(mas
* 0, B
.get_referenced_bytes());
678 cout
<< "r " << r
<< " " << b
<< std::endl
;
679 ASSERT_EQ(1u, r
.size());
680 ASSERT_EQ(0x1u
, r
[0].offset
);
681 ASSERT_EQ(mas
*2, r
[0].length
);
682 ASSERT_EQ(1u, b
.get_extents().size());
683 ASSERT_FALSE(b
.get_extents()[0].is_valid());
687 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
688 B
.shared_blob
->get(); // hack to avoid dtor from running
689 bluestore_blob_t
& b
= B
.dirty_blob();
691 b
.allocated_test(bluestore_pextent_t(1, mas
* 8));
692 B
.get_ref(coll
.get(), 0, mas
*8);
693 ASSERT_EQ(mas
* 8, B
.get_referenced_bytes());
694 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, mas
, &r
));
695 ASSERT_EQ(mas
* 7, B
.get_referenced_bytes());
696 cout
<< "r " << r
<< " " << b
<< std::endl
;
697 ASSERT_EQ(0u, r
.size());
698 ASSERT_TRUE(b
.is_allocated(0, mas
*8));
699 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*7, mas
, &r
));
700 ASSERT_EQ(mas
* 6, B
.get_referenced_bytes());
701 cout
<< "r " << r
<< " " << b
<< std::endl
;
702 ASSERT_EQ(0u, r
.size());
703 ASSERT_TRUE(b
.is_allocated(0, mas
*8));
704 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*2, mas
, &r
));
705 ASSERT_EQ(mas
* 5, B
.get_referenced_bytes());
706 cout
<< "r " << r
<< " " << b
<< std::endl
;
707 ASSERT_EQ(0u, r
.size());
708 ASSERT_TRUE(b
.is_allocated(0, 8));
709 ASSERT_FALSE(B
.put_ref(coll
.get(), mas
*3, mas
*4, &r
));
710 ASSERT_EQ(mas
* 1, B
.get_referenced_bytes());
711 ASSERT_EQ(1u, r
.size());
712 ASSERT_EQ(0x2001u
, r
[0].offset
);
713 ASSERT_EQ(mas
*6, r
[0].length
);
714 ASSERT_TRUE(b
.is_allocated(0, mas
*2));
715 ASSERT_FALSE(b
.is_allocated(mas
*2, mas
*6));
716 ASSERT_EQ(2u, b
.get_extents().size());
717 ASSERT_TRUE(b
.get_extents()[0].is_valid());
718 ASSERT_FALSE(b
.get_extents()[1].is_valid());
719 ASSERT_TRUE(B
.put_ref(coll
.get(), mas
, mas
, &r
));
720 ASSERT_EQ(mas
* 0, B
.get_referenced_bytes());
721 cout
<< "r " << r
<< " " << b
<< std::endl
;
722 ASSERT_EQ(1u, r
.size());
723 ASSERT_EQ(0x1u
, r
[0].offset
);
724 ASSERT_EQ(mas
*2, r
[0].length
);
725 ASSERT_EQ(1u, b
.get_extents().size());
726 ASSERT_FALSE(b
.get_extents()[0].is_valid());
728 // verify csum chunk size if factored in properly
731 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
732 B
.shared_blob
->get(); // hack to avoid dtor from running
733 bluestore_blob_t
& b
= B
.dirty_blob();
735 b
.allocated_test(bluestore_pextent_t(0, mas
*4));
736 b
.init_csum(Checksummer::CSUM_CRC32C
, 14, mas
* 4);
737 B
.get_ref(coll
.get(), 0, mas
*4);
738 ASSERT_EQ(mas
* 4, B
.get_referenced_bytes());
739 ASSERT_TRUE(b
.is_allocated(0, mas
*4));
740 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, mas
*3, &r
));
741 ASSERT_EQ(mas
* 1, B
.get_referenced_bytes());
742 cout
<< "r " << r
<< " " << b
<< std::endl
;
743 ASSERT_EQ(0u, r
.size());
744 ASSERT_TRUE(b
.is_allocated(0, mas
*4));
745 ASSERT_TRUE(b
.get_extents()[0].is_valid());
746 ASSERT_EQ(mas
*4, b
.get_extents()[0].length
);
750 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
751 B
.shared_blob
->get(); // hack to avoid dtor from running
752 bluestore_blob_t
& b
= B
.dirty_blob();
753 b
.allocated_test(bluestore_pextent_t(0x40101000, 0x4000));
754 b
.allocated_test(bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
,
757 b
.allocated_test(bluestore_pextent_t(0x40118000, 0x7000));
758 B
.get_ref(coll
.get(), 0x0, 0x3800);
759 B
.get_ref(coll
.get(), 0x17c00, 0x6400);
760 ASSERT_EQ(0x3800u
+ 0x6400u
, B
.get_referenced_bytes());
761 b
.set_flag(bluestore_blob_t::FLAG_SHARED
);
762 b
.init_csum(Checksummer::CSUM_CRC32C
, 12, 0x1e000);
764 cout
<< "before: " << B
<< std::endl
;
766 ASSERT_FALSE(B
.put_ref(coll
.get(), 0x1800, 0x2000, &r
));
767 ASSERT_EQ(0x3800u
+ 0x6400u
- 0x2000u
, B
.get_referenced_bytes());
768 cout
<< "after: " << B
<< std::endl
;
769 cout
<< "r " << r
<< std::endl
;
773 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
774 B
.shared_blob
->get(); // hack to avoid dtor from running
775 bluestore_blob_t
& b
= B
.dirty_blob();
776 b
.allocated_test(bluestore_pextent_t(1, 0x5000));
777 b
.allocated_test(bluestore_pextent_t(2, 0x5000));
778 B
.get_ref(coll
.get(), 0x0, 0xa000);
779 ASSERT_EQ(0xa000u
, B
.get_referenced_bytes());
780 cout
<< "before: " << B
<< std::endl
;
782 ASSERT_FALSE(B
.put_ref(coll
.get(), 0x8000, 0x2000, &r
));
783 cout
<< "after: " << B
<< std::endl
;
784 cout
<< "r " << r
<< std::endl
;
785 ASSERT_EQ(0x8000u
, B
.get_referenced_bytes());
786 ASSERT_EQ(1u, r
.size());
787 ASSERT_EQ(0x3002u
, r
[0].offset
);
788 ASSERT_EQ(0x2000u
, r
[0].length
);
792 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
793 B
.shared_blob
->get(); // hack to avoid dtor from running
794 bluestore_blob_t
& b
= B
.dirty_blob();
795 b
.allocated_test(bluestore_pextent_t(1, 0x7000));
796 b
.allocated_test(bluestore_pextent_t(2, 0x7000));
797 B
.get_ref(coll
.get(), 0x0, 0xe000);
798 ASSERT_EQ(0xe000u
, B
.get_referenced_bytes());
799 cout
<< "before: " << B
<< std::endl
;
801 ASSERT_FALSE(B
.put_ref(coll
.get(), 0, 0xb000, &r
));
802 ASSERT_EQ(0x3000u
, B
.get_referenced_bytes());
803 cout
<< "after: " << B
<< std::endl
;
804 cout
<< "r " << r
<< std::endl
;
805 ASSERT_EQ(0x3000u
, B
.get_referenced_bytes());
806 ASSERT_EQ(2u, r
.size());
807 ASSERT_EQ(1u, r
[0].offset
);
808 ASSERT_EQ(0x7000u
, r
[0].length
);
809 ASSERT_EQ(2u, r
[1].offset
);
810 ASSERT_EQ(0x3000u
, r
[1].length
); // we have 0x1000 bytes less due to
811 // alignment caused by min_alloc_size = 0x2000
814 BlueStore
store(g_ceph_context
, "", 0x4000);
815 BlueStore::Cache
*cache
= BlueStore::Cache::create(
816 g_ceph_context
, "lru", NULL
);
817 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, cache
, coll_t()));
819 B
.shared_blob
= new BlueStore::SharedBlob(nullptr);
820 B
.shared_blob
->get(); // hack to avoid dtor from running
821 bluestore_blob_t
& b
= B
.dirty_blob();
822 b
.allocated_test(bluestore_pextent_t(1, 0x5000));
823 b
.allocated_test(bluestore_pextent_t(2, 0x7000));
824 B
.get_ref(coll
.get(), 0x0, 0xc000);
825 ASSERT_EQ(0xc000u
, B
.get_referenced_bytes());
826 cout
<< "before: " << B
<< std::endl
;
828 ASSERT_FALSE(B
.put_ref(coll
.get(), 0x2000, 0xa000, &r
));
829 cout
<< "after: " << B
<< std::endl
;
830 cout
<< "r " << r
<< std::endl
;
831 ASSERT_EQ(0x2000u
, B
.get_referenced_bytes());
832 ASSERT_EQ(2u, r
.size());
833 ASSERT_EQ(0x4001u
, r
[0].offset
);
834 ASSERT_EQ(0x1000u
, r
[0].length
);
835 ASSERT_EQ(2u, r
[1].offset
);
836 ASSERT_EQ(0x7000u
, r
[1].length
);
837 ASSERT_EQ(1u, b
.get_extents()[0].offset
);
838 ASSERT_EQ(0x4000u
, b
.get_extents()[0].length
);
842 TEST(bluestore_blob_t
, can_split
)
845 ASSERT_TRUE(a
.can_split());
846 a
.flags
= bluestore_blob_t::FLAG_SHARED
;
847 ASSERT_FALSE(a
.can_split());
848 a
.flags
= bluestore_blob_t::FLAG_COMPRESSED
;
849 ASSERT_FALSE(a
.can_split());
850 a
.flags
= bluestore_blob_t::FLAG_HAS_UNUSED
;
851 ASSERT_FALSE(a
.can_split());
854 TEST(bluestore_blob_t
, can_split_at
)
857 a
.allocated_test(bluestore_pextent_t(0x10000, 0x2000));
858 a
.allocated_test(bluestore_pextent_t(0x20000, 0x2000));
859 ASSERT_TRUE(a
.can_split_at(0x1000));
860 ASSERT_TRUE(a
.can_split_at(0x1800));
861 a
.init_csum(Checksummer::CSUM_CRC32C
, 12, 0x4000);
862 ASSERT_TRUE(a
.can_split_at(0x1000));
863 ASSERT_TRUE(a
.can_split_at(0x2000));
864 ASSERT_TRUE(a
.can_split_at(0x3000));
865 ASSERT_FALSE(a
.can_split_at(0x2800));
868 TEST(bluestore_blob_t
, prune_tail
)
871 a
.allocated_test(bluestore_pextent_t(0x10000, 0x2000));
872 a
.allocated_test(bluestore_pextent_t(0x20000, 0x2000));
873 ASSERT_FALSE(a
.can_prune_tail());
875 bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
, 0x2000));
876 ASSERT_TRUE(a
.can_prune_tail());
878 ASSERT_FALSE(a
.can_prune_tail());
879 ASSERT_EQ(2u, a
.get_extents().size());
880 ASSERT_EQ(0x4000u
, a
.get_logical_length());
883 bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
, 0x2000));
884 a
.init_csum(Checksummer::CSUM_CRC32C_8
, 12, 0x6000);
885 ASSERT_EQ(6u, a
.csum_data
.length());
886 ASSERT_TRUE(a
.can_prune_tail());
888 ASSERT_FALSE(a
.can_prune_tail());
889 ASSERT_EQ(2u, a
.get_extents().size());
890 ASSERT_EQ(0x4000u
, a
.get_logical_length());
891 ASSERT_EQ(4u, a
.csum_data
.length());
895 bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET
, 0x2000));
896 ASSERT_FALSE(a
.can_prune_tail());
901 BlueStore
store(g_ceph_context
, "", 4096);
902 BlueStore::Cache
*cache
= BlueStore::Cache::create(
903 g_ceph_context
, "lru", NULL
);
904 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, cache
, coll_t()));
906 BlueStore::Blob L
, R
;
907 L
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
908 L
.shared_blob
->get(); // hack to avoid dtor from running
909 R
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
910 R
.shared_blob
->get(); // hack to avoid dtor from running
911 L
.dirty_blob().allocated_test(bluestore_pextent_t(0x2000, 0x2000));
912 L
.dirty_blob().init_csum(Checksummer::CSUM_CRC32C
, 12, 0x2000);
913 L
.get_ref(coll
.get(), 0, 0x2000);
914 L
.split(coll
.get(), 0x1000, &R
);
915 ASSERT_EQ(0x1000u
, L
.get_blob().get_logical_length());
916 ASSERT_EQ(4u, L
.get_blob().csum_data
.length());
917 ASSERT_EQ(1u, L
.get_blob().get_extents().size());
918 ASSERT_EQ(0x2000u
, L
.get_blob().get_extents().front().offset
);
919 ASSERT_EQ(0x1000u
, L
.get_blob().get_extents().front().length
);
920 ASSERT_EQ(0x1000u
, L
.get_referenced_bytes());
921 ASSERT_EQ(0x1000u
, R
.get_blob().get_logical_length());
922 ASSERT_EQ(4u, R
.get_blob().csum_data
.length());
923 ASSERT_EQ(1u, R
.get_blob().get_extents().size());
924 ASSERT_EQ(0x3000u
, R
.get_blob().get_extents().front().offset
);
925 ASSERT_EQ(0x1000u
, R
.get_blob().get_extents().front().length
);
926 ASSERT_EQ(0x1000u
, R
.get_referenced_bytes());
929 BlueStore::Blob L
, R
;
930 L
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
931 L
.shared_blob
->get(); // hack to avoid dtor from running
932 R
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
933 R
.shared_blob
->get(); // hack to avoid dtor from running
934 L
.dirty_blob().allocated_test(bluestore_pextent_t(0x2000, 0x1000));
935 L
.dirty_blob().allocated_test(bluestore_pextent_t(0x12000, 0x1000));
936 L
.dirty_blob().init_csum(Checksummer::CSUM_CRC32C
, 12, 0x2000);
937 L
.get_ref(coll
.get(), 0, 0x1000);
938 L
.get_ref(coll
.get(), 0x1000, 0x1000);
939 L
.split(coll
.get(), 0x1000, &R
);
940 ASSERT_EQ(0x1000u
, L
.get_blob().get_logical_length());
941 ASSERT_EQ(4u, L
.get_blob().csum_data
.length());
942 ASSERT_EQ(1u, L
.get_blob().get_extents().size());
943 ASSERT_EQ(0x2000u
, L
.get_blob().get_extents().front().offset
);
944 ASSERT_EQ(0x1000u
, L
.get_blob().get_extents().front().length
);
945 ASSERT_EQ(0x1000u
, L
.get_referenced_bytes());
946 ASSERT_EQ(0x1000u
, R
.get_blob().get_logical_length());
947 ASSERT_EQ(4u, R
.get_blob().csum_data
.length());
948 ASSERT_EQ(1u, R
.get_blob().get_extents().size());
949 ASSERT_EQ(0x12000u
, R
.get_blob().get_extents().front().offset
);
950 ASSERT_EQ(0x1000u
, R
.get_blob().get_extents().front().length
);
951 ASSERT_EQ(0x1000u
, R
.get_referenced_bytes());
955 TEST(Blob
, legacy_decode
)
957 BlueStore
store(g_ceph_context
, "", 4096);
958 BlueStore::Cache
*cache
= BlueStore::Cache::create(
959 g_ceph_context
, "lru", NULL
);
960 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, cache
, coll_t()));
965 B
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
966 B
.dirty_blob().allocated_test(bluestore_pextent_t(0x1, 0x2000));
967 B
.dirty_blob().init_csum(Checksummer::CSUM_CRC32C
, 12, 0x2000);
968 B
.get_ref(coll
.get(), 0, 0xff0);
969 B
.get_ref(coll
.get(), 0x1fff, 1);
971 bluestore_extent_ref_map_t fake_ref_map
;
972 fake_ref_map
.get(0, 0xff0);
973 fake_ref_map
.get(0x1fff, 1);
975 size_t bound
= 0, bound2
= 0;
982 fake_ref_map
.bound_encode(bound
);
991 auto app
= bl
.get_contiguous_appender(bound
);
992 auto app2
= bl2
.get_contiguous_appender(bound2
);
998 fake_ref_map
.encode(app
);
1007 auto p
= bl
.front().begin_deep();
1008 auto p2
= bl2
.front().begin_deep();
1009 BlueStore::Blob Bres
, Bres2
;
1010 Bres
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
1011 Bres2
.shared_blob
= new BlueStore::SharedBlob(coll
.get());
1013 uint64_t sbid
, sbid2
;
1027 ASSERT_EQ(0xff0u
+ 1u, Bres
.get_blob_use_tracker().get_referenced_bytes());
1028 ASSERT_EQ(0xff0u
+ 1u, Bres2
.get_blob_use_tracker().get_referenced_bytes());
1029 ASSERT_TRUE(Bres
.get_blob_use_tracker().equal(Bres2
.get_blob_use_tracker()));
1033 TEST(ExtentMap
, seek_lextent
)
1035 BlueStore
store(g_ceph_context
, "", 4096);
1036 BlueStore::LRUCache
cache(g_ceph_context
);
1037 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1038 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1039 BlueStore::ExtentMap
em(&onode
);
1040 BlueStore::BlobRef
br(new BlueStore::Blob
);
1041 br
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1043 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(0));
1044 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(100));
1046 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, br
));
1047 auto a
= em
.find(100);
1048 ASSERT_EQ(a
, em
.seek_lextent(0));
1049 ASSERT_EQ(a
, em
.seek_lextent(99));
1050 ASSERT_EQ(a
, em
.seek_lextent(100));
1051 ASSERT_EQ(a
, em
.seek_lextent(101));
1052 ASSERT_EQ(a
, em
.seek_lextent(199));
1053 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(200));
1055 em
.extent_map
.insert(*new BlueStore::Extent(200, 0, 100, br
));
1056 auto b
= em
.find(200);
1057 ASSERT_EQ(a
, em
.seek_lextent(0));
1058 ASSERT_EQ(a
, em
.seek_lextent(99));
1059 ASSERT_EQ(a
, em
.seek_lextent(100));
1060 ASSERT_EQ(a
, em
.seek_lextent(101));
1061 ASSERT_EQ(a
, em
.seek_lextent(199));
1062 ASSERT_EQ(b
, em
.seek_lextent(200));
1063 ASSERT_EQ(b
, em
.seek_lextent(299));
1064 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(300));
1066 em
.extent_map
.insert(*new BlueStore::Extent(400, 0, 100, br
));
1067 auto d
= em
.find(400);
1068 ASSERT_EQ(a
, em
.seek_lextent(0));
1069 ASSERT_EQ(a
, em
.seek_lextent(99));
1070 ASSERT_EQ(a
, em
.seek_lextent(100));
1071 ASSERT_EQ(a
, em
.seek_lextent(101));
1072 ASSERT_EQ(a
, em
.seek_lextent(199));
1073 ASSERT_EQ(b
, em
.seek_lextent(200));
1074 ASSERT_EQ(b
, em
.seek_lextent(299));
1075 ASSERT_EQ(d
, em
.seek_lextent(300));
1076 ASSERT_EQ(d
, em
.seek_lextent(399));
1077 ASSERT_EQ(d
, em
.seek_lextent(400));
1078 ASSERT_EQ(d
, em
.seek_lextent(499));
1079 ASSERT_EQ(em
.extent_map
.end(), em
.seek_lextent(500));
1082 TEST(ExtentMap
, has_any_lextents
)
1084 BlueStore
store(g_ceph_context
, "", 4096);
1085 BlueStore::LRUCache
cache(g_ceph_context
);
1086 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1087 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1088 BlueStore::ExtentMap
em(&onode
);
1089 BlueStore::BlobRef
b(new BlueStore::Blob
);
1090 b
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1092 ASSERT_FALSE(em
.has_any_lextents(0, 0));
1093 ASSERT_FALSE(em
.has_any_lextents(0, 1000));
1094 ASSERT_FALSE(em
.has_any_lextents(1000, 1000));
1096 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, b
));
1097 ASSERT_FALSE(em
.has_any_lextents(0, 50));
1098 ASSERT_FALSE(em
.has_any_lextents(0, 100));
1099 ASSERT_FALSE(em
.has_any_lextents(50, 50));
1100 ASSERT_TRUE(em
.has_any_lextents(50, 51));
1101 ASSERT_TRUE(em
.has_any_lextents(50, 100051));
1102 ASSERT_TRUE(em
.has_any_lextents(100, 100));
1103 ASSERT_TRUE(em
.has_any_lextents(100, 1));
1104 ASSERT_TRUE(em
.has_any_lextents(199, 1));
1105 ASSERT_TRUE(em
.has_any_lextents(199, 2));
1106 ASSERT_FALSE(em
.has_any_lextents(200, 2));
1108 em
.extent_map
.insert(*new BlueStore::Extent(200, 0, 100, b
));
1109 ASSERT_TRUE(em
.has_any_lextents(199, 1));
1110 ASSERT_TRUE(em
.has_any_lextents(199, 2));
1111 ASSERT_TRUE(em
.has_any_lextents(200, 2));
1112 ASSERT_TRUE(em
.has_any_lextents(200, 200));
1113 ASSERT_TRUE(em
.has_any_lextents(299, 1));
1114 ASSERT_FALSE(em
.has_any_lextents(300, 1));
1116 em
.extent_map
.insert(*new BlueStore::Extent(400, 0, 100, b
));
1117 ASSERT_TRUE(em
.has_any_lextents(0, 10000));
1118 ASSERT_TRUE(em
.has_any_lextents(199, 1));
1119 ASSERT_FALSE(em
.has_any_lextents(300, 1));
1120 ASSERT_FALSE(em
.has_any_lextents(300, 100));
1121 ASSERT_FALSE(em
.has_any_lextents(399, 1));
1122 ASSERT_TRUE(em
.has_any_lextents(400, 1));
1123 ASSERT_TRUE(em
.has_any_lextents(400, 100));
1124 ASSERT_TRUE(em
.has_any_lextents(400, 1000));
1125 ASSERT_TRUE(em
.has_any_lextents(499, 1000));
1126 ASSERT_FALSE(em
.has_any_lextents(500, 1000));
1129 TEST(ExtentMap
, compress_extent_map
)
1131 BlueStore
store(g_ceph_context
, "", 4096);
1132 BlueStore::LRUCache
cache(g_ceph_context
);
1133 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1134 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1135 BlueStore::ExtentMap
em(&onode
);
1136 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1137 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1138 BlueStore::BlobRef
b3(new BlueStore::Blob
);
1139 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1140 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1141 b3
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1143 em
.extent_map
.insert(*new BlueStore::Extent(0, 0, 100, b1
));
1144 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, b2
));
1145 ASSERT_EQ(0, em
.compress_extent_map(0, 10000));
1146 ASSERT_EQ(2u, em
.extent_map
.size());
1148 em
.extent_map
.insert(*new BlueStore::Extent(200, 100, 100, b2
));
1149 em
.extent_map
.insert(*new BlueStore::Extent(300, 200, 100, b2
));
1150 ASSERT_EQ(0, em
.compress_extent_map(0, 0));
1151 ASSERT_EQ(0, em
.compress_extent_map(100000, 1000));
1152 ASSERT_EQ(2, em
.compress_extent_map(0, 100000));
1153 ASSERT_EQ(2u, em
.extent_map
.size());
1155 em
.extent_map
.erase(em
.find(100));
1156 em
.extent_map
.insert(*new BlueStore::Extent(100, 0, 100, b2
));
1157 em
.extent_map
.insert(*new BlueStore::Extent(200, 100, 100, b3
));
1158 em
.extent_map
.insert(*new BlueStore::Extent(300, 200, 100, b2
));
1159 ASSERT_EQ(0, em
.compress_extent_map(0, 1));
1160 ASSERT_EQ(0, em
.compress_extent_map(0, 100000));
1161 ASSERT_EQ(4u, em
.extent_map
.size());
1163 em
.extent_map
.insert(*new BlueStore::Extent(400, 300, 100, b2
));
1164 em
.extent_map
.insert(*new BlueStore::Extent(500, 500, 100, b2
));
1165 em
.extent_map
.insert(*new BlueStore::Extent(600, 600, 100, b2
));
1166 em
.extent_map
.insert(*new BlueStore::Extent(700, 0, 100, b1
));
1167 em
.extent_map
.insert(*new BlueStore::Extent(800, 0, 100, b3
));
1168 ASSERT_EQ(0, em
.compress_extent_map(0, 99));
1169 ASSERT_EQ(0, em
.compress_extent_map(800, 1000));
1170 ASSERT_EQ(2, em
.compress_extent_map(100, 500));
1171 ASSERT_EQ(7u, em
.extent_map
.size());
1172 em
.extent_map
.erase(em
.find(300));
1173 em
.extent_map
.erase(em
.find(500));
1174 em
.extent_map
.erase(em
.find(700));
1175 em
.extent_map
.insert(*new BlueStore::Extent(400, 300, 100, b2
));
1176 em
.extent_map
.insert(*new BlueStore::Extent(500, 400, 100, b2
));
1177 em
.extent_map
.insert(*new BlueStore::Extent(700, 500, 100, b2
));
1178 ASSERT_EQ(1, em
.compress_extent_map(0, 1000));
1179 ASSERT_EQ(6u, em
.extent_map
.size());
1182 TEST(GarbageCollector
, BasicTest
)
1184 BlueStore::LRUCache
cache(g_ceph_context
);
1185 BlueStore
store(g_ceph_context
, "", 4096);
1186 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1187 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1188 BlueStore::ExtentMap
em(&onode
);
1190 BlueStore::old_extent_map_t old_extents
;
1194 min_alloc_size = 4096
1195 original disposition
1196 extent1 <loffs = 100, boffs = 100, len = 10>
1197 -> blob1<compressed, len_on_disk=4096, logical_len=8192>
1198 extent2 <loffs = 200, boffs = 200, len = 10>
1199 -> blob2<raw, len_on_disk=4096, llen=4096>
1200 extent3 <loffs = 300, boffs = 300, len = 10>
1201 -> blob1<compressed, len_on_disk=4096, llen=8192>
1202 extent4 <loffs = 4096, boffs = 0, len = 10>
1203 -> blob3<raw, len_on_disk=4096, llen=4096>
1204 on write(300~100) resulted in
1205 extent1 <loffs = 100, boffs = 100, len = 10>
1206 -> blob1<compressed, len_on_disk=4096, logical_len=8192>
1207 extent2 <loffs = 200, boffs = 200, len = 10>
1208 -> blob2<raw, len_on_disk=4096, llen=4096>
1209 extent3 <loffs = 300, boffs = 300, len = 100>
1210 -> blob4<raw, len_on_disk=4096, llen=4096>
1211 extent4 <loffs = 4096, boffs = 0, len = 10>
1212 -> blob3<raw, len_on_disk=4096, llen=4096>
1215 BlueStore::GarbageCollector
gc(g_ceph_context
);
1217 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1218 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1219 BlueStore::BlobRef
b3(new BlueStore::Blob
);
1220 BlueStore::BlobRef
b4(new BlueStore::Blob
);
1221 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1222 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1223 b3
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1224 b4
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1225 b1
->dirty_blob().set_compressed(0x2000, 0x1000);
1226 b1
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x1000));
1227 b2
->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x1000));
1228 b3
->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x1000));
1229 b4
->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x1000));
1230 em
.extent_map
.insert(*new BlueStore::Extent(100, 100, 10, b1
));
1231 b1
->get_ref(coll
.get(), 100, 10);
1232 em
.extent_map
.insert(*new BlueStore::Extent(200, 200, 10, b2
));
1233 b2
->get_ref(coll
.get(), 200, 10);
1234 em
.extent_map
.insert(*new BlueStore::Extent(300, 300, 100, b4
));
1235 b4
->get_ref(coll
.get(), 300, 100);
1236 em
.extent_map
.insert(*new BlueStore::Extent(4096, 0, 10, b3
));
1237 b3
->get_ref(coll
.get(), 0, 10);
1239 old_extents
.push_back(*new BlueStore::OldExtent(300, 300, 10, b1
));
1241 saving
= gc
.estimate(300, 100, em
, old_extents
, 4096);
1242 ASSERT_EQ(saving
, 1);
1243 auto& to_collect
= gc
.get_extents_to_collect();
1244 ASSERT_EQ(to_collect
.size(), 1u);
1245 ASSERT_EQ(to_collect
[0], bluestore_pextent_t(100,10) );
1248 old_extents
.clear();
1251 original disposition
1252 min_alloc_size = 0x10000
1253 extent1 <loffs = 0, boffs = 0, len = 0x40000>
1254 -> blob1<compressed, len_on_disk=0x20000, logical_len=0x40000>
1255 Write 0x8000~37000 resulted in the following extent map prior to GC
1256 for the last write_small(0x30000~0xf000):
1258 extent1 <loffs = 0, boffs = 0, len = 0x8000>
1259 -> blob1<compressed, len_on_disk=0x20000, logical_len=0x40000>
1260 extent2 <loffs = 0x8000, boffs = 0x8000, len = 0x8000>
1261 -> blob2<raw, len_on_disk=0x10000, llen=0x10000>
1262 extent3 <loffs = 0x10000, boffs = 0, len = 0x20000>
1263 -> blob3<raw, len_on_disk=0x20000, llen=0x20000>
1264 extent4 <loffs = 0x30000, boffs = 0, len = 0xf000>
1265 -> blob4<raw, len_on_disk=0x10000, llen=0x10000>
1266 extent5 <loffs = 0x3f000, boffs = 0x3f000, len = 0x1000>
1267 -> blob1<compressed, len_on_disk=0x20000, llen=0x40000>
1270 BlueStore
store(g_ceph_context
, "", 0x10000);
1271 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1272 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1273 BlueStore::ExtentMap
em(&onode
);
1275 BlueStore::old_extent_map_t old_extents
;
1276 BlueStore::GarbageCollector
gc(g_ceph_context
);
1278 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1279 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1280 BlueStore::BlobRef
b3(new BlueStore::Blob
);
1281 BlueStore::BlobRef
b4(new BlueStore::Blob
);
1282 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1283 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1284 b3
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1285 b4
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1286 b1
->dirty_blob().set_compressed(0x40000, 0x20000);
1287 b1
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x20000));
1288 b2
->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x10000));
1289 b3
->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x20000));
1290 b4
->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x10000));
1292 em
.extent_map
.insert(*new BlueStore::Extent(0, 0, 0x8000, b1
));
1293 b1
->get_ref(coll
.get(), 0, 0x8000);
1294 em
.extent_map
.insert(
1295 *new BlueStore::Extent(0x8000, 0x8000, 0x8000, b2
)); // new extent
1296 b2
->get_ref(coll
.get(), 0x8000, 0x8000);
1297 em
.extent_map
.insert(
1298 *new BlueStore::Extent(0x10000, 0, 0x20000, b3
)); // new extent
1299 b3
->get_ref(coll
.get(), 0, 0x20000);
1300 em
.extent_map
.insert(
1301 *new BlueStore::Extent(0x30000, 0, 0xf000, b4
)); // new extent
1302 b4
->get_ref(coll
.get(), 0, 0xf000);
1303 em
.extent_map
.insert(*new BlueStore::Extent(0x3f000, 0x3f000, 0x1000, b1
));
1304 b1
->get_ref(coll
.get(), 0x3f000, 0x1000);
1306 old_extents
.push_back(*new BlueStore::OldExtent(0x8000, 0x8000, 0x8000, b1
));
1307 old_extents
.push_back(
1308 *new BlueStore::OldExtent(0x10000, 0x10000, 0x20000, b1
));
1309 old_extents
.push_back(*new BlueStore::OldExtent(0x30000, 0x30000, 0xf000, b1
));
1311 saving
= gc
.estimate(0x30000, 0xf000, em
, old_extents
, 0x10000);
1312 ASSERT_EQ(saving
, 2);
1313 auto& to_collect
= gc
.get_extents_to_collect();
1314 ASSERT_EQ(to_collect
.size(), 2u);
1315 ASSERT_TRUE(to_collect
[0] == bluestore_pextent_t(0x0,0x8000) ||
1316 to_collect
[1] == bluestore_pextent_t(0x0,0x8000));
1317 ASSERT_TRUE(to_collect
[0] == bluestore_pextent_t(0x3f000,0x1000) ||
1318 to_collect
[1] == bluestore_pextent_t(0x3f000,0x1000));
1321 old_extents
.clear();
1324 original disposition
1325 min_alloc_size = 0x1000
1326 extent1 <loffs = 0, boffs = 0, len = 0x4000>
1327 -> blob1<compressed, len_on_disk=0x2000, logical_len=0x4000>
1328 write 0x3000~4000 resulted in the following extent map
1329 (future feature - suppose we can compress incoming write prior to
1332 extent1 <loffs = 0, boffs = 0, len = 0x4000>
1333 -> blob1<compressed, len_on_disk=0x2000, logical_len=0x4000>
1334 extent2 <loffs = 0x3000, boffs = 0, len = 0x4000>
1335 -> blob2<compressed, len_on_disk=0x2000, llen=0x4000>
1338 BlueStore::GarbageCollector
gc(g_ceph_context
);
1340 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1341 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1342 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1343 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1344 b1
->dirty_blob().set_compressed(0x4000, 0x2000);
1345 b1
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x2000));
1346 b2
->dirty_blob().set_compressed(0x4000, 0x2000);
1347 b2
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x2000));
1349 em
.extent_map
.insert(*new BlueStore::Extent(0, 0, 0x3000, b1
));
1350 b1
->get_ref(coll
.get(), 0, 0x3000);
1351 em
.extent_map
.insert(
1352 *new BlueStore::Extent(0x3000, 0, 0x4000, b2
)); // new extent
1353 b2
->get_ref(coll
.get(), 0, 0x4000);
1355 old_extents
.push_back(*new BlueStore::OldExtent(0x3000, 0x3000, 0x1000, b1
));
1357 saving
= gc
.estimate(0x3000, 0x4000, em
, old_extents
, 0x1000);
1358 ASSERT_EQ(saving
, 0);
1359 auto& to_collect
= gc
.get_extents_to_collect();
1360 ASSERT_EQ(to_collect
.size(), 0u);
1362 old_extents
.clear();
1365 original disposition
1366 min_alloc_size = 0x10000
1367 extent0 <loffs = 0, boffs = 0, len = 0x20000>
1368 -> blob0<compressed, len_on_disk=0x10000, logical_len=0x20000>
1369 extent1 <loffs = 0x20000, boffs = 0, len = 0x20000>
1370 -> blob1<compressed, len_on_disk=0x10000, logical_len=0x20000>
1371 write 0x8000~37000 resulted in the following extent map prior
1372 to GC for the last write_small(0x30000~0xf000)
1374 extent0 <loffs = 0, boffs = 0, len = 0x8000>
1375 -> blob0<compressed, len_on_disk=0x10000, logical_len=0x20000>
1376 extent2 <loffs = 0x8000, boffs = 0x8000, len = 0x8000>
1377 -> blob2<raw, len_on_disk=0x10000, llen=0x10000>
1378 extent3 <loffs = 0x10000, boffs = 0, len = 0x20000>
1379 -> blob3<raw, len_on_disk=0x20000, llen=0x20000>
1380 extent4 <loffs = 0x30000, boffs = 0, len = 0xf000>
1381 -> blob4<raw, len_on_disk=0x1000, llen=0x1000>
1382 extent5 <loffs = 0x3f000, boffs = 0x1f000, len = 0x1000>
1383 -> blob1<compressed, len_on_disk=0x10000, llen=0x20000>
1386 BlueStore
store(g_ceph_context
, "", 0x10000);
1387 BlueStore::CollectionRef
coll(new BlueStore::Collection(&store
, &cache
, coll_t()));
1388 BlueStore::Onode
onode(coll
.get(), ghobject_t(), "");
1389 BlueStore::ExtentMap
em(&onode
);
1391 BlueStore::old_extent_map_t old_extents
;
1392 BlueStore::GarbageCollector
gc(g_ceph_context
);
1394 BlueStore::BlobRef
b0(new BlueStore::Blob
);
1395 BlueStore::BlobRef
b1(new BlueStore::Blob
);
1396 BlueStore::BlobRef
b2(new BlueStore::Blob
);
1397 BlueStore::BlobRef
b3(new BlueStore::Blob
);
1398 BlueStore::BlobRef
b4(new BlueStore::Blob
);
1399 b0
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1400 b1
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1401 b2
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1402 b3
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1403 b4
->shared_blob
= new BlueStore::SharedBlob(coll
.get());
1404 b0
->dirty_blob().set_compressed(0x2000, 0x1000);
1405 b0
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x10000));
1406 b1
->dirty_blob().set_compressed(0x20000, 0x10000);
1407 b1
->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x10000));
1408 b2
->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x10000));
1409 b3
->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x20000));
1410 b4
->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x1000));
1412 em
.extent_map
.insert(*new BlueStore::Extent(0, 0, 0x8000, b0
));
1413 b0
->get_ref(coll
.get(), 0, 0x8000);
1414 em
.extent_map
.insert(
1415 *new BlueStore::Extent(0x8000, 0x8000, 0x8000, b2
)); // new extent
1416 b2
->get_ref(coll
.get(), 0x8000, 0x8000);
1417 em
.extent_map
.insert(
1418 *new BlueStore::Extent(0x10000, 0, 0x20000, b3
)); // new extent
1419 b3
->get_ref(coll
.get(), 0, 0x20000);
1420 em
.extent_map
.insert(
1421 *new BlueStore::Extent(0x30000, 0, 0xf000, b4
)); // new extent
1422 b4
->get_ref(coll
.get(), 0, 0xf000);
1423 em
.extent_map
.insert(*new BlueStore::Extent(0x3f000, 0x1f000, 0x1000, b1
));
1424 b1
->get_ref(coll
.get(), 0x1f000, 0x1000);
1426 old_extents
.push_back(*new BlueStore::OldExtent(0x8000, 0x8000, 0x8000, b0
));
1427 old_extents
.push_back(
1428 *new BlueStore::OldExtent(0x10000, 0x10000, 0x10000, b0
));
1429 old_extents
.push_back(
1430 *new BlueStore::OldExtent(0x20000, 0x00000, 0x1f000, b1
));
1432 saving
= gc
.estimate(0x30000, 0xf000, em
, old_extents
, 0x10000);
1433 ASSERT_EQ(saving
, 2);
1434 auto& to_collect
= gc
.get_extents_to_collect();
1435 ASSERT_EQ(to_collect
.size(), 2u);
1436 ASSERT_TRUE(to_collect
[0] == bluestore_pextent_t(0x0,0x8000) ||
1437 to_collect
[1] == bluestore_pextent_t(0x0,0x8000));
1438 ASSERT_TRUE(to_collect
[0] == bluestore_pextent_t(0x3f000,0x1000) ||
1439 to_collect
[1] == bluestore_pextent_t(0x3f000,0x1000));
1442 old_extents
.clear();
1446 int main(int argc
, char **argv
) {
1447 vector
<const char*> args
;
1448 argv_to_vec(argc
, (const char **)argv
, args
);
1450 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
1451 CODE_ENVIRONMENT_UTILITY
, 0);
1452 common_init_finish(g_ceph_context
);
1453 ::testing::InitGoogleTest(&argc
, argv
);
1454 return RUN_ALL_TESTS();