Bcachefs
Bcachefs 是一種寫時複製(CoW)文件系統,支持多設備、RAID、壓縮、校驗和加密。它旨在提供類似於 Btrfs 和 ZFS 的現代功能。
Bcachefs 基於 Bcache,兩者都主要由 Kent Overstreet 開發。
自 2024 年 1 月內核發布 6.7 版本起,Bcachefs 已被合併到上游,因此可以直接安裝 linux包 或是 linux-zen包 來使用。其他的內核軟體包可能基於低於 6.7 版本的內核,所以可能會需要額外的補丁才能使用 Bcachefs。
bcachefs-tools包 是 Bcachefs 用戶空間的工具。
# bcachefs format /dev/sdX # mount -t bcachefs /dev/sdX /mnt
與 RAID0 類似,Bcachefs 默認會將數據條帶化存儲 (stripe)。數據冗餘由 replicas 選項進行處理。 對 2 個存儲設備使用 --replicas=2 相當於 RAID1,對 4 個存儲設備使用 --replicas=2 相當於 RAID10,以此類推。
# bcachefs format /dev/sdX /dev/sdY --replicas=n # mount -t bcachefs /dev/sdX:/dev/sdY /mnt
Bcachefs 支持混合使用不同的儲存設備。如果儲存設備的大小不同,為了讓每個儲存設備以相同的速率填滿數據,文件系統在某些儲存設備上會使用更大的條帶。如果儲存設備的速度不同,對冗餘數據的讀取請求會被發往 IO 延遲最低的設備。如果有些儲存設備比其他更可靠(例如硬體 RAID),可以通過 --durability=2 device 來把上面的每份數據副本算成兩份。
Bcachefs 使用 自行實現 的全文件系統加密,採用 ChaCha20-Poly1305。要格式化加密的文件系統:
# bcachefs format --encrypted /dev/sdX
如果用於根文件系統,請在 /etc/mkinitcpio.conf 的 HOOKS 中添加 bcachefs,以便在啟動或從休眠恢復時提示文件系統解鎖。
bcachefs hook。
Bcachefs 有四個儲存目標(storage targets): metadata、background、foreground 和 promote。對文件系統進行的寫入優先使用 foreground,然後隨著時間推移移動至 background。對文件系統的讀取會緩存在 promote 上。metadata 目標通常與超低讀取延遲的 NVMe 驅動器一起使用,例如 Intel Optane。
推薦的一種配置是使用一組 SSD 作為 foreground 和 promote,使用一組 HDD 作為 background(也就是回寫緩存)。
# bcachefs format \
--label=ssd.ssd1 /dev/sdA \
--label=ssd.ssd2 /dev/sdB \
--label=hdd.hdd1 /dev/sdC \
--label=hdd.hdd2 /dev/sdD \
--label=hdd.hdd3 /dev/sdE \
--label=hdd.hdd4 /dev/sdF \
--replicas=2 \
--foreground_target=ssd \
--promote_target=ssd \
--background_target=hdd
# mount -t bcachefs /dev/sdA:/dev/sdB:/dev/sdC:/dev/sdD:/dev/sdE:/dev/sdF /mnt
如果想配置直寫緩存,和上面操作基本一致,不過要對每個 SSD 設備設置 --durability=0 device。
如果想配置繞寫緩存,只需把 HDD 設為 foreground,把 SSD 設為 promote。
默認的掛載方式是在 mount 指令中指定每個設備。
# mount -t bcachefs /dev/sdA:/dev/sdB:/dev/sdC:/dev/sdD:/
mount.bcachefs 支持通過 UUID 掛載文件系統,UUID 會在使用 bcachefs format 創建文件系統時顯示。
# mount.bcachefs UUID=f66d108f-83d2-4679-b50b-7d5e710f6
大多數選項可以通過以下方式設置:
- 在
bcachefs format期間 - 在格式化後使用
bcachefs set-fs-option - 在掛載時通過
mount -o option=value - 或通過 sysfs,例如
echo X > /sys/fs/bcachefs/UUID/options/option
掛載選項會覆蓋其他方法設置的選項,後者會將選項保存到文件系統的超級塊中。
一些可用選項舉例如下:
| 選項 | 描述 |
|---|---|
| metadata_checksum | 指定用於元數據寫入的校驗和 (checksum)算法。默認情況下,算法為 crc32c。可以從none、crc32c、crc64、xxhash中選擇其一。
|
| data_checksum | 指定用於數據寫入的校驗和 (checksum)算法,與metadata_checksum具有相同的默認值和選項。
|
| compression | 指定用於(前台)壓縮的算法。默認情況下此選項為none。可以從none、lz4、gzip、zstd中選擇其一。
|
| background_compression | 指定用於後台壓縮的算法,與compression具有相同的默認值和選項。
|
| str_hash | 指定用於directory entries和 xattrs 的哈希函數。可以從crc32c、crc64和siphash中選擇其一。
|
| nocow | 在可能的情況下,所有寫入都將就地完成。快照 (snapshot) 和 reflink 仍會導致 COW 寫入。該選項會隱式禁用數據校驗、壓縮和加密。 |
| encrypted | 啟用文件系統加密(chacha20/poly1305);將提示輸入密碼。 |
更多選項可以在 bcachefs 文檔中找到。
以下內容可以通過 bcachefs setattr file --option=value 按每個文件或目錄進行設置。如果在一個目錄中設置,它會進行遞歸傳遞。
- 數據冗餘數 (data_replicas)
- 數據校驗和 (data_checksum)
- 前台壓縮 (compression)、後台壓縮 (background_compression)
- 存儲組配置:foreground_target、background_target、promote_target
要檢查哪些選項處於活動狀態,可以執行 getfattr -d -m 'bcachefs_effective\.' directory/file
可以通過 sysfs 更改所屬儲存組:
# echo group.drive_name > /sys/fs/bcachefs/filesystem_uuid/dev-X/label
# bcachefs device add --label=group.drive_name /mnt /dev/device
若這是某儲存組中的第一個設備,則需要修改儲存目標的設置才能使用。以下例子添加了一個緩存設備。
# echo new_group > /sys/fs/bcachefs/filesystem_uuid/options/promote_target # echo new_group > /sys/fs/bcachefs/filesystem_uuid/options/foreground_target # echo old_group > /sys/fs/bcachefs/filesystem_uuid/options/background_target
首先請確保至少設備上有兩份元數據(設備移除(evacuate)功能似乎對元數據不奏效)。如果數據和元數據都已經有冗餘了,可以跳過這一步。
# echo 2 > /sys/fs/bcachefs/UUID/options/metadata_replicas # bcachefs data rereplicate /mnt # bcachefs device set-state ro device # bcachefs device evacuate device
將狀態設置為 ro,表示只讀。
若想移除設備:
# bcachefs device remove device # bcachefs data rereplicate /mnt
Bcachefs 中的元數據和數據的冗餘級別可以獨立配置,以控制數據冗餘和持久性(durability)。 以下選項既定義了同步(即時)冗餘,它會在寫入時原子執行以確保數據完整;同時也定義了最終冗餘目標(eventual replication target),其會在在後台異步完成以提高冗餘和故障容忍度。
-
--replicas=X設置元數據和數據副本的目標數量。 -
--metadata_replicas=X設置在正常運行和重新平衡期間後台維護的元數據副本的目標數量。 -
--data_replicas=X設置最終要維持的數據副本的目標數量。 -
--metadata_replicas_required=X設置在元數據被視為已提交之前,必須同步寫入的元數據副本的最小數量。 -
--data_replicas_required=X設置在數據被視為已提交之前,必須同步寫入的數據副本的最小數量。
--[meta]data_replicas_required 與 --[meta]data_replicas 非常重要,因為 _replicas_required 值設定了將被立即寫入的副本數量的下限,而 _replicas 值設定了最終會寫入的副本數量。可以將 _replicas_required 解釋為如果我們只能完成這麼多寫入,文件系統依然能以降級模式(degraded)運行 [1]。壓縮通過 --compression= 選項設置,支持設置壓縮級別。比如要設置 zstd 壓縮並使用級別 5,可以使用 --compression=zstd:5。
Bcachefs 支持使用與 Btrfs 類似的用戶空間接口來管理子卷和快照。新子卷可以創建為空子卷,也可以是另一個子卷的快照。快照是可寫的,並且可以多次快照,從而形成快照樹。
創建快照的成本非常低:它們不像 Btrfs 那樣基於 COW btree 的克隆,而是基於 btree 中單個鍵的版本控制。你可以創建成千上萬個快照,唯一的限制是磁碟空間。
創建一個新的空子卷:
# bcachefs subvolume create /path/to/subvolume
刪除已有的子卷或快照:
# bcachefs subvolume delete /path/to/subvolume
為現有子卷創建快照:
# bcachefs subvolume snapshot /path/to/source /path/to/dest
子卷在刪除其中所有內容後也可以使用常規的 rmdir 刪除,比如使用 rm -rf。
遞歸快照創建和遞歸列出子卷等功能仍待實現。
請查看 Systemd/Journal 以獲取更多有用的錯誤信息。
一些 bcachefs format 標誌是根據其參數順序設置的,並且僅影響切換標誌後出現的驅動器。例如,如果希望 SSD 具有 --durability=0 並啟用 --discard 而 HDD 使用默認值,請確保按以下順序傳遞參數:
# bcachefs format \
--label=hdd.hdd1 /dev/sdC \
--label=hdd.hdd2 /dev/sdD \
--label=hdd.hdd3 /dev/sdE \
--label=hdd.hdd4 /dev/sdF \
--durability=0 --discard \
--label=ssd.ssd1 /dev/sdA \
--label=ssd.ssd2 /dev/sdB \
--replicas=2 \
--foreground_target=ssd \
--promote_target=ssd \
--background_target=hdd
可以使用 set-fs-option 在格式化後設置副本(冗餘)數量。
# bcachefs set-fs-option --metadata_replicas=2 --data_replicas=2 /dev/sdX
之後需要讓 bcachefs 確保所有文件都擁有副本,命令為:
# bcachefs data rereplicate /mnt
部分 32 位程序可能無法獲取 Bcachefs 目錄中的內容,這是由於執行 readdir(3) syscall 時文件系統返回的數據不兼容所導致。[3]
要解決這個問題,可以暫時使用不同的文件系統供程序讀寫,比如 tmpfs。
Bcachefs 目前不支持交換文件。
目前 systemd 存在一個 bug,導致無法在啟動時通過在 fstab 中使用以冒號分隔的設備來掛載多設備 bcachefs 文件系統。使用 mount -a 時可以正常掛載,但在開機啟動時不會掛載。不過自從 bcachefs-tools包 版本 1.7.0 起,可以通過單個設備節點來掛載多設備陣列,從而允許使用正常的 UUID 指定方法。
# UUID=10176fc9-c4fa-4a30-9fd0-a756d861c4cd /mnt bcachefs defaults,nofail 0 0
可以通過以下任一命令找到文件系統 UUID / 外部 UUID:
# bcachefs fs usage /mnt # bcachefs show-super /dev/sdXY
對於使用 --encrypted 選項創建的設備,當 bcachefs unlock /dev/sdXY 後掛載失敗時,出現
ERROR - bcachefs::commands::cmd_mount: Fatal error: Required key not available
可以通過手動將密鑰連結到會話來解決這個問題[4]:
# keyctl link @u @s # mount /dev/sdXY /mnt Enter passphrase:
不需要輸入 mount 要求的密碼(按回車鍵即可)。