bluestore 中采用allocator来分配块。allocator的使用者保护bluefs和bluestore
Allocator *Allocator::create(CephContext* cct, string type,
int64_t size, int64_t block_size)
{
if (type == "stupid") {
return new StupidAllocator(cct);
} else if (type == "bitmap") {
return new BitMapAllocator(cct, size, block_size);
}
lderr(cct) << "Allocator::" << __func__ << " unknown alloc type "
<< type << dendl;
return nullptr;
}
从allocator的create中可以看出其实现由stupid和bitmap两种方式,其中bitmap的性能比stupid的性能差,因此默认
使用的是stupid来分别空闲block
再使用stupid分配空闲block前首先要通过init_add_free来向stupid中增加可以分配的空闲block
void StupidAllocator::init_add_free(uint64_t offset, uint64_t length)
{
std::lock_guard<std::mutex> l(lock);
ldout(cct, 10) << __func__ << " 0x" << std::hex << offset << "~" << length
<< std::dec << dendl;
#插入空闲block
_insert_free(offset, length);
#记录总的空闲的长度
num_free += length;
}
void StupidAllocator::_insert_free(uint64_t off, uint64_t len)
{
unsigned bin = _choose_bin(len);
ldout(cct, 30) << __func__ << " 0x" << std::hex << off << "~" << len
<< std::dec << " in bin " << bin << dendl;
while (true) {
#可以看到是将空闲block放到free这个vector中管理,其中free 中采用btree来管理空闲block
free[bin].insert(off, len, &off, &len);
unsigned newbin = _choose_bin(len);
if (newbin == bin)
break;
ldout(cct, 30) << __func__ << " promoting 0x" << std::hex << off << "~" << len
<< std::dec << " to bin " << newbin << dendl;
free[bin].erase(off, len);
bin = newbin;
}
}
除了向stupid中增加用于分配的空闲block外,也可以通过init_rm_free 来从stupid中删除空闲block
void StupidAllocator::init_rm_free(uint64_t offset, uint64_t length)
{
std::lock_guard<std::mutex> l(lock);
ldout(cct, 10) << __func__ << " 0x" << std::hex << offset << "~" << length
<< std::dec << dendl;
interval_set_t rm;
rm.insert(offset, length);
for (unsigned i = 0; i < free.size() && !rm.empty(); ++i) {
interval_set_t overlap;
overlap.intersection_of(rm, free[i]);
if (!overlap.empty()) {
ldout(cct, 20) << __func__ << " bin " << i << " rm 0x" << std::hex << overlap
<< std::dec << dendl;
#从free中删除空闲block
free[i].subtract(overlap);
rm.subtract(overlap);
}
}
assert(rm.empty());
#总的空闲block 减去length
num_free -= length;
assert(num_free >= 0);
}
实际上通过stupid提供的allocate 函数来分配空闲block
int64_t StupidAllocator::allocate(
uint64_t want_size,
uint64_t alloc_unit,
uint64_t max_alloc_size,
int64_t hint,
mempool::bluestore_alloc::vector<AllocExtent> *extents)
{
uint64_t allocated_size = 0;
uint64_t offset = 0;
uint32_t length = 0;
int res = 0;
if (max_alloc_size == 0) {
max_alloc_size = want_size;
}
#从这里可以看到stupid是基于extent方式的
ExtentList block_list = ExtentList(extents, 1, max_alloc_size);
#如果已经申请的长度allocated_size 小于want_size,则通过allocate_int来申请,知道已经申请的长度allocated_size大于want_size
while (allocated_size < want_size) {
res = allocate_int(MIN(max_alloc_size, (want_size - allocated_size)),
alloc_unit, hint, &offset, &length);
if (res != 0) {
/*
* Allocation failed.
*/
break;
}
block_list.add_extents(offset, length);
allocated_size += length;
hint = offset + length;
}
if (allocated_size == 0) {
return -ENOSPC;
}
return allocated_size;
}
最终在allocate_int 中来从free[0].begin()中来时查找符合条件的要分配的空闲block,在这个函数中有一个很重要的hint 变量,这个变量就是上一次
上一次分配的最后的地址,其赋值如下:
if (!hint)
hint = last_alloc;
而这里的last_alloc 等于last_alloc = *offset + *length;即上一次分配的便宜地址加上长度
空闲block分配的allocator
最新推荐文章于 2024-05-27 18:20:37 发布