JFFS2文件系统挂载过程优化的分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
JFFS2文件系统挂载过程优化的分析报告
一问题描述
在上电启动优化中发现Linux系统下挂载JFFS2文件系统耗时较长,以128M的NOR FLASH 为例,用时接近20秒。后续单板的FLASH容量为256M,时间会更长。如此长的挂载时间,会大增加系统的上电启动时间。希望能对mount功能或JFFS2文件系统做适当优化,将256M FLASH的挂载时间降到3~5秒内,优化时需要同时保证文件系统的可靠性和读写速度,要保证兼容优化前的文件系统。
root@CMM:/$ time mount -t jffs2 /dev/mtdblock1 /FLASH0
real 0m 19.83s
user 0m 0.00s
sys 0m 19.73s
二问题分析
与磁盘文件系统不同,JFFS2文件系统不在FLASH设备上存储文件系统结构信息,所有的信息都分散在各个数据实体节点之中,在挂载文件系统的时候,需扫描整个Flash设备,从中建立起文件系统在内存中的映像,系统在运行期间,就利用这些内存中的信息进行各种文件操作。这就造成了JFFS2文件系统挂载时间过长,尤其是FLASH比较大,文件比较多的情况下。
擦除块小结(erase block summary)补丁可以提高JFFS2文件系统的挂载速度,它最基本的思想就是用空间来换时间。具体来说,就是将擦除块每个节点的原数据信息写在这个擦除块最后的固定位置,当JFFS2挂载的时候,对每个擦除块只需要读取这个小结节点。同时该补丁具有一定的稳定性和兼容性。
●稳定性:
If the summary node is missing, maybe because of a system power-down before it could be written to flash, nothing bad happens - JFFS2 just falls back to scanning the whole block as it would have done before.
●兼容性:
The JFFS2 image produced by sumtool is also usable with previous kernel because the summary node is JFFS2_FEATURE_RWCOMPAT_DELETE.
(当不支持擦除块小结特性的JFFS2文件系统发现了一个属性是JFFS2_FEATURE
_RWCOMPAT_DELETE的节点时,在垃圾回收的时候,该节点可以被删除)
三原理介绍
在每个擦除块的末尾,有一个8 byte长的jffs2_sum_marker节点,该sum_marker节点记录summary node信息的存储位置,summary node可以由文件系统在写操作的过程中自动产生。在文件系统挂载的时候,jffs2_scan_eraseblock()会去读取每个擦除块的最后8byte,如果验证是有效的sum_marker节点,就会更据sum_marker中的offset偏移量去读取summary node,所有在挂载中需要的信息都存放在summary node节点中,因此就没有必要扫描整个擦除块。如果没有找到有效的sum_marker则按正当的启动方式去扫描整个擦除块。
3.1 存放在flash上的节点
●jffs2_raw_summary
struct jffs2_raw_summary
{
jint16_t magic; /* A constant magic number. */
jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */
jint32_t totlen; /* Total length of this node (inc data,etc) */
jint32_t hdr_crc; /* CRC checksum */
jint32_t sum_num; /* number of sum entries */
jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */
jint32_t padded; /* sum of the size of padding nodes */
jint32_t sum_crc; /* summary information CRC */
jint32_t node_crc; /* node CRC */
jint32_t sum[0]; /* inode summary info */
};
●jffs2_sum_inode_flash
struct jffs2_sum_inode_flash
{
jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */
jint32_t inode; /* inode number */
jint32_t version; /* inode version */
jint32_t offset; /* offset on jeb */
jint32_t totlen; /* record length */
};
该节点包含在扫描过程中所需的dnode节点必要信息。
●jffs2_sum_dirent_flash
struct jffs2_sum_dirent_flash
{
jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ jint32_t totlen; /* record length */
jint32_t offset; /* ofset on jeb */
jint32_t pino; /* parent inode */
jint32_t version; /* dirent version */
jint32_t ino; /* == zero for unlink */
uint8_t nsize; /* dirent name size */
uint8_t type; /* dirent type */
uint8_t name[0]; /* dirent name */
};
该节点包含扫描过程所需的dirent节点的必要信息。
●jffs2_sum_marker
struct jffs2_sum_marker