《深入浅出SSD》读书笔记——FTL优化和异常处理

在《深入浅出SSD》的读书笔记的FTL主要业务博客中,简单介绍了FTL的映射的基本原理,和垃圾回收的基本原理。在FTL介绍章节中,FTL还做了其他很多工作,我个人理解主要分为两类,一类是优化(包括寿命优化和性能优化),一类是异常处理。以下做简单介绍

寿命优化 性能优化 异常处理
TRIM TRIM 坏块管理
磨损平衡 SLC cache RD & DR
坏块管理 SLC Cache
掉电恢复

1 TRIM

在机械硬盘的场景中,删除文件只是调整对应目录的元数据。并不会涉及到擦写文件对应的数据块本身。SSD上逻辑块和物理块的映射关系还是存在的,只有在后续系统再在相同的地方写入数据时,才会知道数据无效。

这在机械硬盘场景中无伤大雅,但是在固态硬盘场景中,会导致这些数据在后续真正再写入之前,这些物理块都会被认为是有效数据,在垃圾回收时不被回收,或者仍然被认为是有效数据而被搬移,导致写放大和影响固态硬盘的寿命。只有在知道数据无效之后,才会在垃圾回收的时候被回收。

针对这个场景差异,为了优化写放大问题,ATA命令中新增了TRIM命令,在用户删除文件时,OS会发送TRIM命令给SSD,SSD就会把这些数据块标记为无效,后续SSD就可以在垃圾回收时抛弃掉这些数据,可以避免做无谓的搬移。

SCSI有对应命令叫 UNMP,NVMe里则叫 Dataset Management

TRIM命令会影响FTL中的三张表

  • FTL映射表(LBA对应物理页的位置)
  • Valid Page Bit Map (VPBM) 记录每个物理块上哪个页有有效数据。
  • Valid Page Count(VPC) 每个物理块上的有效页个数。

收到TRIM之后,固件需要实现如下处理流程。
1)清除L2P table为空地址。
2)清除VPBM上的有效页的位。
3)更新VPC的有效页个数。
4)重复上述环节,遍历每一个LBA。

下述是TRIM处理后,对GC处理流程影响。
GC处理。
1)根据新的VPC重新计算GC优先级——》
2)回收VPC最少的Block(不考虑磨损平衡)——》
3)擦除全是垃圾的Block。

2 磨损平衡

磨损平衡是让SSD的每个闪存块的磨损(擦除 )次数都保持平衡。闪存块擦写次数超过一定的值,块就不那么可靠了,就变成坏块。过多的坏块会让SSD在保质期前挂掉。

磨损平衡相关的基本划分概念

1、不同集成度的SSD擦写寿命不同。

类型 寿命
SLC 十几万
MLC 几千
TLC 一两千次/几百次

2、数据按照更新的频繁程度不同,分为两类
一类是冷数据,不经常更新的数据。比如 OS数据,只读文件
一类是热数据,更新频繁的数据,会产生很多的垃圾数据,比如一些频繁更新的文档。

3、块按照擦写次数不同分为两类。擦写次数称为EC(Erase Count)
一类是年老块,擦写次数多。
一类是年轻块,擦写次数少。

磨损平衡的相关策略

主要分为两种。
一是动态磨损平衡(DWL, dynamic wear leveling)宗旨是把热数据写到年轻的块上。写新闪存块时,选EC小的。
二是静态磨损平衡(SWL, static wear leveling)宗旨是把冷数据写到年老的块上。以腾出冷数据原来所在的EC小的闪存块,把这些闪存块用于数据写入。

静态磨损平衡的一种选择是通过GC机制来做,即回收时不选择有效数据小的闪存块,而选择冷数据所在的闪存块。但这样的负面作用就是导致冷数据和热数据会混在同一个闪存块上,因为回收的闪存块上的冷数据被搬移到了其他的闪存块上,即写入了GC时读出来的数据。而这个其他的闪存块可能是用户用来写数据的闪存块,这就导致冷数据被混到了热数据上。

但是冷数据的地址中大部分仍然还是冷数据,可能会在GC时被搬移。导致写放大。

SWL写入冷数据到——》Block1
GC写入热数据到——》Block1
Host写入热数据到——》Block1

更进一步的策略就是做冷热数据分离,在静态磨损平衡时,用专门的闪存块来存放冷数据。这个闪存块不与用户数据,或者GC写入的数据混用。这样就这个冷数据的块就不会被GC挑选为源闪存块。(故而这里要区分 常规的GC和 带了静态磨损平衡的GC)

SWL写入冷数据——》Block1
GC or Host 写入热数据——》Block2

3 坏块管理

3.1 坏块来源

坏块分为出厂坏块(Factory Bad Block)和增长坏块(Grown Bad Block)。增长坏块为擦写磨损导致的坏块。

3.2 坏块鉴别

对出厂坏块而言,出厂数据默认全部是 0xFF,坏块会被厂商打上不同的标记用作区分。

  1. 东芝的flash,坏块的第一个闪存页和最后页的第一个字节和spare区第一个字节会写上非0xff的值。用户需要查看闪存文档手册,扫描所有闪存块,建立出厂的坏块表。 p156包含了TOSHIBA建议的建立坏块表的流程。主要是遍历所有的块。
  2. 其他部分厂家的flash,坏块信息存储在闪存内部的某个位置。比如Micron,闪存内部有个叫OTP(one time programming)的区域,用于存储出厂坏块信息。

对增长坏块而言,是以读写擦的形式反映出来。比如出现UECC,擦除失败,写失败等症状,都需要加入坏块表,都是坏块出现的症状。

3.3 坏块管理策略

坏块管理主要存在两种策略,略过策略和替换机制。

  1. 略过策略(skip)跨过坏块,写下一个Block。
  2. 替换机制(replace) 发现坏块时,用好块替换。写数据到替换块上。
    • 同一个DIE上需要额外保留一部分好的闪存块,用于替换坏块。即需要预留空间。
    • 需要维护一张重映射表,如果B块是坏块,在访问B块时,需访问重映射表查询到是否有被重映射,如果有,则需要实际访问 B’ 块。

优劣比较

优点 缺点
略过 性能不稳定(并行度会发生变化)(p.s. 这里个人并不是太理解)
替换 并行度稳定 木桶效应,如果某个DIE质量较差,可用容量就受限于这个坏的DIE

4 RD & DR

4.1 RD (Read disturb 读干扰)

问题根因:

每次读,都会对其他字线 wordline 形成有点像轻微的写入,长此以往,会导致比特翻转(1->0)出错数超过ECC的纠错能力,就会导致数据丢失。

解决策略:

在读的次数低于某一个阈值之前,即比特发生翻转之前,对闪存块上的数据进行一次刷新。搬到别的闪存块上,以实现防患于未然。

解决实现:

FTL记录每个闪存块的读次数,每读一次,读次数+1。FW检测超过“读阈值",检测比特翻转数,决定是否"刷新",或者设一个更大的阈值。

这里的实现涉及到两个未定义的技术策略,如何确定阈值,以及如何刷新。

“读阈值”:阈值与闪存年龄有关,年龄(PE)越大,对RD的免疫力越低。故而一般采用动态阈值,PE越大,读阈值越小。
“刷新”:刷新存在阻塞和非阻塞两种策略,阻塞即专门处理刷新,缺点是时延长。非阻塞即刷新处理与其他操作并行,缺点是实现更为复杂。

4.2 DR(Data Retention 数据翻转)

问题根因:
根据第三章闪存特性的描述,随着时间的推移,电子会从绝缘氧化层中游离出来,造成可能的比特翻转(0->1),如果超过ECC的纠错能力,也就会导致数据丢失。
实际在用户层面的表现就是 长时间不使用,可能启动不了,或者启动很慢,因为在花大量时间做ECC的处理。

解决策略:
FTL需要对闪存空间进行实时扫描,跟RD的处理一样,进行数据刷新,避免丢失。

5 SLC cache

因为SLC 与 MLC和TLC相比有更好的读写寿命,SSD会拿SLC作为cache使用,把MLC或TLC配置为 SLC模式来访问,一般的flash都支持如此设置。SLC模式下的闪存块比MLC和TLC模式下更快更耐写。

SLC MLC TLC 性能和擦写次数对比如下

闪存类型 SLC MLC TLC
每单位bit数 1 2 3
擦写次(次) 约10W 约5000 约1000
读时间(us) ~25 ~50 ~75
写时间(us) ~300 ~600 ~900
擦除时间(us) ~1500 ~3000 ~4500

使用SLC Cache有如下优势

  1. 如上述表格所示性能更优
  2. 防止lowerPageCorruption问题导致数据损坏。
  3. 解决闪存的缺陷(MLC或TLC块没写满时ECC错误的问题)
  4. 更多的数据写入量,SLC更耐写。

实际应用中,一般消费级或移动存储,会使用SLC Cache,因为可以有更好的突发性能。企业级产品因为不追求突发性能,更追求稳态速度,故而不考虑SLC Cache。而且消费级往往没有电容保护,SLC Cache可以保证lowerpage数据不丢,企业级一般有大电容保护,可以保证断电时写入。

SLC Cache的写入策略也存在两种类型

  1. 强制SLC写入,写入数据时,必须先写入到SLC闪存块,然后GC搬到MLC或TLC块。(可以保护LowerPage数据)
  2. 非强制SLC写入,有SLC块则写,没有则直接写TLC或者MLC。优点是有更好的后期写入性能(因为强制SLC写入,在写满时,就需要一边把数据搬移到TLC或者MLC,一边往SLC写入,写满时的写入性能会受影响)

根据SLC Cache 闪存块的来源,也有三种分类。

  1. 静态SLC Cache,用一些Block专门做SLC Cache。
  2. 动态SLC Cache,所有的块都有可能当SLC Cache,SLC和TLC不分家。
  3. 两者混合,既有静态,也有动态。

6 掉电恢复

6.1 掉电恢复的类型

掉电主要区分两种,正常掉电和异常掉电。

(1)正常掉电

主机会通过命令(SATA的Idle Immediately)通知SSD。

  1. 把buffer中缓存的用户数据刷入到闪存
  2. 把映射表刷入到闪存
  3. 把闪存的块信息刷入到闪存
  4. 把SSD的其他信息刷入到闪存

(2)异常掉电

异常掉电分为两种子场景,1、因为没有收到通知时被断电;2、收到了通知,但是没来得及处理完,被断电。

6.2 掉电恢复的影响和解决方案

负面影响如下
1)缓存数据来不及写入到闪存,导致映射表丢失,或者缓存的用户数据丢失。
2)闪存特性问题,写MLC UpperPage断电,导致LowerPage数据破坏。

针对上述负面影响,FTL的设计目标如下
1)尽可能恢复用户数据。
2)让SSD经历异常掉电后还能正常工作。

实现方法如下
1)通过电容放电以维持一段时间的工作(不能100%保证)+ 异常掉电处理模块。
2)把RAM用Non-Volatile 但是速度很快的东西来替代(比如研发中的3D XPoint)

6.3 掉电处理模块的映射表恢复重建流程。
  1. 基本的重建方式。

    用户在写入数据时会写入元数据,spare空间中的元数据包括逻辑地址(LPA,LBA),时间戳(TS)等等内容。
    通过全盘扫描闪存空间,读取元数据,就可以得到La->Pa的映射关系。如果针对一笔逻辑地址,有多笔对应的物理地址(必然有其中部分物理地址是无效的),可以依赖时间戳来决定有效的物理地址。
    该流程的缺点是存在重建速度的问题,如果是TB级别,扫描所有的数据页需要花费 几分钟,甚至几十分钟的时间。

  2. 快速恢复映射表的方式

    定期地把SSD中RAM的数据和状态信息的数据写入到闪存中去,相当于做checkpoint快照。如果在快照C->D之间异常断电,从闪存中读取最新的快照信息即可。

你可能感兴趣的:(SSD技术,FTL)