在前面的《SSD科普二十九》和《SSD科普三十》中,我们介绍了一条 Write Command 从 Host 进入 SSD 后,数据是如何被接收、缓存,并最终进入 NAND 的过程。
但是,对于 SSD 来说,把数据写进去只是完成了一半工作。
因为存储设备最终还要面对另一个问题:
几年以后,当 Host 再次读取这份数据时,SSD 如何准确地把它找回来?
很多人第一次理解 SSD 读取过程时,会认为:
Host 给 SSD 一个 LBA,SSD 查一下地址,然后去 NAND 读取数据。
这个理解方向没有错,但它忽略了 SSD 内部一个非常关键的问题:
Host 想读取的数据,并不一定就在 NAND 里面。
它可能刚刚被写入,还停留在 SSD 内部缓存中;也可能这个 LBA 根本没有有效数据。
所以,一条 Read Command 到达 SSD 后,FTL 首先需要解决的问题并不是:
“去哪个 NAND Page 读取?”
而是:
这个 LBA 对应的最新数据,现在到底在哪里?
这就是 SSD Read Path 的核心。
一、一条 Read Command 如何进入 SSD?
在《SSD科普二十九》中,我们介绍过 Write Command 是如何从 Host 到达 SSD。
Read Command 的前半部分流程其实类似。
Host 首先通过 NVMe Driver 创建一条 Read Command,并将它放入 Submission Queue 中。
随后,Host 更新 Doorbell,通知 SSD:
队列中有新的命令需要处理。
SSD Controller 获取这条命令后,就知道 Host 想读取哪些数据。
对于一条 NVMe Read Command 来说,有几个重要信息。
其中,SLBA 表示读取开始的逻辑地址,NLB 表示需要读取多少个逻辑块,而 Data Pointer 则告诉 SSD:
数据找到以后,应该放到 Host Memory 的什么位置。
因此,Write 和 Read 在这里有一个很有意思的区别。
Write Command:
Host 告诉 SSD:我要把这些数据写入哪个逻辑地址,同时告诉 SSD 数据现在在哪里。
Read Command:
Host 告诉 SSD:我要读取哪个逻辑地址的数据,同时告诉 SSD 找到以后返回到哪里。
但是,到这里 SSD 只是知道:
Host 想要什么数据。
它还不知道:
这份数据现在在哪里。
Read Path,从这里才开始。
二、FTL 首先要寻找:数据现在在哪里?
我们之前介绍过 L2P 表。
简单理解,L2P 就是:
Logical Address 到 Physical Address 的映射关系。
Host 使用的是逻辑地址,也就是 LBA。而 NAND 使用的是实际物理位置。
因此 SSD 需要通过 L2P,把 Host 的逻辑请求转换成 NAND 可以理解的位置。
但是,如果只把 L2P 理解成:
LBA → NAND 地址
其实是不完整的。
因为 SSD 内部存在缓存机制。
例如:
Host 刚刚写入了一笔数据。
数据可能已经进入 SSD,但是还没有 Program 到 NAND。
如果此时 Host 马上读取同一个 LBA,SSD 应该返回什么?
显然不能去 NAND 读取旧数据。
所以,从 Read Path 的角度来看,L2P Search 真正寻找的是:
这个 LBA 当前最新、有效的数据在哪里。
根据搜索结果,通常可以分为三种情况。
三、第一种情况:数据已经在 NAND 中
这是最常见的一种情况。
假设某个 LBA 对应的数据已经完成写入,并且当前仍然有效。
那么 FTL 查询 L2P 后,可以找到对应的物理位置。
此时 Read Path 才进入 NAND 读取阶段。
整个过程可以简单理解为:
Host Read Request
↓
FTL 查询 L2P
↓
找到 NAND Physical Address
↓
NAND Read
NAND Read 并不是简单地把某个 Cell 里的数据直接拿出来。
NAND 内部需要根据读取电压,对 Cell 的状态进行感测,并将读取结果暂存在 NAND 内部的数据寄存结构中。
随后,这些数据才会返回 SSD Controller。
但是,返回 Controller 的数据并不代表读取已经完成。
因为 NAND 本身并不是一个绝对可靠的存储介质。
四、第二种情况:最新数据还在 Write Buffer
第二种情况更加能体现 SSD 的复杂性。
假设 Host 执行了一次写入:
写入 LBA 1000 的数据。
SSD 收到数据以后,并不会一定立即把它 Program 到 NAND。
为了提高性能,SSD 通常会先把数据放入内部缓存。
此时:
最新的数据在 Write Buffer 中。
而 NAND 中可能还保存着这个 LBA 之前的数据。
如果这时候 Host 又读取 LBA 1000,会发生什么?
SSD 不能直接去 NAND。
因为 NAND 中的数据可能已经不是最新版本。
所以,L2P 查询后发现:
这个 LBA 最新的数据位于 Write Buffer。
那么 SSD 会直接从缓存中获取数据,并返回给 Host。
这也是为什么:
SSD 的一次读取,并不一定会触发 NAND Read。
很多情况下,数据可能直接来自 SSD 内部缓存。
五、第三种情况:这个 LBA 没有有效数据
还有一种情况:
Host 请求读取一个从未写入过的位置。
例如:
一个新建的逻辑地址区域。
或者:
之前的数据已经被释放,不再拥有有效映射。
此时 FTL 查询 L2P 后发现:
当前没有有效数据。
那么 SSD 没有必要访问 NAND。
因为 NAND 中不存在需要返回给 Host 的有效用户数据。
所以:
L2P Search 的结果不仅可以告诉 SSD “数据在哪里”,也可以告诉 SSD “这里有没有有效数据”。
具体返回什么内容,会根据 SSD 支持的功能和实现方式有所不同。
但对于 Read Path 来说,最重要的是:
SSD 已经知道,这次读取不需要访问 NAND。
六、只有确定数据在 NAND,SSD 才会读取 NAND
回到第一种情况。
当 FTL 确认:
数据位于 NAND。
SSD 才会根据物理地址发起 NAND Read。
从宏观角度看:
NAND Array
↓
NAND 内部完成数据感测
↓
数据进入 NAND Page Buffer
↓
返回 SSD Controller
这里有一个容易误解的地方。
很多人认为:
“从 NAND 读出来的数据,就是最终正确的数据。”
实际上并不是。
NAND 返回的是原始读取结果,其中可能存在由于存储介质特性产生的错误。
所以 SSD Controller 还需要继续处理。
七、ECC:把 NAND 原始数据恢复成正确数据
NAND Flash 在长期使用过程中,会受到很多因素影响,例如:
• Program/Erase ; • Data Retention; • Read Disturb; • Cell 间干扰。
这些因素都会导致 NAND 读取的数据出现 Bit Error。
因此,SSD 在写入数据时,会同时保存用于纠错的信息。
读取时:
NAND 返回原始数据。
Controller 使用这些校验信息进行 ECC Decode。
整个过程可以理解为:
NAND Read
↓
原始数据返回 Controller
↓
ECC Decode
↓
恢复正确用户数据
如果错误数量在 ECC 能力范围内,SSD 就可以恢复出 Host 当初写入的数据。
如果 ECC 无法纠正,就需要进入后续的数据恢复流程。
八、ECC失败以后,SSD如何继续尝试恢复数据?
如果第一次读取结果无法通过 ECC 校验,SSD 并不会马上认为数据丢失。
因为 NAND 的读取条件并不是固定不变的。
随着 NAND 老化、温度变化以及数据保存时间增加,最佳读取条件可能发生变化。
因此 SSD 可以尝试:
NAND Read
↓
ECC Decode失败
↓
Read Retry
↓
调整读取条件
↓
再次读取
↓
再次 ECC Decode
如果普通 Read Retry 仍然无法恢复,SSD 还可能使用更加复杂的恢复方式,例如 Soft Read 等。
这些内容我们在之前的文章中已经介绍过。
它们并不是独立存在的技术,而都是 Read Path 中为了提高数据可靠性的环节。
九、数据最终如何返回 Host?
经过前面的流程以后,SSD终于得到了正确的数据。
接下来,SSD Controller 根据 Read Command 中提供的信息,通过 DMA 将数据传输到 Host Memory。
整个过程可以总结为:
Correct Data
↓
SSD Controller Buffer
↓
DMA
↓
Host Memory
此时,Host 才真正拿到了自己最开始请求的数据。
十、重新看一遍完整 Read Path
现在,把整个流程串起来。
一条 Read Command 进入 SSD 后,并不是简单地:
LBA → NAND → 返回数据。
真正的过程是:
Host Read Command
↓
FTL 获取 LBA
↓
L2P Search:最新数据在哪里?
↓数据在 Write Buffer
→ 直接返回数据不存在有效映射
→ 按规则处理数据在 NAND
→ NAND Read
→ ECC Decode
→ 返回 Host
如果用一句话总结 Read Path:
SSD读取数据,并不是简单地去 NAND 找数据,而是先找到这个 LBA 当前最新的数据位置,再通过一系列可靠性处理,把正确的数据交还给 Host。
这也正好对应了 Write Path。
Write Path 解决的问题是:
Host 给我的数据,应该放在哪里?
Read Path 解决的问题是:
Host 要的数据,我应该去哪里找到?
一个负责把数据写进去。
一个负责把数据找回来。
这两条路径连接起来,才构成了 SSD 最核心的数据生命周期。
谢谢你读我的文章
支付宝
微信