OCSSD 文档
因为 ocssd 文档非常少,为了方便同学们完成实验,提供一些实验资料如下。
参考资料
ssdfans 可可读 ocssd 系列:
ocssd 标准:
ocssd 原始论文:
OCSSD 结构
存储通道(Channel、Group):可以并行发送数据和接受命令的通道
存储芯片(PU、LUN):可以被片选的一块儿芯片,多个芯片物理上挂载到一个通道上,但同一时间一个通道 上只能片选一个芯片
可清除块(Chunk):可以被清除的最小单元
可编程块(Block):可以被编程或读取的最小单元
注:Chunk 和 Block 在不同的文献中定义不明确,即使是英文文献也有混淆的情况,此处的定义遵循 OCSSD 2.0 标准,和 pblk 代码保持对应。
举例而言
qemu-img create -f ocssd -o num_grp=4,num_pu=1,num_chk=4096,num_sec=32 ocssd.img
这段代码生成了参数如下的 ocssd:
整个 SSD 有 4 个 group
每个 group,挂 1 个 PU
每个 PU 下,有 4096 个 chunk
每个 chunk 下,有 32 个 sector
每个 sector 默认为 4KiB
因此总大小为 4 * 4096 * 32 * 4 KiB = 2 GiB,检查发现该镜像大小基本符合。
pblk 介绍
pblk 是在 LightNVM 上实现的一个主机 FTL 层,FTL 原本是 SSD 主控中的一个模块,负责完成:
逻辑地址到物理地址的转换,保证元数据的完整性
逻辑块的分配,保证存取效率,例如将连续的逻辑块条带化到不同的通道
实现缓存,对主机的逻辑块写入进行缓冲,调整落盘时机,减少不必要的写入量
处理 Flush 操作,文件系统可能要求一些 IO 操作必须落盘才能继续执行(比如实现事务性)
处理写入均衡,SSD 中每个存储单元都有固有寿命,在若干个 PE 循环后会失效损坏,因此需要尽可能 的平均地使用物理单元。
pblk 中的几个代码路径:
对于上层的读请求:
需要先查询是否命中写缓冲,如果命中的话,直接从内存里的写缓冲中读取刚刚写入的数据块
如果未命中写缓冲,查询转换表(L2P Table),得到物理地址,发送到设备层去读取相应的物理数据块
需要注意的是,操作系统在 pblk 之上实现了 buffer/cache 机制,因此在 pblk 中不需要实现读缓存
对于上层的写请求:
检查是否命中写缓冲,如果命中,更新写缓冲中的数据
如果未命中写缓冲,则需要分配写缓冲,如果此时没有空闲的缓冲行,则挂起发起写请求的 OS 线程
如果有空闲的缓冲行,分配并写入缓冲
GC 线程:
在 pblk 中有若干 gc 线程用来选择需要被写入的缓冲行,进行 GC 的策略如下
首先选择没有有效存储块的缓冲行,这些缓冲行可以被快速回收
接着选择过去发生写入错误的缓冲行,这些缓冲行需要尽快被重试
最后按照缓冲行中有效存储块的数量,从少到多选择缓冲行
在选好了一个需要被 GC 的缓冲行之后,GC 模块会读取缓冲行中的其它存储块,补齐一个整行,接着将这个行落盘