Filesystems

創建小 ubifs 卷時的成本驚人地大

  • July 10, 2018

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

引用自:https://unix.stackexchange.com/questions/294656