Linux ubi子系统原理分析

本文思惟导图总纲:
思惟导图总纲html

综述

关于ubi子系统,早已有比较正式的介绍,也提供很是形象的介绍ubi子系统ppt
国内的前辈 alloysystem 不辞辛劳为咱们提供了部分正式介绍的中文译文,以及找不到原文的转载译文linux

感谢这些资料让我迅速入门ubi,进而整理出这博文算法

此博文是对上文的总结以及中文译文的补充ide

在阅读本文以前,建议先学习PPT中文译文函数

概念对比

UBI Vs. MTD

UBI层次

上图很是形象地描述了从Flash到UBIFS的各个层次。从上图咱们发现,MTD子系统在实际的Flash驱动之上 ,而UBI子系统则在MTD子系统之上。工具

要对比UBI和MTD的概念,咱们不妨问本身一个问题,UBI和MTD两个不一样的层次的"使命"分别是什么?学习

Flash驱动直接操做设备,而MTD在Flash驱动之上,向上呈现统一的操做接口。因此MTD的"使命"是 屏蔽不一样Flash的操做差别,向上提供统一的操做接口ui

UBI基于MTD,那么UBI的目的是什么呢? 在MTD上实现nand特性的管理逻辑,向上屏蔽nand的特性.net

nand有什么特性呢?
(下文描述的 Nand驱动,是广义上的操做Nand的集合,包括fs/ubi/mtd的层次,而非纯粹的nand驱动)unix

1. 操做最小单元为页(Page)/块(Block)
    Nand不一样于Nor,Nor能够以字节为单位操做Flash,但Nand的读写最小单元是页,擦除最小单元是块。
    对常见的1Gbit的spinand而言,其页大小2KBytes,块大小是128K,表示一个块有64个页。
2. 擦除寿命限制
    Nand的物理性质决定了其每一个块都有擦除寿命的限制,SLC约10W次,MLC约5000次,TLC约1000次。
    所以,Nand驱动必需要作到磨损平衡。
    所谓磨损平衡,就是尽量均衡使用每个块,既不让一个块太大压力,也不让一个块太过空闲。
3. 位翻转(bit-flips)
    Nand的物理性质使其可能会在使用、保存过程当中出现位翻转的现象。
    例如,原始数据为0xFFFC,在存储过程当中Flash的数据却变成了0xFFFF。
    因此要不在nand内部,要不在nand控制器都会存在ecc校订模块,在位翻转后校订。
    然而,ecc并非万能的,其校订能力有限,因此驱动必须在位翻转数量进一步变多以前把数据搬移到其余块。
    萌新可能会有疑问,ecc都已经校订了为何还要搬移?由于ecc校订的是从Flash中读到内存中的数据,
    而不是Flash自己存储的数据,换句话说,此时Flash中的数据依然是错的,若是不搬移,随着翻转的位数量积累,
    ecc就校订不了了,此时就至关于永久丢失正确数据了。
4. 存在坏块(Bad Block)
    制做工艺和Nand自己的物理性质,致使在出厂和正常使用过程当中都会产生坏块。
    所谓坏块,就是说这个块已经损坏,不能再用于存储数据,所以Nand驱动须要能自动跳过坏块。

关于SLC/MLC/TLC的比较,可参考这篇博客

UBI Vs. UBIFS

若是说UBI在MTD之上,在FS之下的中间层,用于抽象MTD屏蔽nand差别,那么ubifs就是正儿八经的文件系统。
ubifs是基于UBI子系统的文件系统,实现文件系统该有的全部基本功能,例如文件的实现,例如日志的实现。

这里须要特别注意的是,ubifs跟jffs/yaffs相比,并不包含nand特性的管理,而是交由ubi来实现。

UBI Vs. Block Layer

Block Layer是适用于常见块设备的通用块层,其特有的概念有bio、request、电梯算法等,其典型的设备有磁盘、SSD、mmc等。
而ubi基于mtd,虽然能模拟块设备,从本质上来说其并非块设备。跟踪UBIFS的IO操做,发现其IO操做并不通过通用块设备层。

UBI Vs. FTL

FTL(Flash Translation Layer)是一个"黑盒子",其跟UBI很是像,都是对nand特性进行封装。

按个人理解,UBI跟FTL的目标不一样,致使其实现上会有差别。UBI屏蔽nand特性是为了对接UBIFS,而FTL则是为了对接Block Layer。例如MMC其实也是封装起来的Nand,只不过在MMC内部实现了FTL,通过FTL的转换就能以块设备层的方法直接操做Nand,就能在mmc上格式化常见的块文件系统,例如EXT、VFAT等。

UBI Volume Vs. UBI Device

在UBI中还有两个概念,分别是UBI卷(UBI Volume)和UBI设备(UBI Device)。这两个概念,咱们能够这么理解:

UBI设备 至关于 磁盘设备(sda,mmcblk0)
UBI卷 至关于 磁盘上对应分区(sda1,mmcblk0p1)

换句话说,UBI设备是在MTD设备上建立出来的设备,而UBI卷则是从UBI设备上划分出来的分区, 从设备节点名(ubi0)和卷名(ubi0_3)能够看出端倪。

上面的描述是为了方便理解UBI卷和UBI设备,实际上UBI卷和分区的概念之间仍是有差异的。

LEB Vs. PEB

在UBI子系统中,还有LEB和PEB的概念:

LEB指Logical Erase Block,即逻辑擦除块,简称逻辑块,表示逻辑卷中的一个块
PEB指Physical Erase Block,即物理擦除块,简称物理块,表示物理Nand中的一个块

为何要划分逻辑块和物理块?从PPT中咱们能够发现,物理块和逻辑块存在动态映射关系,且因为UBI头的存在,逻辑块通常会比物理块小2个页。

UBI子系统扮演的角色及其做用

UBI子系统就是ubifs与mtd之间的中间层,其向下链接MTD设备,实现nand特性的管理逻辑,向上呈现无坏块的卷。

因此UBI子系统的做用,主要包括两点:

1. 屏蔽nand特性(坏块管理、磨损平衡、位翻转)
2. UBI卷的实现

UBI卷的逻辑擦除块(LEB)与物理擦除块(PEB)之间是动态映射的,详细能够看PPT

UBI相关的工具

ubi的工具集成在包mtd-utils中,分别有如下工具及其做用

工具 做用
ubinfo 提供ubi设备和卷的信息
ubiattach 连接MTD设备到UBI而且建立相应的UBI设备
ubidetach ubiattach相反的操做,将MTD设备从UBI设备上去连接
ubimkvol 从UBI设备上建立UBI卷
ubirmvol 从UBI设备上删除UBI卷
ubiblock 管理UBI卷上的block
ubiupdatevol 更新卷,例如OTA直接更新某个分区镜像
ubicrc32 使用与ubi相同的基数计算文件的crc32
ubinize 制做UBI镜像
ubiformat 格式化空的Flash设备,擦除Flash,保存擦除计数,写入UBI镜像到Flash
mtdinfo 报告从系统中找到的UBI设备的信息

UBI头部

UBI子系统须要往每一个物理块的开头写入两个关键数据,这两个关键数据就叫作UBI的头部。

这两个数据分别是 此物理块擦除次数头此物理块的逻辑卷标记头,也分别称为 EC头(Erase Count)VID头(Volume IDentifier)

不论是EC头仍是VID头,都是64Bytes,分别记录与Nand块的第一个页和第二个页。

以Q&A的形式介绍UBI头:

Q:为何要这两个头?  
A:前文有说道,nand每一个block有擦除寿命限制,所以须要记录擦除次数,以实现磨损平衡,所以须要EC头。此外,为了实现卷,必须记录卷的逻辑块与物理块之间的映射关系,所以须要VID头。

Q:为何不合并成1个头?
A:二者写入的时机不一致,致使两个头必须分开写入。EC头在每次擦除后,必须立刻写入以免丢失,而VID头只有在映射卷后才会写入。

Q:不论是EC头仍是VID头都是64B,为何要用2个Page?  
A:使用2个Page是对Nand来讲的。前文有说过,Nor的读写最小单元是Byte,而Nand的读写最小单元是Page,所以对Nor能够只使用64Bytes,对Nand则必须使用2个Page,就是说,即便只有64Bytes有效数据,也须要用无效数据填充满1个Page一次性写入。

Q:在记录擦除次数时掉电等,致使丢失实际擦除次数怎么办?  
A:取全部物理块的擦除次数的平均数

关于UBI头部的详细介绍,可参考连接

UBI卷表(UBI Volume Table)

UBI子系统有个对用户隐藏的特殊卷,叫层卷(layout volume),用来记录卷表。咱们能够把卷表等价于分区表,记录各个卷的信息。卷表大小为2个逻辑擦除块,每一个逻辑擦除块记录一份卷表,换句话说,UBI子系统为了保证卷表的可靠性,用2个逻辑记录2分卷标信息。

因为层卷的大小是固定的(2个逻辑块),致使能保存的卷信息受限,因此最大支持的卷数量是随着逻辑块的大小改变而改变的,但最多不超过128个。

卷表中每一个卷都保存了什么信息?

struct ubi_vtbl_record {                                                         
        __be32  reserved_pebs; //物理块数量
        __be32  alignment; //卷对齐
        __be32  data_pad;                                                        
        __u8    vol_type; //静态卷or动态卷标识
        __u8    upd_marker; //更新标识
        __be16  name_len; //卷名长度
        __u8    name[UBI_VOL_NAME_MAX+1]; //卷名
        __u8    flags; //经常使用语自动重分配大小标记
        __u8    padding[23]; //保留区域
        __be32  crc; //卷信息的CRC32校验值
} __packed;

由这个结构体咱们能够发现,卷信息是被CRC32保护着的。比较有意思的有两个成员:vol_type 和 flags

动态卷 & 静态卷

vol_type成员标记了卷的类型,在建立卷时指定,可选动态卷和静态卷。那么什么是动态卷?什么又是静态卷?

动态卷和静态卷是两种卷的类型,静态卷标记此卷只读,因而UBI子系统使用CRC32来校验保护整个卷的数据,动态卷是可读写的卷,数据的完整性由文件系统来保证。

关于静态卷和动态卷的介绍,可参考连接

更新标识

flags成员经常使用于标识是否自动重分配大小。怎么样自动充分配大小呢?在首次运行时自动resize卷,让卷大小覆盖全部未使用的逻辑块。

例如Flash大小是128M,在烧录的镜像中分配的全部卷加起来只用了100M,若是有卷被表示为autoresize,那么在首次运行时,那个卷会自动扩大,把剩余的28M囊括在内。

这个功能挺实用的,例如某个方案规划中,除去rootfs、内核等必要空间外,把剩余全部空间尽量分配给用户数据分区。
在开发过程当中加了个应用,致使rootfs卷须要更大的空间,进而须要压缩user_data卷的空间。
若是user_data空间是autoresize的,那么user_data卷的空间就会自动压缩。

再例如旧方案用的是128M的nand,后面升级为256M,即便使用相同的固件,也不用担忧多出来的128M浪费掉了,
由于user_data卷自动扩大囊括多出来的128M。

须要注意的是,只容许1个卷设置autoresize标志

关于更新标识更多的介绍,参考连接

坏块标记

咱们知道Nand的物理性质,致使在使用久以后会产生坏块,那么UBI是如何判断好块是否变成了坏块的呢?

有两个场景可能会标识坏块,分别是写失败和擦除失败。擦除失败且返回是EIO,则直接标记坏块。比较有意思的是写失败的判断逻辑。

UBI子系统有后台进程对疑似的坏块进行"严刑拷打"(torturing),有5个步骤:

1. 擦除嫌疑坏块
2. 读取擦除后的值,判断是否都是0xFF(擦除后理应全为0xFF)
3. 写入特定数据
4. 读取并校验写入的数据
5. 以不一样的数据模式重复步骤1-4

若是"严刑拷打"出问题,则标记坏块,详细的实现逻辑可参考函数torture_peb()

原文可参考连接

UBI管理开销

什么是管理开销呢?为了管理Nand的空间,实现磨损平衡、坏块管理等等功能,必须占用一部分空间来存储关键数据,就好像文件系统的元数据。管理占用的空间是不会呈现给用户空间使用的,这空间即为管理的开销。

对Nand来讲,UBI管理开销主要包含5个部分:

1. 层卷(卷表) : 占用两个物理块
2. 磨损平衡:占用一个物理块
3. 逻辑块修改原子操做:占用一个物理块
4. 坏块管理:默认每1024个块则预留20个块(内核参数可配:CONFIG_MTD_UBI_BEB_LIMIT)
5. UBI头:(物理块总数*2)个页

坏块管理预留的块数量,也能够理解为最大能容纳多少个坏块;再考虑坏块的存在,管理开销计算公式为:

UBI管理总开销 = 特性开销 + UBI头开销

其中:
坏块预留 = MAX(坏块数量,坏块管理预留数量)
特性开销 = (坏块预留 + 1个磨损平衡开销 + 1个原子操做开销 + 2个层卷开销) * 物理块大小
UBI头开销 = 2 * 页大小 * (含坏块的总块数 - 坏块预留 - 1个磨损平衡开销 + 1个原子操做开销 + 2个层卷开销)

也就是说:
UBI管理总开销 = (坏块预留 + 4) * 物理块大小 + 2 * 页大小 * (含坏块的总块数 - 坏块预留 - 4)

以128M的江波龙的FS35ND01G-S1F1 SPI Nand为例,其规格为:

总大小:128M(1Gbit)
页大小:2K bytes
块大小:128K
块数量:1024

假设是彻底无坏块的片子,其管理开销为:

UBI管理开销 = (20 + 4) * 128K + 2 * 2K * (1024 - 20 - 4) = 7072K ≈ 7M

详细参考原文连接

相关文章
相关标签/搜索