Linux ubi子系統原理分析

本文思維導圖總綱:
思維導圖總綱

綜述

關於ubi子系統,早已有比較正式的介紹,也提供非常形象的介紹ubi子系統ppt
國內的前輩 alloysystem 不辭辛勞爲我們提供了部分正式介紹的中文譯文,以及找不到原文的轉載譯文

感謝這些資料讓我迅速入門ubi,進而整理出這博文

此博文是對上文的總結以及中文譯文的補充

在閱讀本文之前,建議先學習PPT中文譯文

概念對比

UBI Vs. MTD

UBI層次

上圖非常形象地描述了從Flash到UBIFS的各個層次。從上圖我們發現,MTD子系統在實際的Flash驅動之上 ,而UBI子系統則在MTD子系統之上。

要對比UBI和MTD的概念,我們不妨問自己一個問題,UBI和MTD兩個不同的層次的"使命"分別是什麼?

Flash驅動直接操作設備,而MTD在Flash驅動之上,向上呈現統一的操作接口。所以MTD的"使命"是 屏蔽不同Flash的操作差異,向上提供統一的操作接口

UBI基於MTD,那麼UBI的目的是什麼呢? 在MTD上實現nand特性的管理邏輯,向上屏蔽nand的特性

nand有什麼特性呢?
(下文描述的 Nand驅動,是廣義上的操作Nand的集合,包括fs/ubi/mtd的層次,而非純粹的nand驅動)

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

詳細參考原文鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章