]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/objectstore/Allocator_test.cc
a52fd53c3c6ba5d80a9d7809fa0af94bb6fa965e
[ceph.git] / ceph / src / test / objectstore / Allocator_test.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * In memory space allocator test cases.
5 * Author: Ramesh Chander, Ramesh.Chander@sandisk.com
6 */
7 #include <iostream>
8 #include <boost/scoped_ptr.hpp>
9 #include <gtest/gtest.h>
10
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"
18
19
20 #if GTEST_HAS_PARAM_TEST
21
22 class AllocTest : public ::testing::TestWithParam<const char*> {
23 public:
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,
29 min_alloc_size));
30 }
31
32 void init_close() {
33 alloc.reset(0);
34 }
35 };
36
37 TEST_P(AllocTest, test_alloc_init)
38 {
39 int64_t blocks = BmapEntry::size();
40 init_alloc(blocks, 1);
41 ASSERT_EQ(0U, alloc->get_free());
42 alloc->shutdown();
43 blocks = BitMapZone::get_total_blocks() * 2 + 16;
44 init_alloc(blocks, 1);
45 ASSERT_EQ(0U, alloc->get_free());
46 alloc->shutdown();
47 blocks = BitMapZone::get_total_blocks() * 2;
48 init_alloc(blocks, 1);
49 ASSERT_EQ(alloc->get_free(), (uint64_t) 0);
50 }
51
52 TEST_P(AllocTest, test_alloc_min_alloc)
53 {
54 int64_t block_size = 1024;
55 int64_t blocks = BitMapZone::get_total_blocks() * 2 * block_size;
56
57 {
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));
64 }
65
66 /*
67 * Allocate extent and make sure all comes in single extent.
68 */
69 {
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);
78 }
79
80 /*
81 * Allocate extent and make sure we get two different extents.
82 */
83 {
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;
88
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);
95 }
96 alloc->shutdown();
97 }
98
99 TEST_P(AllocTest, test_alloc_min_max_alloc)
100 {
101 int64_t block_size = 1024;
102 int64_t blocks = BitMapZone::get_total_blocks() * 2 * block_size;
103
104 init_alloc(blocks, block_size);
105
106 /*
107 * Make sure we get all extents different when
108 * min_alloc_size == max_alloc_size
109 */
110 {
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);
119 }
120 EXPECT_EQ(4u, extents.size());
121 }
122
123
124 /*
125 * Make sure we get extents of length max_alloc size
126 * when max alloc size > min_alloc size
127 */
128 {
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);
138 }
139 }
140
141 /*
142 * Make sure allocations are of min_alloc_size when min_alloc_size > block_size.
143 */
144 {
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);
154 }
155 EXPECT_EQ(1024u/4, extents.size());
156 }
157
158 /*
159 * Allocate and free.
160 */
161 {
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));
168
169 EXPECT_EQ(extents.size(), 8u);
170 for (auto& e : extents) {
171 EXPECT_EQ(e.length, 2 * block_size);
172 }
173 }
174 }
175
176 TEST_P(AllocTest, test_alloc_failure)
177 {
178 int64_t block_size = 1024;
179 int64_t blocks = BitMapZone::get_total_blocks() * block_size;
180
181 init_alloc(blocks, block_size);
182 {
183 alloc->init_add_free(0, block_size * 256);
184 alloc->init_add_free(block_size * 512, block_size * 256);
185
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);
194 extents.clear();
195 EXPECT_EQ(alloc->reserve(block_size * 512), 0);
196 EXPECT_EQ(-ENOSPC,
197 alloc->allocate(512 * (uint64_t)block_size,
198 (uint64_t) block_size * 512,
199 block_size * 512, (int64_t) 0, &extents));
200 }
201 }
202
203 TEST_P(AllocTest, test_alloc_big)
204 {
205 int64_t block_size = 4096;
206 int64_t blocks = 104857600;
207 int64_t mas = 4096;
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;
214 EXPECT_EQ(big,
215 alloc->allocate(big, mas, 0, &extents));
216 }
217 }
218
219 TEST_P(AllocTest, test_alloc_hint_bmap)
220 {
221 if (GetParam() == std::string("stupid")) {
222 return;
223 }
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));
229
230 init_alloc(blocks, 1);
231 alloc->init_add_free(0, blocks);
232
233 AllocExtentVector extents;
234 alloc->reserve(blocks);
235
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);
240
241 extents.clear();
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);
246
247 /*
248 * Wrap around with hint
249 */
250 extents.clear();
251 allocated = alloc->allocate(zone_size * 2, 1, 1, blocks - zone_size * 2,
252 &extents);
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);
256
257 extents.clear();
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);
262 /*
263 * Verify out-of-bound hint
264 */
265 extents.clear();
266 allocated = alloc->allocate(1, 1, 1, blocks, &extents);
267 ASSERT_EQ(1, allocated);
268 EXPECT_EQ(1, (int)extents.size());
269
270 extents.clear();
271 allocated = alloc->allocate(1, 1, 1, blocks * 3 + 1 , &extents);
272 ASSERT_EQ(1, allocated);
273 EXPECT_EQ(1, (int)extents.size());
274 }
275
276 TEST_P(AllocTest, test_alloc_non_aligned_len)
277 {
278 int64_t block_size = 1 << 12;
279 int64_t blocks = (1 << 20) * 100;
280 int64_t want_size = 1 << 22;
281 int64_t alloc_unit = 1 << 20;
282
283 init_alloc(blocks*block_size, block_size);
284 alloc->init_add_free(0, 2097152);
285 alloc->init_add_free(2097152, 1064960);
286 alloc->init_add_free(3670016, 2097152);
287
288 EXPECT_EQ(0, alloc->reserve(want_size));
289 AllocExtentVector extents;
290 EXPECT_EQ(want_size, alloc->allocate(want_size, alloc_unit, 0, &extents));
291 }
292
293
294 INSTANTIATE_TEST_CASE_P(
295 Allocator,
296 AllocTest,
297 ::testing::Values("stupid", "bitmap"));
298
299 #else
300
301 TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
302 #endif