1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * In memory space allocator test cases.
5 * Author: Ramesh Chander, Ramesh.Chander@sandisk.com
8 #include <boost/scoped_ptr.hpp>
9 #include <gtest/gtest.h>
11 #include "common/Mutex.h"
12 #include "common/Cond.h"
13 #include "common/errno.h"
14 #include "include/stringify.h"
15 #include "include/Context.h"
16 #include "os/bluestore/Allocator.h"
17 #include "os/bluestore/BitAllocator.h"
20 #if GTEST_HAS_PARAM_TEST
22 class AllocTest
: public ::testing::TestWithParam
<const char*> {
24 boost::scoped_ptr
<Allocator
> alloc
;
25 AllocTest(): alloc(0) { }
26 void init_alloc(int64_t size
, uint64_t min_alloc_size
) {
27 std::cout
<< "Creating alloc type " << string(GetParam()) << " \n";
28 alloc
.reset(Allocator::create(g_ceph_context
, string(GetParam()), size
,
37 TEST_P(AllocTest
, test_alloc_init
)
39 int64_t blocks
= BmapEntry::size();
40 init_alloc(blocks
, 1);
41 ASSERT_EQ(0U, alloc
->get_free());
43 blocks
= BitMapZone::get_total_blocks() * 2 + 16;
44 init_alloc(blocks
, 1);
45 ASSERT_EQ(0U, alloc
->get_free());
47 blocks
= BitMapZone::get_total_blocks() * 2;
48 init_alloc(blocks
, 1);
49 ASSERT_EQ(alloc
->get_free(), (uint64_t) 0);
52 TEST_P(AllocTest
, test_alloc_min_alloc
)
54 int64_t block_size
= 1024;
55 int64_t blocks
= BitMapZone::get_total_blocks() * 2 * block_size
;
58 init_alloc(blocks
, block_size
);
59 alloc
->init_add_free(block_size
, block_size
);
60 EXPECT_EQ(alloc
->reserve(block_size
), 0);
61 AllocExtentVector extents
;
62 EXPECT_EQ(block_size
, alloc
->allocate(block_size
, block_size
,
63 0, (int64_t) 0, &extents
));
67 * Allocate extent and make sure all comes in single extent.
70 alloc
->init_add_free(0, block_size
* 4);
71 EXPECT_EQ(alloc
->reserve(block_size
* 4), 0);
72 AllocExtentVector extents
;
73 EXPECT_EQ(4*block_size
,
74 alloc
->allocate(4 * (uint64_t)block_size
, (uint64_t) block_size
,
75 0, (int64_t) 0, &extents
));
76 EXPECT_EQ(1u, extents
.size());
77 EXPECT_EQ(extents
[0].length
, 4 * block_size
);
81 * Allocate extent and make sure we get two different extents.
84 alloc
->init_add_free(0, block_size
* 2);
85 alloc
->init_add_free(3 * block_size
, block_size
* 2);
86 EXPECT_EQ(alloc
->reserve(block_size
* 4), 0);
87 AllocExtentVector extents
;
89 EXPECT_EQ(4*block_size
,
90 alloc
->allocate(4 * (uint64_t)block_size
, (uint64_t) block_size
,
91 0, (int64_t) 0, &extents
));
92 EXPECT_EQ(2u, extents
.size());
93 EXPECT_EQ(extents
[0].length
, 2 * block_size
);
94 EXPECT_EQ(extents
[1].length
, 2 * block_size
);
99 TEST_P(AllocTest
, test_alloc_min_max_alloc
)
101 int64_t block_size
= 1024;
102 int64_t blocks
= BitMapZone::get_total_blocks() * 2 * block_size
;
104 init_alloc(blocks
, block_size
);
107 * Make sure we get all extents different when
108 * min_alloc_size == max_alloc_size
111 alloc
->init_add_free(0, block_size
* 4);
112 EXPECT_EQ(alloc
->reserve(block_size
* 4), 0);
113 AllocExtentVector extents
;
114 EXPECT_EQ(4*block_size
,
115 alloc
->allocate(4 * (uint64_t)block_size
, (uint64_t) block_size
,
116 block_size
, (int64_t) 0, &extents
));
117 for (auto e
: extents
) {
118 EXPECT_EQ(e
.length
, block_size
);
120 EXPECT_EQ(4u, extents
.size());
125 * Make sure we get extents of length max_alloc size
126 * when max alloc size > min_alloc size
129 alloc
->init_add_free(0, block_size
* 4);
130 EXPECT_EQ(alloc
->reserve(block_size
* 4), 0);
131 AllocExtentVector extents
;
132 EXPECT_EQ(4*block_size
,
133 alloc
->allocate(4 * (uint64_t)block_size
, (uint64_t) block_size
,
134 2 * block_size
, (int64_t) 0, &extents
));
135 EXPECT_EQ(2u, extents
.size());
136 for (auto& e
: extents
) {
137 EXPECT_EQ(e
.length
, block_size
* 2);
142 * Make sure allocations are of min_alloc_size when min_alloc_size > block_size.
145 alloc
->init_add_free(0, block_size
* 1024);
146 EXPECT_EQ(alloc
->reserve(block_size
* 1024), 0);
147 AllocExtentVector extents
;
148 EXPECT_EQ(1024 * block_size
,
149 alloc
->allocate(1024 * (uint64_t)block_size
,
150 (uint64_t) block_size
* 4,
151 block_size
* 4, (int64_t) 0, &extents
));
152 for (auto& e
: extents
) {
153 EXPECT_EQ(e
.length
, block_size
* 4);
155 EXPECT_EQ(1024u/4, extents
.size());
162 alloc
->init_add_free(0, block_size
* 16);
163 EXPECT_EQ(alloc
->reserve(block_size
* 16), 0);
164 AllocExtentVector extents
;
165 EXPECT_EQ(16 * block_size
,
166 alloc
->allocate(16 * (uint64_t)block_size
, (uint64_t) block_size
,
167 2 * block_size
, (int64_t) 0, &extents
));
169 EXPECT_EQ(extents
.size(), 8u);
170 for (auto& e
: extents
) {
171 EXPECT_EQ(e
.length
, 2 * block_size
);
176 TEST_P(AllocTest
, test_alloc_failure
)
178 int64_t block_size
= 1024;
179 int64_t blocks
= BitMapZone::get_total_blocks() * block_size
;
181 init_alloc(blocks
, block_size
);
183 alloc
->init_add_free(0, block_size
* 256);
184 alloc
->init_add_free(block_size
* 512, block_size
* 256);
186 EXPECT_EQ(alloc
->reserve(block_size
* 512), 0);
187 AllocExtentVector extents
;
188 EXPECT_EQ(512 * block_size
,
189 alloc
->allocate(512 * (uint64_t)block_size
,
190 (uint64_t) block_size
* 256,
191 block_size
* 256, (int64_t) 0, &extents
));
192 alloc
->init_add_free(0, block_size
* 256);
193 alloc
->init_add_free(block_size
* 512, block_size
* 256);
195 EXPECT_EQ(alloc
->reserve(block_size
* 512), 0);
197 alloc
->allocate(512 * (uint64_t)block_size
,
198 (uint64_t) block_size
* 512,
199 block_size
* 512, (int64_t) 0, &extents
));
203 TEST_P(AllocTest
, test_alloc_big
)
205 int64_t block_size
= 4096;
206 int64_t blocks
= 104857600;
208 init_alloc(blocks
*block_size
, block_size
);
209 alloc
->init_add_free(2*block_size
, (blocks
-2)*block_size
);
210 for (int64_t big
= mas
; big
< 1048576*128; big
*=2) {
211 cout
<< big
<< std::endl
;
212 EXPECT_EQ(alloc
->reserve(big
), 0);
213 AllocExtentVector extents
;
215 alloc
->allocate(big
, mas
, 0, &extents
));
219 TEST_P(AllocTest
, test_alloc_hint_bmap
)
221 if (GetParam() == std::string("stupid")) {
224 int64_t blocks
= BitMapArea::get_level_factor(g_ceph_context
, 2) * 4;
225 int64_t allocated
= 0;
226 int64_t zone_size
= 1024;
227 g_conf
->set_val("bluestore_bitmapallocator_blocks_per_zone",
228 std::to_string(zone_size
));
230 init_alloc(blocks
, 1);
231 alloc
->init_add_free(0, blocks
);
233 AllocExtentVector extents
;
234 alloc
->reserve(blocks
);
236 allocated
= alloc
->allocate(1, 1, 1, zone_size
, &extents
);
237 ASSERT_EQ(1, allocated
);
238 ASSERT_EQ(1u, extents
.size());
239 ASSERT_EQ(extents
[0].offset
, (uint64_t) zone_size
);
242 allocated
= alloc
->allocate(1, 1, 1, zone_size
* 2 - 1, &extents
);
243 EXPECT_EQ(1, allocated
);
244 ASSERT_EQ(1u, extents
.size());
245 EXPECT_EQ((int64_t) extents
[0].offset
, zone_size
* 2 - 1);
248 * Wrap around with hint
251 allocated
= alloc
->allocate(zone_size
* 2, 1, 1, blocks
- zone_size
* 2,
253 ASSERT_EQ(zone_size
* 2, allocated
);
254 EXPECT_EQ(zone_size
* 2, (int)extents
.size());
255 EXPECT_EQ((int64_t)extents
[0].offset
, blocks
- zone_size
* 2);
258 allocated
= alloc
->allocate(zone_size
, 1, 1, blocks
- zone_size
, &extents
);
259 ASSERT_EQ(zone_size
, allocated
);
260 EXPECT_EQ(zone_size
, (int)extents
.size());
261 EXPECT_EQ(extents
[0].offset
, (uint64_t) 0);
265 INSTANTIATE_TEST_CASE_P(
268 ::testing::Values("stupid", "bitmap"));
272 TEST(DummyTest
, ValueParameterizedTestsAreNotSupportedOnThisPlatform
) {}