空闲block分配的allocator

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;即上一次分配的便宜地址加上长度

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值