FAT over NAND flash

引子

最近有一個項目需要在NAND FLASH裸片上建立文件系統,由於必須通過USB給Windows訪問,所以FAT是唯一的選擇。由於FAT不是爲Flash設計,因此需要透過FTL(Flash Translation Layer)來訪問NAND FLASH。

 

原本以爲FTL的支持在嵌入式Linux下是很成熟的,因爲在編譯內核時,MTD下就有可選的FTL和NFTL可供選擇,但是dig進去才發現原來事情比想象的複雜。

 

首先科普一下:

1) FLASH的擦除循環壽命比較有限。對於NOR FLASH大約100萬次,對於NAND FLASH大約10萬次(SLC)或幾萬次(MLC)。

 

2)NAND FLASH出廠時可能存在壞塊,而且在使用中有可能不斷地產生新的壞塊。所謂“壞塊”其實通常從僅有一個bit(SLC)或數個bits(MLC)出錯開始。一般可以通過ECC,BCH或RS算法還原數據來大幅度提升NAND FLASH的壽命(10倍左右)。

 

3)可擦除塊: FLASH與磁盤的一個重要區別,就是FLASH在寫入之前必須先進行擦除。經過擦除後的FLASH,內容全部爲‘1’。寫入的過程就是把一些'1'的比特改成'0'。對於FLASH存儲器,內容爲'0'的比特數據需要擦除爲‘1’後才能再次寫入(變爲'0')。對於NAND FLASH還更復雜些,NAND FLASH的存儲單位被組織成頁,頁的大小一般爲512/1024/2048/4096字節,同一個頁的寫入次數有限制(稱爲'寫入區',‘寫入區’的個數就是頁寫入的最大次數),通常爲2次。FLASH的可擦除塊一般在數十k到幾百k。

 

4)FTL: FLASH傳輸層軟件,有兩個作用, 一是對FLASH寫入進行負載均衡,由此提升FLASH的壽命;二是提供類似傳統磁盤大小的塊(512 bytes)訪問界面,以便可以在FLASH上使用爲磁盤存儲介質而設計的文件系統,如FAT。

 

5)NFTL:適合NAND FLASH的FTL。與NOR FLASH相比,增加了壞塊管理,頁管理,以及ECC等糾錯措施。

 

 

爲什麼要FTL?

由於傳統的文件系統不是爲Flash而設計的,如果直接在Flash上運行會很快使Flash局部老化而丟失數據,或崩潰。另外由於FLASH的塊比較大,如果直接映射成塊設備的話,空間利用率低。

 

FTL的作用就是解決負載均衡與提供適合傳統文件系統的,大小合適(如512字節)的塊設備。

 

MTD

很多剛接觸Linux MTD系統的人,很容易把mtd和FTL搞混了。mtd設備是一個字符設備(或者叫"flash"設備),它提供了訪問FLASH存儲器的通用界面。MTD還帶了一個簡單的模擬塊設備:mtdblock。雖然mtdblock提供了大小合適的塊,但它不具備負載均衡的能力,也不具備壞塊管理的能力。我們可以通過mtdblock設備安裝傳統文件系統(如FAT文件系統),但是如果在上面進行寫入操作的話,會迅速磨損FLASH。(如果安裝的是一個只讀文件系統,則沒有問題)

 

許多Flash-aware-filesystem,如JFFS和YAFFS,通過mtd來訪問FLASH;而要在FLASH上使用傳統文件系統,一個可靠的FTL是一定需要的。

 

Linux下的FTL和NFTL

Linux內核的MTD子系統中帶有FTL和NFTL,但它們實際上不是通用的FTL,有諸多的限制。更要命的是它的許可證:

寫道
LEGAL NOTE: The FTL format is patented by M-Systems. They have
granted a license for its use with PCMCIA devices:

"M-Systems grants a royalty-free, non-exclusive license under
any presently existing M-Systems intellectual property rights
necessary for the design and development of FTL-compatible
drivers, file systems and utilities using the data formats with
PCMCIA PC Cards as described in the PCMCIA Flash Translation
Layer (FTL) Specification."

Use of the FTL format for non-PCMCIA applications may be an
infringement of these patents. For additional information,
contact M-Systems (http://www.m-sys.com) directly.

 

在嵌入式系統中,FLASH通常是直接與CPU通過內存總線通訊,而不是PCMCIA接口,因此這個許可證就使得通過非PCMCIA接口使用FTL有可能侵權。

 

也許是因爲這個原因,FTL和NFTL代碼中並不提供對非DiskOnChip(PCMCIA) 設備的支持。

 

UBI

UBI原本是爲了實現更好的負載均衡(全片負載均衡)和更好的擴展性。UBI架構在MTD之上,它要完成的工作就是實現透明的負載均衡和壞塊管理,讓上層的文件系統從這兩部分繁重的工作中釋放出來。

 

看起來與FTL很接近了,只可惜它提供的不是我們需要的塊設備。與MTD一樣,它提供的界面是"flash"設備,供flash-aware-filesystem使用。例如可以在UBI之上使用JFFS2(據說可以獲得更好的負載均衡特性),或者專門設計的UBIFS。

 

UBI是由Nokia開發人員發起的項目,開發者聲稱基於UBI建立FTL很容易...容易到他們都不屑於去實現它了。我們悲哀地發現,雖然UBI項目已經有好幾年了,也進入main stream內核了,卻還看不到基於它的FTL。

 

其實並不是沒有人需要FTL,在google上搜一下就會發現有大把的人在尋找在Linux下可用的FTL,最終得到的答案要麼是“沒有”,要麼是“基於UBI很容易實現FTL”云云。

 

其實從技術上講基於UBI實現FTL確實是省了很多事。事實上確實有人做過,也把patch發到UBI項目,但被拒了,好像是由於幾個很小的問題,包括代碼格式等等。其實那些UBI傢伙根本不想(或這不屑?)去實現FTL界面,他們的邏輯是:FTL是給legacy filesystem用的,既然有更好的flash-aware-filesystem,爲什麼不用?FAT?不是應該扔垃圾堆了麼?....他們在無視某些東西。

 

醜陋的妥協方案

項目不能等UBI傢伙們實現FTL,而自己實現時間上不允許。只能用醜陋的妥協方案:

 

1)在NAND上安裝YAFFS2(over mtd)

2)在YAFFS2分區上創建一個文件,attach一個loop device到這個文件。

3)對這個loop device運行fdisk創建分區,格式化等。

4)重新attach loop device到這個文件(從分區偏移量處開始)。

5)mount FAT到這個loop device上進行讀寫。

6)要通過USB訪問時,指定usb mass storage模塊的file參數到此文件上即可。

 

這些工作通過幾個簡單的腳本即可完成。

 

這個方案的優點是借用YAFFS2實現了負載均衡,缺點是透過loop device來安裝FAT文件系統性能差。實際測試,通過USB傳輸大約僅300KB/s (ARM9, 200MHZ, USB 2.0 full speed)。而如果通過mtdblock而不是loop mount的話,可以達到700KB/s.

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