在此前NVMe 2.0协议规范介绍文章中,我们提到,NVMe 2.0不仅仅是功能的增加与完善,更多的是对整个NVMe协议家族的重新梳理,从技术到架构,应对存储技术持续发展带来的挑战。端到端数据保护(End-to-end Data Protection)作为企业级SSD的重要功能,在新的协议中也得到了一定加强,以实现对大规模存储系统的更强数据保护能力,也是NVMe 2.0“迎战未来”的举措之一。
端到端数据保护将数据的完整性保护范围从SSD内部延伸到外部链路,以防止静默错误产生——通过对逻辑块数据(Logical Block Data,通常指用户数据)添加额外的PI(Protection Information,保护信息,如CRC),使其作为数据的元数据被一同传输,主机端和NVM控制器都可以在接收到数据后,根据PI的内容对数据完整性进行校验,以确定这些数据是否真的可用。
命名空间在格式化并开启端到端数据保护功能时需要指定PI在元数据中的存放位置,要么位于元数据的开头,要么位于元数据的结尾。根据协议规定,PI需要提供逻辑块数据以及位于PI前面的元数据(如果有)的完整性保护,即:
DIF与DIX是我们非常熟悉的两种元数据传输与存放方式,在DIF中,元数据与逻辑块数据毗邻,如下图所示:
在DIX中,元数据会被存放在一个单独的缓冲区中,如下图所示:
NVMe支持的端到端数据保护类型和SBC-3(SCSI Block Commands - 3)中SCSI保护信息模型中的定义保持一致,即同为Type 1、Type 2和Type 3,在命名空间格式化时指定。
上面说完了端到端数据保护的基本概念,接下来我们看看NVMe 2.0增加了哪些内容。
我们知道,16位保护信息可以提供512B和4KiB逻辑块数据的完整性保护。NVMe 2.0协议规范在16位的基础上增加了32位和64位保护信息的定义,对超过4KiB的逻辑块数据提供保护能力。同时,新规范还提出,PI可以携带Storage Tag信息,用于替换部分或全部的Reference Tag,以应对更加复杂的NVM存储架构,并防止数据被误用等情况发生。
在NVMe 1.x Spec时代,PI由2字节的Guard字段、2字节的Application Tag字段和4个字节的Reference Tag字段组成,共8个字节:
STS为零时,16位保护信息结构示意(引自NVMe Spec)
NVMe 2.0允许将Reference Tag部分或全部替换为Storage Tag,其大小由STS(Storage Tag Size)字段指定。关于Reference Tag和Storage Tag的区分,后面会讲到。
STS非零时,16位保护信息结构示意(引自NVMe Spec)
32位保护信息仅适用于LBA大于或等于4KiB的命名空间,总长度增加至16个字节:
32位保护信息结构示意(引自NVMe Spec)
32位CRC采用CRC-32C(Castagnoli)算法,基于1EDC6F41h生成多项式得出。下面是32位CRC的具体示例:
64位保护信息同样仅适用于LBA大于或等于4KiB的命名空间,总长度同为16个字节:
64位保护信息结构示意(引自NVMe Spec)
64位CRC使用Rocksoft™ CRC算法生成,其大致思路为:将需要被保护的数据(逻辑块数据和需要被保护的元数据)按照一定规则转化为二进制的多项式,该多项式除以一个固定的64位生成多项式AD93D235_94C93659h,将计算结果中的余数多项式简单转换,作为Guard字段保存在PI当中。生成多项式的bit数越多,被除尽的可能性就越小,且被保护数据中任何一个bit发生翻转都会造成余数多项式的改变,借此可以更好的发现静默错误。
校验时,数据接收端基于接收到的数据进行相同的64位CRC生成操作,并将计算出来的结果和接收到的结果相比对,以检查数据是否出错。64位CRC的具体计算公式在NVMe Command Set Spec中有详细说明,感兴趣的小伙伴可以仔细阅读。
识别命名空间数据结构中的STS字段用于将保护信息中的Storage and Reference Space分离为Storage Tag和Logical Block Reference Tag。
(引自NVMe Spec)
在已经启用了端到端数据保护功能的命名空间中处理I/O命令,检查Storage Tag(如果有)和Reference Tag实际是对大小可变的LBST(Logical Block Storage Tag,逻辑块存储标记)、ELBST(Expected Logical Block Storage Tag,预期得到的逻辑块存储标记)、ILBRT(Initial Logical Block Reference Tag,初始逻辑块参考标记)和EILBRT(Expected Initial Logical Block Reference Tag,预期得到的初始逻辑块参考标记)字段进行检查。
LBST、ELBST、ILBRT和EILBRT字段的最小和最大比特数如下所示:
LBST/ELBST Size为0时,不存在Storage Tag,也无需检查LBST和ELBST;
ILBRT/EILBRT Size为0时,不存在Reference Tag,也无需检查ILBRT和EILBRT。
PRACT(Protection Information Action)决定在读命令和写命令执行期间,PI的处理方式。
写操作时,如果命名空间格式化为开启端到端数据保护功能:
读操作时,相当于NVM和主机身份互换,此时如果NVM的命名空间格式化为开启端到端数据保护功能:
融合操作,指的是把两个简单的命令融合在一起,以实现一个复杂的命令。融合操作的保护信息生成和校验,与构成该融合操作的子操作的检查和处理方式相同。
下图为Compare命令执行过程中的保护信息处理。Compare命令会同时涉及读和写命令的进行,对于从主机向NVM控制器发送的数据和保护信息的“比较”部分,控制器执行方式和常规的写命令相同;对于从NMV读取出来的数据和保护信息的“比较”部分,控制器执行方式和常规读命令相同。
(引自NVMe Spec)
在Copy命令中,数据的读和写操作同时存在,读和写操作对应的PI处理和常规读、写命令完全相同,只有校验通过,才能继续完成该Copy命令。但需要注意,Copy命令中,读和写的PRACT应保持一致,否则将以命令错误终止。
(引自NVMe Spec)
当且仅当PRACT=0时,数据的接收方需要对发送来的PI进行校验,以写入为例:
Guard Check:如果PRCHK(PI Check)中的Guard Check bit为1,则NVM控制器需要将接收到的Guard字段,与基于接收到的数据计算生成的Guard进行比较,一致,则校验通过。
Application Tag Check:PRCHK字段中的Application Tag Check bit用于指示控制器是否应该对PI中的Application Tag进行检查。如果设置为‘1’,则表示需要对Application Tag中未被“屏蔽”的位进行检查。“屏蔽”的意思是在比较过程中需要控制器忽略的某些位,不需要进行比较,这些位可以通过命令中的LBATM(Logical Block Application Tag Mask,逻辑块应用标签掩码)字段或者ELBATM(Expected Logical Block Application Tag Mask,期望的逻辑块应用标签掩码)字段来控制。
Storage Tag Check:如果PI中包含了Storage Tag且Storage Tag Check位被设置为‘1’,那么NVM控制器将会比较Storage Tag字段中的未屏蔽位和命令中的LBST(Logical Block Storage Tag,逻辑块存储标签)字段。与Application Tag类似,Storage Tag中的某些位也可以被"屏蔽",无需NVM控制器检查,方法是通过将LBSTM(Logical Block Storage Tag Mask,存储标签掩码)字段中的相应位清除为‘0’即可。
Reference Tag Check:如果Reference Tag被定义,且PRCHK中的Reference Tag检查位为1,
不同的 Application Tag 和 Reference Tag 的设定,可能会禁用 PI 的检查,而不管 PRCHK 设定如何。当命名空间格式化为 Type 1 或 Type 2 保护时,如果 Application Tag 设定为 FFFFh,则无论 PRCHK 设定如何,都会禁止 PI 的检查。
当命名空间格式化为 Type 3 保护时,如果 Application Tag 和 Reference Tag 的所有 bits 均设置为 1,则无论 PRCHK 字段处于何种状态,都会禁用 PI 的检查。
以上就是NVMe 2.0协议规范下的端到端数据保护功能介绍。可以说,它在满足我们当前数据完整性保护需求的基础上,为未来存储技术的持续发展和新技术、新架构的应用提供了新的解决方案。忆恒创源将继续紧密关注闪存技术的发展趋势和客户实际需求的变化情况,以确保我们始终处在技术的前沿,不断提供性能更加出色且可靠的解决方案,以更加优异的产品和服务,共同推动存储技术的进步和应用。