bluestore的空闲块管理

bluestore自己管理裸盘的块设备,管理空闲空间的类是FreelistManager,所有的块组成一个bitmap,0为空闲,1为使用。
FreelistManager *FreelistManager::create(
  CephContext* cct,
  string type,
  KeyValueDB *kvdb,
  string prefix)
{
  assert(prefix == "B");
  if (type == "bitmap")
    return new BitmapFreelistManager(cct, kvdb, "B", "b");
  return NULL;
}
从FreelistManager 的create函数可以看出目前空闲list只能由BitmapFreelistManager 来管理,也就是说type只能是bitmap,否则会返回NULL
int BitmapFreelistManager::create(uint64_t new_size, uint64_t min_alloc_size,
				  KeyValueDB::Transaction txn)
{
  bytes_per_block = std::max(cct->_conf->bdev_block_size,
			     (int64_t)min_alloc_size);
  assert(ISP2(bytes_per_block));
  size = P2ALIGN(new_size, bytes_per_block);
  blocks_per_key = cct->_conf->bluestore_freelist_blocks_per_key;

  _init_misc();

  blocks = size / bytes_per_block;
  if (blocks / blocks_per_key * blocks_per_key != blocks) {
    blocks = (blocks / blocks_per_key + 1) * blocks_per_key;
    dout(10) << __func__ << " rounding blocks up from 0x" << std::hex << size
	     << " to 0x" << (blocks * bytes_per_block)
	     << " (0x" << blocks << " blocks)" << std::dec << dendl;
    // set past-eof blocks as allocated
    _xor(size, blocks * bytes_per_block - size, txn);
  }
  dout(10) << __func__
	   << " size 0x" << std::hex << size
	   << " bytes_per_block 0x" << bytes_per_block
	   << " blocks 0x" << blocks
	   << " blocks_per_key 0x" << blocks_per_key
	   << std::dec << dendl;
  {
    bufferlist bl;
    ::encode(bytes_per_block, bl);
    txn->set(meta_prefix, "bytes_per_block", bl);
  }
  {
    bufferlist bl;
    ::encode(blocks_per_key, bl);
    txn->set(meta_prefix, "blocks_per_key", bl);
  }
  {
    bufferlist bl;
    ::encode(blocks, bl);
    txn->set(meta_prefix, "blocks", bl);
  }
  {
    bufferlist bl;
    ::encode(size, bl);
    txn->set(meta_prefix, "size", bl);
  }
  return 0;
}
从BitmapFreelistManager的create函数可以看出,块设备的元数据是用kv存储的,默认有四个key,分别是bytes_per_block/blocks_per_key
/blocks/size

BitmapFreelistManager 提供的申请块设备和释放块设备的函数分别如下:可以看到无论申请还是释放 都是通过xor来进行的
void BitmapFreelistManager::allocate(
  uint64_t offset, uint64_t length,
  KeyValueDB::Transaction txn)
{
  dout(10) << __func__ << " 0x" << std::hex << offset << "~" << length
	   << std::dec << dendl;
  if (cct->_conf->bluestore_debug_freelist)
    _verify_range(offset, length, 0);
  _xor(offset, length, txn);
}

void BitmapFreelistManager::release(
  uint64_t offset, uint64_t length,
  KeyValueDB::Transaction txn)
{
  dout(10) << __func__ << " 0x" << std::hex << offset << "~" << length
	   << std::dec << dendl;
  if (cct->_conf->bluestore_debug_freelist)
    _verify_range(offset, length, 1);
  _xor(offset, length, txn);
}
我们看看xor的实现
在xor中会针对申请的块设备的起始地址和size 来判断要申请的块设备属于哪个块设备组
我们这里以最简单的case为例,即要申请的块设备在同一个组内
void BitmapFreelistManager::_xor(
  uint64_t offset, uint64_t length,
  KeyValueDB::Transaction txn)
{
  // must be block aligned
  assert((offset & block_mask) == offset);
  assert((length & block_mask) == length);

  uint64_t first_key = offset & key_mask;
  uint64_t last_key = (offset + length - 1) & key_mask;
  dout(20) << __func__ << " first_key 0x" << std::hex << first_key
	   << " last_key 0x" << last_key << std::dec << dendl;

  #针对要申请的块设备在同一个组内
  if (first_key == last_key) {
    bufferptr p(blocks_per_key >> 3);
    p.zero();
	#起始block的编号
    unsigned s = (offset & ~key_mask) / bytes_per_block;
	#结束block的编号
    unsigned e = ((offset + length - 1) & ~key_mask) / bytes_per_block;
	#讲s和e之间的block 的bitmap置位为1,表示这段块设备已经被占用
    for (unsigned i = s; i <= e; ++i) {
      p[i >> 3] ^= 1ull << (i & 7);
    }
    string k;
    make_offset_key(first_key, &k);
    bufferlist bl;
    bl.append(p);
    dout(30) << __func__ << " 0x" << std::hex << first_key << std::dec << ": ";
    bl.hexdump(*_dout, false);
    *_dout << dendl;
	#这里的merge操作也是xor操作,表示和目前的value 来xor操作
    txn->merge(bitmap_prefix, k, bl);
  } else {
  }
  
 从下面这个函数知道merge操作其实是调用XorMergeOperator 来进行的
void BitmapFreelistManager::setup_merge_operator(KeyValueDB *db, string prefix)
{
  ceph::shared_ptr<XorMergeOperator> merge_op(new XorMergeOperator);
  db->set_merge_operator(prefix, merge_op);
}
而XorMergeOperator 的merge操作如下:可以看到也是进行xor操作
struct XorMergeOperator : public KeyValueDB::MergeOperator {
  void merge_nonexistent(
    const char *rdata, size_t rlen, std::string *new_value) override {
    *new_value = std::string(rdata, rlen);
  }
  void merge(
    const char *ldata, size_t llen,
    const char *rdata, size_t rlen,
    std::string *new_value) override {
    assert(llen == rlen);
    *new_value = std::string(ldata, llen);
    for (size_t i = 0; i < rlen; ++i) {
      (*new_value)[i] ^= rdata[i];
    }
  }
  }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值