* of the interfaces defined in BitMapArea.
*/
+#include "common/dout.h"
#include "BitAllocator.h"
#include <assert.h>
#include <math.h>
int64_t BitMapAreaLeaf::count = 0;
int64_t BitMapZone::count = 0;
-int64_t BitMapZone::total_blocks = BITMAP_SPAN_SIZE;
+int64_t BitMapZone::total_blocks = 0;
/*
* BmapEntityList functions.
void BitMapZone::init(int64_t zone_num, int64_t total_blocks, bool def)
{
m_area_index = zone_num;
+ BitMapZone::total_blocks = total_blocks;
debug_assert(size() > 0);
m_type = ZONE;
/*
* BitMapArea Leaf and non-Leaf functions.
*/
+int64_t BitMapArea::get_zone_size()
+{
+ return g_conf->bluestore_bitmapallocator_blocks_per_zone;
+}
+
int64_t BitMapArea::get_span_size()
{
- return BITMAP_SPAN_SIZE;
+ return g_conf->bluestore_bitmapallocator_span_size;
}
bmap_area_type_t BitMapArea::level_to_type(int level)
int BitMapArea::get_level(int64_t total_blocks)
{
int level = 1;
- int64_t span_size = BitMapArea::get_span_size();
- int64_t spans = span_size * span_size;
+ int64_t zone_size_block = get_zone_size();
+ int64_t span_size = get_span_size();
+ int64_t spans = zone_size_block * span_size;
while (spans < total_blocks) {
spans *= span_size;
level++;
return level;
}
+int64_t BitMapArea::get_level_factor(int level)
+{
+ debug_assert(level > 0);
+
+ int64_t zone_size = get_zone_size();
+ if (level == 1) {
+ return zone_size;
+ }
+
+ int64_t level_factor = zone_size;
+ int64_t span_size = get_span_size();
+ while (--level) {
+ level_factor *= span_size;
+ }
+
+ return level_factor;
+}
+
int64_t BitMapArea::get_index()
{
return m_area_index;
debug_assert(!(total_blocks % BmapEntry::size()));
init_common(total_blocks, area_idx, def);
- int64_t level_factor = pow(BitMapArea::get_span_size(), m_level);
+ int64_t level_factor = BitMapArea::get_level_factor(m_level);
num_child = (total_blocks + level_factor - 1) / level_factor;
debug_assert(num_child < std::numeric_limits<int16_t>::max());
debug_assert(!(total_blocks % BmapEntry::size()));
init_common(total_blocks, area_idx, def);
- num_child = total_blocks / pow(BitMapArea::get_span_size(), m_level);
+ debug_assert(m_level == 1);
+ int zone_size_block = get_zone_size();
+ debug_assert(zone_size_block > 0);
+ num_child = (total_blocks + zone_size_block - 1) / zone_size_block;
+ debug_assert(num_child);
m_child_size_blocks = total_blocks / num_child;
debug_assert(m_level == 1);
- BitMapArea **children = new BitMapArea*[num_child];
+ BitMapArea **children = new BitMapArea*[num_child];
for (int i = 0; i < num_child; i++) {
children[i] = new BitMapZone(m_child_size_blocks, i, def);
}
return false;
}
- if (num_blocks > BitMapArea::get_span_size()) {
+ if (num_blocks > get_zone_size()) {
return false;
}
return true;
* Author: Ramesh Chander, Ramesh.Chander@sandisk.com
*/
+#include "include/Context.h"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
#include "os/bluestore/BitAllocator.h"
#include <stdio.h>
#include <assert.h>
#include <math.h>
+#include <sstream>
#include <gtest/gtest.h>
#define bmap_test_assert(x) EXPECT_EQ(true, (x))
TEST(BitAllocator, test_bmap_alloc)
{
- int64_t total_blocks = 1024 * 4;
- int64_t zone_size = 1024;
- int64_t allocated = 0;
- int64_t start_block = 0;
-
- BitAllocator *alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT);
+ const int max_iter = 2;
+
+ for (int round = 0; round < 3; round++) {
+ // Test zone of different sizes: 512, 1024, 2048
+ int64_t zone_size = 512ull << round;
+ ostringstream val;
+ val << zone_size;
+ g_conf->set_val("bluestore_bitmapallocator_blocks_per_zone", val.str());
+
+ // choose randomized span_size
+ int64_t span_size = 512ull << (rand() % 4);
+ val.str("");
+ val << span_size;
+ g_conf->set_val("bluestore_bitmapallocator_span_size", val.str());
+ g_ceph_context->_conf->apply_changes(NULL);
+
+ int64_t total_blocks = zone_size * 4;
+ int64_t allocated = 0;
+ int64_t start_block = 0;
+
+ BitAllocator *alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT);
+
+ for (int64_t iter = 0; iter < max_iter; iter++) {
+ for (int64_t i = 0; i < total_blocks; i++) {
+ allocated = alloc->alloc_blocks(1, &start_block);
+ bmap_test_assert(allocated == 1);
+ bmap_test_assert(start_block == i);
+ }
- for (int64_t iter = 0; iter < 4; iter++) {
- for (int64_t i = 0; i < total_blocks; i++) {
- allocated = alloc->alloc_blocks(1, &start_block);
- bmap_test_assert(allocated == 1);
- bmap_test_assert(start_block == i);
+ for (int64_t i = 0; i < total_blocks; i++) {
+ alloc->free_blocks(i, 1);
+ }
}
- for (int64_t i = 0; i < total_blocks; i++) {
- alloc->free_blocks(i, 1);
- }
- }
+ for (int64_t iter = 0; iter < max_iter; iter++) {
+ for (int64_t i = 0; i < total_blocks / zone_size; i++) {
+ allocated = alloc->alloc_blocks(zone_size, &start_block);
+ bmap_test_assert(allocated == zone_size);
+ bmap_test_assert(start_block == i * zone_size);
+ }
- for (int64_t iter = 0; iter < 4; iter++) {
- for (int64_t i = 0; i < total_blocks / zone_size; i++) {
- allocated = alloc->alloc_blocks(zone_size, &start_block);
- bmap_test_assert(allocated == zone_size);
- bmap_test_assert(start_block == i * zone_size);
+ for (int64_t i = 0; i < total_blocks / zone_size; i++) {
+ alloc->free_blocks(i * zone_size, zone_size);
+ }
}
- for (int64_t i = 0; i < total_blocks / zone_size; i++) {
- alloc->free_blocks(i * zone_size, zone_size);
- }
- }
+ allocated = alloc->alloc_blocks(1, &start_block);
+ bmap_test_assert(allocated == 1);
- allocated = alloc->alloc_blocks(1, &start_block);
- bmap_test_assert(allocated == 1);
+ allocated = alloc->alloc_blocks(zone_size - 1, &start_block);
+ bmap_test_assert(allocated == zone_size - 1);
+ bmap_test_assert(start_block == 1);
- allocated = alloc->alloc_blocks(zone_size - 1, &start_block);
- bmap_test_assert(allocated == zone_size - 1);
- bmap_test_assert(start_block == 1);
+ allocated = alloc->alloc_blocks(1, &start_block);
+ bmap_test_assert(allocated == 1);
- allocated = alloc->alloc_blocks(1, &start_block);
- bmap_test_assert(allocated == 1);
+ allocated = alloc->alloc_blocks(zone_size, &start_block);
+ bmap_test_assert(allocated == zone_size);
+ bmap_test_assert(start_block == zone_size * 2);
- allocated = alloc->alloc_blocks(zone_size, &start_block);
- bmap_test_assert(allocated == zone_size);
- bmap_test_assert(start_block == zone_size * 2);
+ // Dis contiguous blocks allocations
+ delete alloc;
+ alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT);
- // Dis contiguous blocks allocations
- delete alloc;
- alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT);
+ for (int64_t i = 0; i < alloc->size(); i++) {
+ allocated = alloc->alloc_blocks(1, &start_block);
+ bmap_test_assert(allocated == 1);
+ }
+ for (int i = 0; i < alloc->size(); i += 2) {
+ alloc->free_blocks(i, 1);
+ }
- for (int64_t i = 0; i < alloc->size(); i++) {
- allocated = alloc->alloc_blocks(1, &start_block);
- bmap_test_assert(allocated == 1);
- }
- for (int i = 0; i < alloc->size(); i += 2) {
- alloc->free_blocks(i, 1);
- }
+ int64_t blocks[alloc->size() / 2];
+ memset(blocks, 0, sizeof(blocks));
+ allocated = alloc->alloc_blocks_dis(alloc->size()/2, blocks);
+ bmap_test_assert(allocated == alloc->size() / 2);
- int64_t blocks[alloc->size() / 2];
- memset(blocks, 0, sizeof(blocks));
- allocated = alloc->alloc_blocks_dis(alloc->size()/2, blocks);
- bmap_test_assert(allocated == alloc->size() / 2);
+ allocated = alloc->alloc_blocks_dis(1, blocks);
+ bmap_test_assert(allocated == 0);
- allocated = alloc->alloc_blocks_dis(1, blocks);
- bmap_test_assert(allocated == 0);
+ alloc->free_blocks(alloc->size()/2, 1);
+ allocated = alloc->alloc_blocks_dis(1, blocks);
- alloc->free_blocks(alloc->size()/2, 1);
- allocated = alloc->alloc_blocks_dis(1, blocks);
+ bmap_test_assert(allocated == 1);
+ bmap_test_assert(blocks[0] == alloc->size()/2);
- bmap_test_assert(allocated == 1);
- bmap_test_assert(blocks[0] == alloc->size()/2);
+ alloc->free_blocks(0, alloc->size());
+ delete alloc;
- alloc->free_blocks(0, alloc->size());
- delete alloc;
+ // unaligned zones
+ total_blocks = zone_size * 2 + 11;
+ alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT);
- // unaligned zones
- total_blocks = 1024 * 2 + 11;
- alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT);
+ for (int64_t iter = 0; iter < max_iter; iter++) {
+ for (int64_t i = 0; i < total_blocks; i++) {
+ allocated = alloc->alloc_blocks(1, &start_block);
+ bmap_test_assert(allocated == 1);
+ bmap_test_assert(start_block == i);
+ }
- for (int64_t iter = 0; iter < 4; iter++) {
- for (int64_t i = 0; i < total_blocks; i++) {
- allocated = alloc->alloc_blocks(1, &start_block);
- bmap_test_assert(allocated == 1);
- bmap_test_assert(start_block == i);
+ for (int64_t i = 0; i < total_blocks; i++) {
+ alloc->free_blocks(i, 1);
+ }
}
+ delete alloc;
+
+ // Make three > 3 levels tree and check allocations and dealloc
+ // in a loop
+ int64_t alloc_size = 64ull << round;
+ total_blocks = BitMapArea::get_level_factor(2) * 4;
+ alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT, false);
+ for (int64_t iter = 0; iter < max_iter; iter++) {
+ for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
+ allocated = alloc->alloc_blocks(alloc_size, &start_block);
+ bmap_test_assert(allocated == alloc_size);
+ bmap_test_assert(start_block == i * alloc_size);
+ }
- for (int64_t i = 0; i < total_blocks; i++) {
- alloc->free_blocks(i, 1);
- }
- }
- delete alloc;
-
- // Make three > 3 levels tree and check allocations and dealloc
- // in a loop
- int64_t alloc_size = 16;
- total_blocks = pow(BITMAP_SPAN_SIZE, 2) * 4;
- alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT, false);
- for (int64_t iter = 0; iter < 3; iter++) {
- for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
- allocated = alloc->alloc_blocks(alloc_size, &start_block);
- bmap_test_assert(allocated == alloc_size);
- bmap_test_assert(start_block == i * alloc_size);
+ for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
+ alloc->free_blocks(i * alloc_size, alloc_size);
+ }
}
- for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
- alloc->free_blocks(i * alloc_size, alloc_size);
- }
- }
+ delete alloc;
+ alloc = new BitAllocator(1024, zone_size, CONCURRENT, true);
+
+ alloc->free_blocks(1, 1023);
+ allocated = alloc->alloc_blocks(16, &start_block);
+ bmap_test_assert(allocated == 16);
+ bmap_test_assert(start_block == 1);
+ delete alloc;
+
+ total_blocks = BitMapArea::get_level_factor(2) * 4;
+ alloc_size = 64ull << round;
+ alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT, false);
+ for (int64_t iter = 0; iter < max_iter; iter++) {
+ for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
+ bmap_test_assert(alloc->reserve_blocks(alloc_size));
+ allocated = alloc->alloc_blocks_res(alloc_size, &start_block);
+ bmap_test_assert(allocated == alloc_size);
+ bmap_test_assert(start_block == i * alloc_size);
+ }
- delete alloc;
- alloc = new BitAllocator(1024, zone_size, CONCURRENT, true);
-
- alloc->free_blocks(1, 1023);
- alloc->alloc_blocks(16, &start_block);
- delete alloc;
-
- total_blocks = pow(BITMAP_SPAN_SIZE, 2) * 4;
- alloc_size = 16;
- alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT, false);
- for (int64_t iter = 0; iter < 3; iter++) {
- for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
- bmap_test_assert(alloc->reserve_blocks(alloc_size));
- allocated = alloc->alloc_blocks_res(alloc_size, &start_block);
- bmap_test_assert(allocated == alloc_size);
- bmap_test_assert(start_block == i * alloc_size);
+ for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
+ alloc->free_blocks(i * alloc_size, alloc_size);
+ }
}
- for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
- alloc->free_blocks(i * alloc_size, alloc_size);
- }
+ delete alloc;
}
- delete alloc;
+ // restore to typical value
+ g_conf->set_val("bluestore_bitmapallocator_blocks_per_zone", "1024");
+ g_conf->set_val("bluestore_bitmapallocator_span_size", "1024");
+ g_ceph_context->_conf->apply_changes(NULL);
}
void
int main(int argc, char **argv)
{
+ vector<const char*> args;
+ argv_to_vec(argc, (const char **)argv, args);
+ env_to_vec(args);
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(g_ceph_context);
+
::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
+ int r = RUN_ALL_TESTS();
+ g_ceph_context->put();
+ return r;
}