OCSSD 文档

因为 ocssd 文档非常少,为了方便同学们完成实验,提供一些实验资料如下。

参考资料

ssdfans 可可读 ocssd 系列:

  1. 可可读 OpenChannelSSD 之一 简介

  2. 可可读 OpenChannelSSD 之二 PPA 接口

  3. 可可读 OpenChannelSSD 之三 LightNVM 子系统

  4. 可可读 OpenChannelSSD 之四 pblk

  5. 可可读 OpenChannelSSD 之五 Virtual OCSSD 实验环境搭建英文

  6. 可可读 OpenChannelSSD 之六 从 OpenChannel SSD 到 ZNS

ocssd 标准:

  1. Open-Channel Solid State Drives Specification Revision 2.0

  2. Open-Channel Solid State Drives NVMe Specification Revision 1.2 (已过时)

ocssd 原始论文:

  1. LightNVM: The Linux Open-Channel SSD Subsystem

  2. The case of FEMU: cheap, accurate, scalable and extensible flash emulator

OCSSD 结构

channel 和 pu 对应关系
  1. 存储通道(Channel、Group):可以并行发送数据和接受命令的通道

  2. 存储芯片(PU、LUN):可以被片选的一块儿芯片,多个芯片物理上挂载到一个通道上,但同一时间一个通道 上只能片选一个芯片

  3. 可清除块(Chunk):可以被清除的最小单元

  4. 可编程块(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:

  1. 整个 SSD 有 4 个 group

  2. 每个 group,挂 1 个 PU

  3. 每个 PU 下,有 4096 个 chunk

  4. 每个 chunk 下,有 32 个 sector

  5. 每个 sector 默认为 4KiB

因此总大小为 4 * 4096 * 32 * 4 KiB = 2 GiB,检查发现该镜像大小基本符合。

pblk 介绍

pblk 是在 LightNVM 上实现的一个主机 FTL 层,FTL 原本是 SSD 主控中的一个模块,负责完成:

  1. 逻辑地址到物理地址的转换,保证元数据的完整性

  2. 逻辑块的分配,保证存取效率,例如将连续的逻辑块条带化到不同的通道

  3. 实现缓存,对主机的逻辑块写入进行缓冲,调整落盘时机,减少不必要的写入量

  4. 处理 Flush 操作,文件系统可能要求一些 IO 操作必须落盘才能继续执行(比如实现事务性)

  5. 处理写入均衡,SSD 中每个存储单元都有固有寿命,在若干个 PE 循环后会失效损坏,因此需要尽可能 的平均地使用物理单元。

pblk 中的几个关键代码路径

pblk 中的几个代码路径:

  • 对于上层的读请求:

    1. 需要先查询是否命中写缓冲,如果命中的话,直接从内存里的写缓冲中读取刚刚写入的数据块

    2. 如果未命中写缓冲,查询转换表(L2P Table),得到物理地址,发送到设备层去读取相应的物理数据块

    3. 需要注意的是,操作系统在 pblk 之上实现了 buffer/cache 机制,因此在 pblk 中不需要实现读缓存

  • 对于上层的写请求:

    1. 检查是否命中写缓冲,如果命中,更新写缓冲中的数据

    2. 如果未命中写缓冲,则需要分配写缓冲,如果此时没有空闲的缓冲行,则挂起发起写请求的 OS 线程

    3. 如果有空闲的缓冲行,分配并写入缓冲

  • GC 线程:

    1. 在 pblk 中有若干 gc 线程用来选择需要被写入的缓冲行,进行 GC 的策略如下

      1. 首先选择没有有效存储块的缓冲行,这些缓冲行可以被快速回收

      2. 接着选择过去发生写入错误的缓冲行,这些缓冲行需要尽快被重试

      3. 最后按照缓冲行中有效存储块的数量,从少到多选择缓冲行

    2. 在选好了一个需要被 GC 的缓冲行之后,GC 模块会读取缓冲行中的其它存储块,补齐一个整行,接着将这个行落盘