在具有 39 个擦除块 (= 4.9 MiB) 的 mtd 分区上,我尝试格式化 ubifs。当保留块减少到最小可能的 1 块时(我知道这不好),生成的文件系统具有 2.2M 未压缩数据的可用空间。这意味着只有 45% 的空间可用于数据。
使用 jffs2 格式化的同一区域允许我写入 4.6 MB 的数据,这是 ubifs 设置中大小的 93% 或两倍以上。
问题是我无法使用 jffs2,因为我的 64 字节 OOB 大小没有为 BCH8 和 JFFS2 OBB 数据提供足够的空间,如TI 警告。
我已经阅读了常见问题解答章节 为什么我的 UBIFS 卷的容量明显低于同等的 JFFS2 卷? 和 为什么 df 报告可用空间太少? 但我还是不敢相信开销这么大。
我可以做些什么来增加我的(可写)ubifs 卷的可用空间吗?
合并 ubi0 和 ubi1 时是否节省空间? (超过保留块?)
这是我的设置:
$ mtdinfo -a
mtd10
Name: NAND.userdata
Type: nand
Eraseblock size: 131072 bytes, 128.0 KiB
Amount of eraseblocks: 39 (5111808 bytes, 4.9 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size: 512 bytes
OOB size: 64 bytes
Character device major/minor: 90:20
Bad blocks are allowed: true
Device is writable: true
$ ubinfo -a
ubi1
Volumes count: 1
Logical eraseblock size: 129024 bytes, 126.0 KiB
Total amount of logical eraseblocks: 39 (5031936 bytes, 4.8 MiB)
Amount of available logical eraseblocks: 0 (0 bytes)
Maximum count of volumes 128
Count of bad physical eraseblocks: 0
Count of reserved physical eraseblocks: 1
Current maximum erase counter value: 2
Minimum input/output unit size: 2048 bytes
Character device major/minor: 249:0
Present volumes: 0
Volume ID: 0 (on ubi1)
Type: dynamic
Alignment: 1
Size: 34 LEBs (4386816 bytes, 4.2 MiB)
State: OK
Name: userdata
Character device major/minor: 249:1
dmesg:
[ 1.340937] nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xf1
[ 1.347903] nand: Micron MT29F1G08ABADAH4
[ 1.352108] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
[ 1.359782] nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme
uname -a:
Linux 4.1.18-g543c284-dirty #3 PREEMPT Mon Jun 27 17:02:46 CEST 2016 armv7l GNU/Linux
创建并测试 ubif:
# flash_erase /dev/mtd10 0 0
Erasing 128 Kibyte @ 4c0000 -- 100 % complete
# ubiformat /dev/mtd10 -s 512 -O 512
ubiformat: mtd10 (nand), size 5111808 bytes (4.9 MiB), 39 eraseblocks of 131072 bytes (128.0 KiB), min. I/O size 2048 bytes
libscan: scanning eraseblock 38 -- 100 % complete
ubiformat: 39 eraseblocks are supposedly empty
ubiformat: formatting eraseblock 38 -- 100 % complete
# ubiattach -d1 -m10 -b 1
UBI device number 1, total 39 LEBs (5031936 bytes, 4.8 MiB), available 34 LEBs (4386816 bytes, 4.2 MiB), LEB size 129024 bytes (126.0 KiB)
# ubimkvol /dev/ubi1 -N userdata -m
Set volume size to 4386816
Volume ID 0, size 34 LEBs (4386816 bytes, 4.2 MiB), LEB size 129024 bytes (126.0 KiB), dynamic, name "userdata", alignment 1
# mount -t ubifs ubi1:userdata /tmp/1
# df -h /tmp/1
Filesystem Size Used Avail Use% Mounted on
- 2.1M 20K 2.0M 2% /tmp/1
# dd if=/dev/urandom of=/tmp/1/bigfile bs=4096
dd: error writing '/tmp/1/bigfile': No space left on device
550+0 records in
549+0 records out
2248704 bytes (2.2 MB) copied, 1.66865 s, 1.3 MB/s
# ls -l /tmp/1/bigfile
-rw-r--r-- 1 root root 2248704 Jan 1 00:07 /tmp/1/bigfile
# sync
# df -h /tmp/1
Filesystem Size Used Avail Use% Mounted on
- 2.1M 2.1M 0 100% /tmp/1
创建并测试 jffs2:
# mkdir /tmp/empty.d
# mkfs.jffs2 -s 2048 -r /tmp/empty.d -o /tmp/empty.jffs2
# flash_erase /dev/mtd10 0 0
Erasing 128 Kibyte @ 4c0000 -- 100 % complete
# nandwrite /dev/mtd10 /tmp/empty.jffs2
Writing data to block 0 at offset 0x0
# mount -t jffs2 /dev/mtdblock10 /tmp/1
# df -h /tmp/1
Filesystem Size Used Avail Use% Mounted on
- 4.9M 384K 4.5M 8% /tmp/1
# dd if=/dev/urandom of=/tmp/1/bigfile bs=4096
dd: error writing '/tmp/1/bigfile': No space left on device
1129+0 records in
1128+0 records out
4620288 bytes (4.6 MB) copied, 4.54715 s, 1.0 MB/s
# ls -l /tmp/1/bigfile
-rw-r--r-- 1 root root 4620288 Jan 1 00:20 /tmp/1/bigfile
# sync
# df -h /tmp/1
Filesystem Size Used Avail Use% Mounted on
- 4.9M 4.9M 0 100% /tmp/1
更新:
所以我现在可以更具体地提出我的问题:
这个“公式”似乎是usable_size_mb = (raw_size_mb - 2.3831) * 0.89423077
换句话说:无论我的 mtd 有多大,总是会丢失 2.38 MB,无论我们的卷有多大。这是19个擦除块的大小。其余的是用户数据 10.6% 的文件系统开销,这是一个很高的值,但对于 ubifs 来说并不意外。
顺便提一句。在进行测试时,我收到内核警告,至少需要 17 个擦除块(= 2.176 MB)。但成功通过测试的最小 mtd 有 22 个块(2.816 MB)。
答案1
为什么数字不匹配
“至少 17 个擦除块”警告对 UBIFS 文件系统本身所需的块进行计数。在这 17 个擦除块中,14 个是 UBIFS 开销,3 个是可用文件系统空间。下面的底层 UBI 层也使用 5 个擦除块的开销。
获得更多空间
没有办法让单个 UBI 分区和单个 UBIFS 文件系统使用更少的开销。
但是,如果同一 MTD 设备上有多个 UBI 分区,我建议将它们合并。它不仅可以释放 5 个擦除块,还可以改善磨损均衡和坏块处理,因为 UBI 将有更多选项根据需要将物理擦除块映射到逻辑擦除块。
(忽略开销,想象一下两个分区,每个分区有两个块,其中一个是坏的。现在一个分区只剩下一个块了,不可能做磨损均衡。但是如果你把这两个合并起来,那么你就剩下三个好块了根据需要在两个文件系统之间共享。)
合并两个相邻的 UBI 分区:
- 更新您的 MTD 分区表,将两个分区替换为一个较大的分区。
ubiformat
在那个大分区上运行。- 运行
ubimkvol
两次,提供适当的分区名称并使用-s
或手动指定大小-S
。
UBI+UBIFS 开销的核算
首先,UBI层占用5个擦除块的开销:
- 2 为体积表
- 1 保留用于磨损均衡算法
- 1 保留用于“原子 LEB 更改”功能,该功能允许对逻辑擦除块进行可靠的就地更新
- 1(理想情况下更多,正如您所提到的)保留用于处理坏的物理擦除块。
接下来,UBIFS 层具有用于文件系统元数据的最小擦除块数量:
- 1 表示文件系统超级块,它将卷标识为有效的 UBIFS 并存储文件系统参数
- 2为主节点区域(冗余副本),它们是用于文件系统查找的树的根
- 2 个或更多用于日志区域(计入可用空间)
- 2为LEB属性树,它跟踪每个逻辑擦除块的使用方式
- 1 个或多个用于孤立区域(用于跟踪已删除的文件,以便在不干净的卸载后正确清理它们)
- 8 保留用于文件系统元数据(垃圾收集、删除、芽、索引)
- 1 个或多个用于不在日志中的已提交数据(可用空间)。
参考
对于 UBI 开销,linux-mtd 站点有一个简单的描述。
对于 UBIFS 开销,我必须做更多的挖掘。这mtd-utils的源代码计算擦除块的绝对最小数量并提及每个块的用途。为了理解它的意义,UBIFS 白皮书很有用。