創建小 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
創建和測試 ubifs:
# 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)。
為什麼數字不匹配
“至少 17 個擦除塊”警告計算 UBIFS 文件系統本身所需的塊。在這 17 個擦除塊中,14 個是 UBIFS 成本,3 個是可用的文件系統空間。下面的底層 UBI 層也使用了 5 個擦除塊成本。
獲得更多空間
沒有辦法使具有單個 UBIFS 文件系統的單個 UBI 分區使用更少的成本。
但是,如果您在同一台 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 白皮書很有用。