稀疏写
我们知道一个文件的逻辑空间上是连续的,但是真正在磁盘上的物理空间分布并不一定是连续的。同时我们也会使用lseek
系统调用,使得文件偏移量大于文件的长度,此时再对文件写入,便会在文件中形成一个空洞,这些空洞中的字节都是0。空洞是否占用磁盘空间是有文件系统决定的,不过大部分的文件系统ext4
、xfs
都不占磁盘空间。我们称部分数据是0同时这部分数据不占磁盘空间的文件为稀疏文件,这种写入方式为稀疏写。
BlueStore中的对象也支持稀疏写,同时支持克隆等功能,所以对象的数据组织结构设计的会相对复杂一点。
BlueStore的每个对象对应一个Onode结构体,每个Onode包含一张extent-map,extent-map包含多个extent(lextent),每个extent负责管理对象内的一个逻辑段数据并且关联一个Blob,Blob包含多个pextent,最终将对象的数据映射到磁盘上。
BlueStore中Object到底层Device的映射关系
这里先从整体上给出在BlueStore中,一个Object的数据映射到底层BlockDevice的实现,如下图:
Extent
Extent是实现object的数据映射的关键数据结构,定义如下:
struct Extent : public ExtentBase { uint32_t logical_offset = 0; // 对应Object的逻辑偏移 uint32_t blob_offset = 0; // 对应Blob上的偏移 uint32_t length = 0; // 数据段长度 BlobRef blob; // 指向对应Blob的指针 };
logical_offset、length、blob_offset关系如下图:
每个Extent都会映射到下一层的Blob上,Extent会依据 block_size 对齐,没写的地方填充全零。
Extent中的length
值,最小:block_size,最大:max_blob_size
Blob
Blob是Bluestore里引入的处理块设备数据映射的中间层,定义如下:
struct Blob { int16_t id = -1; SharedBlobRef shared_blob; // 共享的blob状态 mutable bluestore_blob_t blob; // blob的元数据 }; struct bluestore_blob_t { PExtentVector extents; // 对应磁盘上的一组数据段 uint32_t logical_length = 0; // blob的原始数据长度 uint32_t compressed_length = 0; // 压缩的数据长度 };
每个Blob会对应一组 PExtentVector,它就是 bluestore_pextent_t 的一个数组,指向从Disk中分配的物理空间。
Blob里可能对应一个磁盘pextent,也可能对应多个pextent;
Blob里的pextent个数最多为:max_blob_size / min_alloc_size;
Blob里的多个pextent映射的Blob offset可能不连续,中间有空洞;