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]; } } }
bluestore的空闲块管理
猜你喜欢
转载自blog.csdn.net/tiantao2012/article/details/80166428
今日推荐
周排行