Linux UBI子系統設計初探


問題領域

 flash存儲設備存在如下特點:

  • 存在壞塊
  • 使用壽命較短
  • 存儲介質不穩定
  • 讀寫速度慢
  • 不支持隨機訪問(nand)
  • 只能通過擦除將0改成1
  • 最小讀寫單位為page or sub-page
  • 便宜

針對flash設備的特點,flash文件系統的核心功能需求和質量需求需包括如下這幾個方面:

  • 讀寫
  • 性能
  • 可靠性
  • 持久性

針對這些需求,可分析得出flash文件系統需要滿足如下屬性要求:

  • 數據保護
  • 壞塊管理
  • 垃圾回收
  • 磨損均衡
  • 分區管理
  • 文件管理
  • 性能優化

在ubifs文件系統中,這7條屬性中的數據保護、壞塊管理、垃圾回收、磨損均衡、分區管理等需求由ubi子系統實現,也是此次分析的重點。

架構模型

 ubi是ubifs的一個子系統,其位於MTD之上,ubifs之下,如圖所示。

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

其設計架構如下:

為了管理架構棧中的各個子系統,ubi在用戶態導出多個控制接口,以便於對模型進行控制管理。
/dev/mtd0:
  mtd對象,對mtd設備操作的實體
/dev/ubi_ctrl:
  ubi控制對象,用於ubi與mtd的映射與解映射(attach and detach)
/dev/ubi0:
  ubi 抽象層對象,對ubi操作的實體
/dev/ubi0_0:
  ubi volume對象,對ubi volume操作的實體

UBI數據模型

 數據是建模和設計的核心,UBI有2個頂層數據對象:ubi_attach_info和ubi_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_hdr、ubi_vid_hdr、ubi_vtbl_record、OOB的數據結構定義、存儲位置和數據示例如下:

ubi_ec_hdr,存放在每個PEB(1MB)的page 0,每個page(8K)一段OOB(0x1C0);

ubi_vid_hdr,對於已分配到volume中的PEB,vid hdr存放在PEB page 1(8K) or page 0 sub-page 1(2K);

ubi_vtbl_record,作為UBI_LAYOUT_VOLUME_ID的數據,LEB0,LEB1相互備份,從PEB的page 2 開始存放。

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

UBI attaching子系統

attaching子系統的核心任務就是創建並初始化ubi設備,其核心數據是ubi_attch_info對象,對照上一節的數據模型,這個過程包括創建ubi_ainf_volume對象;掃描所有PEB的ec header和vid header,讀取OOB區壞塊標記,統計壞塊個數,初始化ai->bad_peb_count;如果attaching時PEB的ec header為無效值,此時會有平均的ec值初始化其ec header;如果發現2個PEB具有相同的lnum,選用seqnum大的PEB,seqnum小的PEB放入 ai->erase鏈表。

校驗每個塊的ec header、vid header和data,並對其錯誤類型進行分類,對可糾正的錯誤,放入ai->erase表,對於無法糾正的錯誤,放入ai->corr或ai->alien表;對於沒有錯誤的塊,放入ai->free表。具體分類規則請參照下表。

錯誤類型:

  • UBI_IO_FF: 全0xFF;
  • UBI_IO_FF_BITFLIPS: 全0xFF,但是有可糾正的ECC錯誤;
  • UBI_IO_BAD_HDR: EC或VID頭損壞(如magic number錯誤或者CRC錯誤)
  • UBI_IO_BAD_HDR_EBADMSG: 由不可糾正的ECC錯誤導致的EC或VID頭損壞
  • UBI_IO_BITFLIPS: 有可糾正的ECC錯誤;

PEB分類:

  • free:正常塊;
  • erase:擦除塊,需要進行擦除;
  • corr:損壞塊,不再參與磨損均衡;
  • alien:異常塊,不再參與磨損均衡;
  • scrub:擦洗塊,數據搬移到正常快上,並對其進行擦除,確認沒有問題;
  • torture:拷問塊,數據搬移到正常快上,並對其反復多次讀寫擦除,確認沒有問題;

 

UBI EBA子系統

 EBA子系統主要提供如下功能:

  • LEB/PEB的映射表管理:上層只看到LEB,不再關心塊的讀寫錯誤處理、替換等細節;
  • LEB的sequence counter管理:seq counter主要是為了標記順序,解決LEB/PEB的映射沖突;
  • LEB訪問接口封裝:如read, write, copy, check, unmap, atomic change等;
  • LEB訪問保護:每一個LEB的並發訪問都由讀寫信號量鎖rwsem進行保護;

EBA提供了2種寫方式:ubi_eba_write_leb和ubi_eba_atomic_leb_change。ubi_eba_write_leb用於對塊的write,ubi_eba_atomic_leb_change用於對塊的modify或者append。ubi_eba_write_leb寫后會做讀校驗,如果有-EIO錯誤,將老PEB上的數據移動到新的PEB上,並將新數據也寫到新的PEB中,對老PEB進行torture。ubi_eba_atomic_leb_change為了避免破壞已有數據,采用異地更新的方式來實現原子寫,並加一個ubi->alc_mutex來進行串行化保護,其具體流程如下:

  1. 讀取leb數據(ubifs內完成)
  2. 檢查寫數據長度是否為0,為0時,unmap leb
  3. 分配初始化vid_hdr
  4. 分配新的peb(ubi_wl_get_peb)
  5. 新peb中寫入vid_hdr
  6. 新peb中寫入老leb數據+新增數據
  7. 回收老的peb(ubi_wl_put_peb)
  8. 更新leb map(vol->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 PEB。PEB的回收通過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

 

--EOF--


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM