int64_t BitMapZone::count = 0;
int64_t BitMapZone::total_blocks = 0;
+bool BmapEntry::m_bit_mask_init = false;
+bmap_mask_vec_t BmapEntry::m_bit_to_mask;
+
/*
* BmapEntityList functions.
*/
/*
* Bitmap Entry functions.
*/
+
+void BmapEntry::_init_bit_mask()
+{
+
+ if (m_bit_mask_init) {
+ return;
+ }
+
+ m_bit_to_mask.reserve(BmapEntry::size());
+
+ uint64_t bmask = ((bmap_t) 0x1 << (BmapEntry::size() - 1));
+ for (int i = 0; i < BmapEntry::size(); i++) {
+ m_bit_to_mask[i] = bmask >> i;
+ }
+ BmapEntry::m_bit_mask_init = true;
+}
+
BmapEntry::BmapEntry(bool full)
{
+
+ BmapEntry::_init_bit_mask();
+
if (full) {
m_bits = BmapEntry::full_bmask();
} else {
bmap_t BmapEntry::bit_mask(int bit)
{
- return ((bmap_t) 0x1 << ((BmapEntry::size() - 1) - bit));
+ return m_bit_to_mask[bit];
+// return ((bmap_t) 0x1 << ((BmapEntry::size() - 1) - bit));
}
bool BmapEntry::check_bit(int bit)
{
/*
* Allocate N blocks, dis-contiguous are fine
*/
+#if 0
int64_t BitMapZone::alloc_blocks_dis(int64_t num_blocks,
int64_t hint,
int64_t zone_blk_off,
return allocated;
}
+#endif
-int64_t BitMapZone::alloc_blocks_dis2(int64_t num_blocks,
+int64_t BitMapZone::alloc_blocks_dis(int64_t num_blocks,
int64_t min_alloc,
- int64_t hint,
- int64_t zone_blk_off,
- ExtentList *alloc_blocks)
+ int64_t hint,
+ int64_t zone_blk_off,
+ ExtentList *alloc_blocks)
{
int64_t bmap_idx = hint / BmapEntry::size();
int bit = hint % BmapEntry::size();
BitMapEntityIter <BmapEntry> iter = BitMapEntityIter<BmapEntry>(
m_bmap_list, bmap_idx);
+ bmap = iter.next();
while (allocated < num_blocks) {
- blk_off = zone_blk_off + bmap_idx * size();
- if (last_cont) {
- /*
- * We had bits free at end of last bitmap, try to complete required
- * min alloc size using that.
- */
- alloc_cont = bmap->find_n_cont_bits(0, min_alloc - last_cont);
- allocated += alloc_cont;
- last_cont += alloc_cont;
-
- if (!alloc_cont) {
- this->free_blocks(last_running_ext, last_cont);
- allocated -= last_cont;
- last_cont = 0;
- } else {
- /*
- * Got contiguous min_alloc_size across bitmaps.
- */
- alloc_blocks->add_extents(last_running_ext, last_cont);
- }
- last_running_ext = 0;
- search_idx = alloc_cont;
- } else {
- /*
- * Try to allocate min_alloc_size bits from given bmap.
- */
- alloc_cont = bmap->find_first_set_bits(min_alloc, search_idx, &start_off, &scanned);
- search_idx = search_idx + scanned;
- if (alloc_cont / min_alloc) {
- /*
- * Got contiguous min_alloc_size within a bitmap.
+ blk_off = zone_blk_off + bmap_idx * bmap->size();
+ if (last_cont) {
+ /*
+ * We had bits free at end of last bitmap, try to complete required
+ * min alloc size using that.
+ */
+ alloc_cont = bmap->find_n_cont_bits(0, min_alloc - last_cont);
+ allocated += alloc_cont;
+ last_cont += alloc_cont;
+
+ if (!alloc_cont) {
+ this->free_blocks_int(last_running_ext, last_cont);
+ allocated -= last_cont;
+ last_cont = 0;
+ } else if (last_cont / min_alloc) {
+ /*
+ * Got contiguous min_alloc_size across bitmaps.
+ */
+ alloc_blocks->add_extents(last_running_ext, last_cont);
+ last_cont = 0;
+ last_running_ext = 0;
+ }
+ search_idx = alloc_cont;
+ } else {
+ /*
+ * Try to allocate min_alloc_size bits from given bmap.
*/
- alloc_blocks->add_extents(blk_off + start_off, min_alloc);
- }
-
- if (alloc_cont % min_alloc) {
- /*
- * Got some bits at end of bitmap, carry them to try match with
- * start bits from next bitmap.
- */
- if (!last_cont) {
- last_running_ext = blk_off + start_off;
- }
- last_cont += alloc_cont % min_alloc;
- }
- }
+ alloc_cont = bmap->find_first_set_bits(min_alloc, search_idx, &start_off, &scanned);
+ search_idx = search_idx + scanned;
+ allocated += alloc_cont;
+ if (alloc_cont / min_alloc) {
+ /*
+ * Got contiguous min_alloc_size within a bitmap.
+ */
+ alloc_blocks->add_extents(blk_off + start_off, min_alloc);
+ }
+
+ if (alloc_cont % min_alloc) {
+ /*
+ * Got some bits at end of bitmap, carry them to try match with
+ * start bits from next bitmap.
+ */
+ if (!last_cont) {
+ last_running_ext = blk_off + start_off;
+ }
+ last_cont += alloc_cont % min_alloc;
+ }
+ }
- if (search_idx == BmapEntry::size()) {
- search_idx = 0;
- if ((bmap = iter.next())) {
- this->free_blocks(last_running_ext, last_cont);
- allocated -= last_cont;
- break;
- }
- }
- }
+ if (search_idx == BmapEntry::size()) {
+ search_idx = 0;
+ bmap_idx = iter.index();
+ if ((bmap = iter.next()) == NULL) {
+ this->free_blocks_int(last_running_ext, last_cont);
+ allocated -= last_cont;
+ break;
+ }
+ }
+ }
- return allocated;
+ add_used_blocks(allocated);
+ return allocated;
}
return allocated;
}
-int64_t BitMapAreaIN::alloc_blocks_dis_int_work(bool wait, bool wrap, int64_t num_blocks,
+int64_t BitMapAreaIN::alloc_blocks_dis_int_work(bool wait, bool wrap, int64_t num_blocks, int64_t min_alloc,
int64_t hint, int64_t area_blk_off, ExtentList *block_list)
{
BitMapArea *child = NULL;
}
blk_off = child->get_index() * m_child_size_blocks + area_blk_off;
- allocated += child->alloc_blocks_dis(wait, num_blocks - allocated,
+ allocated += child->alloc_blocks_dis(wait, num_blocks - allocated, min_alloc,
hint % m_child_size_blocks, blk_off, block_list);
hint = 0;
child_unlock(child);
}
int64_t BitMapAreaIN::alloc_blocks_dis_int(bool wait, int64_t num_blocks,
- int64_t hint, int64_t area_blk_off, ExtentList *block_list)
+ int64_t min_alloc, int64_t hint, int64_t area_blk_off, ExtentList *block_list)
{
- return alloc_blocks_dis_int_work(wait, false, num_blocks, hint,
+ return alloc_blocks_dis_int_work(wait, false, num_blocks, min_alloc, hint,
area_blk_off, block_list);
}
-int64_t BitMapAreaIN::alloc_blocks_dis(bool wait, int64_t num_blocks,
+int64_t BitMapAreaIN::alloc_blocks_dis(bool wait, int64_t num_blocks, int64_t min_alloc,
int64_t hint, int64_t blk_off, ExtentList *block_list)
{
int64_t allocated = 0;
lock_shared();
- allocated += alloc_blocks_dis_int(wait, num_blocks, hint, blk_off, block_list);
+ allocated += alloc_blocks_dis_int(wait, num_blocks, min_alloc, hint, blk_off, block_list);
add_used_blocks(allocated);
unlock();
return allocated;
}
-int64_t BitMapAreaLeaf::alloc_blocks_dis_int(bool wait, int64_t num_blocks,
+int64_t BitMapAreaLeaf::alloc_blocks_dis_int(bool wait, int64_t num_blocks, int64_t min_alloc,
int64_t hint, int64_t area_blk_off, ExtentList *block_list)
{
BitMapArea *child = NULL;
}
blk_off = child->get_index() * m_child_size_blocks + area_blk_off;
- allocated += child->alloc_blocks_dis(num_blocks - allocated, hint % m_child_size_blocks,
- blk_off, block_list);
+ allocated += child->alloc_blocks_dis(num_blocks - allocated, min_alloc,
+ hint % m_child_size_blocks, blk_off, block_list);
child_unlock(child);
if (allocated == num_blocks) {
break;
* Allocate N dis-contiguous blocks.
*/
int64_t BitAllocator::alloc_blocks_dis_int(bool wait, int64_t num_blocks,
- int64_t hint, int64_t area_blk_off, ExtentList *block_list)
+ int64_t min_alloc, int64_t hint, int64_t area_blk_off, ExtentList *block_list)
{
- return alloc_blocks_dis_int_work(wait, true, num_blocks, hint,
+ return alloc_blocks_dis_int_work(wait, true, num_blocks, min_alloc, hint,
area_blk_off, block_list);
}
-int64_t BitAllocator::alloc_blocks_dis(int64_t num_blocks, int64_t hint, ExtentList *block_list)
+int64_t BitAllocator::alloc_blocks_dis(int64_t num_blocks, int64_t min_alloc, int64_t hint, ExtentList *block_list)
{
- return alloc_blocks_dis_work(num_blocks, hint, block_list, false);
+ return alloc_blocks_dis_work(num_blocks, min_alloc, hint, block_list, false);
}
-int64_t BitAllocator::alloc_blocks_dis_res(int64_t num_blocks, int64_t hint, ExtentList *block_list)
+int64_t BitAllocator::alloc_blocks_dis_res(int64_t num_blocks, int64_t min_alloc, int64_t hint, ExtentList *block_list)
{
- return alloc_blocks_dis_work(num_blocks, hint, block_list, true);
+ return alloc_blocks_dis_work(num_blocks, min_alloc, hint, block_list, true);
}
-int64_t BitAllocator::alloc_blocks_dis_work(int64_t num_blocks, int64_t hint, ExtentList *block_list, bool reserved)
+int64_t BitAllocator::alloc_blocks_dis_work(int64_t num_blocks, int64_t min_alloc, int64_t hint, ExtentList *block_list, bool reserved)
{
int scans = 1;
int64_t allocated = 0;
}
while (scans && allocated < num_blocks) {
- allocated += alloc_blocks_dis_int(false, num_blocks - allocated, hint + allocated, blk_off, block_list);
+ allocated += alloc_blocks_dis_int(false, num_blocks - allocated, min_alloc, hint + allocated, blk_off, block_list);
scans--;
}
unlock();
lock_excl();
serial_lock();
- allocated += alloc_blocks_dis_int(false, num_blocks - allocated, hint + allocated,
+ allocated += alloc_blocks_dis_int(false, num_blocks - allocated, min_alloc, hint + allocated,
blk_off, block_list);
if (is_stats_on()) {
m_stats->add_serial_scans(1);
};
typedef unsigned long bmap_t;
+typedef mempool::bluestore_alloc::vector<bmap_t> bmap_mask_vec_t;
class BmapEntry {
private:
bmap_t m_bits;
+ static bool m_bit_mask_init;
+ static bmap_mask_vec_t m_bit_to_mask;
+
+
+ static void _init_bit_mask();
public:
MEMPOOL_CLASS_HELPERS();
static int64_t size();
static bmap_t empty_bmask();
static bmap_t align_mask(int x);
- bmap_t bit_mask(int bit_num);
+ static bmap_t bit_mask(int bit_num);
bmap_t atomic_fetch();
BmapEntry(bool val);
BmapEntry() {
return 0;
}
- virtual int64_t alloc_blocks_dis(bool wait, int64_t num_blocks,
+ virtual int64_t alloc_blocks_dis(bool wait, int64_t num_blocks, int64_t min_alloc,
int64_t hint, int64_t blk_off, ExtentList *block_list) {
ceph_abort();
return 0;
}
- virtual int64_t alloc_blocks_dis(int64_t num_blocks,
+ virtual int64_t alloc_blocks_dis(int64_t num_blocks, int64_t min_alloc,
int64_t hint, int64_t blk_off, ExtentList *block_list) {
ceph_abort();
return 0;
return 0;
}
- virtual int64_t alloc_blocks_dis(bool wait, int64_t num_blocks,
+ virtual int64_t alloc_blocks_dis(bool wait, int64_t num_blocks, int64_t min_alloc,
int64_t hint, int64_t blk_off, int64_t *block_list) {
ceph_abort();
return 0;
int64_t alloc_blocks(int64_t num_blocks, int64_t hint, int64_t *start_block);
using BitMapArea::alloc_blocks_dis;
- int64_t alloc_blocks_dis(int64_t num_blocks, int64_t hint,
- int64_t blk_off, ExtentList *block_list);
- int64_t alloc_blocks_dis2(int64_t num_blocks, int64_t min_alloc, int64_t hint,
+ int64_t alloc_blocks_dis(int64_t num_blocks, int64_t min_alloc, int64_t hint,
int64_t blk_off, ExtentList *block_list);
void set_blocks_used(int64_t start_block, int64_t num_blocks);
int64_t alloc_blocks_int_work(bool wait, bool wrap,
int64_t num_blocks, int64_t hint, int64_t *start_block);
- int64_t alloc_blocks_dis_int_work(bool wait, bool wrap, int64_t num_blocks, int64_t hint,
+ int64_t alloc_blocks_dis_int_work(bool wait, bool wrap, int64_t num_blocks, int64_t min_alloc, int64_t hint,
int64_t blk_off, ExtentList *block_list);
public:
}
virtual int64_t alloc_blocks_int(bool wait, int64_t num_blocks,
- int64_t hint, int64_t *start_block);
+ int64_t hint, int64_t *start_block);
using BitMapArea::alloc_blocks; //non-wait version
using BitMapArea::alloc_blocks_dis; //non-wait version
virtual int64_t alloc_blocks(bool wait, int64_t num_blocks, int64_t hint, int64_t *start_block);
- virtual int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks, int64_t hint,
+ virtual int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks, int64_t min_alloc, int64_t hint,
int64_t blk_off, ExtentList *block_list);
- virtual int64_t alloc_blocks_dis(bool wait, int64_t num_blocks, int64_t hint,
+ virtual int64_t alloc_blocks_dis(bool wait, int64_t num_blocks, int64_t min_alloc, int64_t hint,
int64_t blk_off, ExtentList *block_list);
virtual void set_blocks_used_int(int64_t start_block, int64_t num_blocks);
virtual void set_blocks_used(int64_t start_block, int64_t num_blocks);
void child_unlock(BitMapArea *child);
int64_t alloc_blocks_int(bool wait, int64_t num_blocks, int64_t hint, int64_t *start_block);
- int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks, int64_t hint,
+ int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks, int64_t min_alloc, int64_t hint,
int64_t blk_off, ExtentList *block_list);
void free_blocks_int(int64_t start_block, int64_t num_blocks);
bool check_input_dis(int64_t num_blocks);
void init_check(int64_t total_blocks, int64_t zone_size_block,
bmap_alloc_mode_t mode, bool def, bool stats_on);
- int64_t alloc_blocks_dis_work(int64_t num_blocks, int64_t hint, ExtentList *block_list, bool reserved);
+ int64_t alloc_blocks_dis_work(int64_t num_blocks, int64_t min_alloc, int64_t hint, ExtentList *block_list, bool reserved);
int64_t alloc_blocks_int(bool wait, int64_t num_blocks, int64_t hint, int64_t *start_block);
- int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks,
+ int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks, int64_t min_alloc,
int64_t hint, int64_t area_blk_off, ExtentList *block_list);
public:
void set_blocks_used(int64_t start_block, int64_t num_blocks);
void unreserve_blocks(int64_t blocks);
- int64_t alloc_blocks_dis(int64_t num_blocks, int64_t hint, ExtentList *block_list);
- int64_t alloc_blocks_dis_res(int64_t num_blocks, int64_t hint, ExtentList *block_list);
+ int64_t alloc_blocks_dis(int64_t num_blocks, int64_t min_alloc, int64_t hint, ExtentList *block_list);
+ int64_t alloc_blocks_dis_res(int64_t num_blocks, int64_t min_alloc, int64_t hint, ExtentList *block_list);
void free_blocks_dis(int64_t num_blocks, ExtentList *block_list);
bool is_allocated_dis(ExtentList *blocks, int64_t num_blocks);
uint64_t want_size, uint64_t alloc_unit, uint64_t max_alloc_size,
int64_t hint, mempool::bluestore_alloc::vector<AllocExtent> *extents, int *count)
{
+
assert(!(alloc_unit % m_block_size));
assert(alloc_unit);
<< " hint " << hint
<< dendl;
- if (alloc_unit > (uint64_t) m_block_size) {
- return alloc_extents_cont(want_size, alloc_unit,
- max_alloc_size, hint / m_block_size, extents, count);
- } else {
- return alloc_extents_dis(want_size, alloc_unit,
- max_alloc_size, hint / m_block_size, extents, count);
- }
+ return alloc_extents_dis(want_size, alloc_unit / m_block_size,
+ max_alloc_size, hint / m_block_size, extents, count);
}
/*
int64_t num = 0;
*count = 0;
- num = m_bit_alloc->alloc_blocks_dis_res(nblks, hint, &block_list);
+ num = m_bit_alloc->alloc_blocks_dis_res(nblks, alloc_unit, hint, &block_list);
if (num < nblks) {
m_bit_alloc->free_blocks_dis(num, &block_list);
return -ENOSPC;
#include <gtest/gtest.h>
-#define bmap_test_assert(x) ASSERT_EQ(true, (x))
+//#define bmap_test_assert(x) ASSERT_EQ(true, (x))
+#define bmap_test_assert(x) assert((x))
#define NUM_THREADS 16
#define MAX_BLOCKS (1024 * 1024 * 1)
(zone->size() / 2, AllocExtent(-1, -1));
ExtentList *block_list = new ExtentList(&extents, blk_size);
- allocated = zone->alloc_blocks_dis(zone->size() / 2, 0, 0, block_list);
+ allocated = zone->alloc_blocks_dis(zone->size() / 2, 1, 0, 0, block_list);
bmap_test_assert(allocated == zone->size() / 2);
{
bmap_test_assert(lock);
for (int i = 0; i < zone->size(); i += 4) {
block_list->reset();
- allocated = zone->alloc_blocks_dis(1, i, 0, block_list);
+ allocated = zone->alloc_blocks_dis(1, 1, i, 0, block_list);
bmap_test_assert(allocated == 1);
EXPECT_EQ(extents[0].offset, (uint64_t) i * blk_size);
}
zone->free_blocks(i, 1);
}
}
+
+ /*
+ * Min alloc size cases.
+ */
+ {
+ int64_t blk_size = 1;
+ AllocExtentVector extents = AllocExtentVector
+ (zone->size() / 2, AllocExtent(-1, -1));
+
+ for (int i = 1; i <= total_blocks - BmapEntry::size(); i = i << 1) {
+ for (int64_t j = 0; j <= BmapEntry::size(); j = 1 << j) {
+ ExtentList *block_list = new ExtentList(&extents, blk_size);
+ zone = new BitMapZone(total_blocks, 0);
+ lock = zone->lock_excl_try();
+ bmap_test_assert(lock);
+
+ block_list->reset();
+ int64_t need_blks = (((total_blocks - j) / i) * i);
+ allocated = zone->alloc_blocks_dis(need_blks, i, j, 0, block_list);
+ bmap_test_assert(allocated == need_blks);
+ bmap_test_assert(extents[0].offset == (uint64_t) j);
+ delete block_list;
+ delete zone;
+ }
+ }
+ {
+ ExtentList *block_list = new ExtentList(&extents, blk_size);
+ zone = new BitMapZone(total_blocks, 0);
+ lock = zone->lock_excl_try();
+ bmap_test_assert(lock);
+
+ block_list->reset();
+ allocated = zone->alloc_blocks_dis(total_blocks + 1, total_blocks + 1, 0, 0, block_list);
+ bmap_test_assert(allocated == 0);
+
+ block_list->reset();
+ allocated = zone->alloc_blocks_dis(total_blocks, total_blocks, 0, 0, block_list);
+ bmap_test_assert(allocated == total_blocks);
+ bmap_test_assert(extents[0].offset == 0);
+
+ zone->free_blocks(extents[0].offset, allocated);
+
+ delete block_list;
+ block_list = new ExtentList(&extents, blk_size, total_blocks / 4 * blk_size);
+ block_list->reset();
+ allocated = zone->alloc_blocks_dis(total_blocks, total_blocks / 4, 0, 0, block_list);
+ bmap_test_assert(allocated == total_blocks);
+ for (int i = 0; i < 4; i++) {
+ bmap_test_assert(extents[i].offset == (uint64_t) i * (total_blocks / 4));
+ }
+
+ }
+ }
}
TEST(BitAllocator, test_bmap_alloc)
ExtentList *block_list = new ExtentList(&extents, blk_size);
- allocated = alloc->alloc_blocks_dis(alloc->size()/2, 0, block_list);
+ allocated = alloc->alloc_blocks_dis(alloc->size()/2, 1, 0, block_list);
ASSERT_EQ(alloc->size()/2, allocated);
block_list->reset();
- allocated = alloc->alloc_blocks_dis(1, 0, block_list);
+ allocated = alloc->alloc_blocks_dis(1, 1, 0, block_list);
bmap_test_assert(allocated == 0);
alloc->free_blocks(alloc->size()/2, 1);
block_list->reset();
- allocated = alloc->alloc_blocks_dis(1, 0, block_list);
+ allocated = alloc->alloc_blocks_dis(1, 1, 0, block_list);
bmap_test_assert(allocated == 1);
bmap_test_assert((int64_t) extents[0].offset == alloc->size()/2 * blk_size);
ExtentList *block_list = new ExtentList(&extents, blk_size, max_alloc);
- allocated = alloc->alloc_blocks_dis(total_alloc, 0, block_list);
+ allocated = alloc->alloc_blocks_dis(total_alloc, blk_size, 0, block_list);
EXPECT_EQ(allocated, total_alloc);
max_alloc = total_alloc > max_alloc? max_alloc: total_alloc;
while (num_iters--) {
alloc_assert(alloc->reserve_blocks(num_blocks));
- alloced = alloc->alloc_blocks_dis_res(num_blocks, 0, block_list);
+ alloced = alloc->alloc_blocks_dis_res(num_blocks, 1, 0, block_list);
alloc_assert(alloced == num_blocks);
alloc_assert(alloc->is_allocated_dis(block_list, num_blocks));