全部博文(327)
分类: LINUX
2010-08-27 18:21:49
最近有一个项目需要在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等纠错措施。
由于传统的文件系统不是为Flash而设计的,如果直接在Flash上运行会很快使Flash局部老化而丢失数据,或崩溃。另外由于FLASH的块比较大,如果直接映射成块设备的话,空间利用率低。FTL的作用就是解决负载均衡与提供适合传统文件系统的,大小合适(如512字节)的块设备。
很多刚接触Linux MTD系统的人,很容易把mtd和FTL搞混了。mtd设备是一个字符设备(或者叫"flash"设备),它提供了访问FLASH存储器的通用界面。MTD还带了一个简单的模拟块设备:mtdblock。虽然mtdblock提供了大小合适的块,但它不具备负载均衡的能力,也不具备坏块管理的能力。我们可以通过mtdblock设备安装传统文件系统(如FAT文件系统),但是如果在上面进行写入操作的话,会迅速磨损FLASH。(如果安装的是一个只读文件系统,则没有问题)
许多Flash-aware-filesystem,如JFFS和YAFFS,通过mtd来访问FLASH;而要在FLASH上使用传统文件系统,一个可靠的FTL是一定需要的。
Linux内核的MTD子系统中带有FTL和NFTL,但它们实际上不是通用的FTL,有诸多的限制。更要命的是它的许可证:
在嵌入式系统中,FLASH通常是直接与CPU通过内存总线通讯,而不是PCMCIA接口,因此这个许可证就使得通过非PCMCIA接口使用FTL有可能侵权。
也许是因为这个原因,FTL和NFTL代码中并不提供对非DiskOnChip(PCMCIA) 设备的支持。
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.