ftl
有非flash的私有存储空间吗?</p
>
如果没有,如何ftl
在避免wear leveling
.
其实我不知道里面有没有超级块ftl
,但是如果要定位映射数据和物理地址变化频繁的不可用块,可能需要某个物理地址。这个物理地址上的内容肯定会经常变化,如何避免这个物理地址的磨损均衡呢?
ftl
有非flash的私有存储空间吗?</p
>
如果没有,如何ftl
在避免wear leveling
.
其实我不知道里面有没有超级块ftl
,但是如果要定位映射数据和物理地址变化频繁的不可用块,可能需要某个物理地址。这个物理地址上的内容肯定会经常变化,如何避免这个物理地址的磨损均衡呢?
这个问题有很多可能的解决方案,并且它与驱动器用于存储其数据的数据表示非常交织在一起,所以我相信它会因驱动器/制造商而有很大不同。我将概述一种可行的通用方法。
假设您设计了一个 FTL,它维护几个固定大小、仅附加的“日志”,为简单起见,我们总是有一个所有写入都附加到的“活动”日志。如果用户发出随机写入,则活动日志中 LBA 的顺序也将是随机的。当活动日志填满分配给它的所有空间时,它会“冻结”,我们将活动日志切换到闪存中其他地方的一些空日志。随着冻结日志中的数据变得陈旧,我们最终需要通过在擦除原始数据之前将任何仍然引用的块复制到不同的日志来对其进行垃圾收集,以便可以将其重新用于新的写入。
现在,对于每次写入日志,到目前为止,我们界面中的任何内容都不需要块正好是 4KiB(或其他),因此您可以在数据上附加一个小标题,告诉您它的 LBA 是什么,也许还有一些其他元数据-- 写入序列号,以便您可以判断它是否是块的最新副本,并且可能是用于读取完整性检查的校验和。写入完成后,您会使用已更新 LBA 的新位置(SSD 内的 RAM,显然不是计算机主 CPU 的 RAM)来更新映射的 RAM 内副本。
如果 FTL 崩溃或断电,您可以通过读取所有日志中的所有标头来重建映射。缺点是扫描日志会扩展O(number of logs * number of blocks per log)
,因此您可以以某种方式对其进行优化:
O(number of logs * (log_2(number of blocks per log) + number of blocks that need to be scanned))
到目前为止,这大大降低了您需要编写地图的频率,但是对于使用寿命很长的驱动器而言,将其覆盖到固定位置仍然可能过于频繁。为了解决这个问题,我们必须在我们写地图的地方循环:
O(X * log_2(number of maps per log) + runtime to scan the other logs if unclean shutdown)
。另一个方面是完整的地图刷新可能很昂贵,如果它干扰用户 IO 的性能,这会增加尾部延迟——允许增量更新会更好吗?那时您开始考虑使用诸如日志结构合并 (LSM) 树之类的东西来存储您的地图,这样每次增量写入都非常小,您可以分摊完整的地图写入成本。
显然,这个解释遗漏了许多微小的细节,但希望这足以让你开始。:-)