ubifs使用技巧

ubifs使用技巧

2000-02-14 114 写

ubifs号称性能比yaffs2 好,同时压缩可读写,文件系统image体较小同时可写。

1. uboot启用对UBIFS的支持

#define CONFIG_CMD_NAND
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_RBTREE
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_LZO

注:需要烧写mkfs.ubifs结果时候需要打开,ubinize处理过的镜像不需要打开ubi专有配置。

2. Kernel启用对UBIFS的支持

Enabling UBI support on MTD devices.
Device Drivers --->
Memory Technology Device (MTD) support --->
Enable UBI - Unsorted block images --->
Enabling UBIFS file-system support
File systems --->
Miscellaneous filesystems --->
UBIFS file system support

3. 下载和编译MTD Utilities
3.1 下载 MTD Utilites
通过 git://git.infradead.org/mtd-utils.git 下载最新的 MTD-Utils 源代码。
下载 3 个编译所需的依赖库
Zlib: http://zlib.net/
Lzo: http://www.oberhumer.com/opensource/lzo/download/
e2fsprogs: http://e2fsprogs.sourceforge.net/
在用户目录下建立/mtd, /mtd/install 目录,将以上 4 个 source code 包拷贝到/mtd下,安装如下步骤先编译依赖包:
zlib

host$ tar xvf zlib-1.2.5.tar.gz
host$ cd zlib-1.2.5/
host$ ./configure --prefix=~/mtd/install
host$ make
host$ make install
host$ cd ..

lzo

host$ tar xvf lzo-2.06.tar.gz
host$ cd lzo-2.06/
host$ ./configure --build=i686-pc-linux --prefix=~/mtd/install
host$ make
host$ make install
host$ cd ..

e2fsprogs

host$ tar xvf e2fsprogs-1.42.tar.gz
host$ cd e2fsprogs-1.42/
host$ ./configure --build=i686-pc-linux --prefix=~/mtd/install
host$ make
host$ make install
host$ cd lib/uuid/
host$ make install
host$ cd ../../../

3.2 编译 MTD Utilites:
在编译 mtd-utils 之前,先修改 makfile 文件:

host$ vi Makefile
PREFIX = ~/mtd/install
ZLIBCPPFLAGS = -I$(PREFIX)/include
LZOCPPFLAGS = -I$(PREFIX)/include
ZLIBLDFLAGS = -L$(PREFIX)/lib
LZOLDFLAGS = -L$(PREFIX)/lib
LDFLAGS += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
CFLAGS ?= -O2 -g $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
host$ vi common.mk
#PREFIX=/usr

然后依照如下指令编译:

host$ WITHOUT_XATTR=1 make
host$ make install DESTDIR=~/mtd/install
host$ cd ..

制作 ubi 文件系统所用的工具在如下目录下:

~/mtd/install/home/<username>/mtd/install/sbin/mkfs.ubifs ~/mtd/install/home/<username>/mtd/install/sbin/ubinize

注:可直接采用系统自带的mkfs.ubifs和ubinize工具,若不存在可apt-get安装。
4. ubifs制作
(1) mkfs.ubifs
制作UBIFS image

mkfs.ubifs -r system -m 2048 -e 126976 -c 1057 -x zlib -o system.ubifs
mkfs.ubifs -r rootfs -o rootfs.img -F -m 2048 -e 124KiB -c 40
-r:待制作的文件系统目录。
-o:输出的image名字 。
-F:使能“white-space-fixup”,如果是通过u-boot烧写需要使能此功能。
-m:Nand Flash的最小读写单元,一般为page size。
-e:LEB size,说的是逻辑擦除块大小,大家知道nand flash页读页写块擦,一个设备多个块,一个块多个页,一般也都是一个块是64个页,这样算一下无论擦除块大小就是2048*64=131072,-e的算法是物理擦除块大小-2*页大小,这里就是131072-2*2048=126976
-c说的是最大逻辑块数量,这个很重要,不能大也不能小,太小也要大于image大小,太大mount有问题。计算起点是分区的物理块数量,比如128MiB的mtd分区,物理块数量是128MiB/2048/64 = 1024个,需要减去2个坏块保留块,减去1个wear-leveling块,还要减去1个eba的块,等等,比如最终的值是1022,注意,如果物理上这个分区有坏块的话,kernel会扫描到的,这时候,我们计算的这个值就要减去坏块数了,否则会有逻辑块大于物理块数的内核问题mount失败,确切知道坏块数是比较困难的,一般做法是做一个坏块容忍数,比如20个,这样我们再减去20个坏块,不要担心这个会浪费空间,ubinize的autoresize选项就是解决这个问题的。具体的这个值需要计算。!!!!
-x说的是压缩方法,默认是lzo,还支持zlib,zlib压缩率高些,但是lzo压缩解压速度快 。

(2) ubinize
根据UBIFS image制作ubi.img,这个ubi.img是通过u-boot直接烧写到nand flash分区上的。

ubinize -o system.ubi -m 2048 -p 131072 ubinize.cfg

-o说的是输出image
-m还是页大小
-p是物理擦除块大小
ubinize.cfg是volume配置文件,例子如下:

[ubifs]
mode=ubi
image=system.ubifs #说的是mkfs.ubifs的结果
vol_id=0
vol_size=100MiB #说的是volume大小,用-e和-c的值做乘法计算,一般不用写,autoresize会自动根据mtd分区大小适应,默认值是image大小,写了这个作用是帮助检查image是否超过了分区限制,制作时候就提示,否则mount会出错。-c的值是经过计算的最大值了,不过autoresize参数会自适应大小,不会浪费空间的。
vol_type=dynamic
vol_alignment=1
vol_name=system #说的是分区名字
vol_flags=autoresize

5. ubifs烧写
(1)mkfs.ubifs工具制作的结果,就是ubifs镜像,不包含volume信息,需要用

nand erase.part system – 擦除分区
ubi part system - 激活分区
ubi create system - 创建分区
ubi write 84000000 system xxxxx - xxxxx表示镜像实际大小

(2)ubi volume bin烧写
mkfs.ubifs后,使用ubinize处理了ubifs的镜像后,镜像含有了volume信息,直接

nand write 84000000 system xxxxx - xxxxx表示镜像实际大小

(3)示例

TI AM335x一份uboot下烧写记录:

可通过 u-boot 命令将生成的 ubi.img( 25M)烧写到 NAND FLASH 分区上, 如下示例是将 ubi.img 先存储到 SD 卡上,然后通过 u-boot 的 fatload 命令将其拷贝至内存中。

u-boot# mw.b 0x82000000 0xFF
u-boot# mmc rescan
u-boot# fatload mmc 0 0x82000000 ubi.img
u-boot# nand erase 0x00780000 0xF880000
u-boot# nand write 0x82000000 0x00780000 0x1E00000

6. linux启动参数设置
在 U-boot 下设置启动信息如下:

#setenv bootargs 'console=ttyO0,115200n8 noinitrd ip=off mem=256M
rootwait=1 rw ubi.mtd=7,2048 rootfstype=ubifs root=ubi0:rootfs
init=/init'

可在命令行参数中增加多个ubi设备,如ubi.mtd=2,ubi.mtd=1,这样传递后,内核启动后会做attach的操作,attach之后,/dev/下就建立好设备了。

7. ubifs mount

UBI character devices:
a) /dev/ubi0, /dev/ubi1
   UBI devices: volume create, delete, re-size, and get device description operations
b) /dev/ubi0_0, /dev/ubi0_1
   UBI volumes: read, write, update, and get volume description operations
Linux 系统中有关mtd和ubi的接口:
(1) cat /proc/mtd                  可以看到当前系统的各个mtd情况
(2) cat /proc/partitions           分区信息,有上面的类似
(3) cat /sys/class/ubi/ubi0/*      当前系统的ubi0情况
(4) ls /dev/*                      查看设备节点
假设我们想在mtdblock1上加载ubifs文件系统,步骤如下:
(1)ubiformat /dev/mtd1           格式化mtdblock1
(2)ubiattach /dev/ubi_ctrl -m 1  将mtdblock1与ubi建立连接
命令输出如下:
[ 977.342492] UBI: attaching mtd1 to ubi2
[ 977.346417] UBI: physical eraseblock size: 131072 bytes (128 KiB)
[ 977.352631] UBI: logical eraseblock size: 126976 bytes
[ 977.357948] UBI: smallest flash I/O unit: 2048 UBI device number 2, total 2000 LEBs (253952000 bytes, 242.2 MiB), available 1976 LEBs (250904576 bytes, 239.3 MiB), LEB size 126976 bytes (124.0 KiB)
系统自动将mtd1关连到ubi2上,假设系统中已经存在ubi0, ubi1了。

(3) ls /sys/class/ubi/             可以看到该目录下增加了一个ubi2的子目录
(4) cat /sys/class/ubi/ubi2/dev    可以得到该ubi2设备的主次设备号,如249:0
(5) cat /sys/class/ubi/ubi2/volumes_count     结果为0,表示该ubi上没有任何volume
(6) ls /dev/ubi*                   如果/dev中没有ubi2, 则手工创建“mknod /dev/ubi2 c 249 0”
(7) ubimkvol /dev/ubi2 -s 100MiB -N my_ubi_vol   在ubi2上创建一个volume
(8) ls /sys/class/ubi/     
可以看到该目录下增加一个ubi2_0的目录,代表ubi2上的第一个volume,如果“cat /sys/class/ubi/ubi2_0/name”, 你可以得到“my_ubi_vol”,这就是(7)中的名字。
(9) cat /sys/class/ubi/ubi2_0/dev  得到该volume的主次设备号,如249:1
(10) mknod /dev/ubi2_0 c 249 1     如果/dev中没有ubi2_0, 则需要手工创建
(11) mount -t ubifs ubi2_0 /mnt    将ubi2_0挂载到本地目录 /mnt上,
(12) mount                         可以看到ubi2_0成功挂载在/mnt上。

8.ubifs 卸载

umount /mnt/ubi
ubidetach -d 0

9.使用ubi做根文件系统,需要在bootargs中设置如下信息:

 root=ubi0:rootfs ubi.mtd=4 rootfstype=ubifs

linux源码中Documentation/filesystems/ubifs.txt中含有ubifs mount的用法:

Mount options
=============
(*) == default.
bulk_read read more in one go to take advantage of flash media that read faster sequentially
no_bulk_read (*) do not bulk-read
no_chk_data_crc skip checking of CRCs on data nodes in order to
improve read performance. Use this option only
if the flash media is highly reliable. The effect
of this option is that corruption of the contents
of a file can go unnoticed.
chk_data_crc (*) do not skip checking CRCs on data nodes
compr=none override default compressor and set it to "none"
compr=lzo override default compressor and set it to "lzo"
compr=zlib override default compressor and set it to "zlib"
Quick usage instructions
========================
The UBI volume to mount is specified using "ubiX_Y" or "ubiX:NAME" syntax, where "X" is UBI device number, "Y" is UBI volume number, and "NAME" is UBI volume name.
Mount volume 0 on UBI device 0 to /mnt/ubifs:
$ mount -t ubifs ubi0_0 /mnt/ubifs
Mount "rootfs" volume of UBI device 0 to /mnt/ubifs ("rootfs" is volume name):
$ mount -t ubifs ubi0:rootfs /mnt/ubifs
The following is an example of the kernel boot arguments to attach mtd0 to UBI and mount volume "rootfs":
ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs

附:常见问题

(1)

ubifs_check_node: bad CRC: calculated 0xca82b3d7, read 0x9be0e26
ubifs_check_node: bad node at LEB 51:45312

这个crc错误,说的错误并不是LED 0的问题,也就是说第一个逻辑块没问题,CRC是正确的,这个问题的一个解决办法是要精确mkfs.ubifs时候的-c参数的值,不能太大了

(2)


[ 5.433349] UBIFS error (pid 71): ubifs_read_node: bad node type (150 but expected 1)
[ 5.434204] UBIFS error (pid 71): ubifs_read_node: bad node at LEB 524:4072, LEB mapping status 1
[ 5.435241] Not a node, first 24 bytes:
[ 5.435729] 00000000: 34 fb 21 ee 84 18 69 2d 60 b0 33 e6 74 f8 1c 15 da ca a1 c9 96 e3 ac 51 4.!...i-`.3.t..........Q

这个问题是,ubifs给nand驱动的buffer不一定是按照硬件对齐要求的,所以要驱动来判断,dma等地址需要页对齐等特性
(3) crc错误,但是LED 0:0
可能镜像没烧对,或者mtd-utils的版本和内核版本相差较远
(4) 可以擦掉一个分区,并不需要非要烧写image到那个分区,也可以直接mount的,这样可以做实验验证ubi的性能,前提是kernel配置好了,mount正确了
(5) 如果是跟文件系统或者要手动mount,以下步骤供参考:

uboot下, mtd命令后,看到需要用ubifs的mtd分区的编号,比如
device nand0 <rda_nand>, # parts = 10
#: name size offset mask_flags
0: bootloader 0x00200000 0x00000000 0
1: boot 0x00800000 0x00800000 0
2: system 0x08000000 0x02000000 0
system分区mtd编号是2,命令如下:
nand erase.part system
命令行参数增加ubi.mtd=2,如果有多个,可以增加,如ubi.mtd=2,ubi.mtd=1,这样传递后,内核启动后会做attach的操作,类似android的init中的attach那样,attach之后,/dev/下就建立好设备了,进入系统后用:内核控制台里,mount -t ubifs /dev/ubi0_0 /mnt 即可mount

参考文献:http://www.linux-mtd.infradead.org/faq/ubifs.html

标签 , , , , , , , , , , ,