创建小 ubifs 卷时的开销大得惊人

创建小 ubifs 卷时的开销大得惊人

在具有 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 白皮书很有用。

相关内容