2019年1月14日 星期一

Linux UBI子系統設計初探


Source https://www.cnblogs.com/wahaha02/p/4814698.html

問題領域
flash存放裝置存在如下特點:
·         存在壞塊
·         使用壽命較短
·         存儲介質不穩定
·         讀寫速度慢
·         不支援隨機訪問(nand
·         只能通過擦除將0改成1
·         最小讀寫單位為page or sub-page
·         便宜
針對flash設備的特點,flash檔案系統的核心功能需求和品質需求需包括如下這幾個方面:
·         讀寫
·         性能
·         可靠性
·         持久性
針對這些需求,可分析得出flash檔案系統需要滿足如下屬性要求:
·         資料保護
·         壞塊管理
·         垃圾回收
·         磨損均衡
·         分區管理
·         文件管理
·         性能優化
ubifs檔案系統中,這7條屬性中的資料保護、壞塊管理、垃圾回收、磨損均衡、分區管理等需求由ubi子系統實現,也是此次分析的重點。

架構模型
ubiubifs的一個子系統,其位於MTD之上,ubifs之下,如圖所示。

ubi子系統內部又細分多個模組(如下),每個模組後面逐個展開介紹。

其設計架構如下:

為了管理架構棧中的各個子系統,ubi在使用者態匯出多個控制介面,以便於對模型進行控制管理。
/dev/mtd0
  mtd物件,對mtd設備操作的實體
/dev/ubi_ctrl
  ubi控制物件,用於ubimtd的映射與解映射(attach and detach)
/dev/ubi0
  ubi 抽象層物件,對ubi操作的實體
/dev/ubi0_0
  ubi volume物件,對ubi volume操作的實體
UBI資料模型
 資料是建模和設計的核心,UBI2個頂層資料物件:ubi_attach_infoubi_volume_desc。其資料關係模型如下:


UBI資料持久化設計
因為磨損均衡、邏輯塊管理、分卷管理等需要,ubi自身支援這些功能的中繼資料需要持久化存儲,如:塊擦除次數、LEB/PEB映射、volume/LEB映射、分卷表、fastmap等資料,具體的資料結構有:
OOB
ubi_ec_hdr - UBI erase counter header
ubi_vid_hdr - on-flash UBI volume identifier header
ubi_vtbl_record - a record in the volume table.
ubi_fm_sb - UBI fastmap super block
ubi_fm_hdr - header of the fastmap data set
ubi_fm_scan_pool - Fastmap pool PEBs to be scanned while attaching
ubi_fm_ec - stores the erase counter of a PEB
ubi_fm_volhdr - Fastmap volume header
ubi_fm_eba - denotes an association beween a PEB and LEB
其中ubi_ec_hdrubi_vid_hdrubi_vtbl_recordOOB的資料結構定義、存儲位置和資料示例如下:
ubi_ec_hdr,存放在每個PEB1MB)page 0,每個page8K)一段OOB0x1C0)
ubi_vid_hdr,對於已分配到volume中的PEBvid hdr存放在PEB page 1(8K) or page 0 sub-page 1(2K)
ubi_vtbl_record,作為UBI_LAYOUT_VOLUME_ID的資料,LEB0LEB1相互備份,從PEBpage 2 開始存放。

每個PEB塊有個OOB區,OOB前面幾個位元組是壞塊標記(橙色標示),尾部一段位元組為ECC資料(綠色標示),如果中間有多餘位元組,則閒置不用(黃色標示)。各段的大小依賴於頁格式、ecc位數、各flash廠商定義的壞塊標記形式而定。

UBI attaching子系統
attaching子系統的核心任務就是創建並初始化ubi設備,其核心資料是ubi_attch_info物件,對照上一節的資料模型,這個過程包括創建ubi_ainf_volume物件;掃描所有PEBec headervid header,讀取OOB區壞塊標記,統計壞塊個數,初始化ai->bad_peb_count;如果attachingPEBec header為無效值,此時會有平均的ec值初始化其ec header;如果發現2PEB具有相同的lnum,選用seqnum大的PEBseqnum小的PEB放入 ai->erase鏈表。
校驗每個塊的ec headervid headerdata,並對其錯誤類型進行分類,對可糾正的錯誤,放入ai->erase表,對於無法糾正的錯誤,放入ai->corrai->alien表;對於沒有錯誤的塊,放入ai->free表。具體分類規則請參照下表。
錯誤類型:
·         UBI_IO_FF: 0xFF
·         UBI_IO_FF_BITFLIPS: 0xFF,但是有可糾正的ECC錯誤;
·         UBI_IO_BAD_HDR: ECVID頭損壞(magic number錯誤或者CRC錯誤)
·         UBI_IO_BAD_HDR_EBADMSG: 由不可糾正的ECC錯誤導致的ECVID頭損壞
·         UBI_IO_BITFLIPS: 有可糾正的ECC錯誤;
PEB分類:
·         free:正常塊;
·         erase:擦除塊,需要進行擦除;
·         corr:損壞塊,不再參與磨損均衡;
·         alien:異常塊,不再參與磨損均衡;
·         scrub:擦洗塊,資料搬移到正常快上,並對其進行擦除,確認沒有問題;
·         torture:拷問塊,資料搬移到正常快上,並對其反復多次讀寫擦除,確認沒有問題;

UBI EBA子系統
 EBA子系統主要提供如下功能:
·         LEB/PEB的映射表管理:上層只看到LEB,不再關心塊的讀寫錯誤處理、替換等細節;
·         LEBsequence counter管理:seq counter主要是為了標記順序,解決LEB/PEB的映射衝突;
·         LEB訪問介面封裝:如read, write, copy, check, unmap, atomic change等;
·         LEB訪問保護:每一個LEB的併發訪問都由讀寫信號量鎖rwsem進行保護;
EBA提供了2種寫方式:ubi_eba_write_lebubi_eba_atomic_leb_changeubi_eba_write_leb用於對塊的writeubi_eba_atomic_leb_change用於對塊的modify或者appendubi_eba_write_leb寫後會做讀校驗,如果有-EIO錯誤,將老PEB上的資料移動到新的PEB上,並將新資料也寫到新的PEB中,對老PEB進行tortureubi_eba_atomic_leb_change為了避免破壞已有資料,採用異地更新的方式來實現原子寫,並加一個ubi->alc_mutex來進行序列化保護,其具體流程如下:
1.     讀取leb資料(ubifs內完成)
2.     檢查寫資料長度是否為0,為0時,unmap leb
3.     分配初始化vid_hdr
4.     分配新的pebubi_wl_get_peb
5.     peb中寫入vid_hdr
6.     peb中寫入老leb資料+新增資料
7.     回收老的pebubi_wl_put_peb
8.     更新leb mapvol->eba_tbl

UBI wear-leveling子系統
磨損均衡是UBI的核心功能之一,負責管理PEB的分配、回收、擦除、scrub、磨損均衡等。其中scrub、擦除, 磨損均衡功能由UBI後臺執行緒進行非同步調度管理。
UBI磨損均衡基於PEB的擦除次數實現,採用靜態磨損均衡策略。對於靜態磨損均衡,建立在如下假設上:擦除次數(ec)少的PEB比擦除次數多的PEB穩定,將ec大的PEB資料交換到ec小的PEB上,達到磨損均衡的目的。
PEB的分配、回收、擦除、scrub都會觸發磨損均衡檢查。為了避免頻繁磨損均衡,進一步加重磨損情況,磨損均衡的觸發頻率通過UBI_WL_THRESHOLD控制,UBI_WL_THRESHOLD值不宜太小。但這種策略也存在一些問題,為了避免極端情況下對某些特定塊反復擦除,通過磨損均衡_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD)來控制挑選最壞的free PEB範圍。
根據attaching時的PEB分類,磨損均衡模組初始化時,啟動對erase塊的擦除,對torture塊的拷問,構建磨損均衡塊紅黑樹,scrub紅黑樹等。PEB的分配通過ubi_wl_get_peb介面實現,分配具有平均擦除次數的free PEBPEB的回收通過ubi_wl_put_peb介面實現,回收後調度erase_worker擦除。

UBI IO子系統
IO子系統主要為上層模組提供統一的讀寫介面,這主要包含:
PEB讀寫介面的統一封裝,包括mtd read/write 封裝;參數檢查;讀寫檢查(read io check, write verify check, 通過ubi->dbg.chk_io控制,默認沒有使能。
ubi ec/vid hdr的讀寫介面的統一封裝,包括有效性驗證;支援非對齊存儲;支持vid存於sub-page

UBI fastmap子系統
縮短ubi初始化(attach)時間,使attach時間複雜度是個常數,不隨PEB個數成線性增長。(Experimental feature,產品中暫未使能,未研究)

參考資料
Linux kernel 3.14-rc6 source code
http://en.wikipedia.org/wiki/Wear_leveling
www.linux-mtd.infradead.org

沒有留言: